0

I have the following code for a 2 bit multiplier:

module Multiplier (a0, a1, b0, b1, c[3:0]);
output      [3:0]c; 
input       a0, a1, b0, b1;
wire        a0b1, a1b0, ha0c, a1b1;  

and (c[0], a0, b0);
and (a0b1, a0, b1);
and (a1b0, a1, b0);
HalfAdder ha0 (a1b0, a0b1, c[1], ha0c);

and (a1b1, a1, b1);
HalfAdder ha1 (ha0c, a1b1, c[2], c[3]);
endmodule

I want to be able to expand this to more than 2 bits though (32 bits). The structure of my code poses a challenge for this though. First off I would have to have 68 parameters for the module. Also I would have to manually create 64 wires (duplicates of wire a0b1, a1b0, ha0c, a1b1). Finally I would need to manually write out a bunch of logic gates and HalfAdder modules to connect all the logic. Because of this I am wondering if there is a way that I can refactor my code to be able to instantiate a binary multiplier of n (a passed parameter) size.

Tyler Hilbert
  • 2,107
  • 7
  • 35
  • 55
  • What is the point of using structural gates in your model? you can use regular verilog and save a lot of manual effort just using the power of the language. – Serge Jul 06 '17 at 20:05
  • What do you mean regular verilog? Like using "assign" and "&" instead of manually writing the gates? – Tyler Hilbert Jul 06 '17 at 20:11
  • A combination of `generate`/`for` loops may help, but I would prefer to write a script (e.g. in Perl or TCL) instead. –  Jul 06 '17 at 20:33
  • yes, I meant using assign, operators, always blocks, loops, 'if' statements, functions, arrays, structs, .... and no gates. – Serge Jul 06 '17 at 20:47
  • You don't need 68 parameters; 3 at the most. Sample module header: `module Multiplier #(parameter A_WIDTH=2, B_WIDTH=2, C_WIDTH=A_WIDTH+B_WIDTH) (output [C_WIDTH-1:0] c, input [A_WIDTH-1:0] a, input [B_WIDTH-1:0] b);`. If you are planning to synthesize, then you should add a clock. Otherwise the area and timing could become unmanageable. – Greg Jul 07 '17 at 00:50
  • @ahmedus What do you mean you would prefer to write a script instead? How is it possible to program an FPGA with Perl or TCL? – Tyler Hilbert Jul 08 '17 at 13:03
  • @Serge When does it make sense to use logic gates instead of assign, operators, always blocks, loops, 'if' statements, functions, arrays, structs. It seems like if gates are so much work they shouldn't be included in the language... or at least not the first thing taught, – Tyler Hilbert Jul 08 '17 at 13:04
  • @Greg Is it pretty standard to synthesize an HDL script? I haven't heard of doing that before. – Tyler Hilbert Jul 08 '17 at 13:07
  • 1
    gate level presentation makes sense in certain exploration and synthesis procedures, some spice simulations. In my experience all of those get generated by some other tools from RTL or abstracted from schematics. It is very seldom when people create them by hand. maybe in low-level library cells. There is certain class of gates which people use sometimes, like tristate buffers to drive buses. So, general, you should avoid using them. – Serge Jul 08 '17 at 15:00
  • @Serge Ok cool... I'm still a little unsure how to use the **assign** keyword. Do you think you can send me some documentation or a tutorial on it or at least tell me what the technical term for it is so I can google how to use it? – Tyler Hilbert Jul 08 '17 at 17:48
  • google `verilog tutorial`. i.e. http://www.ece.umd.edu/class/enee359a/verilog_tutorial.pdf – Serge Jul 08 '17 at 23:50
  • @user2417339 I mean a script that generates the RTL code. This approach is common in industry and academy, but it seems that the accepted answer solves the problem within Verilog. –  Jul 09 '17 at 19:02

1 Answers1

0

You need to parameterize and use a generate block. (And it is much better to use a synchronous circuit then an asynchronous circuit).

Here is an incomplete example, you can fill in the necessary logic :

module Multiplier (a, b, c, clk);
parameter WIDTH = 64;
output      [2*WIDTH:0]c; 
input       [WIDTH-1:0]a; 
input       [WIDTH-1:0]b; 
input       clk;


genvar i;
generate  for (i = 0; i < WIDTH; i <= i + 1)
begin : shifts
    // shift a 1-bit for each i and 'logical and' it with b
    reg  [WIDTH + i :0]carry;
    wire [WIDTH + i -1:0]shifted = {a,i{0}} & b[i]; 


    // sum the result of shift and 'logical and'
    always @ (posedge clk)
    begin
        carry <= shifted + shifts[i-1].carry ;
    end
end

assign c = shifts[WIDTH].carry;

endgenerate

endmodule
Alper Kucukkomurler
  • 1,706
  • 2
  • 13
  • 19