1. 非阻塞赋值
- 代码如下
always @( posedge clk )
begin
b<=a;
c<=b;
end
- RTL会综合出两个寄存器串行,如下波形图所示,第一个时钟上升沿来临时,会把a的旧值赋值给b;同时,c获得的是b的旧值,而不是从a那里拿到的新值。
- 非阻塞赋值可以理解成 a对b的赋值 并不阻塞 b对c的赋值,两行代码可以看成并行执行,在时钟沿到来时,b和c同时获得值;
- 波形图如下
2. 阻塞赋值
- 代码如下
always @(posedge clk)
begin
b=a;
c=b;
end
- RTL只会综合出一个寄存器,在上升沿来临时,会把a的旧值赋值给b,之后,b再将从a获得的新值赋值给c。
- 阻塞赋值可以理解成a赋值给b的这个过程阻塞b赋值给c,所以当b拿到了a的旧值之后,才会赋值给c。
3. 阻塞赋值和非阻塞赋值的原则
- 错误的使用阻塞赋值可能会导致出现竞争冒险:如果在一个过程块中阻塞赋值的RHS 变量正好是另一个过程块中阻塞赋值的LHS 变量,这两个过程块又用同一个时钟沿触发,如果阻塞赋值的次序安排不好,就会出现竞争。
- 使用下面的原则编码会更安全
- 时序电路建模时,用非阻塞赋值。
- 锁存器建模时,使用非阻塞赋值。
- 用always 块写组合逻辑时,采用阻塞赋值。
- 在同一个always 块中同时建立时序和组合逻辑电路时,用非阻塞赋值。
- 在同一个always 块中不要同时使用非阻塞赋值和阻塞赋值。
- 注意,阻塞赋值和非阻塞赋值都是可用在always块中的时序逻辑和组合逻辑。只是遵守上面的原则编码会更安全。