generate statement : verilog - for-loop

I need to declare a register inside a generate statement to store some temporary values,
to be used in instantiations.
i have
generate
for(i=0; i< N; i=i+1)
begin: i_loop
Inst_file u(S1(i),P1(i),S(i),P(i));
/* S1 and P1 have N bits and
S = S1 ^ P1;
P = S1 & P1
*/
end //i_loop
S1 and P1 are simple combinationl logic and i have used them as wires for the first
iteration. But after each iteration of i, I need to assign the outputs S and P as inputs
(i.e replace S1 and P1 with S and P).
I understand I should do it with a register and not a wire (Am i right?)
In such a case i need S1 and P1 as reg. I tried using always statement inside the
generate. It gives error.
Can u please suggest a way out..

You should use an N+1 bit wide bus, and pull all initialization outside of the generate block.
I believe something like this will do:
wire [N:0]Sarray;
wire [N:0]Parray;
// initialize Sarray[0] and Parray[0] here using continuous assignment
generate
for(i=0; i< N; i=i+1)
begin: i_loop
Inst_file u(Sarray[i],Parray[i],Sarray[i+1],Parray[i+1]);
end //i_loop
Sarray[0] and Parray[0] should be initialized for use in the first iteration; Sarray[N] and Parray[N] will be the final output value of the chain of modules.

Related

Why does this error in indexing BCD adder appear?

