Aim: To design arithmetic circuit Array Multiplier using Verilog RTL

Apparatus Required: Xilinx Vivado

Theory: An Array Multiplier is a digital circuit used to perform the multiplication of two binary numbers. It is based on the standard "paper-and-pencil" method of multiplication, which involves two primary steps:

  1. Generation of Partial Products: Each bit of the multiplier is multiplied (ANDed) with each bit of the multiplicand.
  2. Accumulation of Partial Products: These products are shifted and added together to produce the final result.

Verilog Code:

module half_adder(input a, b, output s0, c0);
  assign s0 = a ^ b;
  assign c0 = a & b;
endmodule

module full_adder(input a, b, cin, output s0, c0);
  assign s0 = a ^ b ^ cin;
  assign c0 = (a & b) | (b & cin) | (a & cin);
endmodule

module array_multiplier(input [3:0] A, B, output [7:0] z);
  // Corrected: Using a 2D wire array for partial products
  wire p [0:3][0:3]; 
  wire [10:0] c; // c represents carry of HA/FA
  wire [5:0] s;  // s represents sum of HA/FA
  
  genvar g;
  generate
    // Added a block name (gen_pp) as required by standard Verilog rules
    for(g = 0; g < 4; g = g + 1) begin : gen_pp
      and a0(p[g][0], A[g], B[0]);
      and a1(p[g][1], A[g], B[1]);
      and a2(p[g][2], A[g], B[2]);
      and a3(p[g][3], A[g], B[3]);
    end
  endgenerate
  
  assign z[0] = p[0][0];

  // row 0
  half_adder h0(p[0][1], p[1][0], z[1], c[0]);
  half_adder h1(p[1][1], p[2][0], s[0], c[1]);
  half_adder h2(p[2][1], p[3][0], s[1], c[2]);
  
  // row 1
  full_adder f0(p[0][2], c[0], s[0], z[2], c[3]);
  full_adder f1(p[1][2], c[1], s[1], s[2], c[4]);
  full_adder f2(p[2][2], c[2], p[3][1], s[3], c[5]);
  
  // row 2
  full_adder f3(p[0][3], c[3], s[2], z[3], c[6]);
  full_adder f4(p[1][3], c[4], s[3], s[4], c[7]);
  full_adder f5(p[2][3], c[5], p[3][2], s[5], c[8]);
  
  // row 3
  half_adder h3(c[6], s[4], z[4], c[9]);
  full_adder f6(c[9], c[7], s[5], z[5], c[10]);
  full_adder f7(c[10], c[8], p[3][3], z[6], z[7]);
  
endmodule

Test Bench:

module tb_array_multiplier();

  // Inputs
  reg [3:0] A;
  reg [3:0] B;

  // Outputs
  wire [7:0] z;

  // Instantiate the Unit Under Test (UUT)
  array_multiplier uut (
    .A(A), 
    .B(B), 
    .z(z)
  );

  initial begin
    // Setup monitoring to print to console automatically when variables change
    $display("Time\\t A \\t B \\t Output (z) \\t Expected");
    $display("---------------------------------------------------------");
    $monitor("%0t\\t %d \\t %d \\t %d \\t\\t %d", $time, A, B, z, A * B);

    // Initialize Inputs
    A = 0; B = 0;

    // Apply Test Cases
    #10 A = 4'd2;  B = 4'd3;   // 2 * 3 = 6
    #10 A = 4'd5;  B = 4'd4;   // 5 * 4 = 20
    #10 A = 4'd7;  B = 4'd8;   // 7 * 8 = 56
    #10 A = 4'd15; B = 4'd15;  // 15 * 15 = 225 (Maximum boundary)
    #10 A = 4'd9;  B = 4'd9;   // 9 * 9 = 81
    #10 A = 4'd10; B = 4'd0;   // 10 * 0 = 0  (Zero boundary)
    #10 A = 4'd1;  B = 4'd15;  // 1 * 15 = 15
    
    // End Simulation
    #10 $finish;
  end
      
endmodule

Conclusion: The design of the 4x4 Array Multiplier was successfully implemented and simulated using Verilog RTL in the Xilinx Vivado environment. The simulation results, verified via the testbench, confirm that the circuit correctly performs binary multiplication for various cases, ranging from 0 * 10 = 0 to the maximum boundary of 15 * 15 = 225.