Verilog compilation error: unexpected '[',

2019-08-26 13:57发布

问题:

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      

回答1:

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.



回答2:

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


标签: verilog