一、核心区别(速记表)
| 执行顺序 | 逐行执行,前一句完成才执行后一句 | 先读取所有右值,时钟沿结束后同时更新所有左值 |
| 生效时间 | 立即生效(同一时间步) | 延迟生效(时钟沿后统一更新) |
| 电路映射 | 组合逻辑(无寄存器、实时响应) | 时序逻辑(寄存器、一拍延迟) |
| 竞争冒险 | 时序逻辑中极易出现 | 时序逻辑中可避免竞争冒险 |
| 适用always块 | always @(*)(组合逻辑) | always @(posedge/negedge clk)(时序逻辑) |
二、阻塞赋值(=):逐行执行、立即生效
1. 核心机制
阻塞赋值的关键是 “阻塞后续执行”—— 赋值语句执行时,左值会立即被右值覆盖,后续语句必须等待当前赋值完成才能启动,类似手工操作:完成前一步后,才能开展下一步。
2. 正确用法:组合逻辑(必用阻塞赋值)
verilog
// 组合逻辑:两数相加后再加1
module blocking_comb_demo(
input [2:0] in1,
input [2:0] in2,
output reg [3:0] out1,
output reg [3:0] out2
);
// 组合逻辑敏感列表:所有输入变化触发
always @(*) begin
out1 = in1 + in2; // 立即赋值,out1实时更新
out2 = out1 + 1; // 使用更新后的out1计算
end
endmodule
代入数值验证:设in1=3(011)、in2=2(010):
3. 错误用法:时序逻辑用阻塞赋值
verilog
// 时序逻辑中错误使用阻塞赋值
module blocking_seq_bad(
input clk,
input [2:0] din,
output reg [2:0] a,
output reg [2:0] b
);
always @(posedge clk) begin
a = din; // 时钟沿触发后,a立即更新为din
b = a; // 立即使用更新后的a赋值给b
end
endmodule
执行结果:时钟上升沿时,a先被赋值为din,b随即被赋值为更新后的a,最终a与b始终相等,综合电路易出现竞争冒险(仿真与硬件行为不一致),违背时序电路设计规范。
三、非阻塞赋值(<=):先读右值、时钟沿后统一更新
1. 核心机制
非阻塞赋值的关键是 “不阻塞、延迟更新”—— 时钟沿触发时,先读取所有赋值语句的右值并暂存(不立即更新左值);待所有右值读取完成后,再将暂存的右值同时赋值给对应左值,类似批量下单:先选好所有商品(读右值),再统一付款发货(更新左值),选品顺序不影响最终结果。
2. 正确用法:时序逻辑(必用非阻塞赋值)
verilog
// 时序逻辑:寄存器延迟一拍
module nonblocking_seq_good(
input clk,
input [2:0] din,
output reg [2:0] a,
output reg [2:0] b
);
// 初始值:a=0,b=0
always @(posedge clk) begin
a <= din; // 读取din并暂存,不立即更新a
b <= a; // 读取当前a的旧值并暂存,不立即更新b
// 时钟沿结束后,a、b同时更新
end
endmodule
按时钟周期(拍)推导:设din按1→2→3→4变化,初始a=0、b=0:
| 第 1 拍 | a=0, b=0 | din=1,a 旧值 = 0 | a=1, b=0 | b 为上一拍的 a 值 |
| 第 2 拍 | a=1, b=0 | din=2,a 旧值 = 1 | a=2, b=1 | b 比 a 慢一拍 |
| 第 3 拍 | a=2, b=1 | din=3,a 旧值 = 2 | a=3, b=2 | 符合寄存器延迟特性 |
| 第 4 拍 | a=3, b=2 | din=4,a 旧值 = 3 | a=4, b=3 | 无竞争冒险 |
3. 错误用法:组合逻辑用非阻塞赋值
verilog
// 组合逻辑中错误使用非阻塞赋值
module nonblocking_comb_bad(
input [2:0] in1,
input [2:0] in2,
output reg [3:0] out1,
output reg [3:0] out2
);
always @(*) begin
out1 <= in1 + in2; // 非阻塞赋值,不立即更新out1
out2 <= out1 + 1; // 读取out1的旧值,而非本次计算值
end
endmodule
问题分析:组合逻辑无时钟,非阻塞赋值的 “延迟更新” 会导致out2读取out1的旧值,仿真易出现未知值(x),综合工具会报错或生成错误电路。
四、关键避坑规则
五、总结
- 阻塞赋值(=):立即更新、顺序执行,适配组合逻辑;
- 非阻塞赋值(<=):先读右值、时钟沿后同步更新,适配时序逻辑;
- 核心原则:按逻辑类型选择赋值方式,杜绝混用,避免竞争冒险与电路错误。


