VHDL · Chapter 1.7 · Foundation
Libraries and the use Clause
Every VHDL file opens with a few lines about libraries and use clauses, and most beginners copy them without knowing what they do. This lesson demystifies them. A library is a named shelf of already-compiled design units, the library keyword makes a shelf visible, and the use clause imports names from a package so you can write short names instead of a long qualified path. You will see where the standard-logic type actually comes from, why the numeric package is the right home for arithmetic, what the work library means for your own code, and why packages are how a design shares its types, constants, and functions across many files. By the end these opening lines will make sense instead of being magic you paste in.
Foundation13 min readVHDLLibrariesuse clauseieeenumeric_stdPackages
1. Intuition — shelves of compiled parts
When a tool analyses your VHDL, it does not leave the results in your .vhd file — it
files each compiled design unit onto a named shelf called a library. A library is
simply a collection of already-compiled units (entities, architectures, packages) that
other code can refer to by name.
Two shelves are always in the room. work is your shelf — everything you compile
lands there by default. ieee is the standard shelf the tool vendor ships,
holding the packages that define std_logic, vector arithmetic, and more. A use
clause is how you say "reach onto that shelf and bring these names into scope so I do
not have to spell out the full path every time."
2. The two lines you write in almost every file
library ieee; -- make the ieee shelf visible
use ieee.std_logic_1164.all; -- bring in std_logic, std_logic_vector, ...
use ieee.numeric_std.all; -- bring in unsigned, signed, + - arithmeticlibrary ieee;declares that you intend to use theieeelibrary. (You never writelibrary work;orlibrary std;— they are always implicitly visible.)use ieee.std_logic_1164.all;imports every name (.all) from thestd_logic_1164package: thestd_logictype,std_logic_vector,rising_edge, and the logic operators on them. Without it, the typestd_logicis simply unknown.use ieee.numeric_std.all;imports theunsignedandsignedtypes and their arithmetic. This is the standard, portable way to do math on vectors.
You could instead write the fully qualified name every time —
ieee.std_logic_1164.std_logic — but nobody does; the use clause exists precisely so
you can write std_logic.
3. Reaching your own shelf — work.<pkg>.all
Anything you compile is on work. When you collect shared definitions into a package
and want them in another file, you import them the same way — just from work:
library ieee;
use ieee.std_logic_1164.all;
package my_types_pkg is
constant BUS_W : integer := 16; -- shared constant
subtype word is std_logic_vector(BUS_W-1 downto 0); -- shared type
end package my_types_pkg;library ieee;
use ieee.std_logic_1164.all;
use work.my_types_pkg.all; -- bring BUS_W and `word` into scope
entity datapath is
port (
a : in word; -- `word` came from your package
y : out word
);
end entity datapath;Because the package is on work, you reach it with work.my_types_pkg.all. The
ieee packages live on the ieee shelf; yours live on work. Same mechanism, two
shelves.
4. Visibility, not timing — the right artifact
A use clause changes what names are visible while compiling, so the honest way to
picture it is a visibility diagram, not a waveform. Each source file declares which
shelves it sees and which packages it imports; the compiler then resolves every type
and function name against those imports:
There is deliberately no waveform here: libraries and use clauses resolve names
before simulation exists. A waveform would teach nothing about visibility.
5. Why packages matter
Packages are why libraries are useful. A package is a shared header that holds types, constants, and functions so a whole project agrees on them in one place:
- Types — a
wordsubtype or a protocol record, defined once and used by every block, so widths never drift. - Constants —
BUS_W, address maps, opcode encodings: change the value in the package, every file follows. - Functions — helpers like a parity reduction, written once and called everywhere.
std_logic_1164 and numeric_std are just very well-known packages on the ieee
shelf — the same idea you use for your own shared definitions on work. (Authoring
packages in depth — the package body, compile order, visibility rules — is its own
later lesson; here you only need to know what a use clause is reaching for.)
6. Common mistakes & what to watch for
- Forgetting
use ieee.std_logic_1164.all;. Thenstd_logicis undefined and the file will not compile — the classic first error. - Writing
library std_logic_1164;.std_logic_1164is a package, not a library. The library isieee; the package is imported withuse. - Mixing
numeric_stdwith the legacy*_arithpackages. Picknumeric_stdand stay consistent, or you invite ambiguous-overload and portability problems. - Expecting
useto compile the package for you.useonly makes names visible; the package must already be analysed into its library first (the subject of the next lesson).
7. Summary & next step
A library is a named shelf of compiled units: work is yours, ieee is the
standard one. library makes a shelf visible and use imports a package's
names into scope — pure compile-time resolution, which is why a visibility diagram, not
a waveform, is the right picture. In nearly every file you import std_logic_1164 and
numeric_std; your own shared types and constants travel the same way via
work.<pkg>.all.
That phrase "the package must already be analysed first" is the hinge into the next lesson: compilation, elaboration, and the build flow — the order in which units are analysed into libraries, how an entity binds to its architecture, and why getting the order wrong produces "cannot find unit" errors.
Standards & specifications
- Governing standard
- IEEE Std 1076 (VHDL)(opens IEEE in a new tab)
Defines the VHDL language — types, the simulation cycle, and the semantics a conforming analyser and simulator must implement. Synthesis restrictions and vendor coding rules are tool behaviour, not language rules.
This page also covers RTL structure, verification approach and debugging technique. Those are engineering practice built on the standard, not requirements the standard itself imposes.
Where this fits
Part of the VHDL curriculum.