到目前为止我读过的所有书籍中提到的一般经验法则是,你必须在由时钟的上升沿或下降沿驱动的始终块中使用非阻塞分配。相反,阻塞分配必须用于组合逻辑描述。这个规则对我来说很有意义,例子的作者可以完全遵循它。
但是,我在其中一个产品代码中发现了以下Verilog:
always @* begin
in_ready <= out_ready || ~out_valid;
end
请注意,正在使用非阻塞分配<=
。我认为这种情况没有任何区别,因为没有多项任务。但是,我似乎无法找到任何解释。所以问题是 - 在给定的始终块的范围内以及作为更大设计的一部分,它是否有任何区别?
答案 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; 端
答案 3 :(得分:0)
如果要模拟门延迟,则需要始终@(*) 中的非阻塞赋值。
例如,以下代码正确模拟了输出延迟为 3 ns 的 OR 门。在这种情况下,阻止分配不起作用。
always @(*) begin
a <= #3 b | c;
end
进一步阅读: