我已阅读“Verilog 综合中的非阻塞分配,致命的编码风格!” 通过克利福德卡明斯。他说以下代码(第 12 页,简化版)是教科书中经常使用的触发器的正确实现,即使不是任何人都应该使用的那种。该文件获得了最佳论文奖,因此我认为该声明是正确的。
module ff (q, d, clk)
output q;
input d, clk;
reg q;
always @(posedge clk)
q = d;
endmodule
我想知道如果两个或多个这些触发器串联连接,为什么它会继续正常工作。说
module two_ffs (q, d, clk)
input d, clk;
output q;
wire tmp;
ff firstff (tmp, d, clk);
ff secondff (q, tmp, clk);
endmodule
在我看来,tmp 的值可能在被 secondff 使用之前被更新,从而导致一个触发器而不是两个触发器。有人可以告诉我标准的哪一部分说不能发生吗?非常感谢。
[并不是说我会考虑编写这样的代码,我只是想了解阻塞/非阻塞行为,即使在糟糕的编码风格使含义不明显的情况下]
后来补充:
我现在认为这篇论文不太可能是正确的。1364-2201 Verilog 标准的第 5 节“调度语义”解释了会发生什么。特别是,第 68 页的第 5.6.6 节“端口连接”说单向端口就像连续分配一样。反过来,连续分配只是对所有内容都敏感的始终块。所以底线是,在我下面的示例中,ff 的两个实例化等效于具有多个 always 子句的模块,每个人都会同意它被破坏了。
在 Clive Cummings 回答问题后添加:
我感谢 CC 指出,从标准第 5 节中取出的上述陈述仅涉及更新事件的时间,并不意味着某些连续赋值和始终块之间的字面等效性。尽管如此,我认为他们解释了为什么一些模拟器(例如 Icarus Verilog)会在“触发器”中产生不同的模拟结果,其中包含阻塞和非阻塞分配。[在一个更大的例子中,我得到了 2 个带有阻塞分配的明显 ffs,而正确的 5 个带有非阻塞分配。] 其他模拟器(例如具有默认选项的 Modelsim 或 Cver)似乎产生相同的结果,无论哪种形式使用赋值。