总是@ *阻止一个非阻塞任务 - 好,坏或不相关?

时间:2012-06-21 12:37:20

标签: verilog

到目前为止我读过的所有书籍中提到的一般经验法则是,你必须在由时钟的上升沿或下降沿驱动的始终块中使用非阻塞分配。相反,阻塞分配必须用于组合逻辑描述。这个规则对我来说很有意义,例子的作者可以完全遵循它。

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

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

请注意,正在使用非阻塞分配<=。我认为这种情况没有任何区别,因为没有多项任务。但是,我似乎无法找到任何解释。所以问题是 - 在给定的始终块的范围内以及作为更大设计的一部分,它是否有任何区别?

4 个答案:

答案 0 :(得分:7)

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

避免使用非阻塞分配来编码组合逻辑的原因是仿真性能。在Munkymorgy的例子中,在总是块触发之后,您将评估所有方程的右侧(RHS),返回到始终块的顶部,更新方程的LHS,这将再次触发总是阻塞,这将再次强制模拟器评估方程的RHS,转到始终块的顶部,然后更新方程的LHS。对于较大的块,这可能导致遍历块的多次迭代,并具有相应的模拟惩罚。

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

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

问候 - Cliff Cummings - Verilog&amp; SystemVerilog Guru

答案 1 :(得分:4)

不相关但不好的做法。

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

如果更大的设计有:

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

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

答案 2 :(得分:1)

如果您了解电路的表现非常好,那么它的选择并不错 所以例如

总是@ *开始  b将= A + C;  A = B;  端

  1. 所以在这个示例代码中,当灵敏度列表中所有输入内的任何内容都会上升或下降时,始终块内部开发的完整电路将被激活
  2. 现在b&lt; = a + c现在这里将使用&#39; a&#39;创建一个完整的加法器。和&#39; c&#39;作为输入,但
  3. 现在进行了设计,或者编译器合成电路的方式是下一个语句a = b这里的导线是从旧值中取出而不是从更新后的b中取出并提供给 ; 所以简单
  4. 如果你想要同样的事情发生,欢迎你做任何问题都将在可综合的
  5. 中出现

答案 3 :(得分:0)

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

例如,以下代码正确模拟了输出延迟为 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