如何解释 Verilog 中的阻塞分配与非阻塞分配?
在绘制硬件图时,我对如何解释阻塞和非阻塞分配感到有点困惑。我们是否必须推断非阻塞赋值给我们一个寄存器?那么根据这条语句c <= a+b
,c应该是一个寄存器吧,而不是a和b?
module add (input logic clock,
output logic[7:0] f);
logic[7:0] a, b, c;
always_ff @(posedge clock)
begin
a = b + c;
b = c + a;
c <= a + b;
end
assign f = c;
endmodule
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
传统的 Verilog 智慧完全错误。对本地变量使用阻塞赋值没有问题。但是,您永远不应该使用阻塞分配进行同步通信,因为这是不确定的。
时钟始终块内的非阻塞分配将始终推断出触发器,如语义所规定的。
时钟始终块内的阻塞分配是否推断触发器完全取决于它的使用方式。如果变量可能在分配之前被读取,则将推断出触发器。否则,这就像一个临时变量,会产生一些组合逻辑。
The conventional Verilog wisdom has it all wrong. There is no problem with using blocking assignments for a local variable. However, you should never use blocking assignments for synchronous communication, as this is nondeterministic.
A non-blocking assignment within a clocked always block will always infer a flip-flop, as dictated by the semantics.
Whether a blocking assignment within a clocked always block infers a flip-flop or not depends entirely on how it is used. If it is possible that the variable is read before being assigned, a flip-flop will be inferred. Otherwise, this is like a temporary variable and it will result in some combinatorial logic.
最初了解阻塞和非阻塞分配之间的差异确实有点棘手。但不用担心 - 有一个方便的经验法则:
您上面的代码可能不是最好的例子。如果不知道您要构建什么加法器/触发器结构,则存在组合反馈路径的危险(这很糟糕)。由于您没有输入总线,因此您实际上是在尝试构造
a
、b
和c
凭空而来!但要回答你的问题,分配给时钟
always
块内的任何变量都会推断出触发器,除非它使用阻塞运算符 (=
) 分配并用作一种局部变量。遵循经验法则而不是在
always
块中混合阻塞和非阻塞分配的一个重要原因是,混合分配可能会导致 RTL 模拟和门模拟/真实硬件操作之间出现严重的模拟不匹配。 verilog 模拟器对=
和<=
的处理方式截然不同。阻塞赋值意味着“立即将值赋给变量”。非阻塞赋值意味着“找出要分配给该变量的内容,并将其存储起来以便在将来的某个时间分配”。为了更好地理解这一点,值得阅读的一篇好论文是:另请参阅:http://www.sunburst -design.com/papers/CummingsSNUG2000SJ_NBA.pdfIt's definitely a bit tricky to get your head around the differences between blocking and nonblocking assignments initially. But no fear - there's a handy rule of thumb:
Your code above is probably not the best example. Without knowing what adder/flipflop structure you were trying to build, there's the danger of having combo feedback paths (which are bad). And since you've no input buses, you're essentially trying to construct
a
,b
&c
out of thin air!But to answer your question, any variable assigned to within a clocked
always
block will infer a flipflop, unless its assigned using the blocking operator (=
) and used as a kind of a local variable.A big reason for following the rule of thumb and not mixing blocking and nonblocking assignments within an
always
block, is that mixing your assignments can cause serious simulation mismatches between RTL sims and gate-sims/real hardware operation. The verilog simulator treats=
and<=
quite differently. Blocking assignments mean 'assign the value to the variable right away this instant'. Nonblocking assignments mean 'figure out what to assign to this variable, and store it away to assign at some future time'. A good paper to read to understand this better is: Also see: http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf只是想补充 Jan Decaluwe 的答案。看起来,实际上很少有代码真正使用了 Jan Decaluwe 所描述的内容,尽管它是绝对正确的。感谢卡明斯先生,混合阻塞和非阻塞语句现在已成为一种禁忌。
问题是,大多数地方都避免对局部变量使用阻塞语句,并且在 Google 的直接搜索空间中几乎没有代码提供了如何完成此操作的示例。我找到 Jan 提到的编码风格的唯一地方是 本文中的获胜代码。还有这个,我无意中发现的
Just want to add to Jan Decaluwe's answer. It seems that there is very little code in the wild that actually actually uses what Jan Decaluwe's describes, even though it is absolutely right. Mixing blocking and non-blocking statements is now a taboo, thanks to Mr.Cummings.
The trouble is, most places avoid using blocking statements for local variables and there is very little code in the immediate search space of Google that looks gives an example of how it is done. The only place where I have found the coding style as mentioned by Jan is the winning code in this article. And this, I came across accidentally
我也为这件事苦恼过。
但首先,你应该明白,非阻塞或阻塞实际上与是否创建latch/ff无关!
对于它们的区别,你可以简单地理解它(一开始):i。如果使用阻塞,则在块语句LHS赋值之前不能执行其后面的语句,因为如果使用变量,则可以更新并使用它的LHS更改的内容。然而,对于非阻塞来说,它不会像与下面的句子并行一样阻塞后面的句子(实际上应该先进行RHS计算,但没关系,混淆时忽略它)。这次执行时 LHS 不会更改/更新(下次始终块再次触发时更新)。下面的句子使用旧值,因为它在执行周期结束时更新。
一个关键点是确定在您的代码(始终阻塞)中是否存在任何未分配值但可能发生的情况变量。如果您不向其传递值并且发生这种情况,则会创建latch/ff 来保留该值。
例如,
以下也可以创建latch/ff:
-->为 in=1 创建闩锁/ffs,b 无分配,in=0 a 无分配。
另外,当你感知到clk的posege
always@(thoughtge clk)
时,它必然以latch/ff结束。因为,对于clk来说,必须存在下降沿,而你什么都不做,就会创建latch/ffs来保留所有旧值!I had a hard time over this too.
But firstly, you should understand that non-blocking or blocking is actually nothing to do with whether a latch/ff would be created!
For their difference you could understand it simply(at beginning) by this point: i. If use blocking, sentences after it could not be executed until block sentence LHS assigned value, since what changed to LHS of it could be updated and used if the variable is used. However, for non-blocking, it don't block following sentence like parallel with following sentence(actually RHS calculation should be done first, but it doesn't matter, ignore it when you confuse). The LHS don't change/updated for this time's execution (updated next time when always block trigged again). And following sentence use the old value, as it updated at the end of execution cycle.
One key point is to find whether in you code (always block) there is any case variable not assigned value but could happen. If you don't pass value to it and that case occurs, then latch/ff is created to keep the value.
For example,
Following could also create latch/ff:
--> latch/ffs created for in=1, b no assignment, in=0 a no assignment.
In addition, when you sense posedge of clk
always @(posedge clk)
, it is bound to end with latch/ff. Because, for clk, there must exist negative edge, and you don't do anything, latch/ffs are created to keep all the old value!请您始终可以在数字域中解释verilog,只是您必须了解如果您编写的相同代码在门级进行转换会发生什么,我个人不遵循在seq中使用非阻塞或在组合中使用阻塞的规则,这会限制你的思维。仅保留代码的数字部分
如果您的代码转换为门级,将会发生以下情况,只要看到您只需要这个,
谢谢
问候
拉胡尔·贾因
please you can always interpret the verilog in digital domain just you have to understand what will happen if the same code you wrote will be converted in gate level , i personally dont go by the rule that to use non blocking in seq or use blocking in combinational , this will limit your thinking . stick to the digital side of the code only
here is what will happen if your code is converted to gate level just see you want this only
thanks
regards
Rahul jain
我可以回答你的问题,但我认为一篇论文最适合这个问题,所以我建议你阅读 Clifford Cummings 的这篇论文。它将消除您所有的疑虑,此外还将加强您对 verilog 的理解。
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf
I can answer your question, but I think one paper would be best for this so I recommend you to read out this paper of Clifford Cummings. It will clear all your doubts and in addition to it will strengthen your understanding of verilog.
http://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA_rev1_2.pdf