Skip to content

VHDL · Chapter 1.8 · Foundation

The std_logic_1164 Package

Almost every VHDL file imports the standard logic package on its first line, and this lesson is what that line buys you. The standard logic type represents a single wire, and unlike a plain bit it carries nine values instead of two, so it can model the things real hardware actually does: tri-state buses, driver contention, uninitialised power-up, and weak pull-ups. You will learn what each value means in hardware, why this is a resolved type and why that is what makes buses possible, and what the package provides beyond the type itself. Understanding these values is what lets your design represent and detect the situations that actually go wrong on real wires, which a two-value type simply cannot describe.

Foundation14 min readVHDLstd_logicstd_logic_vectorTri-stateResolutionTypes

1. Intuition — a real wire is more than 0 and 1

If a wire could only ever be 0 or 1, a two-value type would be enough. But real wires do more: they can be left undriven (floating), fought over by two drivers, not yet powered up, or driven weakly through a pull-up resistor. A type that only knows 0 and 1 cannot describe any of that — and so cannot model real hardware or warn you when something is wrong.

std_logic is VHDL's answer: a single-bit type with nine possible values, chosen so that the situations a digital wire can actually be in each have a name. That is why it, not bit, is the type you use for essentially every signal in a real design.

2. The nine values

ValueNameHardware meaning
'0'Forcing 0strongly driven low (GND)
'1'Forcing 1strongly driven high (VDD)
'Z'High impedancenot driven — tri-state / released bus
'X'Forcing unknownconflict or unknown — cannot tell 0 or 1
'U'Uninitialisednever assigned yet (every signal's start value)
'W'Weak unknownweak conflict
'L'Weak 0weakly pulled low (pull-down)
'H'Weak 1weakly pulled high (pull-up)
'-'Don't carevalue is irrelevant (synthesis optimisation / matching)

The three you will meet constantly are '0'/'1' (normal logic), 'Z' (a driver that has let go of the wire), and 'X' (something is wrong — two drivers disagree, or a value is genuinely unknown). 'U' is what every signal is before it is first assigned, so seeing 'U' in a waveform usually means "you forgot to drive or reset this." The weak values ('L'/'H'/'W') model resistive pulls; '-' is a designer's "I don't care" for optimisation and case matching.

3. std_logic_vector — buses of std_logic

A bus is just many std_logic wires bundled together — that is std_logic_vector:

bus_decl.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
library ieee;
use ieee.std_logic_1164.all;
 
signal byte_bus : std_logic_vector(7 downto 0);   -- 8 wires, each a std_logic
signal one_bit  : std_logic;                       -- a single wire

Each element of the vector is a full nine-valued std_logic, so a bus can carry normal data, be released to 'Z' element-by-element, or show 'X' on exactly the bits that are in conflict. std_logic and std_logic_vector are the two types almost all RTL is written in.

4. Resolution — why std_logic can model a bus

Here is the deep reason nine values matter: std_logic is a resolved type. If two parts of a design drive the same signal, VHDL does not pick "the last one" — it runs a resolution function that combines the drivers into a single value. That is precisely how real wired buses behave, and it is why std_logic (not bit) can model them:

Two drivers onto one resolved std_logic netdriver Adrives '1'driver Breleased → 'Z'resolved net'1' vs 'Z' → '1'if both drive'0' vs '1' → 'X'12
std_logic is a resolved type: when two drivers share one wire, a resolution function combines them. A strong driver against a released ('Z') driver yields the strong value — the normal tri-state bus case. Two strong drivers that disagree ('0' against '1') resolve to 'X' — contention, which std_logic can represent and you can therefore catch. A two-valued type has no way to express either outcome.

A tri-state driver is written by choosing between a value and 'Z':

tri_state.vhd
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
-- drive the bus when enabled, otherwise let go (high-impedance)
bus_line <= data_out when enable = '1' else 'Z';

When every driver on the bus releases to 'Z' except one, resolution yields that one driver's value. If two drive opposite values at once, resolution yields 'X' — and now you can see the contention instead of getting a silent wrong answer.

5. The nine values over time

A waveform makes std_logic's extra states concrete in a way bit never could — watch a single bus wire move through uninitialised, driven, released, and contended:

One std_logic wire: U (power-up) → driven 0/1 → Z (released) → X (contention)

6 cycles
One std_logic wire: U (power-up) → driven 0/1 → Z (released) → X (contention)'U' — never driven yet (power-up)'U' — never driven yet…'Z' — driver released the bus'Z' — driver released …'X' — two drivers conflict'X' — two drivers conf…busXt0t1t2t3t4t5
The same wire is uninitialised, then strongly driven, then high-impedance, then in contention. A two-valued bit type can show none of U, Z, or X — which is exactly why real RTL uses std_logic.

6. What the package gives you

std_logic_1164 is more than the type. Importing it with use ieee.std_logic_1164.all; brings in:

  • the std_logic and std_logic_vector types (and their resolution),
  • the logic operators (and, or, not, xor, …) defined over them,
  • edge detectors rising_edge() and falling_edge() used in every clocked process,
  • conversions between std_logic/std_ulogic and related helpers.

That is why the package is the one line at the top of nearly every file: without it, the type your whole design is written in does not exist. (Arithmetic on vectors is a separate package — numeric_std — covered with the libraries lesson.)

7. Common mistakes & what to watch for

  • Using bit for real signals. It cannot express Z, X, or U, so it hides the very faults you need to see. Use std_logic.
  • Seeing 'U' and ignoring it. 'U' means never driven/reset — almost always a missing reset or an unconnected signal, not a harmless default.
  • Treating 'X' as random. 'X' is a signal of a problem — usually contention or an uninitialised value propagating. Trace it; do not mask it.
  • Reaching for tri-state ('Z') internally. On-chip, tri-state belongs at true shared buses and pads; inside a block, use a multiplexer, not 'Z'.

8. Summary & next step

std_logic is the standard single-wire type, and its nine values exist so VHDL can model what real wires do: 0/1 for normal logic, Z for tri-state, X for contention or unknown, U for uninitialised, and weak/don't-care states for pulls and optimisation. Because it is a resolved type, multiple drivers combine through a resolution function — which is what makes buses and contention representable, and is why RTL uses std_logic/std_logic_vector rather than bit. The std_logic_1164 package ships the type, its operators, and rising_edge/falling_edge.

You now have the foundations' core vocabulary — design units, entities, ports, libraries, and the std_logic type. The next lesson steps up to how a tool actually turns these files into a working design: compilation, elaboration, and the build flow.