fpga4student.com FPGA digital design projects using Verilog/ VHDL: Parameterized Carry-Look-Ahead Multiplier on FPGA using Verilog HDL

Wednesday, November 30, 2016

Parameterized Carry-Look-Ahead Multiplier on FPGA using Verilog HDL


This project is to implement a parameterized carry look-ahead multiplier using Verilog. It means that users can easily change the number of bits of the multiplier without modifying Verilog code inside. There are MULTICAND_WID and MULTIPLIER_WID parameters to define the number of bits of the multiplicand and multiplier, and when we want to change the number of bits, just change these parameters  and re-synthesize or simulate.



carry look-ahead multiplier verilog



The parameterized carry look-ahead multiplier is implemented using a parameterized CLA Adders and very easy for students to understand and develop.

Below is the Verilog and testbench code for parameterized Carry Look Ahead Adder:


`timescale 1ns/1ps

`define DELAY #10

//carry look-ahead adder

module cpu_wb_cla_adder (in1, in2, carry_in, sum, carry_out);
parameter DATA_WID = 32;

input [DATA_WID - 1:0] in1;

input [DATA_WID - 1:0] in2;
input carry_in;
output [DATA_WID - 1:0] sum;
output carry_out;

//assign {carry_out, sum} = in1 + in2 + carry_in;


wire [DATA_WID - 1:0] gen;

wire [DATA_WID - 1:0] pro;
wire [DATA_WID:0] carry_tmp;

genvar j, i;

generate
//assume carry_tmp in is zero
assign carry_tmp[0] = carry_in;

//carry generator
for(j = 0; j < DATA_WID; j = j + 1) begin: carry_generator
assign gen[j] = in1[j] & in2[j];
assign pro[j] = in1[j] | in2[j];
assign carry_tmp[j+1] = gen[j] | pro[j] & carry_tmp[j];
end

//carry out 
assign carry_out = carry_tmp[DATA_WID];

//calculate sum 
//assign sum[0] = in1[0] ^ in2 ^ carry_in;
for(i = 0; i < DATA_WID; i = i+1) begin: sum_without_carry
assign sum[i] = in1[i] ^ in2[i] ^ carry_tmp[i];
end 
endgenerate
endmodule


// module cla_adder_tb();

// parameter DATA_WID = 16;

// /*AUTOREGINPUT*/

// // Beginning of automatic reg inputs (for undeclared instantiated-module inputs)
// reg carry_in; // To cla1 of cla_adder.v
// reg [DATA_WID-1:0] in1; // To cla1 of cla_adder.v
// reg [DATA_WID-1:0] in2; // To cla1 of cla_adder.v
// // End of automatics


// /*AUTOWIRE*/

// // Beginning of automatic wires (for undeclared instantiated-module outputs)
// wire carry_out; // From cla1 of cla_adder.v
// wire [DATA_WID-1:0] sum; // From cla1 of cla_adder.v
// // End of automatics


// cla_adder cla1(/*AUTOINST*/

      // // Outputs
      // .sum (sum[DATA_WID-1:0]),
      // .carry_out (carry_out),
      // // Inputs
      // .in1 (in1[DATA_WID-1:0]),
      // .in2 (in2[DATA_WID-1:0]),
      // .carry_in (carry_in));

// initial begin

// in1 = 16'd0;
// in2 = 16'd0;
// carry_in = 1'b0;
// end 

// initial begin
// #(`DELAY)
// #(`DELAY) in1 = 16'd10;
// #(`DELAY) in1 = 16'd20;
// #(`DELAY) in2 = 16'd10;
// #(`DELAY) in2 = 16'd20;
// #(`DELAY) in2 = 16'd0;
// #(`DELAY*3) in1 = 16'hFFFF; in2 = 16'hFFFF;
// #(`DELAY*3) in1 = 16'h7FFF; in2 = 16'hFFFF;
// #(`DELAY*3) in1 = 16'hBFFF; in2 = 16'hFFFF;
// end 
// endmodule


Finally, the Verilog and testbench code for the parameterized carry look-ahead multiplier:


`timescale 1ns/1ps

`define DELAY 10

module cpu_wb_cla_multiplier (multicand, multiplier, product);

parameter MULTICAND_WID = 32;
parameter MULTIPLIER_WID = 32;

