JanusHDL

Libraries

Last updated: 2026-10-29

A VHDL design lives in libraries: std and ieee for the standard packages, work for your own units by default, and named libraries for anything you want to keep apart. This chapter describes what is built into JanusHDL, how to make libraries of your own, and how to use the verification libraries UVVM, OSVVM and VUnit.

How JanusHDL handles libraries

JanusHDL analyzes from source: each run analyzes the files you name, into the libraries you name, and then elaborates and runs. A library is simply the name you give a group of files, with --work, a library line in a file list, or a library statement in a project.

What makes this fast enough for large libraries is the cache: --cache FILE keeps the analysis and loads it on the next run while no file changed (Caching the analysis).

Two things keep a record of a library's files on disk. jhdl lib compile does so for UVVM and OSVVM, so that a design finds them without listing their files (UVVM and OSVVM, compiled once). The front ends for existing scripts do so for each library, as the commands they stand in for are expected to (Running existing scripts).

Built-in libraries

These libraries are built in. You use them as you always would, with library ieee; and use clauses, and you never analyze them yourself. Their sources are in the vhdl folder of the download, to read (The VHDL sources folder).

STD

Package Contents
std.standard The predefined types and operations
std.textio Text input and output, with the VHDL-2008 and VHDL-2019 additions (sread, hwrite, justify, flush, tee, ...)
std.env stop, finish, resolution_limit, and the VHDL-2019 additions: environment variables, date and time, directories, the call path, file name and line, and the assertion API
std.reflection VHDL-2019 type reflection ('reflect)

IEEE

From IEEE's official sources of the IEEE 1076-2019 packages, unmodified:

Package Contents
std_logic_1164 std_ulogic, std_logic and their vectors
numeric_std, numeric_bit signed and unsigned arithmetic
numeric_std_unsigned, numeric_bit_unsigned Arithmetic on std_ulogic_vector and bit_vector as unsigned numbers
math_real, math_complex Real and complex mathematics
fixed_pkg, fixed_generic_pkg, fixed_float_types Fixed-point types sfixed and ufixed
float_pkg, float_generic_pkg Floating-point types
std_logic_textio Kept for designs that use it; in VHDL-2008 its routines are part of std_logic_1164
ieee_std_context, ieee_bit_context The standard contexts
vital_timing, vital_primitives VITAL (IEEE 1076.4), for simulation libraries of FPGA and ASIC cells that use it

Designs analyzed as VHDL-1993 or VHDL-2002 get the VHDL-93 forms of std_logic_1164, numeric_std and numeric_bit, made from the same sources with the interface of those versions: in them, std_logic_vector, unsigned and signed are types of their own, as designs of that time expect. Their sources are in vhdl/ieee93.

The functions of math_real give exact results where the result is representable: 10.0 ** 2.0 is 100.0 and log(1000.0, 10.0) is 3.0.

Legacy arithmetic packages

Many existing designs use packages that are not IEEE standards but that tools have long placed in library ieee. They are built in too, unchanged, under their own notice (vhdl/legacy/NOTICE.txt):

Package Contents
ieee.std_logic_arith signed and unsigned arithmetic of its own, conv_integer, conv_std_logic_vector, ...
ieee.std_logic_unsigned, ieee.std_logic_signed Arithmetic on std_logic_vector as an unsigned or a signed number
ieee.std_logic_misc Reduction functions such as and_reduce and or_reduce
ieee.std_logic_textio The VHDL-93 text routines for std_logic (read, hread, hwrite, ...), for VHDL-1993 and VHDL-2002 designs

A design that uses them from library ieee runs as it is, in any VHDL version:

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;   -- built in: nothing to compile

For new code, ieee.numeric_std (or numeric_std_unsigned) is the standard way.

Your own libraries

Give a library a name in any of three ways:

  • on the command line: --work util src/util_pkg.vhd (Libraries);
  • in a file list: a line library util before the files (File lists);
  • in a project: library util, with an optional VHDL version for the whole library (Projects).

Then use it as VHDL does:

library util;
use util.util_pkg.all;

Inside the files of a library, work means that library. Library names are not case-sensitive.

If a design uses a library into which nothing was analyzed, the error says so, and what to do:

error[undeclared]: `util_pkg` is not declared in `util`
 --> tb.vhd:2:5
  |
2 | use util.util_pkg.all;
  |     ^^^^^^^^^^^^^
  = help: library `util` has no design units yet: analyze its sources into it first, before the files that use it
  = LRM 8.3

UVVM and OSVVM, compiled once

Instead of listing UVVM's or OSVVM's files with every design, you can compile your copy once:

jhdl lib compile uvvm UVVM
jhdl lib compile osvvm OsvvmLibraries
jhdl lib list
jhdl lib remove uvvm

jhdl lib compile analyzes your copy and keeps a record of it in a folder of your own: %LOCALAPPDATA%\JanusHDL\libraries on Windows, ~/.cache/janushdl/libraries on Linux. The environment variable JHDL_LIBRARIES chooses another folder. For UVVM, give the folder with its script folder; it is read through its compile orders. For OSVVM, give the OsvvmLibraries folder; it is read through its build scripts.

From then on, a design that names one of their libraries (library uvvm_util;, context osvvm.OsvvmContext;) finds it without listing its files: in every jhdl run, in the window and in the language server. The files of the units the design uses are analyzed as it uses them, each as its library is. UVVM is analyzed in compatibility mode, which its shared variables need, whatever your design's mode. A testbench of your own that uses UVVM's utility library then runs on its own, without --compat: jhdl my_tb.vhd.

  • Your copy stays in use. The record points to its files, and each run reads them. Keep the copy where it is, and compile again after you update or move it; a file that can no longer be read is reported, with what to do.
  • A design that lists a library's files, in a file list or a project, uses those instead, and for UVVM needs --compat as before.
  • jhdl lib list shows what is compiled and from where. jhdl lib remove uvvm (or osvvm) forgets it and leaves your copy alone.
  • Neither compiled nor listed. A design that names such a library is told the command that compiles it:

text error[undeclared]: `uvvm_util_context` is not declared in `uvvm_util` --> tb.vhd:2:9 | 2 | context uvvm_util.uvvm_util_context; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: library `uvvm_util` has no design units yet: compile UVVM once from your copy with `jhdl lib compile uvvm FOLDER`, or analyze its sources before the files that use it = LRM 8.3 - Analysis time. Each run analyzes the units it uses from your copy. --cache keeps that analysis between runs and notices when a file of your copy changes (Caching the analysis).

UVVM

UVVM is not part of JanusHDL: you get it from its own project, so you have the version you choose, and either compile it once (UVVM and OSVVM, compiled once) or analyze its sources with your design. All of UVVM analyzes in compatibility mode, and UVVM's demo testbenches run and pass.

UVVM needs compatibility mode. UVVM keeps a few settings in shared variables whose types are not protected, which VHDL-2002 and later forbid. Without compatibility mode each is an error, and the analysis fails; with it each is a warning, and UVVM runs as written (What to expect). Compiled once, UVVM is analyzed in compatibility mode whatever your design's mode, and your commands need no --compat. When you list UVVM's files with your design, as the commands below do, give --compat; in a project, write compat on.

Getting UVVM

git clone https://github.com/UVVM/UVVM.git

or download a release from the UVVM project and unpack it.

UVVM's libraries

UVVM is a set of libraries, each in a folder of its own: uvvm_util (the utility library: logging, alerts, checks, randomization, coverage), uvvm_vvc_framework (the framework for verification components), bitvis_vip_scoreboard, and one library per verification component, such as bitvis_vip_uart or bitvis_vip_axistream. Analyze them in this order, each with the libraries it needs before it:

  1. uvvm_util
  2. uvvm_vvc_framework (for verification components, VVCs)
  3. bitvis_vip_scoreboard (the VVCs use it)
  4. the verification components you use
  5. your design and testbench

The file script/component_list.txt in the UVVM folder lists every component in an order that works.

File lists from UVVM's compile orders

Each UVVM component has a file script/compile_order.txt that lists its files in analysis order, relative to that script folder, under a first line # library NAME. With that first line made into a library line, it is a JanusHDL file list. In the UVVM folder, on Linux or in Git Bash:

for c in $(tr -d '\r' < script/component_list.txt | grep -v '^#'); do
  sed 's/^# *library/library/' $c/script/compile_order.txt > $c/script/$c.f
done

or in PowerShell:

foreach ($c in Get-Content script\component_list.txt) {
  (Get-Content "$c\script\compile_order.txt") -replace '^# *library', 'library' |
    Set-Content "$c\script\$c.f"
}

This writes uvvm_util/script/uvvm_util.f and the others. A testbench that uses only the utility library then runs with:

jhdl --compat -f UVVM/uvvm_util/script/uvvm_util.f -f my_tb.f --top work.my_tb

and one that uses verification components with all the libraries it needs, in order. For example, UVVM's interrupt controller demo, from the UVVM folder (its testbench is in the component's tb folder, which its compile order does not list, so a one-line list adds it):

