这件事我也很难过。
但首先,您应该明白,非阻塞或阻塞实际上与是否创建latch/ff 无关!
对于它们的区别,您可以在这一点上简单地(一开始)理解它:i。如果使用阻塞,它后面的语句直到阻塞语句 LHS 赋值后才能执行,因为如果使用变量,它的 LHS 变化可以更新和使用。但是,对于非阻塞,它不会像与后句并行那样阻塞后句(实际上应该先进行RHS计算,但没关系,混淆时忽略它)。LHS 不会更改/更新这次执行(下次总是再次触发块时更新)。下面的句子使用旧值,因为它在执行周期结束时更新。
a = 0; b= 0;
a = 1;
b = a;
--> output a = 1, b = 1;
a = 0; b= 0;
a <= 1;
b = a;
--> output a = 1, b = 0;
一个关键点是找出在你的代码中(总是阻塞)是否有任何没有赋值但可能发生的 case 变量。如果您没有将值传递给它并且发生这种情况,则创建latch/ff 以保留该值。
例如,
always @(*) begin
if(in) out = 1;
else out = 0;
end
--> this end without latch/ff
always @(*) begin
if(in) out = 1;
end
--> this end with one latch/ff to keep value when in = 0, as it might happen and you didn't assign value to out as in=1 do.
以下也可以创建latch/ff:
always @(*) begin
if(in) a = 1;
else b = 1;
end
--> 为 in=1、b 无赋值、in=0 a 无赋值而创建的锁存器/ffs。
另外,当你感觉到 clk 的 posedge 时always @(posedge clk)
,它必然以latch/ff 结束。因为,对于 clk,必须存在负边沿,并且您什么都不做,因此创建了 latch/ffs 以保留所有旧值!