It is possible to avoid always @*
when you want to do more advanced math with genvar
loops. Use localparam
and a function
.
Make k
a localparam
derived from the genvars with a function, and use k
as originally intended.
The getk
function seems to violate the principles of code reuse by basically recreating the loops from the generate
block, but getk
allows each unrolled loop iteration to derive the immutable localparam k
from genvars i
and j
. There is no separate accumulating variable k
that is tracked across all the unrolled loops. Both iverilog
and ncvlog
are happy with this.
(Note that the original example could optimize with j=i+1
as well, but there is still an issue with deriving k
.)
module top();
localparam N=4;
function automatic integer getk;
input integer istop;
input integer jstop;
integer i,j,k;
begin
k=0;
for (i=0; i<=istop; i=i+1) begin: firstfor
for (j=i+1; j<((i==istop)? jstop : N); j=j+1) begin: secondfor
k=k+1;
end
end
getk=k;
end
endfunction
genvar i,j;
generate
for (i = 0; i < N; i = i + 1) begin: firstfor
for (j = i+1; j < N; j = j + 1) begin: secondfor
localparam k = getk(i,j);
initial $display("Created i=%0d j=%0d k=%0d",i,j,k);
end
end
endgenerate
endmodule
Output:
$ iverilog tmptest.v
$ ./a.out
Created i=0 j=1 k=0
Created i=0 j=2 k=1
Created i=0 j=3 k=2
Created i=1 j=2 k=3
Created i=1 j=3 k=4
Created i=2 j=3 k=5
I discovered the 'trick' of using functions to derive values from the genvars here:
https://electronics.stackexchange.com/questions/53327/generate-gate-with-a-parametrized-number-of-inputs