I want to design a simple multiplier with the generate construct and two dimensional memory. But I can not compile the following verilog code. Could anyone give some hint please?
module classic_multiplier(
a, b,
a_by_b);
parameter M = 2;
input [M-1:0] a, b;
output reg [M-1:0] a_by_b [0:2*M-2];
//the first and
genvar i, k;
generate begin
for(k = 0; k <= M-1; k=k+1) begin
for(i = 0; i <= k; i=i+1) begin
a_by_b[k][i] = a[i] & b[k-i];
end
end
end
endgenerate
endmodule
It seems the problem here is that you have a 2D output port (a_by_b
). I'm not quite sure why you would need it for a multiplier anyway, the output port size should be 2*M
, so:
output reg [(2*M-1):0] a_by_b;
Also, there is no need for the begin
after generate
(and thus no need either for the matching end
), but ok, that's not really the problem here, you can add them if you want.
Next, for loops inside a generate
block need to be named, for example:
generate
for(k = 0; k <= M-1; k=k+1) begin : for_outer
for(i = 0; i <= k; i=i+1) begin : for_inner
a_by_b[k][i] = a[i] & b[k-i];
end
end
endgenerate
Of course, you will need to change the code inside the for loops if you change the definition of a_by_b
.
When the tool sees a_by_b[k][i] = a[i] & b[k-i];
it assures that a_bay_b is a module. Prefix an assign
or always @*
to the line and the tool will accept accept the code.
A generate blocks expands the code during the compile elaboration time. With the given code:
genvar i, k;
generate
for(k = 0; k <= M-1; k=k+1) begin
for(i = 0; i <= k; i=i+1) begin
a_by_b[k][i] = a[i] & b[k-i]; // Error will happen here
end
end
endgenerate
Will expand to:
a_by_b[0][0] = a[0] & b[0-0]; // * Compile Error *
a_by_b[1][0] = a[0] & b[1-0]; // ** Assignment without assign, always @*
a_by_b[1][1] = a[1] & b[1-1]; // ** block statement (e.g. always,initial)
The correct code with assign
:
genvar i, k;
generate
for(k = 0; k <= M-1; k=k+1) begin
for(i = 0; i <= k; i=i+1) begin
assign a_by_b[k][i] = a[i] & b[k-i];
end
end
endgenerate
Will evaluate to:
assign a_by_b[0][0] = a[0] & b[0-0];
assign a_by_b[1][0] = a[0] & b[1-0];
assign a_by_b[1][1] = a[1] & b[1-1];
Or with always @*
:
genvar i, k;
generate
for(k = 0; k <= M-1; k=k+1) begin
for(i = 0; i <= k; i=i+1) begin
always @* a_by_b[k][i] = a[i] & b[k-i];
end
end
endgenerate
Will evaluate to:
always @* a_by_b[0][0] = a[0] & b[0-0];
always @* a_by_b[1][0] = a[0] & b[1-0];
always @* a_by_b[1][1] = a[1] & b[1-1];
Alternatively an single always block can be used without a generate block:
integer i,k;
always @* begin
for(k = 0; k <= M-1; k=k+1) begin
for(i = 0; i <= k; i=i+1) begin
a_by_b[k][i] = a[i] & b[k-i];
end
end