理解 VHDL 中信号与变量的区别
上一教程探讨了如何在进程内声明变量。变量适合局部算法工作,但无法在进程外被看到。当需要与其他设计部分共享值时,应使用信号。
信号声明在架构的声明区域——即 architecture <architecture_name> of <entity_name> is 与 begin 关键字之间。
本文属于基础 VHDL 教程系列。
声明信号的语法:signal <name> : <type>;
信号可选带初始值:signal <name> : <type> := <initial_value>;
练习
本视频教程教你如何声明信号,并发现变量与信号的核心区别。
本教程创建的最终代码:
entity T06_SignalTb is end entity;
architecture sim of T06_SignalTb is
signal MySignal : integer := 0;
begin
process is
variable MyVariable : integer := 0;
begin
report "*** Process begin ***";
MyVariable := MyVariable + 1;
MySignal <= MySignal + 1;
report "MyVariable=" & integer'image(MyVariable) & ", MySignal=" & integer'image(MySignal);
MyVariable := MyVariable + 1;
MySignal <= MySignal + 1;
report "MyVariable=" & integer'image(MyVariable) & ", MySignal=" & integer'image(MySignal);
wait for 10 ns;
report "MyVariable=" & integer'image(MyVariable) & ", MySignal=" & integer'image(MySignal);
end process;
end architecture;
ModelSim 仿真控制台输出:
VSIM 2> run # ** Note: *** Process begin *** # Time: 0 ns Iteration: 0 Instance: /t06_signaltb # ** Note: MyVariable=1, MySignal=0 # Time: 0 ns Iteration: 0 Instance: /t06_signaltb # ** Note: MyVariable=2, MySignal=0 # Time: 0 ns Iteration: 0 Instance: /t06_signaltb # ** Note: MyVariable=2, MySignal=1 # Time: 10 ns Iteration: 0 Instance: /t06_signaltb # ** Note: *** Process begin *** # Time: 10 ns Iteration: 0 Instance: /t06_signaltb # ** Note: MyVariable=3, MySignal=1 # Time: 10 ns Iteration: 0 Instance: /t06_signaltb # ** Note: MyVariable=4, MySignal=1 # Time: 10 ns Iteration: 0 Instance: /t06_signaltb # ** Note: MyVariable=4, MySignal=2 # Time: 20 ns Iteration: 0 Instance: /t06_signaltb ...
分析
我们创建了初始值均为 0 的信号和变量。尽管在进程中对它们做相同操作,控制台输出揭示了截然不同的行为。关键差异:
- 变量用
:=运算符,在进程内立即更新。 - 信号用
<=运算符;新值被调度,仅在进程挂起(如遇wait语句)时生效。 - 信号在进程恢复前被多次赋值,只有最后一次赋值“生效”,因为早先调度的值被覆盖。
示例中,MySignal 前两次递增因在 wait for 10 ns; 前被覆盖而丢失。后续递增在挂起后出现,符合预期行为。
要点
- 需立即、本地更新的临时值用变量。
- 需向其他进程或组件传递变化用信号。
- 记住信号赋值是调度的,仅在进程暂停时提交;无暂停的多次赋值仅最后一个值生存。
进入下一教程 »
VHDL