VHDL · Chapter 2.5 · Data Types
Resolved vs Unresolved Types
Some VHDL types allow a wire to have several drivers and some do not, and that single difference is what separates the standard-logic type from its unresolved base type. The resolved type permits multiple drivers and combines them through a resolution function, which is why two fighting drivers quietly settle to an X value. The unresolved base type allows only one driver, so a second one is illegal and the tool reports it at compile time. Both types carry the same nine values and differ only in this rule. This lesson explains the distinction, why a language needs both, and the practical payoff: the unresolved type turns an accidental double-drive into an error you cannot miss instead of a silent X.
Foundation13 min readVHDLstd_logicstd_ulogicResolutionMultiple DriversTypes
1. Intuition — who is allowed to drive this wire?
Every wire in a design has drivers — the processes or assignments that set its value. The question a type answers here is: how many drivers may a single wire have?
- A resolved type allows many drivers and defines a resolution function to combine
them into one value.
std_logicis resolved — which is exactly why a tri-state bus (many drivers, one at a time) works, and why two fighting drivers produce'X'instead of a compile error. - An unresolved type allows one driver, full stop. A second driver is an error
caught at compile/elaboration time.
std_ulogic(theuis for unresolved) is the unresolved base type, andstd_logicis its resolved subtype.
So the two types describe the same nine values; they differ only in whether multiple drivers are permitted and resolved or forbidden and flagged.
2. The distinction, drawn
There is no waveform on this page: the difference is a compile-time legality rule, not a timing behaviour. (The runtime side — two resolved drivers combining by strength over time — is the resolution waveform you already saw in lesson 2.2.) Here the teaching artifact is the type relationship, not a signal trace.
3. The resolution function — what "resolved" actually does
When a resolved signal has more than one driver, the simulator does not pick one — it calls a resolution function that takes all the driver values and returns a single result, using the strength model from lesson 2.2:
- a forcing driver beats a weak one,
- a weak driver beats
'Z'(a released driver), - two forcing drivers that disagree resolve to
'X'.
This is what makes a real bus work: every driver releases to 'Z' except the active one, so
resolution returns the active driver's value. The same function is also what turns an
accidental second driver into 'X' — useful, but only if you notice the 'X'.
4. Vectors too — std_logic_vector vs std_ulogic_vector
The same pairing exists for buses: std_logic_vector is resolved (each element is a
resolved std_logic), and std_ulogic_vector is unresolved. In modern VHDL (2008 onward)
std_logic_vector is defined as the resolved subtype of std_ulogic_vector, so the two
interoperate, and either can carry a bus. The choice is the same one: should the elements
permit multiple drivers, or forbid them?
library ieee;
use ieee.std_logic_1164.all;
signal sig_r : std_logic; -- resolved: a 2nd driver resolves (to 'X' on conflict)
signal sig_u : std_ulogic; -- unresolved: a 2nd driver is a COMPILE error
signal bus_r : std_logic_vector(7 downto 0); -- resolved bus (the everyday choice)
signal bus_u : std_ulogic_vector(7 downto 0); -- unresolved bus (single-driver enforced)5. Debugging example — a silent X vs a loud error
Suppose two processes accidentally drive the same single-bit signal. The type decides whether you find out at compile time or in a waveform hunt:
-- With std_logic (resolved): COMPILES. At runtime, when both drive,
-- the signal shows 'X' — you must spot it in simulation and trace it.
signal busy : std_logic;
busy <= '1' when state = ACTIVE else '0'; -- driver 1
busy <= sensor_flag; -- driver 2 (accidental) → resolves to 'X'
-- With std_ulogic (unresolved): the SAME two drivers are rejected at
-- elaboration: "signal busy has multiple sources / drivers".
signal busy_u : std_ulogic;With the resolved type, the mistake is a runtime 'X' you might chase for an hour. With
the unresolved type, it is a compile-time error naming the over-driven signal. That is the
practical value of unresolved types: they convert a class of silent bugs into immediate
errors.
6. When to use each
std_logic/std_logic_vector— the default for almost everything, and required anywhere a wire genuinely has multiple drivers (tri-state buses, shared lines). Convention across most code bases.std_ulogic/std_ulogic_vector— when you want the tool to guarantee a signal has exactly one driver, so an accidental second driver is impossible to ship. Some teams use them by default for internal signals precisely for this extra safety.
Either way, the values, operators, and behaviour are identical for a correctly single-driven signal — the choice only changes what happens to a second driver.
7. Common mistakes & what to watch for
- Believing
std_logicprevents double-drives. It does not — it resolves them, often to'X'. Only an unresolved type rejects them. - Chasing an
'X'that is really contention. A persistent'X'on a resolved signal is often a second, unintended driver; switching that signal tostd_ulogicwill name the culprit at compile time. - Thinking they are different value sets.
std_logicandstd_ulogichave the same nine values; only multi-driver legality differs. - Mixing the families carelessly pre-2008. Modern VHDL makes them interoperate as subtypes; very old code may need explicit handling — prefer a 2008-aware flow.
8. Engineering insight
Resolved and unresolved types are two answers to one design rule: should this wire be
allowed more than one driver? Buses need "yes," so std_logic resolves. Most internal
signals should have exactly one driver, and there "no" is safer — std_ulogic makes the
accidental second driver a compile error instead of a 'X' you have to discover. The 'X'
from lesson 2.2 and the "multiple drivers" error here are the same bug seen through the two
type choices: one defers it to simulation, the other catches it at build.
9. Summary & next step
std_logic is a resolved type (multiple drivers allowed, combined by a resolution
function using strength), and std_ulogic is its unresolved base (a second driver is a
compile error). Same nine values, different multi-driver legality. Resolved enables buses
and hides accidental double-drives as 'X'; unresolved forbids them and flags the mistake
early. The vector forms (std_logic_vector / std_ulogic_vector) mirror the choice.
The chapter now turns from logic-valued types to numbers. The next lesson covers VHDL's abstract whole-number type — integer types and ranges — and why constraining an integer's range is what makes it synthesize to the right number of bits.