Error with localparam inside "for" loop on Verilog - verilog

parameter N = 4, FOO = { N { 4'd1 } };
//And then in the generate loop
genvar i;
for( i = 0; i < N; i = i + 1 )
begin : gen_loop
localparam THIS_FOO = FOO[ i * 4 +: 4 ];
end
wire [1:0] rr = THIS_FOO[1:0];
wire [1:0] rt = THIS_FOO[3:2];
I get this error but did not understand why?:
Line 344: <THIS_FOO> is not declared.
Line 345: <THIS_FOO> is not declared.
Module <TCL_vec> ignored due to previous errors.
Please tell me where I was wrong?

Your localparam is declared inside begin:gen_loop..end scope. Moreover your generate for loop created multiple versions of the block, with names
gen_loop[0]
gen_loop[1]
...
So you have multiple versions of the THIS_FOO as well.The way to access them is to use a cross-reference notation.
wire [1:0] rr = gen_loop[0].THIS_FOO[1:0];
wire [1:0] rt = gen_loop[1].THIS_FOO[3:2];
...
and yes, you have to know which iteration of the loop to access.
So, in your case it complained because you do not have THIS_FOO declared in the scope you wanted to access it.

Related

Using assign inside a for loop

I'm trying to assign I/O vectors inside a for loop in order to save space. I am unsure if this is not possible or I am running into a syntax issue.
I have tried using generate and am still running into issues
My current code is as follows:
module Test_IO
(
output [7:0] led,
input [7:0] sw
);
genvar i;
generate
for(i = 0;i < 8; i = i + 1)
{
assign led<i> = sw<i>;
}
endgenerate
endmodule
I was hoping to save space instead of having to use 8 assign statements but I have been receiving the following error:
ERROR:HDLCompiler:806 -
"C:/Users/Danie/Desktop/Digilent/Projects/Test_IO/Test_IO.v" Line 31:
Syntax error near "{".
I am assuming you are using verilog. Try the below code. You really don't need a genvar for the assignment you are doing.
module Test_IO
(
output [7:0] led,
input [7:0] sw
);
genvar i;
generate
for(i = 0;i < 8; i = i + 1)
assign led[i] = sw[i];
endgenerate
endmodule
Alternatively you may try the below one too
module Test_IO
(
output reg [7:0] led,
input [7:0] sw
);
integer i;
always#(*)
begin
for(i=0;i<8;i=i+1)
led[i] = sw[i];
end
endmodule
Your problem is syntax. In verilog use begin and end, not { and }
genvar i;
generate
for(i = 0;i < 8; i = i + 1)
{
assign led<i> = sw<i>;
}
endgenerate
becomes
genvar i;
generate
for(i = 0;i < 8; i = i + 1) begin
assign led[i] = sw[i];
end
endgenerate
sometimes compilers requires the generate loop to be named using : NAME after begin
genvar i;
generate
for(i = 0;i < 8; i = i + 1) begin : ASSIGN_GEN
assign led[i] = sw[i];
end
endgenerate

Selecting a set of parameters based on input value in Verilog

I am working on a Module which changes it's constant values based on the input to calculate it's output.
Let me illustrate what I am looking for,
Let x be the input, y the output and a,b,c,d,e the set of constants.
Module performs something like the following operation:
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); //separate adder and multiplier modules are used and this code itself is huge so just providing the idea.
Now I have used following method to choose the right value for the constants depending on the input: (Pseudo code)
module top (x,clk,y);
input clk;
input [31:0] x;
output [31:0] y;
if (x>=32'h08000000 && x<32'h0A000000) begin
localparam a = 32'h058B90C0;
localparam b = 32'h193C9F60;
localparam c = 32'h29AC1740;
localparam d = 32'hA48B9440;
localparam e = 32'h0B6392E0;
end else if (x>=32'h0A000000 && x<32'h0C000000) begin
localparam a = 32'h028A50C1;
localparam b = 32'hE98B489C;
localparam c = 32'h17402948;
localparam d = 32'h9440E45B;
localparam e = 32'h392E00AF;
end
y=(a*x)+(b*x)+(c*x)+(d*x)+(e*x); // Module that computes using any of the above mentioned constant sets
endmodule
I get the following errors:
(1) "Unable to bind parameter".
(2) "Cannot evaluate genvar conditional expression: ((x)G(32'000010000....00))&& so on......"
My question is:
My user will give the input through x, right constants will be chosen, my module will calculate and provide the output. Just providing the right constants to the module is enough. How shall I do it? Ideas through pseudo code will be helpful for me.
I had to look up where localparam is allowed. You can define a localparam after a begin : < label >.
I tried it and found that (at least in Vivado) it passed and worked.
always #( a )
if (a>=1)
begin : a_be_1
localparam P1 = 3;
c = P1;
end
else
begin : a_sm_1
localparam P1 = 5;
c = P1;
end

verilog compile error - "variable not constant"

Why am I getting error "q is not constant"?
module prv(
input [7:0]x,
input [7:0]y,
output [49:0]z
);
wire [24:0]q;
assign z=1;
genvar k;
for (k=50; k<0; k=k-1)
begin
wire [25:0]a;
assign a=0;
assign q= x;
genvar i;
for(i=0; i<8; i=i+1)
begin
if(q[0]==1)
begin
assign a=a+z;
end
assign {a,q}={a,q}>>1;
end
assign z={a[24:0],q};
end
endmodule
I'm afraid that you are trying to use Verilog the wrong way. q is a wire, not a variable (a reg) so it cannot be assigned with a value that includes itself, because that would cause a combinational loop. You are using the assign statement as if it were a regular variable assignment statement and it's not.
Declare a and q as reg, not wire. i and k don't need to be genvars variables, unless you are trying to generate logic by replicating multiple times a piece of code (description). For for loops that need to behave as regular loops (simulation only) use integer variables.
Besides, behavioral code must be enclosed in a block, let it be combinational, sequential, or initial.
A revised (but I cannot make guarantees about its workings) version of your module would be something like this:
module prv(
input wire [7:0] x,
input wire [7:0] y,
output reg [49:0] z
);
reg [24:0] q;
reg [25:0] a;
integer i,k;
initial begin
z = 1;
for (k=50; k<0; k=k-1) begin
a = 0;
q = x;
for (i=0; i<8; i=i+1) begin
if (q[0] == 1) begin
a = a + z;
end
{a,q} = {a,q}>>1;
end
z = {a[24:0],q};
end
endmodule

Verilog assigning wire by iterating over array

How to assign a wire with a AND operation of a wire array?
parameter row = 4;
parameter col = 8;
wire ready [row-1:0][col-1:0];
output wire allready;
logically i want to do
allready=AND ready[i][j] for all i,j
For a mutlibit wire the reduction operator & can be used:
wire [row-1:0] ready;
wire allready = &ready;
However this will not work with unpacked arrays (multi-dimensions).
One solution is to create a loop to index the dimensions ANDing the values with the result so far. This could be achieved with some thing along the lines of:
output reg allready;
always #* begin
allready=1'b1;
for (int i =0; i<col; i++) begin
allready = allready & (&ready[i]) ;
end
end

In synthesizable verilog, can we use assign statement in generate block?

For example, I have the below piece of code. Can we assign wire inside the generate block in synthesizable verilog? Can we use assign statement inside the generate block in synthesizable verilog?
genvar i;
generate
for (i = 0; i < W; i=i+1) begin:m
wire [2:0] L;
assign L[1:0] = { a[i], b[i] };
end
endgenerate
Yes. It is possible. A generate statement is just a code generator directive to the synthesizer. Basically, it is just loop unrolling. This is if the loop can be statically elaborated. That is, the number of times the loop is to executed should be determinable at compile time.
genvar i;
generate
for (i = 0; i < 2 ; i++) {
assign x[i] = i;}
endgenerate
unrolls into
assign x[0] = 0;
assign x[1] = 1;
In synthesizeable Verilog, it is possible to use an assign statement inside of a generate block. All a generate block does is mimic multiple instants. Be careful though, because just like a for loop, it could be very big space-wise.
You can use assign in generate statment, it is quite common to help parameterise the hook up modules
The original code has some issues: L is defined multiple times and it is only assigned 2 out of 3 bits
genvar i;
generate
for (i = 0; i < W; i=i+1) begin:m
wire [2:0] L;
assign L[1:0] = { a[i], b[i] };
end
endgenerate
Could be changed to:
localparam W = 4;
reg [W-1:0] a;
reg [W-1:0] b;
wire [1:0] L [0:W-1];
genvar i;
generate
for (i = 0; i < W; i=i+1) begin:m
assign L[i] = { a[i], b[i] };
end
endgenerate
Here L[i] selects the i'th wire [1:0] part of L. While a[i] and b[i] are bit selects.

Resources