I want to create 256 instances of foo. Therefore, I have two nested generate loops. However, I need a separate index variable l to for a proper selection of the signal.
genvar j, i, l;
generate
l = 0;
for(j = 0; j < 16; j++)
begin
for(i = 0; i < 16; i++) begin
foo bar
(
.a_i(a_i[(l+1)*8-1:l*8]),
.b_i(b_i[(j+1)*8-1:j*8]),
.c_o(c_i[i][j])
);
if(i < 15)
l = (l + 1) % 16;
end
end
endgenerate
Unfortunately, this construction does not work. How to add l to this generate to get the correct selection of the input signals?
A genvar can only be assigned as the index in a for-loop. So Leave it as an expression:
genvar j, i;
generate
for (j = 0; j < 16; j++) begin
for (i = 0; i < 16; i++) begin
foo bar (
// prefix 1'b0 for correct sign extinction, 4'() does casting
.a_i(a_i[{1'b0,4'(i-j)}*8 +: 8]),
.b_i(b_i[j*8 +: 8]),
.c_o(c_i[i][j])
);
end
end
endgenerate
+: is for array slicing, allowing variable index and constant offset. It is more concise and easier to maintain then specifying the msb:lsb, and it is synthesizable. Refer to 'Indexing vectors and arrays with +:' and 'What is `+:` and `-:`?
You can also combined the this method with dave_59's parameter approach:
genvar j, i;
generate
for (j = 0; j < 16; j++) begin
for (i = 0; i < 16; i++) begin
// defining the parameter with a data type to insure it is a unsigned 4 bit value
parameter bit [3:0] l = (i-j);
foo bar (
.a_i(a_i[l*8 +: 8]),
.b_i(b_i[j*8 +: 8]),
.c_o(c_i[i][j])
);
end
end
endgenerate
Use the conditional operator ?:, and make l a parameter
genvar j, i;
generate
l = 0;
for(j = 0; j < 16; j++)
begin
for(i = 0; i < 16; i++) begin
parameter l = (i < 15) ? ((l + 1) % 16) : 0;
foo bar
(
.a_i(a_i[(l+1)*8-1:l*8]),
.b_i(b_i[(j+1)*8-1:j*8]),
.c_o(c_i[i][j])
);
end
end
endgenerate
Related
I'd like to make an or of some bits, but they are not on a contiguous array. See |ack[i-1:0][j] in the following example, where | is the bitwise reduction or.
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output ack[PORTS][PORTS]
);
generate
genvar i, j, used[PORTS];
for ( i = 0; i < PORTS; i++ )
begin
for ( j = 0; j < PORTS; j++)
begin
assign ack[i][j] = dest[i][j] && ! (|ack[i-1:0][j]);
end
end
endgenerate
endmodule
In this concrete case, what I really want is for the ack[i][j] bit to be 1 for the first dest[i][j] that is 1 in each "column".
Obviously, this gives a "range not allowed in a prefix" error. How could I implement this behaviour?
You can use an auxiliary signal, I guess this is what you tried to do with the genvar used[PORTS], genvars are processed during compilation time so they can't hold values that depends on the inputs, this is why we must use a signal.
used[i][j] is will iteratively compute ack[0][j] | ... | ack[i-1][j]
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output ack[PORTS][PORTS]
);
logic used[PORTS][PORTS];
generate
genvar i, j;
for ( i = 0; i < PORTS; i++ )
begin
for ( j = 0; j < PORTS; j++)
begin
assign used[i][j] = i == 0 ? 1'b0: ack[i][j] | used[i-1][j];
assign ack[i][j] = dest[i][j] && ! used[i-1][j];
end
end
endgenerate
endmodule
Generate block just cause creation of 16 separate assignments in your case. they do not make much sense here. There is a simpler solution with a single procedural block.
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output logic ack[PORTS][PORTS]
);
always #* begin
logic flag;
flag = 0;
for ( int i = 0; i < PORTS; i++ ) begin
for ( int j = 0; j < PORTS; j++) begin
if (dest[i][j] == 1'b1)
flag = 1;
ack[i][j] = flag;
end
end
end
endmodule
You set flag when dest condition is right. It is persistent till the end of the block, setting value of ack. It works according to your description.
I ended up combining both answers to get the following code:
module cb #(
parameter PORTS = 4
)(
input dest[PORTS][PORTS],
output ack[PORTS][PORTS]
);
logic used[PORTS][PORTS];
always_comb begin
logic used[PORTS];
// First resetting to 0
for ( int j = 0; j < PORTS; j++ )
used[j] = 0;
for ( int i = 0; i < PORTS; i++ )
begin
for ( int j = 0; j < PORTS; j++)
begin
ack[i][j] = dest[i][j] && !used[j];
used[j] = used[j] | ack[i][j];
end
end
end
endmodule
This code takes into account that at most one port can be used “per column” (and not just one at all).
I need to initialize arrays in generated instances via generate block in Verilog. I'm trying to use the syntax below, however, I get an error as
External reference foo[0].bar.array[0] remains unresolved.
in Xilinx ISE.
integer i, j;
initial begin
// initialization of arrays
for(i=0; i<(2**7); i=i+1) begin
valid_array[i] = 0;
for(j=0; j<N; j=j+1) begin
foo[j].bar.array[i] = 0;
end
end
end
This is my generate block:
genvar jj;
generate
for(jj = 0; jj < N; jj = jj + 1) begin : foo
Memory_v3
#(
.ADDRESS_WIDTH(INDEX),
.DATA_WIDTH(TAG)
) bar
(
.clock(clock),
.we(we),
.addr_a(addra),
.addr_b(addrb),
.din(din),
.dout(dout)
);
end
endgenerate
What is the correct way to do this?
the problem is that foo block gets resolved at compile time. So, the names like foo[0], foo[1] are pre-generated and are compile-time names, they not work with dynamic index resolution at run-time. Therefore foo[j] will not work.
the solution in this case is to use another generate block to initialize them. Something like the following.
generate
for(jj = 0; jj < N; jj = jj + 1) begin : foo_init
initial begin
// initialization of arrays
for(i=0; i<(2**7); i=i+1) begin
foo[jj].bar.array[i] = 0;
end
end
end
endgenerate
Same story is with array of instances.
FOO bar[3:0](); // array of instances
int i,j;
generate
for(jj = 0; jj < 4; jj = jj + 1) begin : foo_init
initial begin
for(i=0; i<(2**7); i=i+1) begin
bar[jj].array[i] = 0;
end
end
end
endgenerate
BTW, in system verilog you can avoid using generate/endgenerate pairs:
Is below sort of generate loop is valid in system verilog.
genvar i,j;
for (i=0,j=5; i<5 && j<10; i++,j++) begin:M1
integer t;
initial begin
t = i*j;
end
endgenerate
Nope. I'm not even sure what the behavior of this code should be, or in what order they execute.
genvar i,j;
for (i = 0; i <5; i++) begin
for (j = 5; j < 10; j++) begin
$display("%d", i*j);
end
end
you don't need 'endgenerate' in the end.
You cannot do much with genvars in your example.
The following code mimics what you asked for, but it might not work with all simulators. It works with synopsys vcs but does not work with icarus.
module g;
genvar i;
for (i=0; i<5; i++) begin:M
if (i == 0) begin:B
parameter j = 5;
end
else begin:B
parameter j = g.M[i-1].B.j + 1;
end
integer t;
initial begin
t = i*B.j;
$display(i, B.j, t);
end
end // block: M
endmodule // g
the idea is to declare the parameter j inside the generate loop so that its value is an increment of the value declared in the previous iteration. You need to add a named block 'B' to declare conditionally.
Say I have the following code:
genvar i,j;
generate
for(i = 0; i < MAX; i = i + 1) begin: gen_blah
for(j = 0; j < MAX; j = j + 1) begin: gen_foo
assign match[i] = entry[j] = i;
end
end
endgenerate
Is this a synthesizable expression? It seems like it should be since this will just unroll out into a bunch of compare-to-constant assignments. If not, how would I write this to accomplish that?
No. Imagine unrolling this and typing it out by hand. The fist two lines would cause a multiply driven net:
assign match[0] = (entry[0] == 0);
assign match[0] = (entry[1] == 0);
However, if you get rid of the generates and do this with loops inside an always block then it will work:
always_comb begin
for(int i = 0; i < MAX; i = i + 1) begin: gen_blah
for(int j = 0; j < MAX; j = j + 1) begin: gen_foo
match[i] = (entry[j] == i);
end
end
end
Inside this block you get multiple assignments to the same value but the last one "wins". I'm not sure what you are trying to accomplish with your code, so this might not actually perform the function you are looking for. If you are trying to see if any of the entries equal i then you should change it to:
always_comb begin
for(int i = 0; i < MAX; i = i + 1) begin: gen_blah
match[i]=0;
for(int j = 0; j < MAX; j = j + 1) begin: gen_foo
match[i] = match[i] || (entry[j] == i);
end
end
end
Let's say I have N registers and I want a function that checks if all register contents are equal. How do I write that without having to spell out every single element?
function equal (input [0:N-1][width-1:0] in);
equal = (???) ? 1'b1 : 1'b0;
endfunction
A simple for loop is one way:
module tb;
parameter N = 8;
parameter width = 4;
reg [0:N-1][width-1:0] arr;
initial begin
for (int i=0; i<N; i++) arr[i] = 5;
$display(equal(arr));
for (int i=0; i<N; i++) arr[i] = 2*i;
$display(equal(arr));
end
function equal (input [0:N-1][width-1:0] in);
for (int i=1; i<N; i++) begin
if (in[i] !== in[0]) return 0;
end
return 1;
endfunction
endmodule
Output:
1
0
module tb;
parameter W = 8;
parameter N= 4;
logic [N-1:0][W-1:0] in0, in1;
logic res;
initial begin
in0 = {8'd6,8'd6,8'd6,8'd6};
in1 = {8'd6,8'd6,8'd55,8'd6};
res = equal(in0);
$display(res);
res = equal(in1);
$display(res);
end
function logic equal(input logic [N-1:0][W-1:0] in);
equal = (in === {N{in[0]}}) ? 1 : 0;
endfunction
endmodule
Modelsim results:
# 1
# 0