Verilog阻塞与非阻塞赋值:关键区别详解
阻塞赋值
阻塞赋值使用=符号,在过程块中按顺序依次执行。但不会阻止并行块中语句的执行。
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a = 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
b = 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c = 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
d = 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
e = 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
两个initial块在仿真开始时并行执行。每个块内语句顺序执行,两块均在0ns完成。变量先赋值,随后执行显示语句,然后执行其他赋值。首个$display时和
非阻塞赋值
非阻塞赋值使用<=符号,允许调度赋值而不阻塞后续语句执行。同一时间步的所有非阻塞赋值右侧值先被捕获,时间步结束时统一赋给左侧变量。
module tb;
reg [7:0] a, b, c, d, e;
initial begin
a <= 8'hDA;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
b <= 8'hF1;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
c <= 8'h30;
$display ("[%0t] a=0x%0h b=0x%0h c=0x%0h", $time, a, b, c);
end
initial begin
d <= 8'hAA;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
e <= 8'h55;
$display ("[%0t] d=0x%0h e=0x%0h", $time, d, e);
end
endmodule
所有$display均打印'h'x,因为非阻塞赋值在时间步结束前不更新变量。这是建模时序逻辑、避免竞争冒险的关键机制。
核心区别总结
- 阻塞赋值:即时更新,适合组合逻辑建模
- 非阻塞赋值:延迟更新,适合时序逻辑建模,避免竞态条件
- 同一时间步内,非阻塞赋值的RHS先捕获,时间步结束统一更新LHS
Verilog
- Verilog基础:设计你的第一个与门
- Verilog 入门:数字电路设计完整教程
- 掌握 Verilog 拼接操作:实用指南
- 深入理解 Verilog 赋值语句:类型、语法与最佳实践
- 掌握Verilog函数:高效RTL设计的复用利器
- 理解Verilog任务:函数vs任务、语法与用法全解析
- Verilog 时钟发生器设计与实现指南
- 掌握 Verilog 数学函数:高效硬件设计的利器
- 掌握 Verilog $timeformat:精度控制与显示格式化
- 理解与打印 Verilog 任意作用域下的 Timescale
- 掌握 Verilog 文件 I/O:打开、读取、写入和关闭
- Verilog 入门指南:Hello World 示例