Signals, Variables, and Constants
The three ways to store a value in VHDL: signal, variable, and constant — differences and usage.
The Three Storage Types
| Signal | Variable | Constant | |
|---|---|---|---|
| Declaration | Architecture area or port | Inside a process or subprogram | Architecture, package |
| Update | After delta-cycle (deferred) | Immediate | Never (read-only) |
| Scope | Entire architecture | Process only | Architecture or global |
| Synthesis | Wire or register | Temporary variable | Synthesis constant |
Signals
Signals are the wires of the circuit. They communicate between concurrent blocks.
architecture rtl of example is
-- Declaration in the architecture area
signal w_intermediate : std_logic;
signal r_counter : unsigned(7 downto 0) := (others => '0');
begin
-- Signal assignments are deferred
w_intermediate <= i_a AND i_b;
o_result <= w_intermediate OR i_c;
end architecture rtl;Deferred Update (Delta-Cycle)
A signal is not updated immediately after its assignment — it will be updated at the next delta-cycle:
process(i_clk)
begin
if rising_edge(i_clk) then
r_a <= '1';
r_b <= r_a; -- r_b receives the OLD value of r_a!
-- r_a and r_b are both updated after the process
end if;
end process;This simulates the real behavior of flip-flops: r_b follows r_a with a one-cycle delay.
Variables
Variables are temporary registers inside a process. Their update is immediate.
process(i_clk)
variable v_temp : unsigned(8 downto 0);
variable v_sum : unsigned(7 downto 0);
begin
if rising_edge(i_clk) then
v_temp := unsigned('0' & i_a) + unsigned('0' & i_b); -- immediate update
v_sum := v_temp(7 downto 0); -- v_temp already updated!
r_result <= std_logic_vector(v_sum);
end if;
end process;Key Difference: Signal vs Variable in a Process
process(i_clk)
variable v_x : std_logic;
begin
if rising_edge(i_clk) then
-- With variable (immediate update)
v_x := i_data; -- v_x takes i_data immediately
o_y <= v_x; -- o_y = i_data (synchronous, same cycle)
-- With signal (deferred)
-- w_x <= i_data;
-- o_y <= w_x; -- o_y = old value of w_x!
end if;
end process;Practical rule: use variables for intermediate calculations within a process. Use signals for communication between processes or blocks.
Constants
Constants are immutable values defined at compile time.
architecture rtl of uart is
constant c_CLK_FREQ : integer := 100_000_000; -- 100 MHz
constant c_BAUD_RATE : integer := 115_200;
constant c_DIVISOR : integer := c_CLK_FREQ / c_BAUD_RATE;
constant c_PREAMBLE : std_logic_vector(7 downto 0) := x"55";
begin
-- c_DIVISOR = 868 (computed at compile time)
end architecture rtl;Constants in Packages
To share constants between files:
package pkg_common is
constant c_DATA_WIDTH : integer := 8;
constant c_ADDR_WIDTH : integer := 16;
end package pkg_common;
-- In another file
use work.pkg_common.all;Decision Table
| Situation | Use |
|---|---|
| Communication between processes | Signal |
| Intermediate value in a process | Variable |
| Fixed value used everywhere | Constant |
| Component port | Signal (port) |
| Synthesizable counter or register | Signal with r_ prefix |
| Intermediate combinational calculation | Variable or w_ signal |
Recommended Prefixes
According to coding rules (course 07):
signal w_combinational : std_logic; -- w_ = wire, unregistered
signal r_registered : std_logic; -- r_ = registered, flip-flop
constant c_MAX : integer := 255; -- c_ = constant
variable v_temp : unsigned(7 downto 0); -- v_ = variable (internal use)