VHDL-Tutorial

VHDL = Very High Speed Integrated Circuit Hardware Description Language

Ein Projekt von Samuel Santa, Leo Waser, Kilian Jesacher, Gregor Havranek

1. Basiswissen über VHDL

1.1 Wie ist VHDL aufgebaut?

Eine VHDL-Datei besteht grundsätzlich ausfolgenden Elementen:

  • Entity (Schnittstelle)
  • Architecture (Implementierung)
  • Bibliotheken & Packages
  • Optional: Configurations, Testbenches

Entity:

Die Entity beschreibt nur die Außenseite einer Schaltung. Sie legt fest, welche Eingänge und Ausgänge es gibt und wie sie heißen. Dabei werden der Entity sogenannte Ports (Ein- und Ausgänge der Hardware) zugeordnet.

Architecture:

Die Architecture beschreibt, wie die Schaltung innen funktioniert. Jede Entity muss mindestens eine Architecture besitzen, die das Verhalten im Inneren beschreibt.

Bibliotheken und Packages:

Eine Bibliothek ist ein Speicherort, an dem Packages, Entities und Architekturen abgelegt werden. Es gibt bei VHDL zwei Arten von Bibliotheken:

  • Standardbibliotheken
  • Benutzerdefinierte Bibliotheken

Die wohl wichtigste Standardbibliothek ist wohl die IEEE-Bibliothek, die Packages wie std_logic_1164, numeric_std, math_real oder math_complex enthält.

Configurations und Testbenches:

Configurations und Testbenches werden nur für die Simulation von VHDL-Schaltungen benötigt und in Kapitel 4.3 genauer behandelt.

1.2 Unterschiede zu anderen Programmiersprachen

Merkmal Herkömmliche Programmiersprache (Software) VHDL (Hardwarebeschreibung)
Grundkonzept Beschreibung eines Algorithmus (Rechenvorschrift). Beschreibung einer Struktur oder Funktion von Hardware-Komponenten.
Ausführung Sequentiell: Befehle werden nacheinander (Schritt für Schritt) abgearbeitet. Parallel (Nebenläufig): Alle Anweisungen sind gleichzeitig aktiv (wie physische Bauteile).
Zielmedium Ein vorhandener Mikroprozessor führt den Code aus. Es entsteht eine reale digitale Schaltung (z. B. auf einem FPGA oder ASIC).
Ergebnis der Übersetzung Kompilierung: Erzeugt Maschinencode für eine CPU. Synthese: Erzeugt eine Netzliste aus Gattern, Flipflops und Leitungen.
Zeitverständnis Zeit spielt meist nur eine Rolle für die Performance (wie schnell läuft das Programm?). Timing ist kritisch: Signallaufzeiten und Taktflanken bestimmen die Funktion.
Variablen / Signale Variablen speichern Werte im Arbeitsspeicher. Signale repräsentieren reale elektrische Verbindungsdrähte.
Logikzustände Meist binär: 0 (False) und 1 (True). Mehrwertige Logik (z.B. std_ulogic): Erkennt auch Z (hochohmig) oder X (unbekannt).

1.3 Quartus Installation

Installation unter Linux

Vorbereitung

$ mkdir quartus.tmp
$ cd quartus.tmp

Download

Im Browser zum Download navigieren und den .tarball in quartus.tmp platzieren.

$ tar -xvf Quartus-web-13.1.0.162-linux.tar
$ sudo mkdir /usr/share/altera
$ sudo ./components/QuartusSetupWeb-13.1.0.162.run --mode text

Durch die Lizenz scrollen (Enter gedrückt halten) und mit y akzeptieren,
als Installations-pfad /usr/local/altera eingeben,
folgende Auswahl tätigen:

Select the components you want to install Quartus II Web Edition (Free) [Y/n] : y Quartus II Web Edition (Free) - Quartus II Software (includes Nios II EDS) (4017MB) : Y (Cannot be edited) Quartus II Web Edition (Free) - Quartus II Software 64-bit support (1189MB) [Y/n] :y Quartus II Web Edition (Free) - Devices [Y/n] :y Quartus II Web Edition (Free) - Devices - Cyclone III/IV (592.0MB) [Y/n] :y Is the selection above correct? [Y/n]: y

*Alle Optionen die hier nicht mit y aufgelistet sind, werden mit n beantwortet*

Modelsim manuell installieren