I am not sure, what exactly the error is. I think, my indexing in the for-loop is not Verilog-compatible, but I might be wrong.
Is it allowed to index like this (a[(4*i)+3:4*i]) in a for-loop just like in C/C++?
Here is a piece of my code, so the for-loop would make more sense
module testing(
input [399:0] a, b,
input cin,
output reg cout,
output reg [399:0] sum );
// bcd needs 4 bits + 1-bit carry --> 5 bits [4:0]
reg [4:0] temp_1;
always #(*) begin
for (int i = 0; i < 100; i++) begin
if (i == 0) begin // taking care of cin so the rest of the loop works smoothly
temp_1[4:0] = a[3:0] + b[3:0] + cin;
sum[3:0] = temp_1[3:0];
cout = temp_1[4];
end
else begin
temp_1[4:0] = a[(4*i)+3:4*i] + b[(4*i)+3:4*i] + cout;
sum[(4*i)+3:4*i] = temp_1[3:0];
cout = temp_1[4];
end
end
end
endmodule
This might seem obvious. I'm doing the exercises from:
HDLBits and got stuck on this one in particular for a long time (This solution isn't the one intended for the exercise).
Error messages Quartus:
Error (10734): Verilog HDL error at testing.v(46): i is not a constant File: ../testing.v Line: 46
Error (10734): Verilog HDL error at testing.v(47): i is not a constant File: ../testing.v Line: 47
But I tried the same way in indexing and got the same error
The error appears because Verilog does not allow variables at both indices of a part select (bus slice indexes).
The most dynamic thing that can be done involves the indexed part select.
Here is a related but not duplicate What is `+:` and `-:`? SO question.
Variations of this question are common on SO and other programmable logic design forums.
I took your example and used the -: operator rather than the : and changed the RHS of this to a constant. This version compiles.
module testing(
input [399:0] a, b,
input cin,
output reg cout,
output reg [399:0] sum );
// bcd needs 4 bits + 1-bit carry --> 5 bits [4:0]
reg [4:0] temp_1;
always #(*) begin
for (int i = 0; i < 100; i++) begin
if (i == 0) begin // taking care of cin so the rest of the loop works smoothly
temp_1[4:0] = a[3:0] + b[3:0] + cin;
sum[3:0] = temp_1[3:0];
cout = temp_1[4];
end
else begin
temp_1[4:0] = a[(4*i)+3-:4] + b[(4*i)+3-:4] + cout;
sum[(4*i)+3-:4] = temp_1[3:0];
cout = temp_1[4];
end
end
end
endmodule
The code will not behave as you wanted it to using the indexed part select.
You can use other operators that are more dynamic to create the behavior you need.
For example shifting, and masking.
Recommend you research what others have done, then ask again if it still is not clear.

Is the For loop a software for loop instead of the hardware for loop in verilog in the intial block

The for loop outside the intial block generates hardware (with genvar), but the for loop in intial block in verilog works like the software for loop right?
The intial block is ofcourse only for simulation purposes so the software for loop makes sense.
One example is here. The test bench from that example that displays the use of the for loops in discussion is shown below:
module fsm_test;
reg clk, rst, inp;
wire outp;
reg[15:0] sequence;
integer i;
fsm dut( clk, rst, inp, outp);
initial
begin
clk = 0;
rst = 1;
sequence = 16'b0101_0111_0111_0010;
#5 rst = 0;
for( i = 0; i <= 15; i = i + 1)
begin
inp = sequence[i];
#2 clk = 1;
#2 clk = 0;
$display("State = ", dut.state, " Input = ", inp, ", Output = ", outp);
end
test2;
end
task test2;
for( i = 0; i <= 15; i = i + 1)
begin
inp = $random % 2;
#2 clk = 1;
#2 clk = 0;
$display("State = ", dut.state, " Input = ", inp, ", Output = ", outp);
end
endtask
endmodule
All code that you write in Verilog can be simulated (assuming no syntax or semantic errors). Only a subset of the code you write and simulate can be synthesized into hardware. The simulator has no knowledge of what subset will eventually be synthesized, the executional behavior is the same.
A simulator executes a procedural-for loop the same way it would in almost any software programming langauge in 3-steps
Initialize the loop variable.
Test the condition; if true, procedurally execute the loop body statements; if false, proceed to the statement following the for loop.
Increment the loop variable (or whatever needs to be done) at the end of the loop and go back to step 2.
A simulator unrolls a generate-for loop prior to execution. It simply replicates the code inside the loop replacing the loop variable with. different constant loop value for each replication of the loop. And the code inside a generate-for loop is not procedural statements; the code will be instances of structure that could be other always or initial blocks.
A synthesis tool never executes procedural code. From its perspective, there is no difference between a generate-for and a procedural-for; it unrolls both loops into a replications of the loop with a different constant loop value of each iteration of the loop.

System Verilog, how to sum array values?

I'm trying to sum array values using System Verilog.
My data are declared like this:
reg signed [23:0] n2 [31:0];
reg signed [15:0] w2 [195:0];
w2 is a reg with values stock in it.
for(int i2=0; i2<32; i2++) begin
for(int j2=0; j2<196; j2++) begin
n2[i2] <= n2[i2] + w2[j2];
end
end
end
I need to sum 196 * 16bit (*32), so it requires a 24 bit(*32)?
I tried to simulate my design, and I only have X in n2 reg.
Also, I run the RTL Analysis and open the elaborated design, and I have a warning like this:
[Synth 8-324] index 10 out of range
It's pointing to the line:
for(int j2=0; j2<196; j2++) begin
but I don't know why.
I only have X in n2 reg.
Of course you have.
At the start n2 is not initialized so it contains all X-es. Now you add numbers to X-es which still give you X-es. It is the same as if you would add to an uninitialized variable in most languages.
Try this:
for(int i2=0; i2<32; i2++) begin
n2[i2] <= w2[0];
for(int j2=1; j2<196; j2++) begin
n2[i2] <= n2[i2] + w2[j2];
end
end
(I have kept your <= as I don't know the context. But I have doubts this is correct)
I have a warning ...
I can't help you with your synth warning. I don't see anything obvious wrong but then again you provided only a very small snippet of code.

109 bit tree comparator with generate and for loop

I am trying to write a Verilog code for the 109-bit tree comparator, but I am still new to the generate loop.
I have written some code so far, but I am getting some errors. Also, I am not sure if I can use 2-d arrays for g and l signals?
parameter NUM_OF_BITS = 109;
parameter NUM_OF_LEVELS = 7;
genvar i;
for (x=0; x<NUM_OF_LEVELS; x=x+1) begin:
generate for (i=0; i<NUM_OF_BITS/((2*x)+1); i=i+1) begin: MCs
mag_comp2_1 mc (in0[2*i+1:2*i],in1[2*i+1:2*i],g[x][i],l[x][i]);
end
endgenerate
NUM_OF_BITS = NUM_OF_BITS/2;
end
Why not define the interconnections in for blocks? This way it will be more convenent for you.
An incomplete example:
parameter NUM_OF_BITS = 220;
parameter NUM_OF_LEVELS = 7;
genvar i,x;
generate for (x=1; x<NUM_OF_LEVELS; x=x+1)
begin: Ls
wire [NUM_OF_BITS/(2**x)-1:0] output1;
wire [NUM_OF_BITS/(2**x)-1:0] output2;
for (i=0; i<NUM_OF_BITS/(2**x); i=i+1)
begin: MCs
if (x == 1)
begin
// for the first level connect inputs to the module
mag_comp2_1 mc (input1[2*i+1:2*i],input2[2*i+1:2*i],output1[i],output2[i]);
end
else
begin
// for other levels connect ouputs of the previous level
mag_comp2_1 mc (Ls[x-1].output1[2*i+1:2*i],Ls[x-1].output2]2[2*i+1:2*i],output1[i],output2[i]);
end
end
end
endgenerate
you need something like the following. generate .. endgenerate tell the compiler to unroll all the loops and conditional statements between the keywords. So, you end up with a lot of instances of the module mag_comp2_1
parameter NUM_OF_BITS = 109;
parameter NUM_OF_LEVELS = 7;
genvar i, x;
generate
for (x=0; x<NUM_OF_LEVELS; x=x+1) begin: externloop
for (i=0; i<NUM_OF_BITS/((2*x)+1); i=i+1) begin: MCs
mag_comp2_1 mc (in0[2*i+1:2*i],in1[2*i+1:2*i],g[x][i],l[x][i]);
end
//NUM_OF_BITS = NUM_OF_BITS/2;
end
endgenerate
parameter NUM_OF_BITS = 220;
parameter NUM_OF_LEVELS = 7;
genvar x,i;
wire [NUM_OF_LEVELS:0][NUM_OF_BITS:0] g, l;
assign g[0] = in0;
assign l[0] = in1;
generate for (x=1; x<NUM_OF_LEVELS; x=x+1) begin: Ls
for (i=0; i<NUM_OF_BITS/(2**x); i=i+1) begin: MCs
mag_comp2_1 mc (g[x-1][2*i+1:2*i],l[x-1][2*i+1:2*i],g[x][i],l[x][i]);
end
end
endgenerate
assign gt = g[NUM_OF_LEVELS][0];
assign lt = l[NUM_OF_LEVELS][0];

Verilog two dimensional array syntax

I would like to instantiate an array of registers, and declare them all according to a certain function. This is for a multiplier block that I'm hoping to construct.
The code I'm working with is below, but this is the line that the compiler does not appreciate:
q[i][7:0] = {8{a[i]}} & b[7:0];
As the code is written out, I hope to make the registers q[0],q[1],....q[7] all store the 8-bit value define by the RHS above. Can anyone tell me what would be the proper way to do this?
Entire code:
`timescale 1ns / 1ps
module multiplier_2(
input [7:0] A,
input [7:0] B,
output reg [15:0] P,
input start,
output stop
);
reg [7:0] q[7:0];
reg P = 0;
//create 8 bit vectors q[i]
genvar i;
generate
for (i = 0; i < 8;i = i+1)
begin: loop
q[i][7:0] = {8{a[i]}} & b[7:0];
end
endgenerate
always # (*)
begin
if (start == 1'b1)
begin
for (i = 0; i < 8; i = i+1)
begin
P = P + (q[i] << i);
end
end
end
endmodule
EDIT: this code also doesn't work:
`timescale 1ns / 1ps
module multiplier_2(
input [7:0] a,
input [7:0] b,
output reg [15:0] P = 16'd0,
input start,
output stop
);
reg [7:0] q[7:0];
//create 8 bit vectors q[i]
genvar i;
generate
always begin
for (i = 0; i < 8;i = i+1)
begin: loop
q[i] = {8{a[i]}} & b[7:0];
end
end
endgenerate
always # (*)
begin
stop = 1'b0;
if (start == 1'b1)
begin
for (i = 0; i < 8; i = i+1)
begin
P = P + (q[i] << i);
end
end
stop = 1'b1;
end
endmodule
Error message:
"Line 16: Procedural assignment to a non-register i is not permitted, left-hand side should be reg/integer/time/genvar"
I do not think this require a generate statement. A standard for loop will work:
reg [7:0] q [0:7];
integer i;
always #* begin
for (i = 0; i < 8; i=i+1) begin: loop
q[i] = {8{a[i]}} & b[7:0];
end
end
Beware of what hardware you are implying though. For loops like generate statements imply parallel hardware.
NB: it is more common to list memories with the depth from 0 to x ie: reg [7:0] q [0:7];
You've got all sorts of issues here. First off, you're getting confused about what a generate statement is, and what you're trying to generate. Are you (1) trying to generate a single always block, which must contain sequential/procedural code, or are you (2) trying to generate/replicate 8 continuous assignments?
You're presumably not doing (1), since there's no point in generating a single always block; the generate is redundant. That leaves (2). So, get rid of the always begin after the generate. The i in your loop is now the 'genvar', or generation variable, and you're replicating 8 assignments; so far, so good. Get rid of the begin:loop and end; you're replicating a single statement, so they're pointless verbiage.
Next problem: the generate loop is now creating concurrent, or parallel, statements; in Verilog-speak, they're module-level statements. They means that they must be continuous assignments, ie they must have an assign in front of them, and not just ordinary procedural assignments, as you've written them. That also means that q must be declared as a wire, and not a reg. There's no good reason for this; it's just how Verilog is.
You now have a second always block, which is a concurrent (module-level) statement, which must contain sequential/procedural code. The i you're referring to in this block is the original genvar, which doesn't work. A genvar can only be used in specific generation-related circumstances; this isn't inside a generate, and you need an ordinary variable here as your index. you can do this by naming your outer begin/end, and declaring a variable inside it, or any other way. You'll now find out that you're creating a procedural assignment to net stop; this is illegal, so change stop's declaration to a reg. This should be enough to get your code to compile.
BTW, #(*) is verbose and unnecessary, and has historically confused at least one tool. #* is more concise.
You've got other issues. Your second always contains a loop. It looks like it might be logically correct, but your synthesiser has to unroll this, and carry out 8 additions, and set stop. This isn't going to work in real life. Think about making these additions concurrent and putting them in a generate, or creating a clocked pipeline, and some more robust (clocked) way of creating stop.

Resources