对于 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 版)在“a”上创建一个事件,这会导致 cnt 增加。这似乎也符合卡明斯先生在 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。这将是调试的噩梦。