Modelsim kann nicht automatisch installiert werden, da der Installer eine 32bit GUI hat, welche inkompatibel mit modernen glibc Versionen ist.

$ sudo ./components/ModelSimSetup-13.1.0.162.run --mode text
[1] ModelSim-Altera Starter Edition: - License is not required. ... Please choose an option [1] : 1

Durch die Lizenz scrollen (Enter gedrückt halten) und mit y akzeptieren,
als Installations-pfad /usr/local/altera eingeben.

Startskript erstellen

$ sudo tee /usr/local/bin/quartus > /dev/null <<'EOF' #!/bin/bash export QUARTUS_ROOTDIR=/usr/local/altera/quartus export LD_LIBRARY_PATH=$QUARTUS_ROOTDIR/linux64:$QUARTUS_ROOTDIR/linux64/lib:$LD_LIBRARY_PATH $QUARTUS_ROOTDIR/bin/quartus EOF

Ausführbar machen

$ sudo chmod +x /usr/local/bin/quartus

udev Regeln für USB-Blaster

$ sudo tee /etc/udev/rules.d/51-usbblaster.rules > /dev/null <<'EOF' # Altera / Intel USB Blaster SUBSYSTEM=="usb", ATTR{idVendor}=="09fb", ATTR{idProduct}=="6001", MODE="0666" EOF
Installation unter Windows

Downloads

Lade die Setup-Datei und die Gerätebibliothek herunter:

QuartusSetupWeb-13.1.0.162.exe
cyclone_web-13.1.0.162.qdz
Wichtig: Speichere die .qdz-Datei unbedingt im selben Ordner wie die Setup-Datei. Der Installer erkennt die Hardware-Unterstützung (Cyclone-Geräte) so automatisch und bindet sie ein.

Software-Installation

Führe die Setup-Datei aus und folge dem Assistenten:

  • Willkommens-Bildschirm bestätigen


  • Lizenz akzeptieren ("I accept the agreement")


  • Pfad wählen (Standard: C:\altera\13.1)


  • Installation abschließen (Finish)


USB-Blaster Treiber

Öffne den Gerätemanager → Rechtsklick auf USB-Blaster → Treiber aktualisieren





Gib den Pfad C:\altera\13.1\quartus\drivers\usb-blaster ein und stelle sicher, dass der Haken bei "Unterordner einbeziehen" gesetzt ist.

Bestätige die Installation. Der USB-Blaster-Treiber ist nun konfiguriert und einsatzbereit.

1.4 VHDL Demoprogramm

Library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

Entity VHDL_demo IS
    Port(
        SW   : IN  STD_LOGIC_VECTOR (0 TO 9);
        LEDG : OUT STD_LOGIC_VECTOR (0 TO 9)
    );
END VHDL_demo;

ARCHITECTURE BEHAVIORAL OF VHDL_demo IS

BEGIN

    LEDG <= SW;

END BEHAVIORAL;

1.5 Aufbau von ASICs (PROM, PAL/GAL)

ASIC:

Ein ASIC (= Application-Specific Integrated Circuit) ist ein Chip, der das gewünschte logische Verhalten fix in seiner Hardware verbaut hat. Er ist sehr energieeffizient, schnell und klein, allerdings sehr teuer und aufwendig in der Produktion, was seine Anwendung für Prototypen praktisch ausschließt.

ASIC Chips Abbildung 1: ASIC Chips werden meist in großen Stückzahlen gefertigt

Für den Bau von Prototypen gibt es daher PROM, PAL und GAL. Alle drei dieser Bauteile gehören zur Gruppe der programmierbaren Logikbausteine (PLDs).
Hier folgt eine kurze Beschreibung zu den drei Bauteilen:

PROM:

PROM (= Programmable Read Only Memory) ist ein Bauteil, das im Grunde eine Wahrheitstabelle beinhaltet. Es besitzt ein festes AND-Array und ein programmierbares OR-Array. Die internen Verknüpfungen lassen sich nur einmal definieren und dann nicht mehr ändern.
Ein PROM ist also quasi ein Look-Up-Table, mit dem sich nur kombinatorische Logik realisieren lässt.

EPROM (ereasable PROM) ist im Vergleich zum PROM wiederbeschreibbar.

PAL:

