当我正在研究基于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的一致性。感谢。
答案 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
我想,这可能会奏效。