SystemVerilog的问题是否具有非阻塞分配的循环?

时间:2016-02-19 15:33:40

标签: verilog fpga system-verilog modelsim register-transfer-level

当我正在研究基于SystemVerilog的FPGA设计时,我遇到了一种情况,我必须在时钟边缘计算4个元素的数组之和。我能够使用带有非阻塞赋值语句的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.

在此示例代码中,使用非阻塞分配计算 sum 。它的目的是在clk的第一个构造上具有(1 + 3 + 5 + 6)= 15的值;我在原始硬件中观察到过。但是在模拟中,clk的结果是6( abc [3] )。由于systemverilog模拟器安排了非阻塞语句的赋值,我相信会产生4个sum的实例,即

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

由于所有预定作业同时发生,可能是最后一次实例更新的总和,我们的总和值<= 0 + 6.如果我错了,请纠正我。

现在我的问题是如何使模拟器按顺序安排这些分配,以便即使在模拟中我也能获得15的值?由于阻塞分配不是综合中的一个选项,我无法找到任何方法来保持RTL的一致性。感谢。

3 个答案:

答案 0 :(得分:3)

您的分析似乎正确无误。您是否尝试过以下方法?

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

always @(posedge clk)
    sum <= temp;

这样,sum只在时钟边缘更新,但我们仍然可以在组合块中展开for循环(因此添加仍然可以按预期工作)。

答案 1 :(得分:2)

SystemVerilog有一个内置和数组减少运算符,无需for循环

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

需要强制转换为8位,因为默认情况下,结果的类型与数组元素类型相同。

答案 2 :(得分:0)

我想,您可以在另一个始终阻止(不是时钟边缘敏感,组合阻止)中使用阻塞分配,并且可以在update t set date2 = concat_ws('-', left(date2, 4), substr(date2, 4, 2), right(date2, 2)), date3 = concat_ws('-', left(date3, 4), substr(date3, 4, 2), right(date3, 2));

上提供给mkdir(__DIR__ . '/../stuff/newfolder', 0777, true); 的输出
sum

我想,这可能会奏效。