I have an array of registers/buses and a single result bus defined as follows.
wire [BW-1:0] bus_array[NUM-1:0];
reg [BW-1:0] and_result;
where
parameter BW = 4;
parameter NUM = 8;
I wish to perform a BW-bit AND operation on the elements of the array and assign the result to the register and_result
.
I try doing this as follows.
integer l;
generate
genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP
always @ (*)
begin
and_result[m] = 1'b1;
for (l=0; l<NUM; l=l+1)
and_result[m] = and_result[m] & bus_array[l][m];
end
end
endgenerate
However when I simulate this in Modelsim 10.1e, I get the following error.
Error: (vsim-3601) Iteration limit reached at time 2 ns
If I do not use the generate loop, and instead have BW instances of the always @ (*)
block, the simulation works okay.
I can infer from the error message, that there is a problem with the generate for loop, but I am not able to resolve the problem.
Most likely a bug with ModelSim. Reproducible on EDAplayground with ModelSim10.1d. Works fine with Riviera2014 (After localizing l
inside the generate loop). I'm guessing that and_result[m]
is somehow in the @(*)
sensitivity list, which it shouldn't be.
l
needs to be localized or it will be accessed in parallel with the generated always blocks; creating a potential raise condition.
One workaround is to use SystemVerilog and use always_comb
instead of always @(*)
.
A backwarnd compatable solution is to change and_result[m] = and_result[m] & bus_array[l][m];
to if (bus_array[l][m]==1'b0) and_result[m] = 1'b0;
which is equivalent code. This keeps and_result[m]
only on as a left hand expression so it cannot be in the sensitivity list.
genvar m;
for (m=0; m<BW; m=m+1)
begin : BW_LOOP
integer l; // <== 'l' is local to this generate loop
always @ (*)
begin
and_result[m] = 1'b1;
for (l=0; l<NUM; l=l+1) begin
if (bus_array[l][m]==1'b0) begin
and_result[m] = 1'b0;
end
end
end
Working code here