printf 'library bitvis_irqc\n../tb/irqc_demo_tb.vhd\n' > bitvis_irqc/script/demo.f
jhdl --compat \
     -f uvvm_util/script/uvvm_util.f \
     -f uvvm_vvc_framework/script/uvvm_vvc_framework.f \
     -f bitvis_vip_scoreboard/script/bitvis_vip_scoreboard.f \
     -f bitvis_vip_sbi/script/bitvis_vip_sbi.f \
     -f bitvis_irqc/script/bitvis_irqc.f \
     -f bitvis_irqc/script/demo.f \
     --top bitvis_irqc.irqc_demo_tb

It ends with UVVM's verdict, and JanusHDL's summary with the time each phase took:

UVVM:      >> Simulation SUCCESS: No mismatch between counted and expected serious alerts
simulation of bitvis_irqc.irqc_demo_tb ended at 3.4325 µs (stopped); analysis ...

These commands were tried with the UVVM release of April 2026.

The verification components' compile orders also list a few files of uvvm_vvc_framework/src_target_dependent: those files are analyzed into each component's own library, as UVVM intends. Keep them where the compile order puts them.

UVVM in a project

In a project, list the same files under library statements, before your own:

jhdl-project 1
std 2008

library uvvm_util
  source ../UVVM/uvvm_util/src/types_pkg.vhd
  source ../UVVM/uvvm_util/src/adaptations_pkg.vhd
  # ... the rest of uvvm_util's compile order