PAL (= Programmable Array Logic) besitzt im Gegensatz zu PROM ein programmierbares AND-Array und ein fixes OR-Array. Ein PAL ist ebenfalls nur einmal programmierbar.
Seit der Entwicklung des PAL im Jahr 1978 sind viele Versionen auf dem Markt erschienen. So gibt es PALs mit internen NOR-Gattern, negierten Ausgängen oder sogar mit internen Registern, um sequentielle Logik zu ermöglichen.

PAL Bauteil Abbildung 2: PAL Bauteil

GAL:

GAL ist im Grunde eine Weiterentwicklung von PAL.
Er ist wiederbeschreibbar und enthält programmierbare Makrozellen, die dem GAL ermöglichen, die oben genannten PAL Architekturen in einem einzigen Bauteil zu vereinen.

1.6 FPGA

Platzhalter für Inhalte zu 1.6

1.7 Eingänge, Ausgänge, Vektoren, Signale

Eingänge & Ausgänge (I/O):

  • Eingänge (Inputs): Empfangen Daten von Sensoren oder anderen Bauteilen.
  • Ausgänge (Outputs): Geben berechnete Ergebnisse aus.
  • Bidirektional: Anschlüsse, die sowohl senden als auch empfangen können.
  • Tristate (Z): Ein spezieller Zustand ("hochohmig"), der einen Ausgang elektrisch komplett abkoppelt.

Signale:

  • Konzept: Interne Verbindungen ("Leitungen") zwischen Logikgattern.
  • Zustände:
    • 0 (Low/Falsch)
    • 1 (High/Wahr)
    • X (Unbekannt – meist bei Fehlern in der Simulation)
  • Verhalten: Ein Signal ändert seinen Wert basierend auf der Logik und hat oft eine minimale Zeitverzögerung (Propagation Delay).

Vektoren:

  • Konzept: Zusammenfassung mehrerer Signale zu einer logischen Einheit.
  • Vorteil: Erhöht die Übersichtlichkeit und vereinfacht die Adressierung großer Datenmengen.
  • Notation: Angabe der Breite durch Indizes, z. B. Bus[7:0] für ein 8-Bit-Signal.
  • Beispiele:
    • Datenbus: Überträgt ganze Zahlen oder Buchstaben.
    • Adressbus: Bestimmt, wo Daten gespeichert werden.

1.8 Wichtiges zum DE0-Board

Wichtigste Anschlüsse:

  • USB-Blaster: Programmierung & Stromversorgung via PC.
  • VGA: Video-Ausgang.
  • GPIO: Zwei 40-Pin Leisten für externe Hardware.

Wichtigste Pins (Eingänge):

  • CLOCK_50: Interner 50 MHz Takt.
  • SW(0 to 9): 10 Schiebeschalter.
  • BUTTON(0 to 3): 4 Taster.

Wichtigste Pins (Ausgänge):

  • LEDG(0 to 9): 10 grüne LEDs.
  • HEX0 bis HEX3: 4x 7-Segment-Anzeigen.
    • Achtung: Low-Aktiv (Pegel '0' = Segment leuchtet).
    • Bus-Struktur: (0 to 6) entspricht den Segmenten gfedcba.

Hardware-Kern:

  • FPGA: Intel Cyclone III (SRAM-basiert, flüchtig).


2. Kombinatorische Logik

2.1 Beispiel zur Kombinatorischen Logik

Library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

Entity VHDL_demo IS
    Port(
        SW   : IN  STD_LOGIC_VECTOR (0 TO 9);
        LEDG : OUT std_logic_vector(0 to 9)
    );
END VHDL_demo;

ARCHITECTURE BEHAVIORAL OF VHDL_demo IS
    signal tmp : std_logic_vector(0 to 9);
BEGIN

    tmp(0) <= SW(0) or SW(1);
    tmp(1) <= SW(2) or SW(3);
    tmp(2) <= tmp(0) and tmp(1);
    tmp(4 TO 9) <= SW(4 TO 9);
    LEDG <= tmp;

END BEHAVIORAL;

2.2 Demonstration des Codes

3. Sequenzielle Logik

3.1 Beispiel zur sequenziellen Logik

Sequentielle Logik in VHDL beschreibt Schaltungen mit einem Speicher (z.B.: Flipflops)
Um in VHDL eine Sequentielle Anweisung zu machen muss man es innerhalb einem PROCESS-Block schreiben.

Die Reihenfolge dafür ist:

  1. Einen PROCESS mit clk und rst definieren.
  2. Einfügen von der RST-Logik
  3. Taktflanken-Abfrage einfügen: rising_edge(clk)
  4. Die Schaltungslogik innerhalb der Taktflanken Abfrage

