I'm trying to get a module to pass the syntax check in ISE 12.4, and it gives me an error I don't understand. First a code snippet:
parameter ROWBITS = 4; reg [ROWBITS-1:0] temp; genvar c; generate always @(posedge sysclk) begin for (c = 0; c < ROWBITS; c = c + 1) begin: test temp[c] <= 1'b0; end end endgenerate
When I try a syntax check, I get the following error message:
ERROR:HDLCompiler:731 - "test.v" Line 46: Procedural assignment to a non-register <c> is not permitted.
I really don't understand why it's complaining. "c" isn't a wire, it's a genvar. This should be the equivalent of the completely legal syntax:
reg [3:0] temp; always @(posedge sysclk) begin temp[0] <= 1'b0; temp[1] <= 1'b0; temp[2] <= 1'b0; temp[3] <= 1'b0; end
Please, no comments about how it'd be easier to write this without the generate. This is a reduced example of a much more complex piece of code involving multiple ifs and non-blocking assignments to "temp". Also, don't just tell me there are newer versions of ISE, I already know that. OTOH, if you know it's fixed in a later version of ISE, please let me know which version you know works.
We can only use generate statements in concurrent SystemVerilog code. This means we can't use generate statements inside procedural blocks such as always blocks. In addition to this, we have to use either an if statement, case statement or a for loop together with the generate keyword.
A genvar is a variable used in generate-for loop. It stores positive integer values. It differs from other Verilog variables in that it can be assigned values and changed during compilation and elaboration time.
Verilog Generate Loop The genvar is used as an integer to evaluate the generate loop during elaboration. The genvar declaration can be inside or outside the generate region, and the same loop index variable can be used in multiple generate loops, as long as the loops don't nest.
Yes. It is possible. A generate statement is just a code generator directive to the synthesizer. Basically, it is just loop unrolling.
You need to reverse the nesting inside the generate block:
genvar c; generate for (c = 0; c < ROWBITS; c = c + 1) begin: test always @(posedge sysclk) begin temp[c] <= 1'b0; end end endgenerate
Technically, this generates four always blocks:
always @(posedge sysclk) temp[0] <= 1'b0; always @(posedge sysclk) temp[1] <= 1'b0; always @(posedge sysclk) temp[2] <= 1'b0; always @(posedge sysclk) temp[3] <= 1'b0;
In this simple example, there's no difference in behavior between the four always blocks and a single always block containing four assignments, but in other cases there could be.
The genvar-dependent operation needs to be resolved when constructing the in-memory representation of the design (in the case of a simulator) or when mapping to logic gates (in the case of a synthesis tool). The always @posedge
doesn't have meaning until the design is operating.
Subject to certain restrictions, you can put a for loop inside the always block, even for synthesizable code. For synthesis, the loop will be unrolled. However, in that case, the for loop needs to work with a reg
, integer
, or similar. It can't use a genvar
, because having the for loop inside the always block describes an operation that occurs at each edge of the clock, not an operation that can be expanded statically during elaboration of the design.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With