Signals, Variables, and Constants

The three ways to store a value in VHDL: signal, variable, and constant — differences and usage.

The Three Storage Types

SignalVariableConstant
DeclarationArchitecture area or portInside a process or subprogramArchitecture, package
UpdateAfter delta-cycle (deferred)ImmediateNever (read-only)
ScopeEntire architectureProcess onlyArchitecture or global
SynthesisWire or registerTemporary variableSynthesis 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

SituationUse
Communication between processesSignal
Intermediate value in a processVariable
Fixed value used everywhereConstant
Component portSignal (port)
Synthesizable counter or registerSignal with r_ prefix
Intermediate combinational calculationVariable 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)