9

到目前为止,我读过的所有书籍中提到的一般经验法则是,您必须在由时钟的上升沿或下降沿驱动的 always 块中使用非阻塞分配。相反,阻塞赋值必须用于组合逻辑描述。这条规则对我来说很有意义,示例的作者会彻底遵循它。

但是,我在其中一个生产代码中发现了以下 Verilog:

always @* begin
   in_ready <= out_ready || ~out_valid;
end

<=请注意,正在使用非阻塞赋值。我认为在这种情况下没有任何区别,因为没有多重分配。但是,我似乎找不到任何解释。所以问题是——无论是在给定的始终块的范围内还是作为更大设计的一部分,它是否会产生任何影响?

4

4 回答 4

8

当然,这违反了我的编码准则 #3:http ://www.sunburst-design.com/papers/CummingsSNUG2000SJ_NBA.pdf )但它会起作用。

避免对代码组合逻辑使用非阻塞赋值的原因是仿真性能。在 Munkymorgy 的示例中,在 always 块触发后,您将评估所有方程的右侧 (RHS),回到 always 块的顶部,更新方程的 LHS,这将再次触发always 块,这将再次强制模拟器评估方程的 RHS,转到 always 块的顶部,然后更新方程的 LHS。对于较大的块,这可能会导致通过 always 块进行多次迭代,并产生相应的模拟损失。

在您简单的 1 行示例中,没有内部模拟惩罚,但其他地方可能存在交叉分配惩罚。

优秀的编码员使用始终如一的良好编码习惯。我会更改代码。如果更改代码会破坏模拟结果,那么代码中的其他地方就会隐藏额外的不良编码习惯。代码不应该那么脆弱。

于 2012-06-27T21:58:17.787 回答
5

不相关但不好的做法。

我怀疑单一分配会导致任何副作用。always 块将触发右侧的任何更改,更新 in_ready。没有什么可阻塞的,所以非阻塞不会引起问题。

如果更大的设计有:

always @* begin 
  in_ready    <= out_ready || ~out_valid  ;
  other_ready <= in_ready  || other_ready ;
end

我不太确定,因为它是组合的,它可能只需要一个额外的增量步骤来解决。

于 2012-06-21T15:31:15.363 回答
2

如果您了解电路的行为方式,它的选择还不错,例如

总是@* 开始 b<=a+c; a=b; 结尾

  1. 所以在这个示例代码中,当灵敏度列表中的任何东西(所有输入)上升或下降时,总是块内开发的完整电路将被激活,它会改变其当前状态
  2. 现在 b <=a+c 现在这里将使用“a”和“c”作为输入创建一个全加器,但是
  3. 现在设计已经完成,或者编译器以这样的方式合成电路,下一条语句 a=b 这里的线是从旧值中取出的,而不是从更新后的 b 中取出并提供给 a ;如此简单
  4. 如果你想要同样的事情发生,欢迎你做任何问题都不会出现
于 2014-09-30T11:36:58.973 回答
1

如果要模拟门延迟,则需要始终 @(*) 中的非阻塞分配。

例如,下面的代码在输出端正确模拟了具有 3 ns 延迟的 OR 门。在这种情况下,阻塞分配将不起作用。

always @(*) begin
  a <= #3 b | c;
end  

进一步阅读:

  1. http://www.sunburst-design.com/papers/CummingsHDLCON1999_BehavioralDelays_Rev1_1.pdf
  2. https://electronics.stackexchange.com/q/572643/238188
于 2021-06-24T09:34:06.987 回答