VHDL Tutorials

Farben-Legende

FPGA & Board Themen
VHDL Sprache
ASIC & Hardware
Logik & Gatter
Design & Simulation
Häufige Fehler

Was sind FPGAs?

FPGA = Field-Programmable-Gate-Array

Halbleiterbausteine, die auf einer Matrix aus konfigurierbaren Logikblöcken basieren, die über programmierbare Zwischenverbindungen miteinander verbunden sind. Sie sind integrierte Schaltkreise, deren Logik und Verbindungen man auch nach der Herstellung noch umprogrammieren und verändern kann.

Vorteile FPGA:

- Flexibilität: Man kann sie jederzeit vor Ort umprogrammieren.
- Parallele Verarbeitung: Die Hardware-Struktur ist so optimiert, dass FPGAs ohne Probleme Aufgaben hochspezialisiert und parallel ausführen können und so eine höhere Rechenleistung haben.
- Schnelle Markteinführung: Die Programmierbarkeit ermöglicht Entwicklern, Designs schnell zu testen und zu iterieren, was die Time-to-Market verkürzt.

Anwendungsbereiche:

- Telekommunikation
- Automobiltechnik
- Luft- und Raumfahrt
- Datenverarbeitung (z. B. Hochleistungsrechnen, maschinelles Lernen)
- Signalverarbeitung
- Industrielle Steuerungssysteme

Wichtigstes zum DE0-Board, z.B. Anschluss, etc.

Das DE0-Board ist eine Lern- und Entwicklungsplattform für FPGA's:

Der Hauptzweck des Boards ist es, eine zugängliche Plattform zu sein,
um die Grundlagen der digitalen Logik,des synchronen Schaltungsentwurfs und 
von Hardwarebeschreibungssprachen zu lernen.
Es dient als Testumgebung, auf der digitale Schaltungen direkt
in Hardware implementiert werden und getestet werden können, anstatt nur simuliert zu werden.

Sein Kernstück ist ein Altera Cyclone III FPGA:

Das Herzstück des Boards ist der programmierbare Chip selbst.
Dieser Chip sorgt für eine gute Balance aus Kapazität für komplexe
Projekte und einfacher Handhabung.

Anschlüsse:

Das DE0-Board hat eine Vielzahl von integrierte I/O Anschlüsse die sofortiges Feedback und Interaktion bieten. Man kann die Designs sofort visualisieren und steuern:

    DIP-Schalter und Taster als manuelle digitale Eingaben
    LED's und 7-Segment-Anzeigen als direkte visuelle Ausgaben
    VGA- und Audio-Anschlüsse für komplexe Multimedia-Projekte

Diese I/O-Elemente ermöglichen es komplexe Projekte ohne externe Hardware umzusetzen.

Installation von notwendiger FPGA-Software

Installation Quartus II

Link : luke.htlinn
1. QuartusSetupWeb-13.1.0.162.exe herunterladen (nicht installieren)
2. cyclone_web-13.1.0.162.qdz  in das selbe Verzeichnis herunterladen
3. QuartusSetubWeb installieren
4. ModelSim installieren

Installer ModelSim-Altera

ModelSim-Altera Installer

WICHTIG, USB-Blaster Installieren

USB-Blaster Installer

Anlegen eines FPGA-File / Projektes

Erstellung / Kompilierung eines VHDL-FILE

1. Quartus starten und neues Projekt erstellen:

2. Name und Ordner Auswählen:

3. Device mit Einstellungen hinzufügen:

Konfiguration Fertig!

Neues Projekt/File (File->Neu->FPGA-File)

ModelSim-Altera Installer

4. VHDL code hinzufuegen:

5. Den richtigen Top-level entity eingeben. ==> steht im code.

6. Compilen

7. Pin Planner Öffnen

8. Die Location von den Pins den einzelnen Variablen zuweisen:

9. Die Richtigen PINS findet man in der Betriebsanleitung:

10. Programmer öffnen:

11. Mit add File die SOF Datei hinzufügen :

12. Fertig, auf Start drücken

Installation ModelSim

Schritt 1

ModelSim Schritt 1

Schritt 2

ModelSim Schritt 2

Schritt 3

ModelSim Schritt 3

Schritt 4

ModelSim Schritt 4

Was ist VHDL?

VHDL = Very-High-Speed-Integrated-Circuit-Hardware-Description-Language

Unterschiede VHDL zu anderen Programmiersprachen:

