非阻止作业的微妙之处

问题描述 投票:0回答:3

在此示例中,非阻塞分配传播到连续分配。这可以导致任何执行范例。请详细说明这段代码 - 可能的错误,它如何被删除和良好的编码风格。

  always @(posedge clk)
        dff1 <= f(x);

    assign fsm_in = f(dff1);
    assign fsm_out = fsm_state;

    always @(fsm_in)
        fsm_state <= g(fsm_in);
verilog nonblocking
3个回答
2
投票

你的代码很好,虽然我同意Greg的观点,在组合过程中使用阻塞分配是更好的风格。

在你的意见:

简单来说,调度程序包含5个队列(SV有17个),但你只对其中2个有兴趣:active event queuenonblocking assignment update queue。在给定的模拟周期中,模拟器处理活动事件队列,然后处理非阻塞更新队列。通常,这将创建更多事件,并且模拟器以预定顺序在队列周围循环,直到在该模拟时间不再有事件。然后,模拟器移动到下一次安排事件的时间(例如,在下一个时钟边缘)。

假设有4件事情“同时发生”:fsm_state有变化,f(x)有变化,你的NBA任务都被执行了。就模拟器而言,这4个语句在相同的模拟周期中执行,但是以未定义的顺序执行。 'at at'的定义相当复杂,但假设它们都是由时钟边缘发生的,并且语句之间没有排序依赖关系。模拟器通常是单线程的,因此它实际上会在不同的实时执行4个语句,但它知道所有4个语句都应该在相同的模拟时间发生。

fsm_statef(dff1)的变化是update events,并被添加到调度程序的active event queue中。

立即评估两个NBAs的RHS,并将LHS更新添加到nonblocking assignment update queue

模拟器现在看到一个包含4个事件的队列。它首先以未定义的顺序执行两个活动事件,因此fsm_infsm_out获取它们的新值。如果没有更多活动事件,它将以未定义的顺序执行两个非阻塞更新,因此dff1fsm_state现在获取其新值。

在您的情况下,模拟周期没有完成,因为fsm_in上的更改也是更新事件,这会触发对fsm_in敏感的always块的评估/执行。这是一个evaluation event。 sim执行always块,立即读取fsm_in的新值,并将fsm_state的更新添加到NBA赋值更新队列中。如果没有活动事件,则会对该任务执行操作,并且fsm_state会获取它的新值。

这种情况一直持续到这个模拟周期中没有更多事件发生,然后模拟器将推进时间,如果将来安排某些事情的话。

你可以从Verilog LRM的第5部分得到所有这些,但它没有多大意义。所有语言都是在标准化过程的最后阶段嫁接的,并使用了(LRDL)术语,这些术语在LRM的其他地方没有使用。它也是以匹配Verilog-XL行为的方式添加的,特别是记录XL特有的非确定性,所以不要期望太多。我想,直到1992年,NBAs才被添加到语言中。不要打扰SV LRM;还有更多的队列,而且常见的文本已经改变,只是增加了另一层次的混乱。

Cliff Cummings在他的一篇论文(关于非阻塞作业)中有一个简化的描述,但要仔细阅读。我很确定活动事件队列的描述是不正确的(对于NBAs的RHS评估)。如果他是对的,那就会引起各种各样的问题;他可能从早期版本的LRM中获得了描述。

要做的最好的事情是在VHDL delta周期中查找任何文本。这些都很容易理解,而且它们起作用,并且一直都有,并且多年来它们已经悄悄进入Verilog。细节是不同的,但您不需要知道任何比在delta周期中找到的更多的东西。


2
投票

首先:最佳实践是对寄存器进行无阻塞分配,对组合逻辑进行阻塞分配。我建议看看这篇论文:克利福德·卡明斯的Nonblocking Assignments in Verilog Synthesis, Coding, Styles That Kill!。 §11涵盖组合逻辑。本文的指南适用于IEEE Std 1364-1995,现在仍然完全适用; Verilog和SystemVerilog。

也就是说,给定的代码将在功能上起作用,因为您有一个简单的条件。它也可能正确合成(基于Cliff的页面)。

如果您使用较差的编码风格和更复杂的设计,则可能会遇到问题。有关示例,请参阅Cliff's paper。糟糕的编码风格也使其他人更难阅读[1]。您可以为教授和同事提供可读代码。一个理想的linting工具也会标记它。最好让自己养成编写高质量代码的习惯。

1:如果您真的不希望其他人阅读您的代码,请参阅IEEE std 1800-2012§34


0
投票

我建议您始终对时钟驱动信号使用非阻塞,对组合逻辑使用阻塞(如果是RTL)。我已经使用了很多合成器,如果你不像我推荐的那样使用这些作业,它们会显示错误。还有其他linting工具也会显示错误。我同意Greg的观点,为了获得更好的可读代码,您应该遵循本指南。

© www.soinside.com 2019 - 2024. All rights reserved.