在本例中,非阻塞分配传播到连续赋值.这是否会导致任何执行paradigms.Please详细阐述这段代码可能出现的错误,如何删除它和良好的编码风格。
always @(posedge clk)
dff1 <= f(x);
assign fsm_in = f(dff1);
assign fsm_out = fsm_state;
always @(fsm_in)
fsm_state <= g(fsm_in);发布于 2013-08-16 10:54:03
您的代码很好,尽管我同意Greg的观点,在组合过程中使用阻塞分配更好。
关于你的评论:
用非常简单的术语来说,调度程序包含5个队列(SV有17个队列),但您只对其中两个队列感兴趣:active event queue和nonblocking assignment update queue。在给定的仿真周期中,模拟器处理活动事件队列,然后处理非阻塞更新队列。通常,这将创建更多的事件,并且仿真器按照预先确定的顺序在队列周围循环,直到在此模拟时没有更多的事件。然后仿真器移动到下一次调度事件的时间(例如,在下一个时钟边缘)。
假设“一次”发生四件事:fsm_state有变化,f(x)有变化,你们的任务都被执行了。就模拟器而言,这4条语句在相同的仿真周期内执行,但顺序不明。“立即”的定义相当复杂,但假设它们都是由时钟边造成的,语句之间没有顺序依赖关系。模拟器通常是单线程的,因此它实际上会在不同的实际时间执行这4条语句,但它知道所有4条语句都是在相同的模拟时间发生的。
fsm_state和f(dff1)上的更改是update events,并添加到调度程序的active event queue中。
将立即评估两个NBA的RHS,并将LHS更新添加到nonblocking assignment update queue中。
模拟器现在看到一个包含4个事件的队列。它首先以未定义的顺序执行两个活动事件,因此fsm_in和fsm_out获得它们的新值。如果没有更多的活动事件,那么它将以未定义的顺序执行两个非阻塞更新,因此dff1和fsm_state现在获得了它们的新值。
在您的示例中,模拟周期尚未完成,因为fsm_in上的更改也是一个更新事件,这将触发对fsm_in敏感的始终块的评估/执行。这是一个evaluation event。sim执行始终块,立即读取fsm_in的新值,并将fsm_state的更新添加到NBA分配更新队列中。如果没有活动事件,则对赋值进行操作,然后fsm_state获得它的新值。
这种情况一直持续到这个模拟周期中没有更多的事件,如果将来有什么计划的话,模拟器就会提前时间。
您可以从Verilog LRM的第5部分获得所有这些,但这没有多大意义。在标准化过程的后期,所有的语言都被移植到了标准化过程中,并使用了LRM中其他地方没有使用的术语(VHDL)。它也都是以与Verilog的行为相匹配的方式添加的,特别是记录了XL特有的非决定论,所以不要对它期望太高。我认为,NBA甚至直到1992年才被添加到语言中。不要费心于SV;还有更多的队列,普通文本已经改变,只是增加了另一个层次的混乱。
克里夫·卡明斯在他的一篇论文(关于非阻塞作业)中有一个简单的描述,但仔细阅读。我确信活动事件队列的描述是不正确的(对于NBAs的RHS评估)。如果他是对的,就会引起各种各样的问题;他大概是从早期版本的LRM中得到描述的。
最好的方法就是查找VHDL增量循环上的任何文本。这些都很容易理解,而且它们一直都在工作,而且这些年来它们悄悄地进入了Verilog。细节是不同的,但你不需要知道更多的东西,你会发现,在三角洲周期。
发布于 2013-08-16 15:38:34
我建议您始终使用非阻塞时钟驱动信号和阻塞组合逻辑(如果是RTL)。我使用了许多合成器,如果你不使用我推荐的作业,它们会显示错误。此外,还有其他衬里工具,这也会显示错误。我同意Greg的观点,为了获得更好的可读性代码,您应该遵循这个准则。
https://stackoverflow.com/questions/18263996
复制相似问题