2016-02-19 125 views
2

當我在研究基於SystemVerilog的FPGA設計時,遇到了一種情況,我必須計算時鐘邊緣上4個元素數組的總和。我能夠用非阻塞賦值語句使用for循環來做到這一點。問題與SystemVerilog for循環具有非阻塞分配?

設計在Quartus 15.0上成功合成,但是當我試圖在Modelsim Altera上使用相同的RTL運行模擬時,結果出乎意料。我寫了一個示例代碼來說明這一點。

module schedule; 

logic [7:0] abc [0:3]; 
logic [7:0] sum=0; 
logic clk=0; 

always begin 
    #5.0ns clk <= ~clk; 
end 

initial begin 
    abc = '{1,3,5,6}; 
end 

initial @(posedge clk) begin 
    for(int i = 0; i <= 3;i++) begin 
     sum <= sum + abc[i]; 
    end 
end 

initial 
$monitor("Sum is %d",sum); 

endmodule 

This image shows the simulation results.

在此示例代碼,總和使用非阻塞賦值計算。它打算在clk的第一個posedge上具有(1 + 3 + 5 + 6)= 15的值;這是我在原始硬件中觀察到的。但是在仿真中,結果在clk posedge處是6(這是abc [3])。由於systemverilog模擬器計劃非阻塞語句的分配,我相信有4個總和被創建,即。

sum <= sum + abc[0]; 
sum <= sum + abc[1]; 
sum <= sum + abc[2]; 
sum <= sum + abc[3]; 

由於所有預定任務同時發生,可能是最後一個實例更新總和,我們有合計值< = 0 + 6,請糾正我,如果我錯了。

現在我的問題是如何使模擬器按順序安排這些分配,以便即使在模擬中也能得到15的值?由於阻塞賦值不是合成中的一個選項,因此我找不到任何方法來保持RTL一致。謝謝。

+0

@skrrgwasme你不應該在鍾控塊內使用阻塞賦值。 – wilcroft

+0

@wilcroft ... –

回答

3

您的分析看起來是正確的。您是否嘗試過以下方法?

logic [7:0] temp; 
[email protected](*) begin 
    temp = 0; 
    for (int i = 0; i < 4; i = i + 1) 
     temp = temp + abc[i]; 
end 

always @(posedge clk) 
    sum <= temp; 

這樣,sum只會被更新時鐘邊沿上,但我們仍然可以展開的for循環中一個組合模塊(所以加仍應工作打算)。

+0

雅這工作正常,但是當我添加一個**單個clk脈衝爲基礎的啓用信號**的溫度計算總和只會在下一個時鐘邊緣更新右? –

2

SystemVerilog的具有內置求和陣列減少操作者消除了對有此需要的for循環

sum <= abc.sum() with (8'(item)); 

是需要的,流延到8位,因爲,在默認情況下,該結果的類型是一樣的數組元素類型。

+0

您認爲這個縮減操作符會在Altera Quartus中進行合成嗎?我會嘗試相同的。謝謝。 –

0

我想,你可以用另一阻擋分配總是阻止(是不是時鐘邊沿觸發,組合模塊),它的輸出可以提供給sumposedge clk

reg [7:0] temp_sum; 

always @ (*) 
begin 
    temp_sum = abc[0]; 
    temp_sum = temp_sum + abc[1]; 
    temp_sum = temp_sum + abc[2]; 
    temp_sum = temp_sum + abc[3]; 
end 

always @ (posedge clk) 
    sum <= temp_sum; 

我想,這可能工作。