30.10.2013 Aufrufe

Eine Einführung in die Schaltungsent- wicklung mit VHDL

Eine Einführung in die Schaltungsent- wicklung mit VHDL

Eine Einführung in die Schaltungsent- wicklung mit VHDL

MEHR ANZEIGEN
WENIGER ANZEIGEN

Sie wollen auch ein ePaper? Erhöhen Sie die Reichweite Ihrer Titel.

YUMPU macht aus Druck-PDFs automatisch weboptimierte ePaper, die Google liebt.

INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

<strong>E<strong>in</strong>e</strong> <strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>die</strong> <strong>Schaltungsent</strong><strong>wicklung</strong><br />

<strong>mit</strong> <strong>VHDL</strong><br />

Version 05 März 2013<br />

Urs Graf, Laszlo Arato<br />

Beispiele und Illustrationen wurden entnommen aus:<br />

„<strong>VHDL</strong> Kompakt“, http:// tams-www.<strong>in</strong>formatik.uni-hamburg.de<br />

„The Student’s Guide to <strong>VHDL</strong>“, P. Ashenden<br />

“<strong>VHDL</strong> Tutorial”, http://www.vhdl-onl<strong>in</strong>e.de/


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

1 <strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong> ............................................................................................................................... 4<br />

2 Grundstruktur e<strong>in</strong>es <strong>VHDL</strong>-Modells und 1. Beispiel .............................................................................. 6<br />

2.1 Elemente des <strong>VHDL</strong>-Modells ............................................................................................................. 6<br />

2.2 Packages und Libraries ....................................................................................................................... 8<br />

2.3 Konfiguration .................................................................................................................................... 10<br />

3 Konzepte ................................................................................................................................................ 11<br />

3.1 Grundlagen ........................................................................................................................................ 11<br />

3.2 Abstraktionsebenen ........................................................................................................................... 12<br />

3.3 Beispiel 3-Bit Komparator ................................................................................................................ 14<br />

3.4 Beispiel 3-Bit Zähler ......................................................................................................................... 15<br />

4 Datentypen ............................................................................................................................................. 16<br />

4.1 Skalare Datentypen ........................................................................................................................... 16<br />

4.2 Komplexe Typen (composite)........................................................................................................... 17<br />

4.3 Attribute von Datentypen .................................................................................................................. 19<br />

4.4 Typumwandlungen ............................................................................................................................ 19<br />

4.5 Arithmetik <strong>mit</strong> Vektoren ................................................................................................................... 20<br />

4.6 Typumwandlungen <strong>mit</strong> Vektoren ...................................................................................................... 21<br />

5 Operatoren ............................................................................................................................................. 22<br />

6 Parallel laufende Anweisungen .............................................................................................................. 23<br />

6.1 Signalzuweisung ............................................................................................................................... 23<br />

7 Signale und Variablen ............................................................................................................................ 24<br />

7.1 Deklaration von Signalen .................................................................................................................. 24<br />

7.2 Verzögerungszeiten ........................................................................................................................... 25<br />

7.3 Attribute von Signalen ...................................................................................................................... 26<br />

7.4 Variablen ........................................................................................................................................... 27<br />

7.5 Konstanten ........................................................................................................................................ 27<br />

8 Sequentielle Anweisungen ..................................................................................................................... 28<br />

8.1 Der Prozess ....................................................................................................................................... 28<br />

8.2 Das IF-Statement ............................................................................................................................... 31<br />

8.3 Das Case-Statement .......................................................................................................................... 31<br />

8.4 Die FOR-Schleife .............................................................................................................................. 32<br />

8.5 Die WHILE-Schleife ......................................................................................................................... 33<br />

8.6 Schleifen <strong>mit</strong> LOOP ... EXIT ............................................................................................................ 33<br />

8.7 Der NEXT-Befehl ............................................................................................................................. 34<br />

8.8 Beispiel für sequentiellen Code <strong>mit</strong> Schleifen .................................................................................. 35<br />

9 Gültigkeitsbereich von Deklarationen.................................................................................................... 36<br />

10 Unterprogramme .................................................................................................................................... 37<br />

10.1 FUNCTION Unterprogramm ....................................................................................................... 37<br />

10.2 PROCEDURE Unterprogramm .................................................................................................... 38<br />

2


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

11 Bibliotheken und Packages .................................................................................................................... 39<br />

12 Hierarchie durch strukturierte Modelle / Komponenten ........................................................................ 40<br />

13 Parametrisierbare Modelle ..................................................................................................................... 41<br />

3


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

1 <strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Ziel <strong>die</strong>ser <strong>E<strong>in</strong>führung</strong><br />

„<strong>VHDL</strong>“<br />

Top-Down-Design<br />

Wie wird <strong>VHDL</strong><br />

e<strong>in</strong>gesetzt?<br />

Synthetisierbares <strong>VHDL</strong><br />

Nicht synthetisierbares <strong>VHDL</strong><br />

<strong>VHDL</strong> 87<br />

Diese <strong>E<strong>in</strong>führung</strong> soll <strong>die</strong> wesentlichen Konzepte von <strong>VHDL</strong> aufzeigen.<br />

Anhand praktischer Beispiele wird der Gebrauch <strong>die</strong>ser Beschreibungssprache<br />

erläutert.<br />

Diese <strong>E<strong>in</strong>führung</strong> ist ke<strong>in</strong>e komplette Referenz aller <strong>VHDL</strong>-Konstrukte.<br />

Weiterführende Konzepte wie z.B. generische Module, GENERATE und<br />

Overload wurden weggelassen.<br />

Very High Speed Integrated Circuit Hardware Description Language. Mit<br />

<strong>VHDL</strong> kann man digitale Schaltungen und Systeme durchgängig von der<br />

Systemdef<strong>in</strong>ition bis zum <strong>Schaltungsent</strong>wurf beschreiben und verifizieren.<br />

Top-Down-Design ist der Ansatz zur Lösung von Designproblemen bei<br />

zunehmend komplexerer Hardware. Bei <strong>die</strong>ser Methodik wird zuerst das<br />

Verhalten e<strong>in</strong>es Designs auf e<strong>in</strong>er hohen Abstraktionsebene beschrieben.<br />

Dabei ist es wichtig, dass noch ke<strong>in</strong>erlei Rücksicht auf Technologien oder<br />

Details der Implementierung genommen werden muss. Um <strong>die</strong> Spezifikation<br />

selbst großer Schaltungen genau def<strong>in</strong>ieren und austesten zu können,<br />

wird e<strong>in</strong>e Simulation aufgrund der abstrakten Beschreibung des Modells<br />

durchgeführt.<br />

Da<strong>mit</strong> lassen sich mehrere Varianten der Spezifikation ohne großen Aufwand<br />

am Simulator <strong>mit</strong>e<strong>in</strong>ander vergleichen. Die Simulationsergebnisse<br />

e<strong>in</strong>er solchen Spezifikation können dann über <strong>die</strong> gesamte Ent<strong>wicklung</strong>sphase<br />

als Maßstab für <strong>die</strong> Übere<strong>in</strong>stimmung zwischen Spezifikation (Zielsetzung)<br />

und Design (Ergebnis) <strong>die</strong>nen.<br />

<strong>VHDL</strong> ist e<strong>in</strong>e sehr mächtige und flexible Sprache.<br />

Im Gegensatz zu klassischen Programmiersprachen kann <strong>VHDL</strong> sowohl<br />

sequentielle wie auch parallel ablaufende Vorgänge beschreiben. <strong>VHDL</strong><br />

wurde nicht nur für <strong>die</strong> Beschreibung von elektronischen Bauelementen<br />

entworfen, sondern für <strong>die</strong> Spezifikation und funktionelle Simulation von<br />

komplexen Schaltkreisen, Baugruppen und Systemen.<br />

Anders als beim schematischen Design <strong>mit</strong> Logik-Blöcken <strong>die</strong> manuell<br />

platziert und verbunden werden bietet <strong>die</strong> automatische Synthese e<strong>in</strong>er <strong>in</strong><br />

<strong>VHDL</strong> def<strong>in</strong>ierten Struktur viele Vorteile wie <strong>die</strong> Elim<strong>in</strong>ierung von duplizierter<br />

Logik, Reduktion von komb<strong>in</strong>atorischen Vorgängen und Implementation<br />

der gewünschten Funktion <strong>mit</strong> verfügbaren Gattern und Logikbauteilen<br />

(z.B. <strong>in</strong> e<strong>in</strong>em FPGA).<br />

Nur e<strong>in</strong> relativ kle<strong>in</strong>er Teil der Sprache <strong>VHDL</strong> kann wirklich effizient synthetisiert<br />

werden (z.B. std_logic_vector, std_logic, signed und<br />

unsigned). Andere Elemente werden zwar von e<strong>in</strong>em Synthesewerkzeug<br />

umgesetzt, aber erzeugen <strong>in</strong>effiziente Strukturen (z.B. INTEGER, REAL).<br />

Deshalb muss beim Schreiben von <strong>VHDL</strong> Code für FPGA und ASIC immer<br />

vor Augen gehalten werden, was das Synthesewerkzeug da<strong>mit</strong> anstellen<br />

wird.<br />

<strong>VHDL</strong> wird nicht nur beim Design der Logik <strong>in</strong> FPGAs und ASICs e<strong>in</strong>gesetzt,<br />

sondern auch zur Beschreibung und Funktion von Testumgebungen<br />

<strong>in</strong> Simulationen, sogenannten Test-Benches.<br />

Da <strong>die</strong>ser Code immer nur simuliert und nie synthetisiert wird, darf man<br />

hier nach Belieben alle Sprachelemente und Konstrukte von <strong>VHDL</strong> verwenden.<br />

Im Jahre 1987 wurde <strong>VHDL</strong> als <strong>in</strong>ternationaler Standard <strong>mit</strong> der Bezeichnung<br />

IEEE Std. 1076-1987 e<strong>in</strong>geführt.<br />

4


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

<strong>VHDL</strong> 93<br />

<strong>VHDL</strong> 2008<br />

<strong>VHDL</strong>-AMS<br />

Sechs Jahre später wurden etliche Modifikationen gemacht und <strong>die</strong> Sprache<br />

um e<strong>in</strong>ige Elemente erweitert. Dieser Standard heisst IEEE Std. 1076-<br />

1993, kurz <strong>VHDL</strong>93. In <strong>die</strong>sem Kurs verwenden wir <strong>die</strong>se neuere Fassung.<br />

Mit <strong>VHDL</strong> 2008 wurde <strong>die</strong> Sprache um e<strong>in</strong> paar praktische Elemente erweitert.<br />

Während <strong>die</strong>se zusätzlichen Funktionen <strong>in</strong> Quartus II, Version<br />

11.0 bereits implementiert s<strong>in</strong>d, werden sie von ModelSim der Firma Mentor<br />

Graphics bis Version 6.6 noch nicht unterstützt …<br />

… deshalb verzichten wir im Rahmen <strong>die</strong>ses Kurses auf <strong>die</strong>se Funktionen.<br />

<strong>VHDL</strong> wurde auch um analoge und mixed-signal Sprachelement erweitert.<br />

Diese Erweiterung nennt sich <strong>VHDL</strong>-AMS (für Analog Mixed Signal) und<br />

ist e<strong>in</strong>e Obermenge zu <strong>VHDL</strong>. Die re<strong>in</strong> digitalen Methoden von <strong>VHDL</strong>93<br />

werden auch weiterh<strong>in</strong> gelten. Es ist absehbar, dass auf der analogen Seite<br />

bis auf weiteres nur <strong>die</strong> Simulation durchführbar ist.<br />

H<strong>in</strong>weis zur Benutzung <strong>die</strong>ses Leitfadens:<br />

In den folgenden Kapiteln werden <strong>die</strong> wesentlichen Sprachkonstrukte von <strong>VHDL</strong> präsentiert. Die l<strong>in</strong>ke<br />

Spalte zeigt stets <strong>die</strong> Theorie und Erklärung dazu, auf der rechten Seite f<strong>in</strong>den Sie passende Beispiele.<br />

5


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

2 Grundstruktur e<strong>in</strong>es <strong>VHDL</strong>-Modells und 1. Beispiel<br />

2.1 Elemente des <strong>VHDL</strong>-Modells<br />

Der Code e<strong>in</strong>es <strong>VHDL</strong>-Modells besteht immer aus<br />

zwei zusammenhängenden Teilen: e<strong>in</strong>er Entity und<br />

e<strong>in</strong>er ARCHITECTURE. Der Begriff Entity bezeichnet<br />

e<strong>in</strong> zusammenhängendes, <strong>in</strong> sich abgeschlossenes System<br />

<strong>mit</strong> e<strong>in</strong>er def<strong>in</strong>ierten Schnittstelle zur Umgebung.<br />

Neben anderen D<strong>in</strong>gen wird eben <strong>die</strong>se Schnittstelle<br />

