Skip to content

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

the standard opening
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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, + - arithmetic
  • library ieee; declares that you intend to use the ieee library. (You never write library work; or library std; — they are always implicitly visible.)
  • use ieee.std_logic_1164.all; imports every name (.all) from the std_logic_1164 package: the std_logic type, std_logic_vector, rising_edge, and the logic operators on them. Without it, the type std_logic is simply unknown.
  • use ieee.numeric_std.all; imports the unsigned and signed types 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:

my_types_pkg.vhd — a small shared package
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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;
using it in another file
Azvya Education Pvt. Ltd.VLSI Mentor
Snippet
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:

A source file importing packages from the ieee and work librariesmy_design.vhduse ... allstd_logic_1164std_logic, vectornumeric_stdunsigned, signedmy_types_pkgyour shared declslibrary ieeestandard shelflibrary workyour shelf12
A source file imports packages from libraries. The ieee shelf provides std_logic_1164 (std_logic, std_logic_vector) and numeric_std (unsigned, signed, arithmetic); the work shelf holds your own packages. Each `use ...all` pulls that package's names into the file's scope so they can be written unqualified. This is pure compile-time name resolution — it decides what the compiler can see, and produces no signals or timing.

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 word subtype or a protocol record, defined once and used by every block, so widths never drift.
  • ConstantsBUS_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;. Then std_logic is undefined and the file will not compile — the classic first error.
  • Writing library std_logic_1164;. std_logic_1164 is a package, not a library. The library is ieee; the package is imported with use.
  • Mixing numeric_std with the legacy *_arith packages. Pick numeric_std and stay consistent, or you invite ambiguous-overload and portability problems.
  • Expecting use to compile the package for you. use only 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.