A VHDL signal assignment is the basic statement that connects logic to a signal: target <= expression. It looks like an ordinary variable assignment, but it describes a continuous dataflow connection — the target signal continuously takes the value of the expression, just like a wire driven by gates in real hardware.
f <= (x1 AND x3) OR (x2 AND x4);The <= is the signal-assignment operator. Read it as “is driven by.” Whenever any input changes, the target re-evaluates.
Concurrent semantics
The defining property: all signal assignments in a VHDL architecture body run in parallel. There’s no order:
architecture LogicFunc of example2 is
begin
f <= (x1 AND x3) OR (x2 AND x4);
g <= (x1 OR NOT x3) AND (NOT x2 OR x4);
end architecture;Both f and g are assigned “simultaneously” in the hardware sense — every time the inputs change, both outputs re-evaluate. There’s no notion of “f’s assignment runs before g’s.” The order they appear in the source is irrelevant.
This matches actual hardware: a chip has both gates wired up, both responding to input changes in parallel. VHDL signal assignments describe that.
Signals as wires
A signal in VHDL is the abstraction for a wire. Signals can be declared between is and begin of an architecture (internal signals) or appear as ports in an entity.
architecture rtl of Q1 is
signal k : std_logic;
begin
k <= x1 AND x2;
f <= k AND NOT x1;
end architecture rtl;Here, k is an internal wire. The first assignment drives k; the second uses it.
Operators
The operators legal in signal-assignment expressions:
- Boolean:
AND,OR,NOT,NAND,NOR,XOR,XNOR. - Arithmetic (with appropriate types):
+,-,*,/,mod,rem. - Comparison:
=,/=,<,<=,>,>=. - Concatenation:
&for joining vectors.
Conditional assignments
A more elaborate form using when ... else:
f <= a when sel = '0' else b;This is a 2-to-1 MUX in dataflow style. Multiple conditions chain:
y <= "00" when state = idle
else "01" when state = read
else "10" when state = write
else "11";Equivalent to a tree of MUXes in hardware.
Selected signal assignment
Another conditional form, parallel to a case statement:
with sel select
f <= a when "00",
b when "01",
c when "10",
d when others;Synthesizes to one -to- MUX. Behaves identically to nested when ... else but reads more cleanly when one selector picks among many alternatives.
Variables vs signals (a subtle point)
Inside a process, you can also declare variables with := for assignment. Variables update immediately (sequential, like normal programming). Signal assignments inside a process don’t take effect until the process suspends — the new value is scheduled for the next delta cycle, a zero-time but ordered simulation step that runs after the process has finished executing. So if you write:
process(clk)
variable v : std_logic;
begin
v := a; -- variable updates now
s <= a; -- signal scheduled, takes effect at end of process
if v = s then -- v has new a; s still has its old value
...
end if;
end process;v already holds the new value, but s still reads as its previous value inside the same process activation. This is the classic trap: a chain of signal assignments to the same target inside a process keeps only the last assignment, because all of them schedule for the same delta cycle. Use a variable when you need an intermediate that updates immediately.
For most synthesizable designs, you use signals everywhere. Variables show up in process bodies for loop counters or temporary computations within a single process iteration.
For the surrounding container, see VHDL architecture. For the language overview, see VHDL.