<strong>in</strong> Form von Signalen <strong>in</strong> der Entity beschrieben. <strong>E<strong>in</strong>e</strong><br />

Entity entspricht also e<strong>in</strong>em sozusagen e<strong>in</strong>em Symbol<br />

<strong>in</strong> e<strong>in</strong>er grafischen Schaltungsbeschreibung.<br />

Im Gegensatz dazu beschreibt <strong>die</strong> ARCHITECTURE den<br />

<strong>in</strong>neren Aufbau und <strong>die</strong> Funktion des Systems. Die<br />

ARCHITECTURE entspricht daher der Netzliste bei der<br />

grafischen Beschreibung. Während e<strong>in</strong>e Architektur<br />

immer e<strong>in</strong>er bestimmten Entity zugeordnet ist, kann<br />

e<strong>in</strong>e Entity kann beliebig viele Architekturen „besitzen“.<br />

Dadurch lassen sich ohne Änderung des Systemnamens<br />

verschiedene Versionen oder Arten e<strong>in</strong>es<br />

Modells verwalten.<br />

Design Block<br />

Package Declaration<br />

Component Declaration<br />

Entity Declaration<br />

Architecture Body<br />

2.1.1 Kommentare<br />

Mit „--„ beg<strong>in</strong>nender Text ist <strong>in</strong> <strong>VHDL</strong> bis zum Ende<br />

der jeweiligen Zeile als Kommentar def<strong>in</strong>iert und wird<br />

vom Compiler ignoriert.<br />

-- Dies ist nur re<strong>in</strong> Kommentar der auf<br />

-- der zweiten Zeile fortgesetzt wird<br />

2.1.2 Die Entity<br />

Die Entity ist <strong>die</strong> Schnittstellenbeschreibung zwischen<br />

e<strong>in</strong>em Moduls und der Umwelt.<br />

Worte <strong>in</strong> Grossbuchstaben, wie beispielsweise<br />

ENTITY oder PORT s<strong>in</strong>d <strong>VHDL</strong>-spezifische Schlüsselwörter<br />

<strong>mit</strong> e<strong>in</strong>er bestimmten Bedeutung (ähnlich<br />

wie „for“ oder „<strong>in</strong>t“ <strong>in</strong> Java). Diese Reservierten Wörter<br />

dürfen nicht für eigene Bezeichnungen verwendet<br />

werden.<br />

ENTITY entity_name IS<br />

PORT ( port_list );<br />

END [entity_name];<br />

Der entity_name bezeichnet den Namen des Systems.<br />

Auf <strong>die</strong>sen Namen bezieht sich dann <strong>die</strong> jeweilige<br />

Umgebung des Systems.<br />

Die port_list bezeichnet e<strong>in</strong>e Liste von E<strong>in</strong>- und Ausgangssignalen<br />

des Systems.<br />

2.1.3 Die port_list<br />

Bei der PORT Liste handelt es sich um e<strong>in</strong>e durch<br />

Strichpunkt getrennte Liste von E<strong>in</strong>gangs- und Ausgangssignalen.<br />

Jedes Signal wird durch e<strong>in</strong> Bezeichner,<br />

e<strong>in</strong> Modus und e<strong>in</strong> Datentyp spezifiziert.<br />

Der Strichpunkt trennt nur <strong>die</strong> e<strong>in</strong>zelnen Elemente der<br />

Liste, und deshalb hat das letzte Element (output_1)<br />

am Ende ke<strong>in</strong>en Strichpunkt!<br />

ENTITY entity_name IS<br />

);<br />

END;<br />

