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
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