Bibliotheken und use-Klauseln:
Werden zu Beginn eingebunden
• Entitäten
  Sind Schnittstellen in der Hardware
• Architekturen
  Interne Struktur und Verhalten von Entitäten
• Prozesse
  Ein VHDL-Code, der auf Ereignisse reagiert
• Signale und Variablen
  Signale: Kommunikation zwischen Komponenten und Prozessen
  Variablen: lokal in Prozessen
• Konstrukte und Operatoren
  Logische Operatoren (AND, OR, NOT)
  Vergleichsoperatoren (=, <, >)
  Mathematische Operatoren (+, -, *)
• Synchronisation
  Getaktete Logik
• Modularität
  Mit Entitäten und Architekturen, eigenständige Komponenten
    

Wie ist VHDL aufgebaut:

• Bibliotheken und use-Klauseln
• Entitäten (Interfaces)
• Architekturen (Interne Struktur)
• Prozesse (Reaktion auf Ereignisse)
• Signale & Variablen
• Konstrukte & Operatoren
• Getaktete / Synchrone Logik
• Modularer Aufbau durch Komponenten
    

Eingänge-/Ausgänge, Vector, Signale:

Eingänge sind Komponenten, die Signale oder Daten an das FPGA-Logikarray senden, typischerweise gesteuert durch den Benutzer oder externe Quellen.

Diese Signale könnten sein:

• DIP-Switches
• Taster
• Clock Signal

Ausgänge:

Ausgänge sind Komponenten, die Signale vom FPGA empfangen und in einer für den Benutzer sichtbaren oder nutzbaren Weise darstellen.

Diese können dargestellt werden durch:

• LED's 
• 7-Segment-Anzeigen
• VGA-Anschluss
• Videoausgang

Vector und Signale:

In VHDL sind Signale grundlegende Kommunikationswege, sie entsprechen Drähten in realen Schaltungen. Ein Vektor ist eine Gruppierung mehrerer zusammengehöriger Signale in einer einzigen benannten Einheit. Dies vereinfacht die Handhabung im Code erheblich, da man beispielsweise den Zustand aller Schalter in einer einzigen Zuweisungsanweisung den LEDs zuweisen kann.

VHDL-Befehle und Logik

VHDL (VHSIC Hardware Description Language) dient zur Beschreibung digitaler Schaltungen. Es kombiniert strukturelle Beschreibung, sequentielle Abläufe und kombinatorische Logik.

1. Datentypen

Datentypen definieren, welche Art von Informationen ein Signal oder eine Variable speichern kann.

  • STD_LOGIC: 1-Bit, 9-wertig (0, 1, Z, X, …)
  • STD_LOGIC_VECTOR: Mehrbit-Signale (z. B. 7 downto 0)
  • INTEGER: Ganzzahlen
  • SIGNED / UNSIGNED: Arithmetische Vektoren
  • BIT / BIT_VECTOR: Einfache 0/1-Signale
signal data  : STD_LOGIC_VECTOR(7 downto 0);
signal flag  : STD_LOGIC;
variable cnt : integer := 0;

2. Wichtige Befehle

Library-Einbindung

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

If / Elsif / Else

if a = '1' then
    y <= '1';
elsif b = '1' then
    y <= '0';
else
    y <= 'Z';
end if;

Case

case sel is
    when "00" => y <= a;
    when "01" => y <= b;
    when others => y <= '0';
end case;

with … select (Multiplexer)

with sel select
    y <= a when "00",
         b when "01",
         c when "10",
         '0' when others;

Process

process(clk)
begin
    if rising_edge(clk) then
        q <= d;
    end if;
end process;

Entity & Architecture

entity example is
    Port (
        a : in  STD_LOGIC;
        y : out STD_LOGIC
    );
end example;

architecture Behavioral of example is
begin
    y <= a;
end Behavioral;

Signal vs. Variable

  • Signal: Global, Aktualisierung verzögert
  • Variable: Lokal im Prozess, sofortige Aktualisierung
signal s : STD_LOGIC;
variable v : integer := 0;

Signalzuweisungen

-- Kombinatorisch
y <= a AND b;

-- Mit Verzögerung (nur Simulation)
y <= a after 5 ns;

3. Operatoren

  • Logisch: AND, OR, NOT, XOR, NAND, NOR
  • Arithmetisch: +, −, *, / (SIGNED, UNSIGNED)
  • Vergleich: =, /=, <, >, <=, >=
  • Konkatenation: &
  • Bereiche: downto, to
y <= "1" & x(2 downto 0);