PORT (<br />

<strong>in</strong>put_1 : modus signal_type;<br />

<strong>in</strong>put_2 : modus signal_type;<br />

output_1 : modus signal_type<br />

6


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Als Modus kommen <strong>die</strong> Schlüsselwörter IN, OUT,<br />

INOUT oder BUFFER <strong>in</strong> Frage. Der Datentyp beschreibt<br />

<strong>die</strong> Art der Werte, <strong>die</strong> das PORT-Signal annehmen<br />

kann.<br />

2.1.4 Port Modi<br />

Der Modus e<strong>in</strong>es Entity-Ports gibt <strong>die</strong> Datenflußrichtung<br />

vor.<br />

Der Modus IN wird für re<strong>in</strong> lesbare Signale verwendet.<br />

Signale, deren Ports <strong>die</strong>sen Mode haben, können<br />

<strong>in</strong> der untergeordneten Architektur ke<strong>in</strong>e Werte zugewiesen<br />

werden.<br />

Entsprechend bezeichnet der OUT Modus Signale,<br />

denen e<strong>in</strong> Wert zugewiesen werden kann, aber <strong>die</strong><br />

nicht gelesen werden können.<br />

PORT (<br />

a, b : IN std_logic;<br />

c : OUT std_logic<br />

);<br />

E<strong>in</strong> Port <strong>mit</strong> dem Modus BUFFER erlaubt es, e<strong>in</strong><br />

Ausgangssignal auch <strong>in</strong>tern zu „sehen“.<br />

Die Verwendung des Port-Modus<br />

BUFFER sche<strong>in</strong>t bequemer, als e<strong>in</strong><br />

zusätzliches <strong>in</strong>ternes Signal zu erzeugen<br />

welches auf das Ausgangssignal<br />

kopiert wird.<br />

Gerade bei hierarchischen Strukturen<br />

wird <strong>die</strong>s aber zur Zeitbombe, weil Ports <strong>mit</strong> Modus<br />

BUFFER nicht <strong>mit</strong> anderen Ports verbunden<br />

werden können!!!<br />

PORT (<br />

clk : IN std_logic;<br />

count : BUFFER std_logic<br />

);<br />

Wir werden <strong>die</strong>sen Port-Modus nicht verwenden!!!<br />

Wenn e<strong>in</strong> Modul treibend und lesend auf e<strong>in</strong>en Port<br />

zugreifen muss, wird der Modus INOUT verwendet.<br />

INOUT beschreibt eigentlich nichts anderes als e<strong>in</strong>en<br />

Tri-State Buffer.<br />

INOUT macht nur für Signale an<br />

der Peripherie e<strong>in</strong>es Chips S<strong>in</strong>n, wie<br />

zum Beispiel für<br />

e<strong>in</strong>en bidir. Datenbus!<br />

Innerhalb e<strong>in</strong>es FPGAs gibt es aus technischen Gründen<br />

ke<strong>in</strong>e echten Tri-State Signale, alles wird auf klar<br />

def<strong>in</strong>ierte Signale abgebildet.<br />

Bei e<strong>in</strong>em ASIC ist es möglich e<strong>in</strong>en echten <strong>in</strong>ternen<br />

Tri-State Bus def<strong>in</strong>ieren … aber dann muss man<br />

GANZ GENAU wissen was man tut – weil dann z.B.<br />

ke<strong>in</strong>e automatische Optimierung und ke<strong>in</strong>e statische<br />

enable_1<br />

out_1<br />

<strong>in</strong>_1<br />

<strong>in</strong>out_1<br />

PORT (<br />

<strong>in</strong>_1 : IN std_logic;<br />

enable_1 : IN std_logic;<br />

out_1 : OUT std_logic;<br />

<strong>in</strong>out_1 : INOUT std_logic<br />

);<br />

7


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Tim<strong>in</strong>g-Analyse mehr möglich ist.<br />

2.1.5 Die Architektur<br />

Die Architektur beschreibt das <strong>in</strong>nere Verhalten e<strong>in</strong>es<br />

Moduls.<br />

Die Architektur beg<strong>in</strong>nt <strong>mit</strong> dem Schlüssel-wort<br />

ARCHITECTURE und e<strong>in</strong>em selbstdef<strong>in</strong>ierten Namen.<br />

Dann folgt der Name der ENTITY, zu der <strong>die</strong>se Architektur<br />

gehört. Dies stellt e<strong>in</strong>en e<strong>in</strong>deutigen Bezug zu<br />

e<strong>in</strong>er ENTITY her und bietet andererseits <strong>die</strong> Möglichkeit<br />

e<strong>in</strong>er Verknüpfung beliebiger Architekturen zu<br />

e<strong>in</strong>er ENTITY.<br />

Im Bereich vor dem Schlüsselwort BEGIN kann man<br />

architekturspezifische Objekte deklarieren, <strong>E<strong>in</strong>e</strong> Erläuterung<br />

hierzu folgt später.<br />

ARCHITECTURE arch_name OF entity_name IS<br />

-- declarative region<br />

BEGIN<br />

-- architecture body<br />

END [ARCHITECTURE] arch_name;<br />

2.2 Packages und Libraries<br />

Im nächsten Beispiel wird der Typ STD_LOGIC verwendet.<br />

Dieser Typ ist nicht <strong>in</strong> <strong>VHDL</strong> selbst enthalten, sondern<br />

wird <strong>in</strong> e<strong>in</strong>em sogenannten Paket (PACAKGE) def<strong>in</strong>iert.<br />

Pakete werden <strong>in</strong> e<strong>in</strong>er Bibliothek (entspricht<br />

e<strong>in</strong>em Verzeichnis auf Ihrem Rechner) gesammelt.<br />

Mit der USE-Klausel wird e<strong>in</strong> Paket e<strong>in</strong>gebunden. Das<br />

.ALL nach dem Paketnamen bedeutet, dass alle Teile<br />

aus e<strong>in</strong>er Bibliothek verwendet werden. Das können<br />

z.B. Konstanten, Typen, Signale oder Komponenten<br />

se<strong>in</strong>.<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

USE IEEE.numeric_std.ALL;<br />

2.2.1 Vollständiges Beispiel<br />

Das zu entwerfende System soll von zwei digitalen<br />

Signalen angesteuert werden und e<strong>in</strong> e<strong>in</strong>zelnes Digitalsignal<br />

ausgeben. Wenn an beiden E<strong>in</strong>gängen der<br />

High-Zustand anliegt, soll der Ausgang den<br />

Low-Zustand annehmen. Für jede andere Komb<strong>in</strong>ation<br />

an den E<strong>in</strong>gängen soll der Ausgang im<br />

High-Zustand se<strong>in</strong>.<br />

Beim Betrachten der Wahrheitstabelle erkennt man:<br />

Beim beschriebenen Verhalten handelt es sich um e<strong>in</strong><br />

NAND-Gatter.<br />

Natürlich bräuchte man dazu ke<strong>in</strong>e solch komplizierte<br />

Struktur sondern man könnte <strong>die</strong> <strong>in</strong> <strong>VHDL</strong> e<strong>in</strong>gebaute<br />

Funktion verwenden. Um das erste Beispiel e<strong>in</strong>fach zu<br />

halten, werden wir dennoch <strong>die</strong> Implementation <strong>die</strong>ses<br />

NANDs <strong>in</strong> verschiedenen Varianten zu untersuchen.<br />

Die erste Architektur „truth“ implementiert genau <strong>die</strong><br />

Wahrheitstabelle <strong>mit</strong> e<strong>in</strong>er Reihe von IF – THEN –<br />

ELSE Befehlen.<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

ENTITY nand_gate IS<br />

PORT (<br />

<strong>in</strong>_a : IN std_logic;<br />

<strong>in</strong>_b : IN std_logic;<br />

output : OUT std_logic<br />

);<br />

END;<br />

ARCHITECTURE truth OF nand_gate IS<br />

-- Truth table<br />

-- ===========<br />

8


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Nicht sehr elegant, aber genau der Spezifikation entsprechend<br />

–sollte man zum<strong>in</strong>dest me<strong>in</strong>en.<br />

Der Signal-Typ „std_logic“ <strong>die</strong>nt, anders als der Typ<br />

BIT, nicht nur zur Darstellung von logisch ‚1‘ und ‚0‘,<br />

sondern zur Modellierung von realen Signalen. Reale<br />

Signale können neben den logischen Zuständen noch<br />

Zustände wie ‚U‘ (Un<strong>in</strong>itialized), ‚X‘ (Unknown),<br />

und noch e<strong>in</strong>ige mehr annehmen (siehe Kap. 4.1).<br />

Was passiert nun, wenn der E<strong>in</strong>gang A auf ‚0‘ ist, und<br />

der E<strong>in</strong>gang B auf ‚X‘ steht? Intuitiv würde man me<strong>in</strong>en,<br />

dass dann der Ausgang 1 se<strong>in</strong> sollte, weil <strong>die</strong>ser<br />

nur dann auf ‚0‘ geht, wenn beide E<strong>in</strong>gänge auf ‚1‘<br />

s<strong>in</strong>d. Aber unsere Schaltung macht das nicht so.<br />

Also def<strong>in</strong>ieren wir e<strong>in</strong>e zweite Architektur „smart“,<br />

<strong>die</strong> <strong>die</strong>sen Fehler nicht hat und auf unspezifische E<strong>in</strong>gänge<br />

richtig reagiert.<br />

In-<strong>VHDL</strong> gibt es relationale Operatoren wie = oder<br />

>=. Diese liefern e<strong>in</strong>en Booleschen Wert zurück. Daneben<br />

existieren aber auch logische Operatoren wie<br />

AND, OR, NAND, usw. Mit <strong>die</strong>sen lässt sich das vorangegangene<br />

Beispiel eleganter formulieren.<br />

Wenn man (wie wir hier) mehr als nur e<strong>in</strong>e Architektur<br />

verwendet, dann muss man <strong>mit</strong> der<br />

CONFIGURATION def<strong>in</strong>ieren, welche der Architekturen<br />

man simulieren oder synthetisieren will.<br />

-- <strong>in</strong>_a <strong>in</strong>_b | output<br />

-- ------------|--------<br />

-- 0 0 | 1<br />

-- 0 1 | 1<br />

-- 1 0 | 1<br />

-- 1 1 | 0<br />

BEGIN<br />

PROCESS (<strong>in</strong>_a, <strong>in</strong>_b)<br />

BEGIN<br />

IF<br />

<strong>in</strong>_a=’0’ AND <strong>in</strong>_b=’0’ THEN<br />

output


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

2.3 Konfiguration<br />

Es gibt <strong>in</strong> <strong>VHDL</strong> <strong>die</strong> Möglichkeit, <strong>mit</strong> dem Schlüsselwort<br />

„CONFIGURATION“ e<strong>in</strong>e bestimmte Architektur<br />

zur Implementation auszuwählen.<br />

Dabei ist <strong>die</strong> Syntax etwas speziell, wie man am Beispiel<br />

rechts sehen kann.<br />

Für ALTERA Quartus II funktioniert <strong>die</strong>s ganz gut.<br />

CONFIGURATION nandconf OF nand_gate<br />

IS<br />

FOR smart<br />

END FOR;<br />

END CONFIGURATION nandconf;<br />

Leider hat es sich <strong>in</strong> Versuchen gezeigt, dass ModelSim den Befehl<br />

„CONFIGURATION“ nicht beachtet, sondern dass zur Simulation immer <strong>die</strong> LETZTE Architektur<br />

verwendet wird.<br />

Dies kann entsprechend zu sehr unterschiedlichen Ergebnissen zwischen Simulation und<br />

Implementation führen.<br />

Wenn man mehrere Architekturen verwendet, und sicherstellen will dass <strong>die</strong> richtige<br />

Architektur simuliert wird, empfiehlt sich statt dem „CONFIGURATION“ Befehl <strong>die</strong><br />

verwendung von je e<strong>in</strong>em File pro Architektur.<br />

Dadurch kann bei Quartus <strong>in</strong> der Liste der Design-Files e<strong>in</strong>fach das File e<strong>in</strong>gebunden<br />

werden, welches <strong>die</strong> gerade gewünschte Architektur enthält. Die Kompilations-Liste für<br />

Modelsim wird jeweils von Quartus automatisch erstellt, oder kann bei Bedarf auch<br />

manuell editiert werden.<br />

10


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

3 Konzepte<br />

3.1 Grundlagen<br />

Sequentiell<br />

Concurrent<br />

Beispiel<br />

<strong>VHDL</strong> besitzt zwei Arten von Anweisungen.<br />

Sequentielle Anweisungen werden wie bei Softwarebeschreibungssprachen<br />

strikt nache<strong>in</strong>ander abgearbeitet. Nachfolgende Anweisungen können<br />

vorhergehende dabei überschreiben. Die Reihenfolge der Anweisungen<br />

muss also beachtet werden. Da<strong>mit</strong> sequentielle Anweisungen auch wirklich<br />

sequentiell bearbeitet werden, packt man sie <strong>in</strong> e<strong>in</strong>en Prozess.<br />

Nebenläufige Anweisungen s<strong>in</strong>d gleichzeitig wirksam. Die Reihenfolge<br />

der Anweisungen spielt also ke<strong>in</strong>e Rolle. Mit nebenläufigen Anweisungen<br />

wird <strong>die</strong> Parallelität von echter Hardware nachgebildet.<br />

Das Beispiel zeigt drei nebenläufige (concurrent) Blöcke <strong>mit</strong> sequentiellen<br />

Anweisungen.<br />

Prozesse<br />

E<strong>in</strong> Prozess <strong>in</strong> <strong>VHDL</strong> ist e<strong>in</strong> besonderer Bereich <strong>mit</strong> sequentieller Abarbeitung.<br />

E<strong>in</strong> Prozess wird von bestimmten Signaländerungen (def<strong>in</strong>iert <strong>in</strong><br />

e<strong>in</strong>er Sensitivitätsliste) angestossen und dann analog e<strong>in</strong>er konventionellen<br />

Programmiersprache abgearbeitet. Für <strong>in</strong>terne Zwischenresultate können<br />

Variablen def<strong>in</strong>iert werden.<br />

11


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Modularität<br />

Abstraktion<br />

Hierarchie<br />

Für <strong>die</strong> Modellierung werden 3 wichtige Methoden verwendet<br />

Die Modularität hat das Ziel, große Funktionsblöcke zu unterteilen und <strong>in</strong><br />

abgeschlossene Unterblöcke, den so genannten Modulen, zusammenzufassen.<br />

Module werden <strong>in</strong> Packages und Libraries zusammengefasst und können<br />

als Dienstmodule <strong>in</strong> neuen Projekten wiederverwendet werden.<br />

Die Abstraktion erlaubt es, verschiedene Teile e<strong>in</strong>es Modells unterschiedlich<br />

detailliert zu beschreiben. Module, <strong>die</strong> nur für <strong>die</strong> Simulation gebraucht<br />

werden, müssen z.B. nicht so genau beschrieben werden, wie Module<br />

<strong>die</strong> für <strong>die</strong> Synthese gedacht s<strong>in</strong>d. Verschiedene Ebenen der Abstraktion<br />

s<strong>in</strong>d z.B. <strong>die</strong> Verhaltensbeschreibung oder <strong>die</strong> Register-Transfer-<br />

Ebene (siehe weiter unten).<br />

Die Hierarchie erlaubt es, e<strong>in</strong> System aus mehreren Modulen, <strong>die</strong> wiederum<br />

aus mehreren Modulen bestehen können, aufzubauen. <strong>E<strong>in</strong>e</strong> Ebene <strong>in</strong><br />

der Beschreibungshierarchie kann e<strong>in</strong> oder mehrere Module <strong>mit</strong> unterschiedlichen<br />

Abstraktionsgrad, be<strong>in</strong>halten. Die Untermodule der dar<strong>in</strong> enthaltenen<br />

Module bilden <strong>die</strong> nächste darunter liegende Hierarchieebene.<br />

Dadurch kann e<strong>in</strong> Entwurf schrittweise Top-Down verfe<strong>in</strong>ert werden.<br />

3.2 Abstraktionsebenen<br />

Verhaltensbeschreibung<br />

(behaviour)<br />

Die Verhaltensebene gibt <strong>die</strong> funktionale Beschreibung des Modells wieder.<br />

Es gibt ke<strong>in</strong>en Systemtakt und <strong>die</strong> Signalwechsel s<strong>in</strong>d asynchron, <strong>mit</strong><br />

Schaltzeiten beschrieben. Man beschreibt Bussysteme oder komplexe Algorithmen,<br />

ohne auf <strong>die</strong> Synthetisierbarkeit e<strong>in</strong>zugehen.<br />

Input<br />

Output<br />

IN_1<br />

IN_2<br />

IN_3<br />

out = f(<strong>in</strong>)<br />

OUT<br />

Specification:<br />

Input<br />

Output<br />

max 100 ns<br />

Das Bild zeigt e<strong>in</strong>e e<strong>in</strong>fache Vorgabe für <strong>die</strong> Funktion e<strong>in</strong>es Moduls. Es<br />

soll aus den drei E<strong>in</strong>gängen I1, I2, I3 e<strong>in</strong> Ausgangswert (Output) berechnet<br />

werden. Des Weiteren ist vorgegeben, dass der Ausgangswert nach maximal<br />

100 ns, nachdem sich <strong>die</strong> E<strong>in</strong>gänge geändert haben, stabil anliegen<br />

muss. Als Verhaltensbeschreibung <strong>in</strong> <strong>VHDL</strong> wird <strong>die</strong>s zum Beispiel als<br />

entsprechende Gleichung (I1 + I2*I3) modelliert. Das Ergebnis der Gleichung<br />

wird direkt an das Ausgangssignal <strong>mit</strong> der angenommenen maximal<br />

erlaubten Bearbeitungszeit verzögert (after 100 ns) an den Ausgang übergeben.<br />

Das Verhaltensmodell ist e<strong>in</strong>e e<strong>in</strong>fache Art, das Verhalten e<strong>in</strong>er Schaltung<br />

ähnlich den herkömmlichen Programmiersprachen wie PASCAL oder C<br />

zu beschreiben.<br />

12


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Register-Transfer-Level<br />

(RTL) oder Datenflussbeschreibung<br />

Auf Register-Transfer-Ebene versucht man das System <strong>in</strong> Blöcken re<strong>in</strong>er<br />

Komb<strong>in</strong>atorik oder <strong>mit</strong> Registern zu beschreiben. Letztendlich besteht das<br />

Design <strong>in</strong> der RT-Ebene nur aus zwei unterschiedlichen, nebenläufigen<br />

Prozessen (siehe Kap. 8.1): Zum e<strong>in</strong>en der re<strong>in</strong> komb<strong>in</strong>atorische Prozess<br />

und zum anderen der getaktete Prozess. Der getaktete Prozess erzeugt<br />

Flip-Flops und beschreibt letztendlich e<strong>in</strong>en Zustandsautomaten.<br />

IN_B<br />

IN_B<br />

CLOCK<br />

RESET<br />

registered process<br />

state<br />

logic<br />

FFs<br />

comb<strong>in</strong>atorial<br />

process<br />

output<br />

logic<br />

OUT_A<br />

OUT_B<br />

Logikebene<br />

Layout<br />

Es werden bei der Modellierung also zusätzlich zu den Datene<strong>in</strong>gängen<br />

und Datenausgängen noch <strong>die</strong> Steuersignale berücksichtigt, wie e<strong>in</strong> Taktsignal<br />

(CLOCK) und gegebenenfalls e<strong>in</strong>e Rücksetzsignal (RESET). Diese<br />

Steuersignale s<strong>in</strong>d für <strong>die</strong> Register notwendig.<br />

Man sieht, dass auf RT-Ebene nicht nur <strong>die</strong> re<strong>in</strong>e Funktion (logic) beschrieben<br />

wird, sondern auch Strukturen (Trennung <strong>in</strong> speichernde und<br />

nichtspeichernde Elemente) und Zeit (<strong>in</strong> Form der zeitgleichen Aktualisierung<br />

durch e<strong>in</strong> Taktsignal) berücksichtigt werden.<br />

Auf RT-Ebene ist der Takt das entscheidende Merkmal. Alle Operationen<br />

werden auf e<strong>in</strong> Taktsignal bezogen. Die RT-Level Simulation gibt ke<strong>in</strong>en<br />

Aufschluss über das reale Zeitverhalten, d.h. ob auch wirklich <strong>in</strong>nerhalb<br />

e<strong>in</strong>er Taktperiode alle Signale zur Ruhe gekommen s<strong>in</strong>d.<br />

Auf Logikebene wird das gesamte Design durch Logikgatter und speichernde<br />

Elemente beschrieben. Das entspricht e<strong>in</strong>er sog. Netzliste. Hierfür<br />

benötigt es e<strong>in</strong>e Zellenbibliothek, <strong>in</strong> der <strong>die</strong> e<strong>in</strong>zelnen Gatterparameter<br />

(fan-<strong>in</strong>, fan-out, Verzögerungszeiten, Temperaturabhängigkeiten...) enthalten<br />

s<strong>in</strong>d. Den Schritt von der RT-Ebene zur Logikebene übernehmen <strong>die</strong><br />

Synthesewerkzeuge.<br />

Die unterste Ebene bildet bei e<strong>in</strong>em ASIC das physikalische Layout der<br />

Standard-Zellen, beziehungsweise bei e<strong>in</strong>em FPGA das Mapp<strong>in</strong>g der<br />

Funktionen auf <strong>die</strong> vorhandenen Logik-Zellen. Hier werden <strong>die</strong> verschiedenen<br />

elektronischen Bauelemente <strong>in</strong> der entsprechenden Technologie auf<br />

dem Chip verteilt: Bei e<strong>in</strong>em ASIC, <strong>in</strong>dem <strong>die</strong> entsprechenden Gatter platziert<br />

werden (Plac<strong>in</strong>g) oder bei e<strong>in</strong>em FPGA, <strong>in</strong>dem aus den frei verfügbaren<br />

Gattern <strong>die</strong>se zugeordnet werden (Fitt<strong>in</strong>g).<br />

In e<strong>in</strong>em zweiten Schritt werden dann <strong>die</strong> so def<strong>in</strong>ierten Gatter <strong>mit</strong>e<strong>in</strong>ander<br />

verbunden (Rout<strong>in</strong>g). Da<strong>mit</strong> s<strong>in</strong>d dann <strong>die</strong> Leitungslängen und <strong>die</strong> Leitungsverzögerungen<br />

bekannt.<br />

Das Design kann auf <strong>die</strong>ser Ebene auch wieder simuliert werden, wobei<br />

jetzt weniger <strong>die</strong> Funktionalität als mehr das Zeitverhalten der gesamten<br />

Schaltung überprüft werden. Weil <strong>mit</strong> steigender Information auch der<br />

Aufwand für <strong>die</strong> Simulation stark ansteigt, werden solche „post-fitt<strong>in</strong>g“<br />

Simulationen nur begrenzt und sehr gezielt durchgeführt. Statt <strong>die</strong>ser auch<br />

„back-annotated“ genannten Simulation werden Static-Tim<strong>in</strong>g-Analysis<br />

Werkzeuge verwendet, welche nicht jeden Pfad e<strong>in</strong>zeln simulieren, sondern<br />

aus den verschiedenen echten Laufzeiten <strong>die</strong> gegenseitigen Abhängigkeiten<br />

berechnen und überprüfen.<br />

13


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

3.3 Beispiel 3-Bit Komparator<br />

Zur Veranschaulichung folgen zwei Beispiele, beide <strong>in</strong> zwei Versionen. Beide Versionen erzeugen das genau<br />

gleiche Verhalten auch wenn sie ev. unterschiedlich <strong>in</strong> e<strong>in</strong>em programmierbaren Bauste<strong>in</strong> implementiert werden.<br />

Das erste Beispiel beschreibt e<strong>in</strong>en 3-Bit Komparator. Bei gleichem E<strong>in</strong>gangssignal geht der Ausgang auf logisch<br />

1.<br />

Register-Level Beschreibung<br />

(Datenflussbeschreibung)<br />

Verhaltensbeschreibung (behaviour)<br />

ENTITY ThreeBitComp IS<br />

PORT (<br />

a, b : IN std_logic_vector(0 TO 2);<br />

eq : OUT std_logic<br />

);<br />

END ENTITY ThreeBitComp;<br />

ENTITY ThreeBitComp IS<br />

PORT (<br />

a, b : IN std_logic_vector(0 TO 2);<br />

eq : OUT std_logic<br />

);<br />

END ENTITY ThreeBitComp;<br />

ARCHITECTURE dataflow OF ThreeBitComp IS<br />

BEGIN<br />

eq


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

3.4 Beispiel 3-Bit Zähler<br />

Das nächste Beispiel beschreibt e<strong>in</strong>en 3-Bit Zähler.<br />

Register-Level Beschreibung<br />

(Datenflussbeschreibung)<br />

Verhaltensbeschreibung (behaviour)<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

ENTITY three_bit_counter IS<br />

PORT (<br />

clk : IN std_logic;<br />

enable : IN std_logic;<br />

count : OUT unsigned (2 DOWNTO 0);<br />

END ENTITY three_bit_counter;<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

USE IEEE.numeric_std.ALL;<br />

ENTITY three_bit_counter IS<br />

PORT (<br />

clk : IN std_logic;<br />

enable : IN std_logic;<br />

count : OUT unsigned (2 DOWNTO 0);<br />

END ENTITY three_bit_counter;<br />

ARCHITECTURE dataflow OF three_bit_counter<br />

IS<br />

TYPE t_state IS (s0, s1, s2, s3,<br />

s4, s5, s6, s7 );<br />

ARCHITECTURE behave OF three_bit_counter IS<br />

SIGNAL current_count<br />

: unsigned (2 DOWNTO 0);<br />

SIGNAL state, next_state: t_state;<br />

BEGIN<br />

comb<strong>in</strong>atorial : PROCESS (state)<br />

BEGIN<br />

CASE state IS<br />

WHEN s0 => next_state


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

4 Datentypen<br />

4.1 Skalare Datentypen<br />

Der Datentyp def<strong>in</strong>iert <strong>die</strong> möglichen Werte e<strong>in</strong>es Objektes<br />

und <strong>die</strong> Operationen, <strong>die</strong> <strong>mit</strong> ihm ausgeführt<br />

werden können. So ist es z.B. nicht möglich, e<strong>in</strong>em<br />

digitalen Signal e<strong>in</strong>en Integer-Wert zuzuweisen.<br />

Als Standarddatentypen s<strong>in</strong>d <strong>in</strong> <strong>VHDL</strong> u.a. def<strong>in</strong>iert:<br />

BOOLEAN: false / true SIGNAL done : BOOLEAN := FALSE;<br />

BIT: '0' / '1' SIGNAL a : BIT := ‘0’;<br />

INTEGER:<br />

- 2 147 483 647 bis<br />

+ 2 147 483 647<br />

VARIABLE start_year: INTEGER := 2004;<br />

REAL: -1.0E38 bis +1.0E38 CONSTANT pi : REAL := 3.14159;<br />

Neben <strong>die</strong>sen Standarddatentypen bietet <strong>VHDL</strong> <strong>die</strong><br />

Möglichkeit, beliebig eigene Datentypen zu def<strong>in</strong>ieren.<br />

(vergleichbar <strong>mit</strong> typedef <strong>in</strong> C/C++)<br />

TYPE identifier IS type_def<strong>in</strong>ition;<br />

TYPE my_<strong>in</strong>teger IS RANGE -6 TO 25;<br />

VARIABLE b : my_<strong>in</strong>teger;<br />

Mit RANGE kann man e<strong>in</strong>en zulässigen Wertebereich<br />

angeben. Dies hat e<strong>in</strong>en zweifachen S<strong>in</strong>n:<br />

- gerät bei der Simulation oder Compilation der<br />

Wert ausserhalb des spezifizierten Bereiches, so<br />

wird e<strong>in</strong> Fehlverhalten des Codes sofort als Fehler<br />

sichtbar<br />

- durch <strong>die</strong> E<strong>in</strong>schränkung werden bei der Compilation<br />

nur <strong>die</strong> notwendigen Bits implementiert, und<br />

<strong>die</strong> ganze Hardware wird effizienter.<br />

Die Variable b kann da<strong>mit</strong> nur ganzzahlige Werte<br />

zwischen -6 und 25 annehmen.<br />

Oder auch<br />

TYPE my_real IS RANGE 0.5 TO 15.0;<br />

VARIABLE a : my_real;<br />

Durch <strong>die</strong> Angabe der Bereichsgrenzen <strong>in</strong> Form von<br />

Float<strong>in</strong>g-Po<strong>in</strong>t-Werten umfasst der gesamte Bereich<br />

REAL-Zahlen <strong>in</strong>nerhalb der gegebenen Grenzen.<br />

Wir verwenden <strong>die</strong> Gross-Kle<strong>in</strong>-Schreibung gezielt<br />

um <strong>die</strong> Sprachelemente von <strong>VHDL</strong> gegenüber den frei<br />

def<strong>in</strong>ierten Namen zu unterscheiden. Dies hilft nicht<br />

nur beim Unterricht, sondern macht bei konsequenter<br />

Anwendung auch den Code übersichtlicher und<br />

dadurch e<strong>in</strong>facher und eleganter.<br />

In <strong>die</strong>sem Zusammenhang ist es nur konsequent,<br />

wenn Typen wie BOOLEAN, BIT, INTEGER und REAL<br />

gross geschrieben werden, da sie e<strong>in</strong> Teil der Sprache<br />

von <strong>VHDL</strong> s<strong>in</strong>d.<br />

Typen wie std_logic, std_logic_vector,<br />

signed und unsigned s<strong>in</strong>d jedoch NICHT Teil der<br />

Sprachdef<strong>in</strong>ition, sondern werden <strong>in</strong> Packages wie<br />

IEEE.std_logic_1164 oder IEEE.numeric_std<br />

def<strong>in</strong>iert.<br />

16


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Bei den Aufzählungstypen müssen alle e<strong>in</strong>zelnen zulässigen<br />

Elemente <strong>die</strong>ses Typs explizit aufführt werden<br />

Für <strong>die</strong> Modellierung digitaler Hardware genügt der<br />

Typ BIT nicht. BIT kann für abstrakte Modelle verwendet<br />

werden, wo <strong>die</strong> elektrischen Details ke<strong>in</strong>e Rolle<br />

spielen.<br />

Im Package std_logic_1164, das sich <strong>in</strong> der<br />

Bibliothek IEEE bef<strong>in</strong>det, wird e<strong>in</strong> Typ<br />

std_logic def<strong>in</strong>iert. Er hat <strong>die</strong> folgenden 9 def<strong>in</strong>ierten<br />

Zustände:<br />

0 logische 0<br />

1 logische 1<br />

L<br />

schwach auf 0 gehalten<br />

H<br />

schwach auf 1 gehalten<br />

U<br />

nicht <strong>in</strong>itialisiert<br />

W<br />

schwach, zu unbestimmt<br />

X<br />

nicht bestimmbar<br />

Z<br />

hochohmig<br />

- don’t care<br />

std_logic_vector ist entsprechend e<strong>in</strong> Vektor<br />

aus e<strong>in</strong>zelnen Bits, wobei jedes <strong>die</strong>ser Bits jeden<br />

beliebigen für std_logic def<strong>in</strong>ierten Zustand annehmen<br />

kann.<br />

Zum Beispiel könnte e<strong>in</strong> Steuersignal für e<strong>in</strong>e ALU<br />

<strong>die</strong> Werte add, sub, mul und div annehmen.<br />

TYPE alu_function IS (add, sub,<br />

mul, div);<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

ENTITY test IS<br />

PORT(<br />

a, b : IN std_logic;<br />

bus : OUT std_logic_vector<br />

(7 DOWNTO 0)<br />

);<br />

END ENTITY test;<br />

4.2 Komplexe Typen (composite)<br />

Komplexe Datentypen bestehen aus Werten, <strong>die</strong> mehrere<br />

Elemente be<strong>in</strong>halten. Es gibt Arrays und Records.<br />

4.2.1 Arrays<br />

Arrays s<strong>in</strong>d e<strong>in</strong>e Sammlung von durchnummerierten<br />

Elemente des gleichen Typs<br />

Zu den skalaren Typen s<strong>in</strong>d bereits e<strong>in</strong>ige Arraytypen<br />

vordef<strong>in</strong>iert, <strong>in</strong>sbesondere zu den Typen BIT und<br />

STD_LOGIC. Sie tragen den Zusatz _VECTOR<br />

Benötigt man z.B. e<strong>in</strong>en 4 Bit breiten Datenbus zur<br />

Verknüpfung logischer Komponenten, so könnte man<br />

e<strong>in</strong>en entsprechenden Typ wie folgt deklarieren:<br />

TYPE bus IS ARRAY (0 TO 3) OF BIT;<br />

TYPE bus IS BIT_VECTOR (0 TO 3);<br />

TYPE next_bus IS STD_LOGIC_VECTOR (0 TO 3);<br />

Bei der Angabe ganzer Bereiche ist <strong>die</strong> Laufrichtung<br />

der Index’ wichtig. Bereiche können aufwärts <strong>mit</strong> TO<br />

und abwärts <strong>mit</strong> DOWNTO angegeben werden.<br />

Bei den Array-Zuweisungen gibt es sehr viele Möglichkeiten.<br />

- 4-bit Str<strong>in</strong>g-Zuweisung c


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

- Verschiedenste Komb<strong>in</strong>ationen der obigen Varianten<br />

a j OR k,<br />

1 => I , 2 => '0');<br />

a '0')<br />

Auch Ausschnitte aus Arrays können adressiert werden.<br />

SIGNAL a : BIT_VECTOR (3 DOWNTO 0);<br />

SIGNAL b : BIT_VECTOR (8 DOWNTO 0);<br />

b(6 DOWNTO 3)


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

4.3 Attribute von Datentypen<br />

<strong>VHDL</strong> kennt auch Signalattribute, <strong>die</strong> sich auf Arrays<br />

anwenden lassen:<br />

'LEFT liefert den Index des am weitesten l<strong>in</strong>ks<br />

liegenden Elementes;<br />

'RIGHT liefert den Index des am weitesten<br />

rechts liegenden Elementes;<br />

'HIGH liefert den Index des obersten<br />

Elementes;<br />

'LOW liefert den Index des untersten Elementes;<br />

'LENGTH liefert <strong>die</strong> Länge des Array;<br />

'RANGE liefert den Wertebereich des Index;<br />

'REVERSE_RANGE liefert den Wertebereich des<br />

Index <strong>in</strong> umgekehrter Reihenfolge;<br />

PROCESS (clock)<br />

VARIABLE max_cnt : INTEGER := 0;<br />

BEGIN<br />

FOR i IN counter'RANGE LOOP<br />

IF counter(i) > max_cnt THEN<br />

max_cnt := counter(i);<br />

END IF;<br />

END LOOP;<br />

END PROCESS;<br />

Der FOR … LOOP wird im<br />

Abschnitt 8.4 erklärt …<br />

TYPE t_data_ram IS ARRAY (0 TO 255)<br />

OF INTEGER;<br />

VARIABLE data : t_data_ram;<br />

FOR i IN data’LOW TO data’HIGH LOOP …<br />

4.4 Typumwandlungen<br />

Da bei Signalzuweisungen <strong>die</strong> Signaltypen übere<strong>in</strong>stimmen<br />

müssen (starke Typisierung), werden für verschiedene<br />

Typen von Konvertierungsfunktionen benötigt.<br />

Bei eng verwandten Typen (closely related types)<br />

reicht für <strong>die</strong> Typkonvertierung das Voranstellen des<br />

Ziel Typs. Eng verwandte Typen s<strong>in</strong>d z.B. Arrays derselben<br />

Länge, <strong>mit</strong> derselben Indexmenge und denselben<br />

Elementtypen.<br />

TYPE my_byte IS ARRAY (7 DOWNTO 0)<br />

OF std_logic;<br />

SIGNAL byte : my_byte;<br />

SIGNAL vector : std_logic_vector<br />

(7 DOWNTO 0);<br />

byte


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

4.5 Arithmetik <strong>mit</strong> Vektoren<br />

<strong>VHDL</strong> selbst unterstützt ke<strong>in</strong>e mathematischen Operationen.<br />

Dafür wurden spezielle Packages geschaffen<br />

(siehe auch Kapitel 11).<br />

Für synthetisierbare Funktionen <strong>die</strong> für <strong>die</strong> Ausführung<br />

<strong>in</strong> FPGAs und/oder ASICs bestimmt s<strong>in</strong>d, verwendet<br />

man am besten das Paket<br />

IEEE.numeric_std, welches <strong>die</strong> Typen<br />

unsigned und signed als Vektoren vom Typ<br />

std_logic def<strong>in</strong>iert.<br />

Beim Schreiben von Testbench-Funktionen welche<br />

nicht synthetisiert werden darf man ruhig auch auf<br />

komplexere mathematische Operationen zurückgreifen,<br />

wie S<strong>in</strong>, Cos oder Wurzeln. Dafür verwendet man<br />

<strong>mit</strong> Vorteil das Packet IEEE.math_real beziehungsweise<br />

IEEE.math_complex.<br />

Es gibt noch viele alte Beispiele und<br />

Implementation, welche <strong>die</strong> IEEE<br />

Pakete std_logic_arith sowie<br />

std_logic_signed und<br />

std_logic_unsigned verwenden.<br />

Die dar<strong>in</strong> def<strong>in</strong>ierten Funktionen<br />

können <strong>mit</strong> anderen Def<strong>in</strong>itionen kolli<strong>die</strong>ren<br />

und sollten deshalb nicht mehr verwendet werden.<br />

Ebenso sollte das Packet numeric_bit nicht verwendet<br />

werden, weil es unsigned und signed als<br />

Vektoren vom Typ BIT def<strong>in</strong>iert, und <strong>die</strong>s für reale<br />

Schaltungen nicht alle auftretenden Zustände abbilden<br />

kann.<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

USE IEEE.numeric_std.ALL;<br />

SIGNAL a: UNSIGNED;<br />

a


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

4.6 Typumwandlungen <strong>mit</strong> Vektoren<br />

Die nachfolgende Tabelle zeigt alle Typumwandlungen im Package NUMERIC_STD.<br />

Quellenoperand Zieloperand Funktion<br />

std_logic_vector unsigned unsigned(arg)<br />

std_logic_vector signed signed(arg)<br />

unsigned std_logic_vector std_logic_vector(arg)<br />

signed std_logic_vector std_logic_vector(arg)<br />

INTEGER unsigned to_unsigned(arg, size)<br />

INTEGER signed to_signed(arg, size)<br />

unsigned INTEGER to_<strong>in</strong>teger(arg)<br />

signed INTEGER to_<strong>in</strong>teger(arg)<br />

INTEGER<br />

std_logic_vector<br />

Zuerst <strong>die</strong> <strong>in</strong>teger Zahl <strong>in</strong> unsigned<br />

oder signed wandeln, dann <strong>in</strong><br />

std_logic_vector<br />

std_logic_vector<br />

INTEGER<br />

Zuerst std_logic_vector <strong>in</strong> signed<br />

oder unsigned wandeln, dann weiter<br />

zum Typ INTEGER<br />

unsigned + unsigned std_logic_vector std_logic_vector(arg1 + arg2)<br />

signed + signed std_logic_vector std_logic_vector(arg1 + arg2)<br />

INTEGER<br />

to_unsigned(arg,size)<br />

to_<strong>in</strong>teger(arg)<br />

unsigned<br />

to_<strong>in</strong>teger(arg)<br />

std_logic_vector(arg)<br />

to_signed(arg,size)<br />

signed('0' & arg)<br />

unsigned(arg)<br />

unsigned(arg)<br />

signed<br />

std_logic_vector(arg)<br />

signed(arg)<br />

std_logic_vector<br />

21


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

5 Operatoren<br />

Die folgende Tabelle führt alle Klassen von Operatoren<br />

nach Prioritäten geordnet (von oben nach unten)<br />

auf.<br />

NOT ** ABS<br />

* / MOD REM<br />

- (Negation)<br />

+ - &<br />

SLL SRL SLA SRA ROL ROR SRL<br />

= /= < = > /=<br />

AND OR NAND NOR XOR XNOR OR<br />

c


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

6 Parallel laufende Anweisungen<br />

Innerhalb e<strong>in</strong>er Architektur laufen alle Prozesse parallel<br />

(concurrent) ab. Die Reihenfolge der e<strong>in</strong>zelnen<br />

Anweisungen hat weder auf das Verhalten noch auf<br />

<strong>die</strong> resultierende Hardware e<strong>in</strong>en E<strong>in</strong>fluss hat.<br />

Es ist nicht möglich, <strong>mit</strong> nebenläufigen Anweisungen<br />

alle<strong>in</strong>e speichernde Elemente, wie z.B. Flip Flops zu<br />

modellieren. Allerd<strong>in</strong>gs kann umgekehrt jede concurrent<br />

Anweisung durch e<strong>in</strong>en entsprechenden Prozess<br />

beschrieben werden.<br />

Concurrent<br />

statement 1<br />

Concurrent<br />

statement 2<br />

Concurrent<br />

statement 3<br />

<strong>VHDL</strong> Code<br />

Signals<br />

6.1 Signalzuweisung<br />

<strong>E<strong>in</strong>e</strong> Signalzuweisung (Signal Assignment) ist e<strong>in</strong><br />

Concurrent Statement; sie wird also gleichzeitig <strong>mit</strong><br />

anderen Signalzuweisungen abgearbeitet.<br />

target


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

7 Signale und Variablen<br />

7.1 Deklaration von Signalen<br />

Signale verb<strong>in</strong>den e<strong>in</strong>zelne Elemente (z.B. Prozesse,<br />

Komponenten) – sie s<strong>in</strong>d quasi Leitungen. Signale<br />

werden wie folgt deklariert:<br />

SIGNAL signal_name : TYPE<br />

[: = <strong>in</strong>it_val];<br />

In der Syntax der Signaldeklaration kann man dem<br />

Signal optional e<strong>in</strong>en def<strong>in</strong>ierten Anfangswert <strong>mit</strong>geben.<br />

Geschieht das nicht, wie <strong>in</strong> nebenstehendem Beispiel,<br />

so ist der Anfangswert des deklarierten Objektes bei<br />

e<strong>in</strong>er FPGA-Implementation abhängig von se<strong>in</strong>em<br />

Datentyp:<br />

- bei sogenannten skalaren Datentypen <strong>mit</strong> def<strong>in</strong>ierten<br />

Wertebereichen gilt dann automatisch der<br />

kle<strong>in</strong>ste Wert<br />

- bei INTEGER als skalarer Datentyp wird es zu -<br />

2 147 483 647 (= -2 31 + 1)<br />

SIGNAL sel: std_logic := '1';<br />

SIGNAL count : std_logic_vector<br />

(7 DOWNTO 0)<br />

:= "00001111";<br />

TYPE t_state IS (wait<strong>in</strong>g, runn<strong>in</strong>g,<br />

dead);<br />

SIGNAL my_state : t_state;<br />

IF my_state = wait<strong>in</strong>g THEN …<br />

Dies liefert <strong>in</strong> e<strong>in</strong>em FPGA das Resultat TRUE für<br />

ersten Durchlauf, da bei e<strong>in</strong>em Aufzählungs-Typ der<br />

erste Wert als Default angenommen wird.<br />

- Bei REAL wird <strong>die</strong>s zu -1 ∙ 10 308<br />

- bei Enumerationen, <strong>die</strong> e<strong>in</strong>e explizite Aufzählung<br />

der e<strong>in</strong>zelnen Werte des Datentyps darstellen,<br />

kommt der erste Wert <strong>in</strong> der Liste zur Anwendung.<br />

- Bei std_logic wird der Wert zu „U“ für<br />

„Unknown“ (unbekannt). Das gleiche gilt auch<br />

für std_logic_vector.<br />

- Bei BIT ist der Default Wert '0',<br />

- bei BOOLEAN ist es FALSE<br />

Im Gegensatz zu e<strong>in</strong>em FPGA (wo<br />

alle Register automatisch <strong>in</strong>itialisiert<br />

werden) wird bei e<strong>in</strong>em ASIC e<strong>in</strong><br />

nicht def<strong>in</strong>iertes Signal nicht e<strong>in</strong>fach<br />

„0“, sondern kann tatsächlich e<strong>in</strong>en<br />

zufälligen Wert annehmen.<br />

Deshalb ist es IMMER e<strong>in</strong>e sehr gute Idee, alle Signale<br />

explizit <strong>mit</strong> e<strong>in</strong>em Anfangswert zu def<strong>in</strong>ieren!<br />

24


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Signale können nur an zwei Stellen deklariert werden:<br />

1. In der Port-Deklaration e<strong>in</strong>er Entity.<br />

2. Innerhalb der Declarative Region e<strong>in</strong>er Architektur.<br />

Die so genannten Declarative Region e<strong>in</strong>er Architektur<br />

bef<strong>in</strong>det sich nach dem Schlüsselwort<br />

ARCHITECTURE … IS, aber noch vor dem<br />

BEGIN Befehl.<br />

ENTITY xyz IS<br />

PORT (<br />

clock : IN std_logic;<br />

led : OUT std_logic;<br />

q : OUT std_logic<br />

);<br />

END ENTITY xyz;<br />

ARCHITECTURE rtl OF concurrent IS<br />

SIGNAL <strong>in</strong>t : std_logic;<br />

BEGIN<br />

<strong>in</strong>t


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

7.3 Attribute von Signalen<br />

Neben den Attributen für Datentypen (siehe Kapitel<br />

4.3) gibt es <strong>in</strong> <strong>VHDL</strong> auch signalgebundene Attribute.<br />

Signalattribute liefern Informationen über Signale,<br />

auf <strong>die</strong> sie angewendet werden. Das Format e<strong>in</strong>es<br />

Standardaufrufes sieht folgendermaßen aus:<br />

object_name ' attribute_designator<br />

Taktflankengesteuertes D-Latch <strong>mit</strong> Abfrage e<strong>in</strong>es<br />

Signalattributes:<br />

PROCESS (clk)<br />

BEGIN<br />

IF clk = 'l' AND clk'EVENT THEN<br />

q


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

7.4 Variablen<br />

In e<strong>in</strong>em sequentiellen Code müssen Zuweisungen<br />

e<strong>in</strong>er Zeile sehr oft <strong>in</strong> der nächsten Zeile schon zur<br />

Verfügung stehen, da es ke<strong>in</strong>e Iterationen gibt. Der<br />

E<strong>in</strong>satz von Signalen ist hier also nicht immer s<strong>in</strong>nvoll.<br />

Daher bietet <strong>VHDL</strong> <strong>mit</strong> den Variablen e<strong>in</strong>e weitere<br />

Objektklasse, der sofort ohne Zeitfaktor e<strong>in</strong> neuer<br />

Wert zugewiesen werden kann. Durch <strong>die</strong>se Eigenschaft<br />

s<strong>in</strong>d Variablen speziell für <strong>die</strong> Verwendung<br />

<strong>in</strong> sequentiellem Code geeignet.<br />

Variablen werden bei jedem Prozess-Aufruf neu „geboren“,<br />

und gelten nur bis zum Ende der Prozessbearbeitung.<br />

Sie existieren nicht ausserhalb e<strong>in</strong>es Prozesses<br />

und können deshalb z.B. auch nicht <strong>in</strong> der<br />

Declarative Region e<strong>in</strong>er Architektur def<strong>in</strong>iert werden.<br />

Variablen sollten nur für Zwischenresultate<br />

verwendet werden. Den<br />

Wert e<strong>in</strong>er Variablen aus e<strong>in</strong>em<br />

Prozess-Durchgang im nächsten<br />

Durchgang wieder weiter zu verwenden<br />

(z.B. für e<strong>in</strong>en Zähler) ist e<strong>in</strong>e sehr schlechte<br />

Praxis, weil man dabei riskiert dass e<strong>in</strong> Latch implementiert<br />

wird. Das führt dann zu dramatisch unterschiedlichen<br />

Resultaten zwischen Simulation und<br />

dem Tim<strong>in</strong>g <strong>in</strong> Hardware! Die Folge ist e<strong>in</strong>e schlechte<br />

Performanz der Schaltung.<br />

one_bit_add : PROCESS (a,b,c_<strong>in</strong>)<br />

VARIABLE sig : std_logic;<br />

BEGIN<br />

sig := a XOR b;<br />

sum


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

8 Sequentielle Anweisungen<br />

Will man <strong>VHDL</strong> <strong>in</strong> e<strong>in</strong>em Top-down-Designablauf<br />

e<strong>in</strong>setzen, so müssen Modelle ohne irgendwelche<br />

Vorstellungen über <strong>die</strong> entsprechende Hardware auf<br />

e<strong>in</strong>er sehr hohen Abstraktionsebene dargestellt werden<br />

können.<br />

8.1 Der Prozess<br />

Nachdem im <strong>VHDL</strong>-Architekturbereich zwischen<br />

BEGIN und END nur „concurrent“ gearbeitet werden<br />

darf, schuf man <strong>in</strong> der <strong>VHDL</strong>-Syntax besondere Bereiche<br />

<strong>mit</strong> sequentiellem <strong>in</strong>ternem Ablauf.<br />

Die ganze Architektur kann <strong>mit</strong> e<strong>in</strong>em oder mehreren<br />

<strong>VHDL</strong>-Konstrukten gefüllt se<strong>in</strong>, <strong>die</strong> jeweils <strong>mit</strong> dem<br />

Schlüsselwort PROCESS beg<strong>in</strong>nen und <strong>mit</strong> END<br />

PROCESS abgeschlossen werden.<br />

E<strong>in</strong> Prozess wird <strong>in</strong> se<strong>in</strong>er Gesamtheit parallel <strong>mit</strong> anderen<br />

abgearbeitet, <strong>in</strong>nerhalb des Bereiches zwischen<br />

BEGIN und END PROCESS allerd<strong>in</strong>gs läuft der<br />

Code grundsätzlich nur sequentiell ab. In <strong>die</strong>sem Bereich<br />

können abstrakte Algorithmen beschrieben werden,<br />

wie sie aus anderen Hochsprachen bekannt s<strong>in</strong>d.<br />

ARCHITECTURE algorithm OF my_nor IS<br />

BEGIN<br />

comb_proc : PROCESS<br />

VARIABLE <strong>in</strong>t : std_logic;<br />

BEGIN<br />

IF (a = 'l') OR (b = 'l') THEN<br />

<strong>in</strong>t := 'l';<br />

ELSE<br />

<strong>in</strong>t := '0';<br />

END IF;<br />

c


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

Es gibt 4 Grundformen der WAIT Anweisung.<br />

• Unterbrechen des Prozesses bis e<strong>in</strong> Signalwechsel<br />

passiert.<br />

• Unterbrechen des Prozesses bis e<strong>in</strong>e Bed<strong>in</strong>gung<br />

erfüllt ist.<br />

• Unterbrechen des Prozesses bis e<strong>in</strong>e Zeitspanne<br />

verstrichen ist<br />

• Unendlich langes Warten. Da e<strong>in</strong> Prozess<br />

immer aktiv ist, bietet <strong>die</strong>se Anweisung <strong>die</strong><br />

e<strong>in</strong>zige Möglichkeit ihn anzuhalten (z.B.<br />

nach der Initialisierungen)<br />

Die Signale selber erhalten ihren Ausgangswert erst<br />

am Ende des Prozesses (im Falle e<strong>in</strong>er Sensitivitätsliste)<br />

oder bei Erreichen e<strong>in</strong>es WAIT-Statements.<br />

Aus <strong>die</strong>sem Grund kann e<strong>in</strong>em Signal <strong>in</strong>nerhalb des<br />

Prozesses mehrfach e<strong>in</strong> Wert zugewiesen werden,<br />

weil <strong>die</strong> Zuweisung erst am Ende ausgeführt wird.<br />

Andererseits erklärt <strong>die</strong>s auch, warum <strong>die</strong> „Zwischenresultate“<br />

von Signalen, anders als bei Variablen,<br />

nicht zur Verfügung stehen.<br />

Da e<strong>in</strong> Prozess als Ganzes e<strong>in</strong>e gleichzeitige Anweisung<br />

ist (concurrent), kann der Modellierer beim Entwerfen<br />

von Modellen weiterh<strong>in</strong> <strong>in</strong> Blöcken denken.<br />

Da<strong>mit</strong> lässt sich <strong>die</strong> Beschreibung e<strong>in</strong>es komplexen<br />

Systems <strong>in</strong> übersichtliche funktionelle Blöcke aufteilen.<br />

Diese „concurrent“ Blöcke werden gleichzeitig<br />

abgearbeitet und können wie <strong>in</strong> e<strong>in</strong>em Blockschaltbild<br />

über Signale <strong>mit</strong>e<strong>in</strong>ander verbunden werden.<br />

Siehe dazu das Beispiel auf der rechten Seite. Zwei<br />

Prozesse simulieren e<strong>in</strong>e Erzeuger / Verbraucher Situation.<br />

Über e<strong>in</strong> e<strong>in</strong>faches Handshake-Protokoll<br />

(producer_done und consumer_done)<br />

werden <strong>die</strong> Prozesse synchronisiert. Dabei wird angenommen,<br />

dass <strong>die</strong> Tätigkeit des „produce“ und „consume“<br />

e<strong>in</strong>e bestimmte Zeit oder Zyklen braucht.<br />

Nachdem sequentieller Code immer nur zeilenweise<br />

von Anfang bis Ende abgearbeitet wird, muss er <strong>mit</strong><br />

anderen Mitteln als durch Signaländerungen parallel<br />

gesteuert werden. Zu <strong>die</strong>sem Zweck gibt es <strong>in</strong> <strong>VHDL</strong><br />

Konstrukte wie IF-Statements oder Schleifen.<br />

WAIT ON a, b, c;<br />

WAIT UNTIL x > 10;<br />

WAIT FOR 10 ns;<br />

WAIT;<br />

<strong>in</strong>terest<strong>in</strong>g : PROCESS (a, b, c)<br />

BEGIN<br />

x


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

8.1.2 Aktivierung für <strong>die</strong> Simulation<br />

Im Gegensatz zur echten Hardware wie z.B. <strong>in</strong> e<strong>in</strong>em<br />

FPGA oder ASIC muss bei der Simulation e<strong>in</strong> Prozess<br />

durch <strong>die</strong> Änderung e<strong>in</strong>es Signals der Sensitivity-Liste<br />

aktiviert werden.<br />

Dabei kann es wesentliche Unterschiede im Verhalten<br />

geben, wenn nicht alle notwendigen Signale <strong>in</strong><br />

der Sensitivity-Liste aufgeführt s<strong>in</strong>d.<br />

Bei e<strong>in</strong>em Latch soll der E<strong>in</strong>gang auf den Ausgang<br />

kopiert werden solange das Enable Signal hoch ist.<br />

Ist das Enable Signal tief, soll der letzte Zustand des<br />

E<strong>in</strong>gangs gehalten werden.<br />

Von den drei Beispielen rechts funktioniert<br />

nur das dritte Modell richtig.<br />

Bei den ersten beiden wird der Ausgang<br />

sich nicht ändern, wenn Enable<br />

hoch ist, und der E<strong>in</strong>gang sich ändert<br />

weil der Prozess durch das E<strong>in</strong>gangs-Signal<br />

„<strong>in</strong>“ nicht aktiviert wird!<br />

latch_1 : PROCESS (enable);<br />

BEGIN<br />

q


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

8.2 Das IF-Statement<br />

Ist <strong>die</strong> Bed<strong>in</strong>gung nach dem IF nicht erfüllt, werden,<br />

wenn vorhanden, <strong>die</strong> Bed<strong>in</strong>gung nach ELSIF geprüft<br />

(alternative zu ELSE IF um <strong>die</strong> Verschachtelung <strong>in</strong><br />

Grenzen zu halten). Treffen <strong>die</strong>se ebenfalls nicht zu,<br />

so wird das Statement nach dem ELSE ohne weitere<br />

Überprüfung ausgeführt (falls vorhanden). <strong>E<strong>in</strong>e</strong> beliebige<br />

Anzahl von ELSlF-Statements darf vorkommen.<br />

ELSE steht nur e<strong>in</strong>mal am Ende des IF Statements<br />

oder kann ganz weggelassen werden.<br />

Als e<strong>in</strong>faches Beispiel zeigt e<strong>in</strong> Prozess, der e<strong>in</strong><br />

NAND-Gatter algorithmisch beschreibt.<br />

ENTITY alg_nand IS<br />

PORT (<br />

a, b : IN std_logic;<br />

c : OUT std_logic<br />

);<br />

END ENTITY alg_nand;<br />

ARCHITECTURE rtl OF alg_nand IS<br />

BEGIN<br />

nand_proc : PROCESS (a, b)<br />

BEGIN<br />

IF a = '1' AND b = '1' THEN<br />

c < = '0';<br />

ELSIF a = '0' OR b = '0' THEN<br />

c < = '1';<br />

ELSE<br />

c < = 'X';<br />

END IF;<br />

END PROCESS nand_proc;<br />

END ARCHITECTURE algorithm;<br />

8.3 Das Case-Statement<br />

<strong>E<strong>in</strong>e</strong> weitere Möglichkeit für <strong>die</strong> Steuerung von sequentiellem<br />

Code ist das CASE Statement.<br />

Das Statement CASE ... IS überprüft den Zustand<br />

e<strong>in</strong>es Signales und führt e<strong>in</strong>e bestimmte Aktion<br />

abhängig vom Ergebnis aus. Das CASE-Statement<br />

muss vollständig auflösbar se<strong>in</strong>, das bedeutet, jedem<br />

möglichen Zustand (Datentyp und gegebenenfalls<br />

Wertebereich beachten!) des geprüften Ausdrucks<br />

muss e<strong>in</strong>e Aktion zugewiesen werden. WHEN<br />

OTHERS <strong>die</strong>nt dazu, sämtliche noch nicht abgefragten<br />

Zustände zu erfassen und <strong>die</strong>sen e<strong>in</strong>e geme<strong>in</strong>same<br />

Aktion zuzuweisen (analog dem „default“-Statement<br />

<strong>in</strong> Java).<br />

Im Beispiel rechts könnte man denken, dass <strong>mit</strong> den 4<br />

Komb<strong>in</strong>ationen alle Möglichkeiten bereits abgedeckt<br />

s<strong>in</strong>d, und dass es deshalb das WHEN OTHERS nicht<br />

braucht.<br />

Da aber sel vom Typ std_logic ist, kann das<br />

Signal auch Zustände wie „UU“ oder „X1“ annehmen.<br />

ENTITY mux_4_to_1 IS<br />

PORT (<br />

a,b,c,d : IN std_logic;<br />

sel : IN std_logic_vector<br />

(1 DOWNTO 0);<br />

out : OUT std_logic<br />

);<br />

END ENTITY mux_4_to_1;<br />

ARCHITECTURE rtl OF mux_4_to_1 IS<br />

BEGIN<br />

mux_proc : PROCESS (a,b,c,d,sel)<br />

BEGIN<br />

CASE sel IS<br />

WHEN "00" => out out out out out


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

8.4 Die FOR-Schleife<br />

Die generelle Syntax für <strong>die</strong> FOR-Schleife ist wie<br />

folgt:<br />

[loop_label:] FOR identifier IN<br />

discrete_range LOOP<br />

{sequential_statements}<br />

END LOOP [loop_label];<br />

Die Laufvariable <strong>in</strong> der FOR-Schleife ist implizit deklariert,<br />

d.h. sie muss nirgendwo sonst im Code als<br />

Variable def<strong>in</strong>iert werden. Die Variable nimmt automatisch<br />

den Datentyp der Elemente des angegebenen<br />

Wertebereichs an.<br />

Da<strong>mit</strong> <strong>die</strong> FOR-Schleife synthetisierbar<br />

ist, müssen <strong>die</strong> Grenzen des<br />

Wertebereichs konstant und zum<br />

Zeitpunkt der Compilation bekannt<br />

se<strong>in</strong>.<br />

Es ist auch ganz wichtig zu verstehen,<br />

dass <strong>die</strong> FOR-Schleife ke<strong>in</strong>e<br />

sequentiell ausgeführte Logik beschreibt<br />

oder impliziert. Es ist nichts<br />

anderes als Art parallel auszuführenden<br />

Code <strong>mit</strong> regelmässiger Struktur effizient zu beschreiben.<br />

Beide Beispiele rechts erzeugen <strong>die</strong> gleiche Logik<br />

und brauchen exakt gleich viel Zeit für <strong>die</strong> Ausführung!<br />

Zwei Beispiele für e<strong>in</strong>en Prozess, der <strong>die</strong><br />

Reihenfolge (12 Bits) e<strong>in</strong>es Vektors umkehrt.<br />

Die beiden Ko<strong>die</strong>rungen s<strong>in</strong>d absolut<br />

gleichwertig, aber unterschiedlich elegant …<br />

reverse_proc_1 : PROCESS (<strong>in</strong>put)<br />

BEGIN<br />

output(11)


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

8.5 Die WHILE-Schleife<br />

[loop_label:] WHILE condition<br />

LOOP<br />

{sequential_statements}<br />

END LOOP [loop_label];<br />

Hier steht nach dem Schlüsselwort WHILE e<strong>in</strong>e Bed<strong>in</strong>gung,<br />

<strong>die</strong> vor Beg<strong>in</strong>n jedes e<strong>in</strong>zelnen Schleifendurchlaufs<br />

abgefragt wird. Der Durchlauf erfolgt abhängig<br />

vom Ergebnis <strong>die</strong>ser Abfrage. Anders als bei<br />

der FOR-Schleife muss man hier <strong>die</strong> Laufvariable<br />

ausserhalb der Schleife deklarieren. Auch <strong>die</strong> Änderung<br />

der Laufvariablen sowie der Abbruch müssen<br />

explizit gesteuert werden. Hier kann man also Endlosschleifen<br />

aufbauen, <strong>die</strong> nach dem Aufruf nie mehr<br />

verlassen werden.<br />

ARCHITECTURE sim OF my_cos<strong>in</strong>us IS<br />

BEGIN<br />

PROCESS (angle)<br />

VARIABLE sum, term : REAL;<br />

VARIABLE n<br />

: INTEGER;<br />

BEGIN<br />

sum := 1.0;<br />

term := 1.0;<br />

WHILE ABS term > ABS(sum/1.0E6)<br />

LOOP<br />

n := n + 2;<br />

term := (-term) * angle**2 /<br />

real(((n-1)*n));<br />

sum := sum + term;<br />

END LOOP;<br />

result


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

8.7 Der NEXT-Befehl<br />

Mit e<strong>in</strong>em NEXT-Statement wird der aktuelle Durchlauf<br />

e<strong>in</strong>er Schleife abgebrochen und <strong>die</strong> nächste Iteration<br />

begonnen (analog „cont<strong>in</strong>ue“ <strong>in</strong> Java).<br />

Wie auch schon <strong>die</strong> „normale“ LOOP-<br />

Schleife ist <strong>die</strong>se Konstruktion <strong>mit</strong> dem<br />

NEXT-Abbruch synthetisierbar, wenn<br />

der Wertebereich der Schleife zum Zeitpunkt<br />

der Kompilation bekannt und konstant ist.<br />

Der NEXT-Abbruch muss nicht statisch se<strong>in</strong>, sondern<br />

wird e<strong>in</strong>fach als e<strong>in</strong>e Bed<strong>in</strong>gte Ausführung für e<strong>in</strong>en<br />

Teil des Codes implementiert, als ob dort z.B. e<strong>in</strong>e IF<br />

Anweisung <strong>die</strong> entsprechenden Zeilen umgeben würde.<br />

PROCESS (a)<br />

VARIABLE a, b : unsigned<br />

(5 DOWNTO 0);<br />

BEGIN<br />

a := (OTHERS => '0');<br />

b := (OTHERS => '0');<br />

loop_1 : FOR i IN 0 TO 5 LOOP<br />

a := a + 5;<br />

IF a > 20 THEN NEXT loop_1;<br />

END IF;<br />

b := b + 5;<br />

END LOOP loop_1;<br />

END PROCESS;<br />

Wird das NEXT-Kommando durch das IF-Statement<br />

erreicht, so wird <strong>die</strong> Schleife nicht fertig abgearbeitet;<br />

stattdessen beg<strong>in</strong>nt sofort der nächste Schleifendurchgang.<br />

"b := b+5" wird also nicht mehr ausgeführt, wenn<br />

a größer als 20 ist, so dass am Ende der Schleife a den<br />

Wert 25 und b den Wert 20 hat.<br />

34


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

8.8 Beispiel für sequentiellen Code <strong>mit</strong><br />

Schleifen<br />

Der abgebildete Prozess deko<strong>die</strong>rt den b<strong>in</strong>ären 4 Bit<br />

breiten E<strong>in</strong>gang <strong>in</strong>_array derart, dass <strong>in</strong> e<strong>in</strong>em 16<br />

Bit breiten Ausgangsfeld out_array <strong>die</strong> Leitung<br />

gesetzt wird, <strong>die</strong> dem dezimalen Wert des E<strong>in</strong>gangs<br />

entspricht. Liegt am E<strong>in</strong>gang <strong>in</strong>_array also<br />

z.B. der B<strong>in</strong>ärwert "0101" an, so wird der Ausgang<br />

out_array (5) auf '1' gesetzt. Natürlich wäre <strong>die</strong>se<br />

Aufgabe <strong>mit</strong> anderen Sprachkonstrukten wesentlich<br />

eleganter umsetzbar. Das Beispiel eignet sich jedoch<br />

auch gut zur Demonstration von Schleifen.<br />

Liegt an <strong>in</strong>_array e<strong>in</strong> Ereignis vor, so wird <strong>in</strong> der<br />

ersten Schleife e<strong>in</strong>e Variable sum auf den dezimalen<br />

Wert des b<strong>in</strong>ären E<strong>in</strong>gangs gesetzt. Jedes Element von<br />

<strong>in</strong>_array muss dabei vom Datentyp INTEGER<br />

se<strong>in</strong>, da<strong>mit</strong> es multipliziert werden kann. Die Elemente<br />

werden darum <strong>in</strong> e<strong>in</strong>en INTEGER -Typ umgewandelt.<br />

Bei <strong>die</strong>sem Beispiel ist auch zu beachten, dass <strong>die</strong> Variable<br />

sum am Beg<strong>in</strong>n des Prozesses auf 0 gesetzt<br />

werden muss, obwohl sie bereits während der Initialisierung<br />

zurückgesetzt wurde! Dies ist notwendig, da<br />

sich der Prozess nach e<strong>in</strong>em erneuten Aufruf bei e<strong>in</strong>er<br />

Zustandsänderung von <strong>in</strong>_array nur noch zwischen<br />

BEGIN und END bewegt, so dass ke<strong>in</strong>e erneute<br />

Initialisierung mehr erfolgt.<br />

Beispielcode e<strong>in</strong>es 4-zu-1 Decoders<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

USE IEEE.numeric_std.ALL;<br />

ENTITY dec_4_1 IS<br />

PORT(<br />

<strong>in</strong>_array : IN std_logic_vector<br />

( 3 DOWNTO 0);<br />

out_array: OUT std_logic_vector<br />

(15 DOWNTO 0));<br />

END dec_4_1;<br />

ARCHITECTURE behavior OF dec_4_1 IS<br />

BEGIN<br />

PROCESS (<strong>in</strong>_array)<br />

VARIABLE sum : INTEGER<br />

RANGE 0 TO 15;<br />

BEGIN<br />

sum := 0;<br />

sum_of_<strong>in</strong>_array: FOR i IN 0 TO 3<br />

LOOP<br />

IF <strong>in</strong>_array(i) = '1' THEN<br />

sum := sum + (2**i);<br />

END IF;<br />

END LOOP sum_of_<strong>in</strong>_array;<br />

zero_array : FOR j IN 0 TO 15<br />

LOOP<br />

out_array(j)


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

9 Gültigkeitsbereich von Deklarationen<br />

In <strong>VHDL</strong> bestimmt e<strong>in</strong>e Deklaration <strong>die</strong> Bedeutung<br />

e<strong>in</strong>es Objektes. Deklarationen werden <strong>in</strong> den Declarative<br />

Regions von <strong>VHDL</strong>-Elementen gemacht, meistens<br />

zwischen dem Namen e<strong>in</strong>es Elementes und<br />

BEGIN. Nicht alle Arten von Objekten lassen sich <strong>in</strong><br />

jedem Bereich deklarieren. So kann man <strong>in</strong> e<strong>in</strong>er Architektur<br />

ke<strong>in</strong>e Variable deklarieren, <strong>in</strong> e<strong>in</strong>em Prozess<br />

ke<strong>in</strong> Signal.<br />

Der Ort e<strong>in</strong>er Objektdeklaration hat E<strong>in</strong>fluss auf den<br />

Gültigkeitsbereich, den sogenannten Scope der Deklaration.<br />

Pr<strong>in</strong>zipiell ist e<strong>in</strong> Objekt im Bereich der<br />

verwendeten Declarative Region gültig. E<strong>in</strong> Objekt,<br />

das <strong>in</strong>nerhalb e<strong>in</strong>er Architektur deklariert wurde, ist<br />

auch <strong>in</strong>nerhalb jedes Prozesses oder Unterprogrammes<br />

im Inneren <strong>die</strong>ser Architektur bekannt.<br />

Hierarchie der Gültigkeitsbereiche <strong>in</strong> <strong>VHDL</strong><br />

component (design entity)<br />

entity declaration<br />

architecture<br />

Concurrent<br />

block<br />

process<br />

Sequential<br />

subprogram<br />

Die Sichtbarkeit (Visibility) e<strong>in</strong>es Objektes beschreibt<br />

<strong>die</strong> Bereiche, <strong>in</strong> denen der Zugriff auf e<strong>in</strong> gültiges<br />

Objekt möglich ist.<br />

Im Inneren des Prozesses ist <strong>die</strong> <strong>in</strong> der Architektur<br />

def<strong>in</strong>ierte Konstante x zwar gültig, aber nicht sichtbar.<br />

Sie wird von der deklarierten Variable x verdeckt.<br />

Code <strong>in</strong>nerhalb des Prozesses wird also immer<br />

nur <strong>die</strong> Variable x sehen.<br />

Man kann über Selected Names trotzdem auf nicht<br />

sichtbare Objekte zugreife. Stellt man vor den Objektnamen<br />

den Namen des Deklarationsabschnittes,<br />

<strong>in</strong> dem das Objekt deklariert wurde, so ist es für den<br />

Compiler sichtbar.<br />

ARCHITECTURE test_1 OF example IS<br />

-- global def<strong>in</strong>ition<br />

CONSTANT x: INTEGER := 2;<br />

BEGIN<br />

p1 : PROCESS (<strong>in</strong>)<br />

-- local def<strong>in</strong>ition<br />

VARIABLE x : INTEGER := 3;<br />

BEGIN<br />

...<br />

END PROCESS p1;<br />

END ARCHITECTURE test;<br />

ARCHITECTURE test_2 OF example IS<br />

-- global def<strong>in</strong>ition<br />

CONSTANT x: INTEGER := 2;<br />

BEGIN<br />

p2 : PROCESS (<strong>in</strong>)<br />

-- local def<strong>in</strong>ition<br />

VARIABLE x : INTEGER := 3;<br />

BEGIN<br />

out_1


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

10 Unterprogramme<br />

Es gibt <strong>in</strong> <strong>VHDL</strong> zwei Möglichkeiten Unterprogramme<br />

zu def<strong>in</strong>ieren:<br />

FUNCTION<br />

<strong>mit</strong> genau e<strong>in</strong>em Rückgabewert<br />

PROCEDURE <strong>mit</strong> ke<strong>in</strong>em, oder mehreren<br />

Rückgabewerten.<br />

10.1 FUNCTION Unterprogramm<br />

<strong>E<strong>in</strong>e</strong> Funktion hat meist mehrere Parameter und gibt<br />

genau e<strong>in</strong>en Wert zurück. Da<strong>mit</strong> ist der Aufruf e<strong>in</strong>er<br />

Funktion von der Syntax her wie e<strong>in</strong> Ausdruck.<br />

<strong>E<strong>in</strong>e</strong> Funktion kann e<strong>in</strong>e wiederkehrende Gruppe von<br />

zusammenhängenden Operationen elegant zusammenfassen<br />

und dadurch den Code übersichtlicher gestalten.<br />

<strong>E<strong>in</strong>e</strong> Funktion muss m<strong>in</strong>destens e<strong>in</strong>e RETURN Anweisung<br />

enthalten, aber <strong>die</strong>se muss nicht zw<strong>in</strong>gend am<br />

Ende stehen.<br />

Funktionen dürfen ke<strong>in</strong>e WAIT Befehle verwenden.<br />

Die Funktion muss <strong>in</strong> der Declarative Region e<strong>in</strong>er<br />

Architektur stehen, also im Bereich nach dem Schlüsselwort<br />

ARCHITECTURE und noch vor dem Schlüsselwort<br />

BEGIN.<br />

Soll e<strong>in</strong>e Funktion allgeme<strong>in</strong> verfügbar se<strong>in</strong>, so kann<br />

sie statt <strong>in</strong> e<strong>in</strong>er Architektur auch <strong>in</strong> e<strong>in</strong>em PACKAGE<br />

BODY def<strong>in</strong>iert werden. Siehe dazu Kapitel 11.<br />

Innerhalb e<strong>in</strong>er Architektur wird e<strong>in</strong>e Funktion wie<br />

e<strong>in</strong>e Zuweisung aufgerufen.<br />

FUNCTION li<strong>mit</strong> (<br />

value : unsigned(15 DOWNTO 0);<br />

m<strong>in</strong> : unsigned(15 DOWNTO 0);<br />

max : unsigned(15 DOWNTO 0)<br />

) RETURN unsigned IS<br />

BEGIN<br />

IF value > max THEN RETURN max;<br />

ELSIF value < m<strong>in</strong> THEN RETURN m<strong>in</strong>;<br />

ELSE RETURN value;<br />

END IF;<br />

END FUNCTION li<strong>mit</strong>;<br />

Für <strong>in</strong>dexierten Typen (wie<br />

std_logic_vector, unsigned<br />

und signed) darf beim der<br />

RETURN Def<strong>in</strong>ition ke<strong>in</strong> Bereich stehen!<br />

ranged_val


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

10.2 PROCEDURE Unterprogramm<br />

Benötigt man e<strong>in</strong> Unterprogramm <strong>mit</strong> mehreren<br />

Rückgabewerten, so muss man statt e<strong>in</strong>er Funktion<br />

e<strong>in</strong>e PROCEDURE verwenden.<br />

Prozeduren s<strong>in</strong>d vor allem bei der Programmierung<br />

von Test-Benches sehr hilfreich.<br />

Wie man am Beispiel rechts sehen kann, bietet e<strong>in</strong>e<br />

PROCEDURE viel mehr Flexibilität bei der Wahl der<br />

E<strong>in</strong>- und Ausgangssignale, und kann WAIT Befehle<br />

verarbeiten.<br />

PROCEDURE generate_clock (<br />

CONSTANT t_period : IN TIME;<br />

CONSTANT t_pulse : IN TIME;<br />

CONSTANT t_phase : IN TIME;<br />

SIGNAL clk_out : OUT std_logic<br />

) IS<br />

BEGIN<br />

WAIT FOR t_phase;<br />

LOOP<br />

clk_out 5 ns,<br />

t_phase => 2 ns,<br />

clk_out => clock_3<br />

);<br />

