我仍然对SystemVerilog 2012规则4.7的实施方式感到困惑。 规则规定在这种情况下:
module test;
logic a;
integer cnt;
initial begin
cnt = 0;
#100;
a <= 0;
a <= 1;
a <= 0;
a <= 1;
a <= 0;
end
always @(posedge a)
begin
cnt <= cnt + 1;
end
endmodule
所有分配都将在非阻塞分配队列上进行调度,然后必须按顺序执行。最后一个值获胜。 到目前为止,一切都很清楚。
接下来会发生什么,但对于所有模拟器来说都不一样。 iverilog和Modelsim(至少是Vivado 2016/3版)在&#39; a&#39;上创建一个事件,这会导致cnt递增。这似乎也符合Cummings先生在SNUG 2000上的行为
然而,VCS过滤掉中间值并仅应用最后一个值,顺便说一下,这也是真正的触发器工作的方式。
在这种情况下,它不是一个纯粹的假设讨论,模拟结果是不同的,并且iverilog / modelsim行为可能导致很难捕获的错误,因为触发器切换但波形中没有看到值变化。
另一点是:如果iverilog / modelsim是正确的,为什么他们会创建一个事件而不是两个?
编辑: 补充说明。
上面的例子确实不是很有意义。 一个更现实的案例是
always @(posedge clk)
begin
clk2 <= 1'b1;
if (somecondition)
clk2 <= 1'b0;
end
always @(posedge clk2, negedge rst_n)
begin
if (!rst_n)
q <= 1'b0;
else
q <= ~q;
end
这是完全合法的,在真正的硬件中永远不会出现问题。 第一个总是在逻辑上与
完全相同always @(posedge clk)
begin
if (somecondition)
clk2 <= 1'b0;
else
clk2 <= 1'b1;
end
但是,如果你使用ModelSim模拟第一个版本,你会看到你的q愉快地切换,clk2常数为0.这将是一个调试的噩梦。
答案 0 :(得分:1)
您的上一个问题很容易解释。并非模拟器只创建一个事件,他们不会认为只有第一个事件安排@(posedge)恢复always
进程而其他事件发生在NBA区域之前总是阻止在下一个活动区域恢复执行。
我不能证明其他模拟器的行为是正确的。你不允许在真实硬件中对同一个触发器进行多次分配,所以你不能这么简单地进行类比。可以有一个不定时的描述,并且可以在没有时间的情况下获得多个(@ posedge&#39; s)。因此过滤会阻止编码风格。