Schleifen in VHDL

In VHDL existieren verschiedene Arten von Schleifen. Sie werden hauptsächlich im sequentiellen Kontext, also innerhalb von process-Blöcken, eingesetzt. Zusätzlich gibt es das generate-Statement, das ähnlich einer Schleife Hardwarestrukturen vervielfacht.

For-Schleife

Iteriert über einen festen Bereich. Der Loop-Parameter wird implizit deklariert. Bei Synthese entsteht aus einer for ... loop keine Ablauf-Schleife, sondern parallele Hardware.

[Label:] for ... in ... loop
    -- ...
end loop [Label];

While-Schleife

Wiederholt sich, solange eine Bedingung wahr ist. In der Regel nicht synthetisierbar, außer in Sonderfällen, in denen sie einer for-Schleife entspricht. Die Iterationsanzahl kann dynamisch sein.

[Label:] while ... loop
    -- code
end loop [Label];

Infinite-Schleife

Eine endlose Schleife loop ... end loop, gesteuert über exit oder wait.

loop
    -- ...
    exit when ...;
end loop;

For-Generate

Kein sequentielles Konstrukt, sondern ein Mechanismus zur Hardware-Vervielfältigung: parametrische Instanziierung von Logik oder Komponenten innerhalb einer Architektur. Funktioniert ähnlich wie eine for-Schleife, befindet sich aber außerhalb von Processes.

[Label:] for ... in ... generate
    -- ...
end generate [Label];

std_logic und std_ulogic

Der Datentyp std_logic ist der am häufigsten genutzte Typ in VHDL zur Darstellung eines einzelnen Bits. Er stammt aus dem IEEE-Standard 1164 und wird über ieee.std_logic_1164.all eingebunden.

Im Gegensatz zum einfachen Basistyp bit kann std_logic neun verschiedene Zustände annehmen, wodurch reales Hardware-Verhalten sehr präzise simulierbar wird – etwa unbekannte Pegel, Tristate oder schwache Pull-Werte.

Zustände von std_logic

  • 'U' – uninitialized (nicht initialisiert)
  • 'X' – forcing unknown (starker unbekannter Pegel / Konflikt)
  • '0' – forcing low (logische 0, stark getrieben)
  • '1' – forcing high (logische 1, stark getrieben)
  • 'Z' – high impedance (hochohmig, Tristate)
  • 'W' – weak unknown (schwach unbekannt)
  • 'L' – weak low (schwache 0, z. B. Pull-Down)
  • 'H' – weak high (schwache 1, z. B. Pull-Up)
  • '-' – don't care (für Synthese-Optimierung)

Hauptmerkmale

  • Resolved Type: std_logic darf mehrere Treiber besitzen. Eine interne Resolution-Function entscheidet über den resultierenden Wert. Daher gibt es keinen Compilerfehler, selbst wenn das Signal mehrfach zugewiesen wird.
  • Synthese: In echter Hardware setzt der FPGA meist nur '0', '1' und bei Pins 'Z' um. Die restlichen Zustände dienen hauptsächlich der Fehlersuche in Simulationen.
  • Unterschied zu std_ulogic: std_ulogic ist „unresolved“ und erlaubt keine mehrfachen Treiber. Schon bei zwei Zuweisungen tritt ein Compilerfehler auf – ideal zur Fehlersuche. Abgesehen davon funktionieren sie exakt gleich.

Kurz gesagt: std_logic ist flexibel und praxisnah, std_ulogic dagegen streng und hilfreich beim Debuggen.

STD-ULOGIC

Compilerfehler!
Da std_ulogic nicht neu definiert werden darf.

STD-LOGIC

Hierarchisches Design in VHDL

Blöcke und Untereinheiten dienen dazu, Designs hierarchisch zu strukturieren und sowohl Lesbarkeit als auch Wiederverwendbarkeit eines VHDL-Codes zu verbessern.

Blöcke

Ein block-Statement innerhalb einer Architektur wird genutzt, um Teile des Designs logisch zu gruppieren.

  • Zweck: saubere Strukturierung innerhalb einer Architektur
  • Eigenschaften: lokale Signale, Konstanten und Datentypen möglich
  • Guard-Ausdrücke waren historisch relevant, heute kaum genutzt

Untereinheiten