38


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

11 Bibliotheken und Packages<br />

Benötigt man für <strong>VHDL</strong>-Modelle wiederholt bestimmte<br />

Typen, Objekte oder typspezifische Operatoren,<br />

so bietet sich <strong>die</strong> Verwendung von Bibliotheken<br />

an. Die entsprechenden Def<strong>in</strong>itionen kann man dort <strong>in</strong><br />

kompilierter Form abspeichern. Bibliotheken lassen<br />

sich dann <strong>in</strong> jedes <strong>VHDL</strong>-Modell e<strong>in</strong>b<strong>in</strong>den und s<strong>in</strong>d<br />

dann dort bekannt. Solche geme<strong>in</strong>samen Def<strong>in</strong>itionen<br />

werden <strong>in</strong> Packages gemacht, <strong>die</strong> aus e<strong>in</strong>er Declaration<br />

und e<strong>in</strong>em Body bestehen. Gäbe es <strong>in</strong> <strong>die</strong>sem Package<br />

ke<strong>in</strong>e Funktion, so wäre auch ke<strong>in</strong> Body erforderlich.<br />

Der Vorteil <strong>die</strong>ser Aufteilung: Bei e<strong>in</strong>er Änderung<br />

an der Funktion muss nur der Body neu kompiliert<br />

