我知道Always块将在其敏感度列表中的任何元素发生更改时触发,但是,我的问题是,如果在Always块中的语句仍在执行时,敏感度列表发生更改会发生什么(由于之前的触发器)。始终阻塞是在并行线程中再次开始执行还是触发阻塞直到执行首先完成?
答案 0 :(得分: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
这四个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 :(得分:1)
每个阻塞始终是一个线程(除非它包含fork
-join
)。因此,如果它正在执行,如果敏感度列表中的某些内容发生更改,它将不会重新触发。 (如果它确实包含fork
-join
,则一旦触发它就会分裂为多个线程,但不会再次触发。)
答案 2 :(得分:1)
一旦触发Always块,它将从头到尾执行。 Verilog是单线程模拟引擎,因此一次只能执行一个块。在执行Always块时,除非包含延迟语句或等待事件,否则什么都不会发生。在后一种情况下,它只会产生 允许其他块被执行,然后继续。
如果始终块在执行结束时更改其输入,则下一个模拟行为取决于该块的类型:
使用v2k / v95始终阻止,如果不小心,可能会导致零延迟循环。换句话说,模拟会挂起。
使用SystemVerilog块,您可以获得有趣的写前读取条件(在将变量写入同一块之前先对其进行读取)。这可能会导致模拟/合成不匹配。