VUnit 101: Praktischer Leitfaden für automatisierte VHDL-Verifikation
VUnit ist ein führendes Open-Source VHDL-Verifikationsframework, das einen Python-Test-Suite-Runner mit einer dedizierten VHDL-Bibliothek koppelt. Zusammen automatisieren sie Testbench-Kompilierung, Ausführung und Ergebnisberichterstattung, sodass Ingenieure einen testgetriebenen Entwicklungszyklus verfolgen können.
In diesem Tutorial führt Ahmadmunthar Zaklouta, der Autor hinter VHDLwhiz, Sie durch den gesamten VUnit-Workflow – von Installation und Konfiguration über Testbench-Erstellung, Testfall-Schreiben bis hin zur Ausführung in ModelSim. Ein sofort ausführbares Beispielprojekt steht zum Download bereit.
Überblick
Nutzen Sie die Sidebar oder den mobilen Navigationsbutton, um zwischen Abschnitten zu springen. Das Tutorial enthält Screenshots als visuelle Referenz.
Voraussetzungen
- Intel ModelSim – Kostenlos installieren wie hier beschrieben. Zum System
PATHhinzufügen. - Python 3.6+ – Herunterladen und zu
PATHhinzufügen. - Git (optional) – Herunterladen.
- Windows Terminal (optional) – Herunterladen.
Grundlegende VHDL- und ModelSim-Kenntnisse werden vorausgesetzt.
VUnit installieren
Repository mit Submodulen klonen:
git clone --recurse-submodules https://github.com/VUnit/vunit.git
Oder ZIP herunterladen, nach C:\vunit entpacken, dann installieren via:
cd C:\vunit python setup.py install
Umgebungsvariablen konfigurieren:
VUNIT_MODELSIM_PATH– Pfad zum ModelSim Executable.VUNIT_SIMULATOR– AufModelsimsetzen.
Beispiel-Screenshot:

Beispielprojekt herunterladen
ZIP nach C:\vunit_tutorial entpacken und enthaltene Skripte ausführen.
Einführung in VUnit
VUnit vereinfacht HDL-Verifikation durch Bereitstellung von:
- Einer Python-Bibliothek für Testautomatisierung, Konfiguration und Administration.
- Einer VHDL-Bibliothek mit wiederverwendbaren Verifikationskomponenten.
Die VHDL-Seite umfasst sechs Bibliotheken; dieses Tutorial fokussiert auf logging und check.

Design Under Test (DUT)
Das Beispiel-DUT, motor_start, steuert drei LEDs (ROT, GELB, GRÜN) zur Darstellung einer Motor-Startsequenz. Seine Schnittstelle nutzt Record-Typen für Ein- und Ausgänge.