Zwei wichtige Zuweisungsarten die in der sequentiellen Logik notwendig sind ist:

  • Signale werden am ende des PROCESS mit <= zugewiesen.
  • Variablen werden mit := zugewiesen.
library ieee;
use ieee.std_logic_1164.all;

entity VHDL_demo is
    port (
        CLOCK_50 : in  std_logic;
        HEX0_D, HEX1_D, HEX2_D, HEX3_D : out std_logic_vector(0 to 7)
    );
end entity;

architecture rtl of VHDL_demo is
    type msg_array is array (0 to 12) of std_logic_vector(0 to 7);
    constant MESSAGE : msg_array := (
        "10010001", -- H
        "01100001", -- E
        "11100011", -- L
        "11100011", -- L
        "11000101", -- O
        "11111111", -- space
        "10101011", -- W
        "11000101", -- O
        "11110101", -- r
        "11100011", -- L
        "10000101", -- d
        "11111111", -- space
        "11111111"  -- space
    );

    signal counter : integer := 0;
    signal i : integer range 0 to 10 := 0;

begin

    process(CLOCK_50)
    begin
        if rising_edge(CLOCK_50) then
            if counter = 6000000 then
                counter <= 0;
                if i = 13 then
                    i <= 0;
                else
                    i <= i + 1;
                end if;
            else
                counter <= counter + 1;
            end if;
        end if;
    end process;

    HEX3_D <= MESSAGE(i);
    HEX2_D <= MESSAGE((i + 1) mod 13);
    HEX1_D <= MESSAGE((i + 2) mod 13);
    HEX0_D <= MESSAGE((i + 3) mod 13);

end architecture;

3.2 Demonstration des Codes

4. Erweiterte Themen

4.1 std\_logic & std\_ulogic

In VHDL sind std_logic und std_ulogic die am meisten verwendeten Datentypen für den Entwurf von Schaltungen sowie für die Simulation. Sie sind nach dem IEEE 1164 genormt.
Beide Datentypen haben einen gewissen Wertebereich:

Wertebereich IEEE 1164

Der Unterschied zwischen std_logic und std_ulogic:
Der entscheidende Unterschied liegt in der sogenannten Resolution Function.

  • std_ulogic: Es darf pro Signal nur genau ein Treiber (Zuweisung) existieren. Mehrere Zuweisungen an dasselbe Signal führen bereits beim Kompilieren zu einem Fehler. Dies hilft, unbeabsichtigte Kurzschlüsse im Design frühzeitig zu erkennen.
  • std_logic: Es sind mehrere Treiber für ein Signal zulässig. Wenn beispielsweise ein Treiber '0' und ein anderer 'Z' liefert, bestimmt die Resolution Function, dass das Ergebnis '0' ist. Liefern zwei Treiber unterschiedliche starke Werte (z. B. '0' und '1'), resultiert daraus der Zustand 'X'.

Beispiel-Code zu std_logic und std_ulogic:

4.2 Simulation von VHDL-Schaltungen

Platzhalter für Inhalte zu 4.2

4.3 Hierarchische Verschaltung von Blöcken

In VHDL bezieht sich hierarchisches Design auf die Aufteilung einer komplexen digitalen Schaltung in kleinere, Teilaufgaben oder Funktionsblöcke. Diese Blöcke werden unabhängig voneinander definiert und anschließend über Signale miteinander verknüpft, um das Gesamtsystem zu bilden.

Das Grundprinzip von Anarchie in VHDL:

  1. Grundaufteilung:
    Eine Große Schaltung wird in mehrere kleine teile unterteil: (Zähler, Multiplexer) sodass man die einzelnen Blöcke voneinander unabhängig getestet werden können.
  2. Verknüpfung von den einzelnen Blöcken:
    Die Signale zwischen den einzelnen Blöcken oder zwischen den Prozessen innerhalb einer Architektur erfolgen über Lokale Signale. Innerhalb einer Architektur werden die Blöcke parallel abgearbeitet.

Wesentliche Vorteile von so einer Struktur sind:

  • Große Schaltungen werden nicht so unübersichtlich da sie in wichtige gruppen unterteilt ist.
  • Gut designte Blöcke können in andere Designs wiederverwendet werden.
  • Die einzelnen Blöcke können einzeln getestet werden.