werden.<br />

-- function header only<br />

PACKAGE mean3_pkg IS<br />

FUNCTION mean (a, b, c: REAL)<br />

RETURN REAL;<br />

END PACKAGE mean3_pkg;<br />

-- function def<strong>in</strong>ition<br />

PACKAGE BODY mean3_pkg IS<br />

FUNCTION mean (a, b, c: REAL)<br />

RETURN REAL IS<br />

BEGIN<br />

RETURN (a+b+c) / 3.0;<br />

END FUNCTION mean;<br />

END PACKAGE mean3_pkg;<br />

Das Statement LIBRARY def<strong>in</strong>iert den logischen<br />

Namen der Bibliothek. Er entspricht üblicherweise<br />

dem physikalischen Verzeichnis im Dateisystem des<br />

Rechners wo <strong>die</strong> Bibliothek gefunden werden kann.<br />

Neben benutzerdef<strong>in</strong>ierten Bibliotheken gibt es zwei<br />

Standardbibliotheken:<br />

WORK: Default-Bibliothek des Projekts.<br />

STD:<br />

Bibliothek <strong>mit</strong> vordef<strong>in</strong>ierten Datentypen<br />

und Funktionen.<br />

Wichtig ist v.a. <strong>die</strong> Bibliothek IEEE. Dar<strong>in</strong> s<strong>in</strong>d<br />