VHDL-Code ist in verschiedene funktionale Einheiten gegliedert, die jeweils unterschiedliche Aufgaben übernehmen.

  • Entity: Definiert die externe Schnittstelle über Ports
  • Architecture: Beschreibt internes Verhalten oder Struktur
  • Configuration: Legt fest, welche Architektur einer Entity-Instanz zugeordnet wird
  • Package: Sammlung von globalen Datentypen, Konstanten, Funktionen und Prozeduren

Hierarchische Untereinheiten

Untereinheiten werden durch Komponenteninstanziierung in einem Design eingebunden.

  • Component Declaration: Schnittstelle der Untereinheit wird bekannt gemacht
  • Component Instantiation: Untereinheit wird im Anweisungsteil eingefügt und über port map verbunden

Unterprogramme

Unterprogramme ermöglichen wiederkehrende Logik und verbessern Struktur und Klarheit.

  • Function: Gibt genau einen Wert zurück und hat keine Seiteneffekte
  • Procedure: Kann mehrere Werte zurückgeben und Signale manipulieren
UND-Schaltung Grafik

ModelSim Simulation

In dieser Sektion werden die Schritte zur Simulation eines VHDL-Designs in ModelSim gezeigt. Jeder Schritt ist als Screenshot dokumentiert, um den Ablauf visuell nachzuvollziehen.

Den Pfad des Simulations programms angeben sonst fehler: Tools Options EDA Tool Options Pfad des Programms

ModelSim Schritt 5

Assigmentè Settings èEDA Tool SettingsèModel-SIM Altera, VHDL

ModelSim Schritt 6

Schritt 3

ModelSim Schritt 7

Dann die INPUTS und Outputs hinzufügen: Rechtsklick auf die leere Tabelle èInsert NODE or BUS

ModelSim Schritt 8

Dann die Signale hinzufügen:

ModelSim Schritt 9

Schritt 6

ModelSim Schritt 10

Schritt 7

ModelSim Schritt 11

Für eine Korrekte Simulation muss jede mögliche Kombination der Eingangssignale vorhanden sein. Deshalb werden die Eingänge als Overwrite Clock mit Perioden von (2,4,8,16,usw angegeben).

Schritt 8

ModelSim Schritt 12

Simulation Fertig!

Aufbau von ASICs (PROM, PAL/GAL)

ASICs = Application-Specific-Integrated-Circuits
PROM = Programmable-Read-Only-Memory
PAL/GAL = Programmable-Array-Logic/Generic-Array-Logic

ASICs sind spezielle Halbleiterbauelemente die aus Komponenten wie PROM und PAL/GAL bestehen.

PROM:

PROM ist ein nichtflüchtiger einmal programmierbarer Speicher.
Er Besteht aus einem Array von Speicherzellen die anfangs auf 0 (nicht
programmiert) stehen. Beim Programmieren werden gewisse Zellen durch
„Schmelzen“ (z.B. mit Hochspannung) auf 1 gesetzt. Zellen können nur einmal
programmiert werden.

PROM-Typen:

• OTP = One-Time-Programmable:
Kann nur einmal programmiert werden.
• EPROM = Erasable-PROM: kann mit UV-Licht gelöscht und neu programmiert werden.
• EEPROM = Electrically-Erasable-PROM: kann elektrisch gelöscht und neu programmiert werden.

PAL (Programmable Array Logic):

Ein PAL ist ein digitaler Logikbaustein, der aus einem programmierbaren
AND-Array und einem fest verdrahteten OR-Array besteht.

Im AND-Array können die Verbindungen zwischen den Eingängen und den einzelnen
AND-Gattern frei programmiert werden. Dadurch lässt sich bestimmen, welche
Eingangssignale in die jeweiligen Produktterme eingehen.

Das OR-Array hingegen ist nicht programmierbar: die Ausgänge der AND-Gatter
sind fest mit den Eingängen der OR-Gatter verbunden.

PALs eignen sich gut für einfache kombinatorische Logikschaltungen und kleinere
Steueraufgaben, bieten jedoch weniger Flexibilität als GALs oder moderne FPGAs.

GAL (Generic Array Logic):

Ein GAL ist eine Form eines programmierbaren logischen Bausteins und gilt als
ein einfacher Vorläufer moderner FPGAs.

Der Aufbau basiert auf einem programmierbaren AND-Array und einem festen
OR-Array. Das bedeutet: nur das AND-Array kann vom Benutzer programmiert werden.

Die Logikfunktionen lassen sich nachträglich verändern, da im Inneren des GALs
winzige Sicherungen bzw. moderne EEPROM/Flash-Zellen an den Kreuzungspunkten
der Gatter sitzen. Durch gezieltes Durchtrennen bzw. Programmieren dieser
Verbindungen wird festgelegt, welche Eingänge mit welchen Logikausdrücken
verknüpft werden.

