VHDL · Chapter 2.2 · Data Types
The Nine Values of std_logic
Module 1 introduced the standard logic type as a nine-valued wire type and listed what each value means. This lesson explains the system behind those nine values, a strength model in which forcing levels beat weak levels, which in turn beat high-impedance. That single idea is what lets the type resolve multiple drivers on one wire, propagate an unknown through logic to flag trouble, and mark anything never driven as uninitialised. A transistor drives a wire hard, a pull resistor drives it gently, and an undriven wire drives it not at all, and the strongest driver present wins. Understanding strengths turns the nine values from a table to memorise into a model you can reason with about resolution and contention.
Foundation15 min readVHDLstd_logicResolutionStrengthX-propagationTypes
1. Intuition — strength, not just value
In Module 1 you saw the nine values — '0' '1' 'Z' 'X' 'U' 'W' 'L' 'H' '-' — and what
each means. The deeper idea is that they are organised by strength: how hard a
driver is pushing on the wire. A real wire driven by a transistor pushes hard; the same
wire pulled by a resistor pushes gently; an undriven wire pushes not at all.
std_logic encodes exactly this. The values split into forcing (strong),
weak (resistive), and high-impedance (no drive), plus two non-electrical markers.
Strength is what decides what happens when more than one driver touches the same wire —
and that is the whole reason the type exists.
2. The strength hierarchy
Group the nine values by how hard they drive, strongest first:
- Forcing —
'0','1','X'. A transistor actively pulling the wire.'0'and'1'are clean strong drives;'X'is a forcing unknown — strongly driven, but the simulator cannot tell to what (typically because two forcing drivers disagree). - Weak —
'L','H','W'. A pull-down/pull-up resistor or a weak conflict. These set the wire only when nothing forcing is present. - High-impedance —
'Z'. The driver has let go; the wire floats.'Z'loses to any real drive — which is exactly how a tri-state bus releases the line for someone else. 'U'and'-'. Not electrical levels:'U'is the power-on value of any signal never assigned, and'-'is a don't-care you write to let synthesis optimise.
3. How each value arises in hardware
'0'/'1'— a gate or driver outputs a clean logic level.'Z'— a tri-state driver is disabled (bus <= data when oe = '1' else 'Z';), so the wire is undriven and free for another driver.'X'— two forcing drivers fight (one says'0', one says'1'); the result is a real electrical contention the simulator reports as unknown.'U'— a signal that was never reset or driven; seeing it means "this has no defined value yet."'L'/'H'— a pull-down / pull-up resistor gently holds a line at 0 / 1 when nothing is actively driving it.
4. Strength decides resolution — over time
When two drivers share one wire, std_logic is a resolved type: a resolution function
combines the drivers using strength. The waveform makes the rule concrete — watch one net
with two drivers a and b as their strengths change:
Resolution by strength on one shared net (a and b both drive 'net')
8 cyclesThis is why std_logic (and not bit) is used for buses: only a value set with strengths
can express "driven", "released", "pulled", and "fought over" on the same wire.
5. X-propagation — unknown is contagious (on purpose)
A forcing 'X' is not random; it is unknown, and unknown spreads through logic. If one
input to a gate is 'X', the output is 'X' whenever that input could change the result:
y <= a and b;
-- a = 'X', b = '1' -> y = 'X' (a could be 0 or 1, so y is unknown)
-- a = 'X', b = '0' -> y = '0' (0 forces the AND low regardless of a)That propagation is a feature: an 'X' that reaches an output is the simulator tracing an
unknown back to its source for you. Masking it (forcing it to '0') throws away the very
signal that locates the bug.
6. Debugging example — an X on a result signal
You run a simulation and a data signal shows 'X' partway through. Read it as a strength
story:
'X'from cycle zero, never recovering → usually contention: two processes or drivers assign the same signal, fighting forcing values. Search for the second driver.'X'appearing after a'U'→ an uninitialised value propagated into logic; the real fault is a missing reset upstream, not the gate showing'X'.'X'only on some bits of a vector → contention or unknown on exactly those bit positions — narrow the search to the drivers of those bits.
The discipline: do not "fix" the 'X' at the output — trace it upstream to the forcing
conflict or the 'U' that produced it.
7. Common mistakes & what to watch for
- Treating
'X'as a value to clamp.'X'is a diagnostic; clamping it to'0'hides the contention or missing reset that caused it. - Confusing
'Z'and'X'.'Z'is no drive (intentional, on a bus);'X'is conflicting drive (a fault). They look similar in a list and mean opposite things. - Ignoring
'U'.'U'is the loudest possible "no reset / not driven" signal — never background noise. - Using weak values (
'L'/'H') on purpose inside a chip. Pull strengths model board resistors and pads; on-chip RTL should drive forcing values and use multiplexers, not resistive pulls.
8. Engineering insight
The nine values are not nine arbitrary symbols — they are a small, complete model of what a
wire can do, ordered by how hard it is being driven. Once you see them as forcing > weak >
Z, plus U and '-', resolution stops being a lookup table and becomes obvious: the strongest
driver present wins, and disagreement among equals is 'X'. That model is also a debugging
map — every stray 'X' or 'U' points back along the strength chain to its cause.
9. Summary & next step
std_logic's nine values encode a strength model: forcing (0 1 X) beats weak
(L H W) beats high-impedance (Z), with U for uninitialised and '-' for don't-care.
Strength decides multi-driver resolution, X propagates to flag unknowns, and U/X are
diagnostics that point to their own causes. This is the electrical realism std_logic buys
over a two-value type.
Which raises the natural question: if std_logic is so capable, why does VHDL also have
bit and boolean? The next lesson compares the three — and shows when each is the right
type to reach for.