input [MULTICAND_WID-1:0] multicand;

input [MULTIPLIER_WID-1:0] multiplier;
output [(MULTICAND_WID + MULTIPLIER_WID - 1):0] product;

wire [MULTICAND_WID - 1:0] multicand_tmp [MULTIPLIER_WID-1:0];

wire [MULTICAND_WID - 1:0] product_tmp [MULTIPLIER_WID-1:0];
wire [MULTIPLIER_WID -1:0] carry_tmp;

genvar i, j;

generate 
//initialize values
for(j = 0; j < MULTIPLIER_WID; j = j + 1) begin: for_loop_j
assign multicand_tmp[j] =  multicand & {MULTICAND_WID{multiplier[j]}};
end

assign product_tmp[0] = multicand_tmp[0];
assign carry_tmp[0] = 1'b0;
assign product[0] = product_tmp[0][0];

for(i = 1; i < MULTIPLIER_WID; i = i + 1) begin: for_loop_i
cpu_wb_cla_adder #(.DATA_WID(MULTIPLIER_WID)) add1 (
   // Outputs
   .sum(product_tmp[i]),
   .carry_out(carry_tmp[i]),
   // Inputs
 .carry_in(1'b0),
   .in1(multicand_tmp[i]),
   .in2({carry_tmp[i-1],product_tmp[i-1][31-:31]}));
assign product[i] = product_tmp[i][0];
end //end for loop
assign product[(MULTIPLIER_WID+MULTIPLIER_WID-1):MULTIPLIER_WID] = {carry_tmp[MULTIPLIER_WID-1],product_tmp[MULTIPLIER_WID-1][31-:31]};
endgenerate
endmodule


 module cla_multiplier_tb();

 parameter MULTICAND_WID = 32;
 parameter MULTIPLIER_WID = 32;

// /*AUTOREGINPUT*/

 // Beginning of automatic reg inputs (for undeclared instantiated-module inputs)
 reg [MULTICAND_WID-1:0] multicand; // To mul1 of cla_multiplier.v
 reg [MULTIPLIER_WID-1:0]multiplier; // To mul1 of cla_multiplier.v
 // End of automatics

 /*AUTOWIRE*/

 // Beginning of automatic wires (for undeclared instantiated-module outputs)
 wire [(MULTICAND_WID+MULTIPLIER_WID-1):0]product;// From mul1 of cla_multiplier.v
 // End of automatics

 cpu_wb_cla_multiplier mul1(/*AUTOINST*/

   // // Outputs
    .product (product[(MULTICAND_WID+MULTIPLIER_WID-1):0]),
   // // Inputs
    .multicand (multicand[MULTICAND_WID-1:0]),
   .multiplier (multiplier[MULTIPLIER_WID-1:0]));

 //initial begin

// multicand = 16'd0;
// multiplier = 8'd0;
// end 

 integer i;

 initial begin
for (i = 0; i < 30; i = i + 1) begin: W
#(`DELAY) multicand = multicand + 1; multiplier = multiplier + 1;
 end

#(`DELAY) //correct
multicand = 32'h00007FFF;
multiplier = 32'h0000007F;

#(`DELAY) //correct
multicand = 32'h00008000;
multiplier = 32'h000000F0;

#(`DELAY) //faila
multicand = 32'h00008FF0;
multiplier = 32'h000000F0;

#(`DELAY) //correct
multicand = 32'h00007FF0;
multiplier = 32'h000000F7;

#(`DELAY) //correct
multicand = 32'h0000FFFF;
multiplier = 32'h000000FF;
 end

 endmodule



Simulation results:



Carry-Look-Ahead Multiplier Verilog FPGA


Synthesized RTL Schematic:


Carry-Look-Ahead Multiplier Verilog FPGA

The Verilog code for the parameterized multiplier is synthesizable and can be implemented on FPGA for verification.

4 comments:

  1. Thanks. Please keep updating the blog: http://www.fpga4student.com/

    ReplyDelete
  2. Hello,
    Do you have code for divider in Verilog ? Thanks.

    ReplyDelete
  3. Please check this: http://www.fpga4student.com/2016/11/a-multi-cycle-32-bit-divider-on-fpga.html
    Verilog code for divider

    ReplyDelete