Typen und Funktionen für digitale Signale enthalten.<br />

Das USE-Statement bestimmt, welches Package aus<br />

e<strong>in</strong>er Bibliothek und welche Deklarationen aus e<strong>in</strong>em<br />

Package e<strong>in</strong>gebunden werden sollen. Das ALL<br />

Schlüsselwort legt fest, dass alle Deklarationen des<br />

Packages verwendet werden sollen. Natürlich könnte<br />

hier auch nur der Name e<strong>in</strong>er bestimmten Deklaration<br />

aus dem Package stehen. Dann wäre auch nur <strong>die</strong>se<br />

Deklaration <strong>in</strong>nerhalb des Modells bekannt. Da<strong>mit</strong><br />

kann man gezielt Überschneidungen und Kollisionen<br />

zwischen verschiedenen Packages vermeiden.<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.std_logic;<br />

Oder <strong>mit</strong> dem Beispiel von oben:<br />

LIBRARY work;<br />

USE work.myPackage.ALL;<br />

ENTITY average IS<br />

PORT(<strong>in</strong>_l, <strong>in</strong>_2, <strong>in</strong> _ 3: IN REAL;<br />

output : OUT REAL);<br />

END average;<br />

ARCHITECTURE pkg_example OF average<br />

IS<br />

BEGIN<br />

