2012-09-20 127 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