library work
  source src/my_design.vhd
  source tb/my_tb.vhd

top work.my_tb
compat on

The easy way to write it: make a file list of everything, then File → Import a file list (.f) as a project… in the window.

With UVVM compiled once, the project lists only your own files and needs no compat on:

jhdl-project 1
std 2008

library work
  source src/my_design.vhd
  source tb/my_tb.vhd

top work.my_tb

What to expect

  • Compatibility mode. UVVM keeps a few settings in shared variables that are not of a protected type. VHDL-2002 and later allow only protected types there (LRM 6.4.2.4), so without --compat each is an error, and the help says what to do:

text error[unprotected-shared-variable]: a shared variable must be of a protected type, not T_LOG_DESTINATION --> uvvm_util/src/string_methods_pkg.vhd:31:3 | 31 | shared variable shared_default_log_destination : t_log_destination := C_DEFAULT_LOG_DESTINATION; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: wrap the value in a protected type, or analyze the file as VHDL-93 (--std 93); or run with --compat, which accepts it and simulates it as written = LRM 6.4.2.4

Each is reported once, where it is, and the last line says how many there are and that --compat accepts them; the units that use those packages report nothing more. With --compat, each is a warning (42 of them for the UART demo), and the run is not affected. To leave the warnings out as well, add --allow unprotected-shared-variable (or allow unprotected-shared-variable in a project). With UVVM compiled once, neither the errors nor the warnings appear in your runs. - In the window and in editors. With UVVM compiled once, the window and the language server find it and analyze it in compatibility mode themselves. When your design lists UVVM's files, tick Compatibility mode in the Run dialog, or set compat on in the project; for the language server, set its compat option (Options). - Logs. UVVM prints its log as text output, which appears in the terminal and on the standard output, and also writes UVVM_Log.txt and UVVM_Alert.txt into the current folder. Run each testbench in a folder of its own if you run several at once. - Speed. Analysis of UVVM takes a moment on every run. Use --cache with a file per testbench (Caching the analysis). - Errors on purpose. A testbench that checks error handling may make its design report errors on purpose. UVVM then says SUCCESS, because it expected them, while jhdl exits with 1, because a report of severity error came up. Raise the exit level for such a testbench: --exit-level failure.

OSVVM

OSVVM is not part of JanusHDL either: get it from its own project, and compile it once (UVVM and OSVVM, compiled once) or analyze its sources with your design. OSVVM's own regression suite passes on JanusHDL: 314 of 314 tests. OSVVM needs no compatibility mode.

git clone --recursive https://github.com/OSVVM/OsvvmLibraries.git

Compiled once, jhdl lib compile osvvm OsvvmLibraries reads OSVVM's build scripts itself, its verification component libraries (osvvm_common, osvvm_uart, osvvm_axi4 and the others) included, and a testbench that names osvvm runs with jhdl my_tb.vhd. To list the files with your design instead:

OSVVM's build scripts (.pro files) choose some files by simulator and VHDL version. For JanusHDL with VHDL-2008, the osvvm library is these files, in this order (paths relative to the OsvvmLibraries folder):