output


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

12 Hierarchie durch strukturierte Modelle / Komponenten<br />

Hierarchisches Design ist e<strong>in</strong>e Technik um komplexe<br />

und Umfangreiche Elemente e<strong>in</strong>es Designs <strong>in</strong> s<strong>in</strong>nvolle<br />

Gruppen zusammen zu fassen, und so für das Verständnis<br />

zu abstrahieren.<br />

Wenn man vom Ganzen beg<strong>in</strong>nt und es immer weiter<br />

<strong>in</strong> detailliertere Module aufteilt, nennt man das „topdown<br />

design“. Verwendet man so gebildete Module<br />

nicht nur e<strong>in</strong>mal sondern immer wieder, gew<strong>in</strong>nt man<br />

an Effizienz, spart Zeit und vermeidet Flüchtigkeitsfehler.<br />

<strong>E<strong>in</strong>e</strong> hierarchische Ebene welche ke<strong>in</strong>e RTL Logik<br />

besitz, sondern nur bestehende Module enthält und<br />

<strong>die</strong>se <strong>mit</strong>e<strong>in</strong>ander verb<strong>in</strong>det nennt man „Structure“<br />

oder kurz struct. In der Regel ist <strong>die</strong> höchste Eben<br />

(top-level) von <strong>die</strong>sem Typ.<br />