Der Startprozess hat drei Schritte:
- Konfiguration laden (ROTE LED)
- Kalibrierung (GELBE LED)
- Rotation (GRÜNE LED)
Startsequenz
- ROTE LED – Blinkt fünfmal, dann dauerhaft an.
- GELBE LED – Schaltet nach Schalter 2 für zehn Zyklen ein, dann aus zusammen mit ROT.
- GRÜNE LED – Leuchtet solange Schalter 3 aktiv ist.
Testbench-Entwicklung
- Python
run.pySkript konfigurieren. - VUnit-Gerüst aufbauen.
- DUT instantiieren und Signale treiben.
Python Run Script
Das run.py Skript definiert Pfade, erstellt eine VUnit-Instanz und fügt Design- und Testbench-Bibliotheken hinzu:
# ROOT directory ROOT = Path(__file__).resolve().parent # Source paths DUT_PATH = ROOT / "design" TEST_PATH = ROOT / "testbench" # VUnit instance VU = VUnit.from_argv() VU.enable_location_preprocessing() # Libraries design_lib = VU.add_library("design_lib") design_lib.add_source_files([DUT_PATH / "*.vhdl"]) tb_lib = VU.add_library("tb_lib") tb_lib.add_source_files([TEST_PATH / "*.vhdl"])
VUnit-Gerüst
In der Testbench-Entity VUnit-Kontext und ein obligatorisches Generic hinzufügen:
LIBRARY VUNIT_LIB; CONTEXT VUNIT_LIB.VUNIT_CONTEXT; ENTITY motor_start_tb IS GENERIC(runner_cfg : string := runner_cfg_default); END ENTITY motor_start_tb;
Die Architektur beherbergt den Test-Runner-Prozess:
ARCHITECTURE tb OF motor_start_tb IS test_runner : PROCESS BEGIN test_runner_setup(runner, runner_cfg); WHILE test_suite LOOP -- test cases END LOOP; test_runner_cleanup(runner); END PROCESS; END ARCHITECTURE;
Individuelle Testfälle werden mit IF run("case_name") THEN Blöcken definiert.
Signaldeklarationen & DUT-Instantiierung
Takte, Resets und Interface-Records definieren:
CONSTANT C_CLK_PERIOD : time := 10 ns; SIGNAL clk, reset : STD_LOGIC := '0'; SIGNAL motor_start_in : MOTOR_START_IN_RECORD_TYPE := (switch_1 => '0', switch_2 => '0', switch_3 => '0'); SIGNAL motor_start_out : MOTOR_START_OUT_RECORD_TYPE;
DUT instantiieren:
motor_start_tb_inst : ENTITY DESIGN_LIB.motor_start(rtl) PORT MAP( clk => clk, reset => reset, motor_start_in => motor_start_in, motor_start_out => motor_start_out );
Takt und Reset treiben:
clk <= NOT clk after C_CLK_PERIOD / 2; reset <= '0' after 5 * (C_CLK_PERIOD / 2);
Testfall-Entwicklung
Wir erkunden drei Verifikationsstile: Inline Driver & Checker, Controlled Checker, Self-Checking Checker.
Inline Driver & Checker
Ein simpler Testfall, der switch_1 treibt und LED-Zustände mit VUnits check-Familie prüft:
IF run("switch_1_on_output_check") THEN WAIT UNTIL reset = '0'; WAIT UNTIL falling_edge(clk); motor_start_in.switch_1 <= '1'; FOR i IN 0 TO 4 LOOP WAIT UNTIL rising_edge(clk); check(motor_start_out.red_led = '1', "Red LED should be on"); check_false(motor_start_out.yellow_led, "Yellow LED should be off"); check_equal(motor_start_out.green_led, '0', "Green LED should be off"); END LOOP; END IF;
Controlled Checker
Hier bleibt der Driver im Testfall, während der Checker in einem separaten Prozess läuft, gesteuert durch Start/End-Events. Beispiel: Verifikation der GELBEN LED nach Aktivierung von switch_2:
check_stable(clock => clk, en => enable, start_event => yellow_low_start_event, end_event => yellow_low_end_event, expr => motor_start_out.yellow_led, msg => "YELLOW LED low before switch_2");
Self-Checking Checker
Verifikationslogik in einem dedizierten Prozess kapseln, der check oder check_stable intern nutzt. Eine Driver-Prozedur vereinfacht Stimulus:
PROCEDURE switch_driver( SIGNAL switches : OUT MOTOR_START_IN_RECORD_TYPE; CONSTANT clk_period : IN TIME; CONSTANT sw1_delay : IN INTEGER; CONSTANT sw2_delay : IN INTEGER; CONSTANT sw3_delay : IN INTEGER) IS BEGIN IF sw1_delay >= 0 THEN WAIT FOR clk_period * sw1_delay; switches.switch_1 <= '1'; END IF; IF sw2_delay >= 0 THEN WAIT FOR clk_period * sw2_delay; switches.switch_2 <= '1'; END IF; IF sw3_delay >= 0 THEN WAIT FOR clk_period * sw3_delay; switches.switch_3 <= '1'; END IF; END PROCEDURE;
Tests ausführen
Aus dem Terminal:
python .\run.py *switch_1_on_output_check
VUnit kompiliert das Design, entdeckt Testbenches und führt den spezifizierten Fall aus. Ausgabe wird in C:\vunit_tutorial\vunit_out\test_output geloggt.
Nutzen Sie -v für verbose Logs, -l um alle Fälle aufzulisten, --clean um vorherige Ergebnisse zu löschen, oder -g um ModelSim mit Waveform-Fenster zu starten (benötigt wave.do Datei).
Zusammenfassung
VUnit bietet ein robustes, leichtes Framework, das sowohl Design- als auch Verifikationsteams beschleunigt. Sein Python-getriebener Test-Harness, reiche VHDL-Bibliotheken und flexible Checker-API machen es zu einer wertvollen Ergänzung jedes HDL-Workflows.
Nächste Schritte
- Lesen Sie die offizielle Dokumentation.
- Verfolgen Sie den VUnit Blog für Updates.
- Treten Sie der Community auf Gitter bei.
Laden Sie das vollständige Beispielprojekt über das untenstehende Formular herunter.
VHDL
- Code-Ready Containers: Praktischer Leitfaden für Cloud-native Prozessautomatisierung mit Red Hat OpenShift
- Praktischer Leitfaden zu keramischem 3D-Druck: Techniken, Materialien, Design-Tipps
- Basisfarbstoffe (Basic Dyes) verstehen: Anwendungen, Sicherheit & Branchenanwendungen
- TJBot starten: Bauen, konfigurieren und per Sprache steuern
- Schritt-für-Schritt: RAK 831 LoRa Gateway auf Raspberry Pi 3 deployen
- LoRa-Gateway mit RAK831-Modul auf Raspberry Pi 3 bauen – Schritt-für-Schritt-Anleitung
- IoT im Edge-Zeitalter: Wachstum, Daten, Sicherheit und Partnerstrategie
- KI in der Versicherung: Ein praxisnaher Starter-Guide für die reale Umsetzung
- Arduino Einsteiger Tutorial #1: Erstes Projekt (Blink)
- Cat®-Maschinen optimieren: Der ultimative My.Cat.com-Leitfaden