library osvvm
osvvm/IfElsePkg.vhd
osvvm/OsvvmTypesPkg.vhd
osvvm/SetGetBoundedGenericPkg.vhd
osvvm/SetGetBoundedPkg_Instances.vhd
osvvm/OsvvmScriptSettingsPkg.vhd
osvvm/OsvvmScriptSettingsPkg_default.vhd
osvvm/OsvvmSettingsPkg.vhd
osvvm/OsvvmSettingsPkg_default.vhd
osvvm/TextUtilPkg.vhd
osvvm/FileUtilPkg.vhd
osvvm/ResolutionPkg.vhd
osvvm/NamePkg.vhd
osvvm/OsvvmGlobalPkg.vhd
osvvm/CoverageVendorApiPkg_default.vhd
osvvm/NameStorePkg.vhd
osvvm/TranscriptBasePkg.vhd
osvvm/deprecated/LanguageSupport2019Pkg_c.vhd
osvvm/deprecated/FileLinePathPkg_c.vhd
osvvm/deprecated/AssertApiPkg_c.vhd
osvvm/AlertLogPkg.vhd
osvvm/IdFifoPtPkg.vhd
osvvm/TbUtilPkg.vhd
osvvm/MessageListPkg.vhd
osvvm/SortListPkg_int.vhd
osvvm/RandomBasePkg.vhd
osvvm/RandomPkg.vhd
osvvm/RandomProcedurePkg.vhd
osvvm/CoveragePkg.vhd
osvvm/CoveragePtPkg.vhd
osvvm/DelayCoveragePkg.vhd
osvvm/ResizePkg.vhd
osvvm/deprecated/DynamicVectorPkg_IntV_c.vhd
osvvm/deprecated/DynamicVectorPkg_slv_c.vhd
osvvm/ScoreboardGenericPkg.vhd
osvvm/ScoreboardPkg_IntV.vhd
osvvm/ScoreboardPkg_slv.vhd
osvvm/ScoreboardPkg_int.vhd
osvvm/ScoreboardPkg_signed.vhd
osvvm/ScoreboardPkg_unsigned.vhd
osvvm/MemorySupportPkg.vhd
osvvm/MemoryGenericPkg.vhd
osvvm/MemoryPkg.vhd
osvvm/TranscriptPkg.vhd
osvvm/ReportPkg.vhd
osvvm/deprecated/RandomPkg2019_c.vhd
osvvm/ClockResetPkg.vhd
osvvm/OsvvmContext.vhd

Save it as osvvm.f in the OsvvmLibraries folder. The _default package bodies are the ones OSVVM's scripts use when they do not generate their own. The list was made from OSVVM as of October 2026; if your version has added or moved a file, its osvvm/osvvm.pro script shows where (and the error for a missing file names it). OSVVM's verification component libraries (osvvm_common, osvvm_uart, osvvm_axi4 and the others) follow in the same way, each from its own build.pro.

A testbench then uses the context as usual:

library osvvm;
context osvvm.OsvvmContext;
jhdl -f OsvvmLibraries/osvvm.f -f my_tb.f --top work.my_tb

OSVVM writes its reports (.yml files and others) into the current folder.

VUnit

VUnit is a Python test runner with VHDL libraries of its own. It runs on JanusHDL through VUnit's own package for JanusHDL, vunit-janushdl, which needs VUnit 5.0.0.dev16 or later. VUnit 5 is a pre-release, so install both with --pre:

pip install --pre "vunit_hdl>=5.0.0.dev16" vunit-janushdl

In run.py, add the package before the calls that depend on the simulator, and select JanusHDL with the environment variable VUNIT_SIMULATOR=janushdl:

vu.add_package("vunit-janushdl", allow_setup=True)

VUnit then analyzes its own libraries (vunit_lib and the rest) with your sources, and runs each test case in a simulation of its own; nothing needs compiling first. --gui records a test's waveform and opens it in jhdlw. A design that needs compatibility mode gets --compat through VUnit's option janushdl.a_flags; the package uses those flags for both analysis and simulation.

With VUnit 4.x, run.py scripts still run unchanged through one of the front ends in the compat folder: you put that folder first on your PATH and select it in VUnit as you would select a simulator.

VUnit in the chapter on existing scripts gives the exact settings.

Libraries from other tools

Simulation libraries delivered as VHDL sources, such as the cell and primitive libraries of FPGA and ASIC tools, are analyzed like any other library: name the library and list its files. Those that use VITAL find ieee.vital_timing and ieee.vital_primitives built in.

Libraries delivered only in a tool's own compiled form, or as encrypted (IEEE 1735) sources, cannot be used: JanusHDL needs the VHDL text, and does not decrypt protected code yet.