关于触发始终块的问题

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

我知道一个始终的块将触发其灵敏度列表中任何元素的更改但是,我的问题是如果在始终块内的语句仍在执行时灵敏度列表发生更改会发生什么(由于先前的触发器)。 always块是否在并行线程中再次开始执行,或者在执行完成之前触发阻塞?

verilog system-verilog execution hdl
3个回答
1
投票

一旦触发了始终块,它将从开始到结束执行。 Verilog是一个单线程模拟引擎,因此一次只能执行一个块。执行always块时不会发生任何其他情况,除非它包含延迟语句或等待事件。在后一种情况下,它只会屈服于允许其他块被执行,然后它继续。

如果always块在​​执行结束时更改其输入,则下一个模拟行为取决于块的类型:

  • 所有v95 / v2k总是阻塞(例如总是@ *)将被重新触发,
  • 系统verilog块(例如,always_comb)将不会在当前增量循环中重新触发。

对于v2k / v95始终阻塞,如果不小心,最终可能会出现零延迟循环。换句话说,模拟可以挂起。

使用SystemVerilog块,您可以获得有趣的先读后读取条件(在将变量写入同一块之前读取变量)。这可能会造成模拟/合成不匹配。


2
投票

许多人没有意识到@是一个语句修饰符,而不是自己构造。它说要延迟发生事件之前的声明。 @(A or B)表示等到A或B的值发生变化(不要与A | B结果的变化相混淆)。 @*意味着查看后面的语句,并构建一个隐含的敏感信号列表以等待更改。

always @(A or B) C = A + B;
always begin
         @(A or B) C = A + B;
       end
always begin
         @* C = A + B;
       end
always_comb
       begin
         C = A + B;
       end

这4个always块具有相同的行为,除了最后一个always_comb也在0时触发,无论A或B是否有任何变化。

如果查看always后面的代码作为执行语句的过程序列,可能更容易将@构造视为该过程序列的一部分,并且在执行构造时必须进行更改。只是添加另一个延迟将显示这个概念(不可综合)

always @(A or B) begin
         #10 C = A + B;
       end

这表示“等待A或B上的更改,然后再等待10个时间单位,然后使用当前A + B值对C进行分配”。如果在10次单位等待期间A或B发生变化,则错过该变化。在这10个时间单位之后,您必须等待A或B上的其他更改。


1
投票

每个always块都是一个单独的线程(除非它包含fork-join)。因此,如果它正在执行,如果灵敏度列表中的某些内容发生变化,则不会重新触发。 (如果它确实包含fork-join,那么一旦触发它就会分裂成多个线程,但同样不会重新触发)。

最新问题
© www.soinside.com 2019 - 2024. All rights reserved.