Verilog generate/genvar in an always block

匿名 (未验证) 提交于 2019-12-03 02:20:02

问题:

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 

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 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] 

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.

回答1:

You need to reverse the nesting inside the generate block:

genvar c; generate     for (c = 0; c 

Technically, this generates four always blocks:

always @(posedge sysclk) temp[0] 

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.



回答2:

You don't need a generate bock if you want all the bits of temp assigned in the same always block.

parameter ROWBITS = 4; reg [ROWBITS-1:0] temp; always @(posedge sysclk) begin     for (integer c=0; c

Alternatively, if your simulator supports IEEE 1800 (SytemVerilog), then

parameter ROWBITS = 4; reg [ROWBITS-1:0] temp; always @(posedge sysclk) begin         temp 


回答3:

Within a module, Verilog contains essentially two constructs: items and statements. Statements are always found in procedural contexts, which include anything in between begin..end, functions, tasks, always blocks and initial blocks. Items, such as generate constructs, are listed directly in the module. For loops and most variable/constant declarations can exist in both contexts.

In your code, it appears that you want the for loop to be evaluated as a generate item but the loop is actually part of the procedural context of the always block. For a for loop to be treated as a generate loop it must be in the module context. The generate..endgenerate keywords are entirely optional(some tools require them) and have no effect. See this answer for an example of how generate loops are evaluated.

//Compiler sees this parameter ROWBITS = 4; reg [ROWBITS-1:0] temp; genvar c;      always @(posedge sysclk) //Procedural context starts here     begin         for (c = 0; c 


回答4:

If you do not mind having to compile/generate the file then you could use a pre processing technique. This gives you the power of the generate but results in a clean Verilog file which is often easier to debug and leads to less simulator issues.

I use RubyIt to generate verilog files from templates using ERB (Embedded Ruby).

parameter ROWBITS =  ; always @(posedge sysclk) begin        temp[]  end 

Generating the module_name.v file with :

$ ruby_it --parameter ROWBITS=4 --outpath ./ --file ./module_name.rv 

The generated module_name.v

parameter ROWBITS = 4 ; always @(posedge sysclk) begin   temp[0] 


回答5:

for verilog just do

parameter ROWBITS = 4; reg [ROWBITS-1:0] temp; always @(posedge sysclk) begin   temp 


标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!