0

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

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

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

    always @(fsm_in)
        fsm_state <= g(fsm_in);
4

3 回答 3

2

您的代码很好,尽管我同意 Greg 的观点,即在组合过程中使用阻塞分配更好。

关于您的评论:

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

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

和上的更改是fsm_state和被添加到调度程序的.f(dff1)update eventsactive event queue

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

模拟器现在看到一个队列,上面有 4 个事件。它首先以未定义的顺序执行两个活动事件,fsm_in然后fsm_out获取它们的新值。如果没有更多活动事件,它会以未定义的顺序执行两个非阻塞更新,因此dff1现在fsm_state获取它们的新值。

在您的情况下,模拟周期尚未完成,因为更改 fsm_in也是一个更新事件,这会触发对fsm_in. 这是一个evaluation event. sim 执行 always 块,立即读取 的新值 fsm_in,并将 的更新添加fsm_state到 NBA 分配更新队列。如果没有活动事件,则分配将被执行,并 fsm_state获取它的新值。

这种情况一直持续到该模拟周期中没有更多事件为止,如果将来安排了某些事情,则模拟器会提前时间。

您可以从 Verilog LRM 的第 5 节中获得所有这些信息,但这没有多大意义。所有语言都在标准化过程的后期移植,并使用 LRM 其他地方未使用的 (VHDL) 术语。它也是以匹配 Verilog-XL 的行为的方式添加的,特别是为了记录特定于 XL 的非确定性,所以不要对它期望太多。我认为,直到 1992 年 NBA 才被添加到语言中。不要为 SV LRM 烦恼;队列更多了,通用文本也发生了变化,只是增加了另一层混乱。

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

最好的办法是在 VHDL delta 周期上查找任何文本。这些很容易理解,而且它们有效,而且一直有效,并且多年来它们已经悄悄进入 Verilog。细节是不同的,但你不需要知道比你在增量周期中发现的更多的东西。

于 2013-08-16T10:54:03.603 回答
2

首先:最佳实践是对寄存器进行非阻塞分配,对组合逻辑进行阻塞分配。我建议看一下这篇论文:Verilog Synthesis, Coding, Styles That Kill 中的非阻塞赋值!通过克利福德 E.卡明斯。§ 11 涵盖组合逻辑。该论文的指南适用于 IEEE Std 1364-1995,并且在今天仍然完全适用;Verilog 和 SystemVerilog。

也就是说,给定的代码原样可以正常工作,因为您有一个简单的条件。它也可能会正确合成(基于 Cliff 的页面)。

如果你使用糟糕的编码风格和更复杂的设计,你可能会遇到问题。有关示例,请参见Cliff 的论文。糟糕的编码风格也会让其他人更难阅读[1]。可读的代码是你想要教授和同事的东西。一个理想的 linting 工具也会标记它。最好让自己养成编写高质量代码的习惯。

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

于 2013-08-16T02:05:36.757 回答
0

我建议您始终对时钟驱动信号使用非阻塞,对组合逻辑使用阻塞(如果是 RTL)。我使用了许多合成器,如果您不按照我的建议使用分配,它们会显示错误。还有其他 linting 工具也会显示错误。我同意 Greg 的观点,为了获得更好的可读性代码,您应该遵循本指南。

于 2013-08-16T15:38:34.333 回答