Im Gegensatz zu älteren PALs, die nur einmal programmierbar waren, verwenden
GALs EEPROM- oder Flash-Technologie. Dadurch können sie gelöscht und mehrfach
neu programmiert werden (typisch bis zu rund 100-mal).

GALs sind relativ einfache Bausteine. Sie können grundlegende logische
Funktionen und einfache Zustandsautomaten realisieren, eignen sich aber nur
bedingt für sehr komplexe digitale Schaltungen.

Grundgatter Tutorial (beispiel mit AND)

Entity Deklaration

entity and_gate is
Port (
a : in  STD_LOGIC;   -- input 1
b : in  STD_LOGIC;   -- input 2
y : out STD_LOGIC    -- output
);
end and_gate;

Architektur

architecture Behavioral of and_gate is
begin
y <= a AND b;
end Behavioral;;

Andere gates:

Wichtige Keywords:
        AND - OR - NOT - NAND - NOR - XOR - XNOR

Kombinatorische Logik mit Erklärung

Beispiel UND-Verknüpfung mit LED und 2 Schaltern

UND-Schaltung Grafik

Sequentielle Logik in VHDL

Sequentielle Logik unterscheidet sich von kombinatorischer Logik dadurch, dass sie Zustände speichern kann. Änderungen erfolgen synchron zu einem Taktsignal (Clock). In VHDL wird dies typischerweise mit PROCESS und einer Flankenerkennung (rising_edge(clk)) beschrieben.

Zustandsregister und Speicher

Diese Elemente speichern Werte über mehrere Taktzyklen hinweg und bilden die Grundlage sequentieller Logik.

  • Flip-Flops: Speicherung eines einzelnen Bits (z. B. D-Flip-Flop)
  • Register: Mehrere Flip-Flops zur Speicherung von Vektoren oder Bussen
  • Speicher (RAM/ROM): Größere Datenmengen, synchron zum Takt
process(clk)
begin
    if rising_edge(clk) then
        q <= d; -- D-Flip-Flop
    end if;
end process;

Zähler (Counter)

Zähler sind wesentliche Bausteine zur Erfassung von Taktzyklen oder Ereignissen.

  • Binärzähler (aufwärts / abwärts)
  • Modulo-N-Zähler
  • Frequenzteiler
process(clk)
begin
    if rising_edge(clk) then
        counter <= counter + 1;
    end if;
end process;

Zustandsautomaten (FSM)

Finite State Machines steuern komplexe Abläufe. Der nächste Zustand hängt vom aktuellen Zustand und ggf. von Eingängen ab.

  • Moore-Automat: Ausgabe hängt nur vom Zustand ab
  • Mealy-Automat: Ausgabe hängt von Zustand und Eingängen ab
process(clk)
begin
    if rising_edge(clk) then
        state <= next_state;
    end if;
end process;

Synchronisatoren und Entpreller

Externe Signale müssen an die interne Takt-Domäne angepasst werden, um Metastabilität zu vermeiden.

  • 2-Flip-Flop-Synchronisatoren
  • Taster-Entprellung mit Zählern oder FSMs

Schieberegister

Schieberegister speichern und verschieben Daten bitweise pro Takt.

  • Serielle Kommunikation (SPI, I²C, UART)
  • Datenverzögerung über mehrere Takte
  • Parallel-/Seriell-Wandlung
process(clk)
begin
    if rising_edge(clk) then
        shift_reg <= shift_reg(6 downto 0) & data_in;
    end if;
end process;
UND-Schaltung Grafik

Häufige Fehler beim Programmieren des DE-0 Boards / Quartus.

Compile-Fehler

  • fehlerhafter Code (falsche Syntax, Befehle, Regeln nicht befolgt, etc.)
  • falsche Top-Entity

Upload-Fehler

  • USB-Blaster nicht installiert (Board wird nicht erkannt)
  • falsches Board ausgewählt
  • Störung mit Kabel
  • Board fehlerhaft
  • Netzversorgung nicht angeschlossen

Simulationsfehler

  • Altera ModelSim nicht installiert
  • Pfad nicht angegeben für ModelSim
  • I/O falsch angegeben
  • nicht alle Zustände angegeben

Andere

  • falsche Pinbelegung
  • falsche Logik im Code
  • Taster nicht entprellt