2012-09-20 123 views
11

我试图让一个模块通过ISE 12.4中的语法检查,它给了我一个我不明白的错误。首先代码片段:Verilog generate/genvar总是阻止

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 

当我尝试进行语法检查,我得到了以下错误消息:

ERROR:HDLCompiler:731 - "test.v" Line 46: Procedural assignment to a non-register <c> is not permitted.

我真的不明白为什么它的抱怨。 “c”不是电线,而是genvar。这应该是相当于完全合法的语法:

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 

请不要评论如何更容易地编写这个没有生成。这是一个涉及多个if和非阻塞赋值给“temp”的非常复杂的代码片段的简化示例。另外,不要只是告诉我有更新版本的ISE,我已经知道了。 OTOH,如果你知道它在ISE的更高版本中被修复,请告诉我你知道哪个版本的作品。

回答

15

你需要扭转产生块内的嵌套:

genvar c; 
generate 
    for (c = 0; c < ROWBITS; c = c + 1) begin: test 
     always @(posedge sysclk) begin 
      temp[c] <= 1'b0; 
     end 
    end 
endgenerate 

技术上讲,这产生四个始终块:

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; 

在这个简单的例子,有四间的行为没有什么区别总是包含四个任务的块和一个总是阻塞,但在其他情况下可能会有。

当构建设计的内存中表示(在模拟器的情况下)或映射到逻辑门(在综合工具的情况下)时,genvar相关操作需要解析。在设计运行之前,always @posedge没有意义。

受限于某些限制,您可以在always块中放置for循环,即使对于可合成代码。为了合成,循环将被展开。但是,在这种情况下,for循环需要使用reg,integer或类似的。它不能使用genvar,因为在always块内部具有for循环描述了在时钟的每个边缘发生的操作,而不是在设计细化过程中可以静态扩展的操作。

+0

感谢您的快速反应。我担心它会是这样的。部分问题是我想用for循环生成一系列if语句或case选择符,这不能在单独的always块中完成。 – user1684538

+0

有没有什么办法可以在一个always块中生成所有的代码,或者genvar是不是可以做到这一点? – user2569332

2

在模块中,Verilog基本上包含两个结构:项目和语句。语句总是在程序上下文中找到,其中包括begin..end,functions,tasks,always块和初始块之间的任何内容。项目(例如生成构造)直接列在模块中。对于循环和大多数变量/常量声明可以存在于两个上下文中。

在你的代码中,看起来你希望for循环被评估为一个生成项目,但该循环实际上是always块的过程上下文的一部分。要将for循环视为生成循环,它必须位于模块上下文中。 generate..endgenerate关键字完全是可选的(某些工具需要它们)并且没有任何作用。有关如何评估生成循环的示例,请参见this answer

//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 < ROWBITS; c = c + 1) begin: test 
      temp[c] <= 1'b0; //Still a genvar 
     end 
    end 
2

如果你不介意编译/生成文件,那么你可以使用预处理技术。这为您提供了生成的功能,但是会生成一个干净的Verilog文件,该文件通常更容易调试,并且可以减少模拟器问题。

我使用RubyIt来使用ERB(嵌入式Ruby)从模板生成verilog文件。

parameter ROWBITS = <%= ROWBITS %> ; 
always @(posedge sysclk) begin 
    <% (0...ROWBITS).each do |addr| -%> 
    temp[<%= addr %>] <= 1'b0; 
    <% end -%> 
end 

产生module_name.v文件有:

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

生成module_name.v

parameter ROWBITS = 4 ; 
always @(posedge sysclk) begin 
    temp[0] <= 1'b0; 
    temp[1] <= 1'b0; 
    temp[2] <= 1'b0; 
    temp[3] <= 1'b0; 
end 
4

你不会,如果你想的temp所有位需要产生博克分配在同一块始终。

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
    for (integer c=0; c<ROWBITS; c=c+1) begin: test 
     temp[c] <= 1'b0; 
    end 
end 

另外,如果您的仿真器支持IEEE 1800(SytemVerilog),然后

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
     temp <= '0; // fill with 0 
    end 
end 
0

对Verilog只是做

parameter ROWBITS = 4; 
reg [ROWBITS-1:0] temp; 
always @(posedge sysclk) begin 
    temp <= {ROWBITS{1'b0}}; // fill with 0 
end