E<strong>in</strong> e<strong>in</strong>faches Beispiel ist rechts gezeigt. E<strong>in</strong> 4-Bit<br />

Ad<strong>die</strong>rer adder4 wird aus vier e<strong>in</strong>zelnen E<strong>in</strong>-Bit<br />

Vollad<strong>die</strong>rern full_add aufgebaut. In der Architekturbeschreibung<br />

von adder4 wird zuerst e<strong>in</strong>e<br />

Komponente full_add für <strong>die</strong> Entity full_add<br />

deklariert.<br />

Es ist e<strong>in</strong>e Eigenheit von <strong>VHDL</strong>, dass jedes Modul<br />

sowohl e<strong>in</strong>e ENTITY wie auch e<strong>in</strong>e (identische)<br />

COMPONENT Def<strong>in</strong>ition benötigt.<br />

Die Spezifikation <strong>die</strong>ser COMPONENT Def<strong>in</strong>ition<br />

könnte als Teil von add_full <strong>in</strong> e<strong>in</strong> eigenes Package<br />

add_full_pkg <strong>in</strong>tegriert werden. Da<strong>mit</strong><br />

stünde sie auch für weitere Anwendungen zur Verfügung<br />

und müsste nicht mehr explizit im Code e<strong>in</strong>gefügt<br />

werden. Stattdessen würde <strong>die</strong> E<strong>in</strong>b<strong>in</strong>dung über<br />

<strong>die</strong> USE-Klausel erfolgen..<br />

In <strong>die</strong>sem Beispiel hier wurde stattdessen <strong>die</strong> Komponente<br />

<strong>in</strong> der Declarative Region der Architektur von<br />

adder4 platziert.<br />

LIBRARY IEEE;<br />

USE IEEE.std_logic_1164.ALL;<br />

ENTITY full_add IS<br />

PORT (<br />

u, v, carry_<strong>in</strong> : IN std_logic;<br />

sum, carry_out : OUT std_logic<br />

);<br />

END full_add;<br />

ARCHITECTURE rtl OF full_add IS<br />

BEGIN<br />

sum


INTERSTAATLICHE HOCHSCHULE<br />

FÜR TECHNIK BUCHS NTB<br />

<strong>E<strong>in</strong>führung</strong> <strong>in</strong> <strong>VHDL</strong><br />

13 Parametrisierbare Modelle<br />

Alle Beispiele bis anh<strong>in</strong> zeigten e<strong>in</strong>e <strong>in</strong> der Portbeschreibung<br />

fixierte Schnittstelle. <strong>VHDL</strong> stellt uns darüber<br />

h<strong>in</strong>aus e<strong>in</strong>en Mechanismus zur Verfügung, wie<br />

allgeme<strong>in</strong>ere (generische) Modelle formuliert werden<br />

können.<br />

Als häufigste Anwendung davon wird e<strong>in</strong>e Schnittstellenbeschreibung<br />

<strong>mit</strong> dem Schlüsselwort GENERIC<br />

parametrisiert. Dabei kann dem Parameter width<br />

gleich bei der Deklaration e<strong>in</strong> Wert zugewiesen werden.<br />

Diese Generics können im Code wie Konstanten<br />

verwendet werden. Sie bieten aber den Vorteil, dass<br />

sich bei der Integration „überschrieben“ werden können.<br />

ENTITY generic_register IS<br />

GENERIC (<br />

width : positive := 16<br />

);<br />

PORT (<br />

d : IN std_logic_vector<br />

(width-1 DOWNTO 0);<br />

q : OUT std_logic_vector<br />

(width-1 DOWNTO 0)<br />

);<br />

END ENTITY generic_register;<br />

<strong>E<strong>in</strong>e</strong> Parametrierbare Komponente macht nur dann<br />

s<strong>in</strong>n, wenn <strong>die</strong> Parametrierung kurz vor der Verwendung<br />

der Komponente erfolgen kann. <strong>VHDL</strong> bietet<br />

daher <strong>die</strong> Möglichkeit zum Festlegen der Parameter<br />

zum Zeitpunkt der Instanziierung e<strong>in</strong>er Komponente.<br />

Das nebenstehende Beispiel zeigt, wie <strong>die</strong> Komponente<br />

generic_register <strong>in</strong> e<strong>in</strong>em weiteren<br />

<strong>VHDL</strong>-Modul verwendet werden kann. Dabei wird<br />

bei der Instanziierung <strong>die</strong> ursprüngliche Def<strong>in</strong>ition<br />

von width <strong>mit</strong> dem Wert aus der Konstante<br />

bus_width (32) überschrieben.<br />

ARCHITECTURE struct OF example IS<br />

CONSTANT bus_width : INTEGER<br />

:= 32;<br />

SIGNAL <strong>in</strong>put : std_logic_vector<br />

(bus_width-1 DOWNTO 0);<br />

SIGNAL output : std_logic_vector<br />

(bus_width-1 DOWNTO 0);<br />

BEGIN<br />

reg0 : ENTITY generic_register<br />

GENERIC MAP (width => bus_width)<br />

PORT MAP (<br />

d => <strong>in</strong>put,<br />

q => output<br />

);<br />

…<br />

END ARCHITECTURE struct;<br />

41

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!