Einführung in VHDL und Anleitung zur CPLD Simulation und Synthese

Transcription

Einführung in VHDL und Anleitung zur CPLD Simulation und Synthese
Einführung in VHDL und Anleitung zur
CPLD Simulation und Synthese
Z ÜRCHER H OCHSCHULE FÜR A NGEWANDTE
W ISSENSCHAFTEN
I NSTITUTE OF E MBEDDED S YSTEMS
Autoren:
Letzte Änderung:
Hans-Joachim Gelke
24. Februar 2009
Inhaltsverzeichnis
Inhaltsverzeichnis
Abbildungsverzeichnis
iii
Tabellenverzeichnis
iv
Listings
v
1
1
Die Hardwarebeschreibungssprache VHDL
1.1
1.2
1.3
1.4
1.5
1.6
2
Was ist eine Hardwarebeschreibung? . . . . . . . . . . . . . . .
Was ist VHDL? . . . . . . . . . . . . . . . . . . . . . . . . . .
Aufbau einer VHDL-Schaltungsbeschreibung . . . . . . . . . .
1.3.1 Schnittstellenbeschreibung (Entity) . . . . . . . . . . .
1.3.2 Die Funktionsbeschreibung (Architecture) . . . . . . . .
1.3.3 Erzeugung einer Hierarchie durch Strukturbeschreibung
1.3.3.1 Beispiel einer Strukturbeschreibung . . . . . .
Grundelemente von VHDL . . . . . . . . . . . . . . . . . . . .
1.4.1 Identifier . . . . . . . . . . . . . . . . . . . . . . . . .
1.4.2 Kommentare . . . . . . . . . . . . . . . . . . . . . . .
1.4.3 Daten-Objekte . . . . . . . . . . . . . . . . . . . . . .
1.4.4 Daten-Typen . . . . . . . . . . . . . . . . . . . . . . .
1.4.5 Operatoren . . . . . . . . . . . . . . . . . . . . . . . .
Verhaltensbeschreibung in VHDL . . . . . . . . . . . . . . . .
1.5.1 Nebenläufige (Concurrent) Anweisungen . . . . . . . .
1.5.1.1 „WHEN_ELSE“-Anweisung . . . . . . . . .
1.5.1.2 „SELECT_WHEN“-Anweisung . . . . . . .
1.5.2 Sequenzielle (Sequential) Statements und Prozesse . . .
1.5.2.1 „IF_ELSIF“ im Prozess . . . . . . . . . . . .
1.5.2.2 Die „CASE_WHEN„Anweisung im Prozess .
1.5.2.3 Erzeugen von getakteten Flip-Flops . . . . . .
1.5.2.4 Zähler in VHDL . . . . . . . . . . . . . . . .
1.5.2.5 Konvertierungsroutinen . . . . . . . . . . . .
1.5.2.6 Zustandsautomaten . . . . . . . . . . . . . .
VHDL Kode zum Verifizieren von Schaltungen . . . . . . . . .
1.6.1 Architecture der Testbench . . . . . . . . . . . . . . . .
1.6.2 Erzeugung von Takten . . . . . . . . . . . . . . . . . .
1.6.3 Assert Statements . . . . . . . . . . . . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
CPLD Design Flow
2.1
2.2
1
2
3
4
5
6
6
9
9
9
9
10
11
12
12
13
13
13
15
16
16
17
18
19
22
22
22
23
24
Einrichten von Lizenzen auf Windows XP . . . . . . . . . . . . . . . . . . . . . . .
Arbeiten mit dem Mentor ModelSim Simulator . . . . . . . . . . . . . . . . . . . .
2.2.1 Anlegen einer Verzeichnissstruktur . . . . . . . . . . . . . . . . . . . . . .
2.2.2 Vorbereiten eines „compile.do“ files für VHDL simualtion (vor der Synthese)
2.2.3 Aufsetzen eines ModelSim Projektes . . . . . . . . . . . . . . . . . . . . .
2.2.4 Generieren eines wave.do files . . . . . . . . . . . . . . . . . . . . . . . . .
i
.
.
.
.
.
.
.
.
.
.
.
.
24
25
25
27
27
30
Inhaltsverzeichnis
2.3
2.2.5 Simulationswarnungen . . . . . . . . . . . . . . . . . . .
2.2.6 Backannotierte Simulation . . . . . . . . . . . . . . . . .
Aufsetzen einer CPLD Synthese mit Altera Quartus . . . . . . . .
2.3.1 Aufsetzen eines Quartus Projektes . . . . . . . . . . . . .
2.3.2 Hinzufügen oder Entfernen von Dateien aus einem Projekt
2.3.3 Starten der Synthese . . . . . . . . . . . . . . . . . . . .
2.3.4 Auswerten der Berichte nach Synthese Place und Route .
2.3.5 Zuweisen von I/O Pins . . . . . . . . . . . . . . . . . . .
Literaturverzeichnis
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
31
31
33
33
35
35
36
36
37
ii
Abbildungsverzeichnis
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
Schaltplan eines RS-Flip-Flop . . . . . . .
Syntax der Entity . . . . . . . . . . . . . .
Syntax der Architecture . . . . . . . . . . .
Struktur des Volladdierers . . . . . . . . . .
Nebenläufige und Sequentielle Ausführung
Zustände eines Zählers mit 6 Schritten . . .
Die zwei Prozesse des Zählers . . . . . . .
Blockdiagram eines Mealy Automaten . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
3
5
6
7
14
17
17
20
2.1
2.2
2.3
2.4
2.5
2.6
2.7
Typische Unterverzeichnisse in einem Projekt . . . . . . .
Festlegen des Arbeitsverzeichnisses in dem Modelsim läuft
Festlegen des Arbeitsverzeichnisses in dem Modelsim läuft
Generieren der Delay Werte für Backannotierte Simulation
Einstellen des Arbeitsverzeichnises . . . . . . . . . . . . .
Wählen des CPLDs . . . . . . . . . . . . . . . . . . . . .
Wählen des Mentor Graphics EDA tools . . . . . . . . . .
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
25
28
29
32
33
34
35
iii
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
Tabellenverzeichnis
Tabellenverzeichnis
1.1
Mit numeric_std zur Verfügung stehende Convertierungsroutinen . . . . . . . . . . . . .
iv
19
Listings
1.1
1.2
1.3
1.4
1.5
1.6
1.7
1.8
1.9
1.10
1.11
1.12
1.13
1.14
1.15
1.16
1.17
1.18
1.19
1.20
1.21
1.22
1.23
1.24
1.25
1.26
1.27
1.28
1.29
1.30
1.31
1.32
1.33
Anschlüsse eines RS-FF . . . . . . . . . . . . . . . . . . . .
Entity RS-FF mit std_logic . . . . . . . . . . . . . . . . . . .
Funktionsbeschreibung des RS-FF . . . . . . . . . . . . . . .
Struktur des Volladierers . . . . . . . . . . . . . . . . . . . .
Beispiel für Named Association . . . . . . . . . . . . . . . .
Kommandozeile . . . . . . . . . . . . . . . . . . . . . . . . .
Daten Objekte . . . . . . . . . . . . . . . . . . . . . . . . . .
Beispiele von Deklarationen . . . . . . . . . . . . . . . . . .
Deklaration von Vektoren . . . . . . . . . . . . . . . . . . . .
Zuweisung von Werten . . . . . . . . . . . . . . . . . . . . .
Deklarierung von eigenen Datentypen . . . . . . . . . . . . .
Datentypen zum Beschreiben von Automaten . . . . . . . . .
Verwendung von Operatoren . . . . . . . . . . . . . . . . . .
Verknüpfung von Strings . . . . . . . . . . . . . . . . . . . .
Nebenläufige Anweisungen . . . . . . . . . . . . . . . . . . .
Multiplexer mit logischen Gleichungen ausgedrückt . . . . . .
Multiplexer mit WHEN-ELSE ausgedrückt . . . . . . . . . .
Multiplexer mit SELECT_WHEN ausgedrückt . . . . . . . .
Sensitivity Liste . . . . . . . . . . . . . . . . . . . . . . . . .
D-FF mit asynchronem Reset . . . . . . . . . . . . . . . . . .
Multiplexer mit IF_ELSIF ausgedrückt . . . . . . . . . . . . .
Multiplexer mit CASE Statement ausgedrückt . . . . . . . . .
Erzeugen eines D-FF . . . . . . . . . . . . . . . . . . . . . .
DFF mit asynchronem Reset . . . . . . . . . . . . . . . . . .
Code Beispiel eines Zählers . . . . . . . . . . . . . . . . . . .
Umwandlung von Integer in std_logic_vector . . . . . . . . .
Umwandlung von std_logic_vector in Integer . . . . . . . . .
Beispiel eines Mealy Automaten . . . . . . . . . . . . . . . .
ENtity einer Testbench . . . . . . . . . . . . . . . . . . . . .
Erzeugen eines Taktes . . . . . . . . . . . . . . . . . . . . . .
Melden von Simulationsfehlern . . . . . . . . . . . . . . . . .
Prüfen des Signals sig_reset . . . . . . . . . . . . . . . . . .
Unterdrückung der Fehlermeldung am Anfang der Simulation
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
4
4
5
7
8
9
9
9
10
10
11
11
11
11
12
12
13
13
14
15
15
16
16
16
18
18
18
20
22
22
23
23
23
2.1
2.2
2.3
Das compile.do script . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Compilierung ist richtig, aber es fehlt noch das wave.do . . . . . . . . . . . . . . . . . .
Script für Simulation mit Backannotation . . . . . . . . . . . . . . . . . . . . . . . . .
27
29
32
v
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
.
1 Die Hardwarebeschreibungssprache VHDL
Dieses Kapitel soll einen ersten Eindruck von der Hardwarebeschreibungssprache VHDL vermitteln. Für
einen tiefen, gründlichen Einstieg in VHDL sind ist die vorgeschlagene Literatur empfohlen:
• „An Introductory VHDL Tutorial“ von der Firma Green Mountain Computing Systems; im HTMLFormat:
/eda/g m- vhd1/ 1ib/tutoria1.htm
• „VHDL Kurzbeschreibung“ von Andreas Mäder, Universität Hamburg; 120 Seiten im PDF-Format:
/www/vhdl/maeder/vhdl .pdf
• „How to declare in VHDL“ von der Firma MINC Inc.; 113 Seiten im PDF Format:
/eda/minc_int/pls_doc/how_vhdl.pdf
Die im Anhang zu diesem Kapitel genannten Bücher bieten eine weitere Möglichkeit, um sich genauere
Kenntnisse über VHDL anzueignen. Unter den deutschsprachigen Büchern bietet [GL94] eine umfassende und gut verständliche Einführung, während bei den angloamerikanischen Titeln [Pel96] als sehr
praxisnahes Buch hervorzuheben ist. Als weiterer Schritt kann der Einsatz eines Lernprogramms oder
die Teilnahme an einer VHDL-Schulung in Erwägung gezogen werden. Die Übungen im MeK1 Labor
sollten aber für die meisten VHDL Anwendungen ausreichend sein.
1.1 Was ist eine Hardwarebeschreibung?
Anhand der Sprache VHDL wird in diesem Kapitel dargestellt, wie eine Hardwarebeschreibungssprache (HDL) aussieht, wie sie aufgebaut ist und welche Vor- und Nachteile die Anwendung einer HDL
bietet. Vieles, was in diesem Kapitel allgemein zu VHDL gesagt wird, gilt natürlich entsprechend für
andere HDLs. VHDL ist nur eine HDL unter vielen. In der Vergangenheit haben Halbleiterhersteller und
Hersteller von EDA-Werkzeugen ihre eigenen Sprachen entwickelt, wie z.B. PALASM, ABEL, CUPL,
ALTERA-HDL. Diese Sprachen haben zumeist einen einfachen Aufbau und sind für den Entwurf von
PLDs gedacht. In den letzten 10 Jahren haben sich aber auch in diesem Bereich VHDL und Verilog als
Standard durchgesetzt.
Fast genauso Verbreitet wie VHDL ist die Sprache Verilog. Diese wurde von der Firma Gateway Design
Automation eingeführt und hat sich durch die Firma Cadence vor allem im Bereich des ASIC-Entwurfs
einen Platz erobert. Während Verilog eher an die Programmiersprache C angelehnt ist, erinnert VHDL
mehr an PASCAL oder ADA. Verilog wurde 1995 als IEEE 1364 genormt und ist vor allem in den USA
weit verbreitet.
VHDL ist eine universelle Programmiersprache, die für den Entwurf von digitalen Schaltungen optimiert
ist. Daher kann VHDL benutzt werden zur:
• Spezifikation
• Entwurfseingabe
• Simulation
• Synthese
1
1 Die Hardwarebeschreibungssprache VHDL
• Dokumentation und Archivierung von Schaltungen
Da VHDL auch die Beschreibung einer Schaltung auf einer hohen Abstraktionsebene erlaubt, kann
VHDL bereits bei der Spezifikation eines Entwurfs eingesetzt werden. Die dabei erstellten Festlegungen, wie die Aufteilung in einzelne Blöcke und die Definition der Schnittstellen, können bei der weiteren
Schaltungseingabe benutzt werden. Bei der Entwurfseingabe ist VHDL im Vergleich zur Schaltplaneingabe zu betrachten. Ein VHDL-Modell hat hier den Vorteil, dass es parametrisierbar und unabhängig von
der Zieltechnologie ist. Ausserdem lassen sich regelmässige Strukturen sehr leicht erzeugen.
VHDL-Modelle können auf allen Abstraktionsebenen simuliert werden. Damit können Fehler sehr frühzeitig entdeckt werden. Von Vorteil ist dabei, dass eine einmal erstellte Simulationsumgebung (engl.:
Testbench) auf allen Ebenen benutzt werden kann. Durch die Synthese werden die Abstraktionsebenen
automatisch überbrückt und so der Entwurfsablauf - besonders bei grossen Schaltungen - wesentlich
beschleunigt.
Diese durchgängige Verwendung von VHDL bis hin zur Dokumentation ist auch gleichzeitig einer der
grössten Vorteile beim Einsatz von VHDL. Der Datenaustausch zwischen den verschiedenen Entwurfsebenen, zwischen den verschiedenen Entwurfswerkzeugen, zwischen den verschiedenen Entwicklern
eines Projektteams und auch zwischen Auftraggeber und Auftragnehmer eines Projektes ist damit einfach möglich. Dies war auch ein Hauptanliegen, als Anfang der 80er Jahre die Sprache VHDL entwickelt
wurde.
Beim Einsatz von VHDL sind einige Punkte zu beachten. Auch ergeben sich einige Nachteile, die nicht
verschwiegen werden sollen.
VHDL ist eine Programmiersprache. Von daher hat das Erstellen eines VHDL-Modells viel gemein
mit dem Erstellen eines Programms. Der Ablauf, die Denkweise und die Werkzeuge entsprechen dem
vertrauten Umfeld eines Software-Entwicklers, nicht jedoch dem eines Hardware-Entwicklers. Für den
(reinen) Hardware-Entwickler ist daher ein Umdenken und das Erlernen neuer Techniken erforderlich.
Dies ist mit Sicherheit das grösste Hindernis bei der Einführung von VHDL. Die alte Weisheit „Eine
Stunde Programmieren erspart eine Minute Denken“ gilt auch beim Erstellen von VHDL-Modellen. Die
schöpferische Fähigkeit, die Intuition und die Erfahrung des Hardware-Entwicklers kann - zumindest
noch - nicht durch EDA-Werkzeuge ersetzt werden. Um VHDL produktiv einsetzen zu können, muss
der Entwickler nicht nur die Sprache kennen, sondern auch wissen, wie sie gewinnbringend eingesetzt
werden kann.
1.2 Was ist VHDL?
Die Hardwarebeschreibungssprache VHDL wurde im Auftrag der US-Regierung im Rahmen des VHSICProjekts entwickelt. VHDL steht für
V VHSIC = Very High Speed Integrated Circuit HDL Hardware Description Language
Mit VHDL kann eine Schaltung auf unterschiedliche Weise dargestellt werden. VHDL stellt Sprachelemente zur Verfügung, die sowohl eine Beschreibung des Verhaltens als auch der Struktur einer Schaltung erlauben. Neben diesen beiden grundlegenden Sichten kann auch der Datenfluss beschrieben und
das zeitliche Verhalten dargestellt werden. VHDL ist eine grosse, komplizierte und mächtige Sprache.
Spötter deuten daher VHDL als „Very Hard to Deal with Language“. Dies mag der Fall sein, will -oder
muss - man wirklich in die tiefsten Details von VHDL eintauchen, z.B. um Simulationsmodelle oder
Synthesealgorithmen zu erstellen. Es ist jedoch nicht notwendig, alle Einzelheiten von VHDL zu kennen, bevor man mit den ersten Entwürfen starten kann. Viele der fortgeschrittenen Möglichkeiten werden
zu Beginn nicht benötigt und können nach und nach „erkundet“ werden. Es ist ratsam, sich zunächst an
bewährte Konventionen bei der Erstellung eines VHDL-Modells zu halten und sich freizügig Anleihen
2
1.3 Aufbau einer VHDL-Schaltungsbeschreibung
bei existierenden Beispielen zu holen. Das Kopieren aus vorhandenen VHDL Modellen erleichtert zudem die mühsame Eingabe der Modelle, die schon für einfache Schaltungen recht umfangreich werden
können.
Die Sprache VHDL wurde 1987 als IEEE 1076 standardisiert. Eine überarbeitete Version wurde 1994 als
IEEE 1076-1993 freigegeben. Um eine einheitliche Simulation von VHDL-Modellen auf verschiedenen
Simulatoren zu gewährleisten, wurde mit dem Standard IEEE 1164 das Package std_logic_1164 definiert. Ein Package ist ein VHDL-Entwurfselement, das eine Sammlung von Deklarationen beinhaltet.
Das Package std_logic_1164 beinhaltet das 9-wertige Logiksystem std_ulogic zur genaueren Modellierung verschiedener Signalstärken sowie davon abgeleitete Logiksysteme, die zugehörigen logischen
Operatoren und Konvertierungsfunktionen.
Zur Beschleunigung der Simulation von VHDL-Modellen auf der Gatterebene hat die VITAL-Initiative
(VHDL Initiative Toward ASIC Libraries) den Standard IEEE 1076.4 entwickelt. Es wurden zum einen
genormte Modelle auf Gatterebene definiert und zum anderen eine Methode zum Annotieren von TimingInformationen. Dabei wurden bewährte Konzepte der Sprache Verilog übernommen.
Eine Erweiterung von VHDL für analoge Schaltungen ist AHDL. Diese analoge HDL (AHDL) ist als
IEEE 1076.1-1999 genormt worden.
1.3 Aufbau einer VHDL-Schaltungsbeschreibung
Ein VHDL-Modell besteht aus einzelnen Entwurfseinheiten. Eine Entwurfseinheit ist ein abgeschlossener Block von Anweisungen, die einzeln überprüft und simuliert werden kann.
Die Beschreibung einer Entwurfseinheit besteht in VHDL aus drei Teilen:
1. Die Schnittstellenbeschreibung genannt Entity
2. Die Funktionsbeschreibung genannt Architecture
3. Zuordnungsbeschreibung genannt Configuration
Eine Configuration ist nur dann erforderlich, wenn mehr als eine Architektur zur Auswahl steht.
Im folgenden soll die VHDL Beschreibung eines RS-Flip-Flop beschrieben werden. Die Entsprechende
Architecture
Gatter Schaltung
ist hier aufgezeigt.
Beisp: RS - Flip Flop mit NOR Gates
R
ARCHITECTURE comb OF rsff IS
>1
Q
>1
Qn
BEGIN
q
<= not (r or qn);
qn <= not (s or q);
END comb;
S
Abbildung 1.1: Schaltplan eines RS-Flip-Flop
3
1 Die Hardwarebeschreibungssprache VHDL
1.3.1 Schnittstellenbeschreibung (Entity)
Für die Entity wird das zu beschreibende System als „Black Box“ betrachtet. In der Schnittstellenbeschreibung werden nur die nach aussen führenden Signale mit ihren Bezeichnungen, Modi und Typen
aufgeführt.
ENTITY rsff IS
PORT ( s,r : IN bit;
q,qn: OUT bit);
END rsff;
Listing 1.1: Anschlüsse eines RS-FF
Es wurde dabei für alle vier Ports der vordefinierte Typ b i t benutzt. Dieser Typ kann die Werte ’0’ und
’1’ annehmen. Wenn das oben erwähnte Package std_logic_1164 in ein VHDL-Modell mit eingebunden
wird, dann kann z.B. auch der darin definierte Typ std_logic benutzt werden. Dieser Typ kennt folgende
Werte:
• Starke Signalwerte: ’0’,’1’, ’ X’
• Schwache Signalwerte: ’ L’, ’H’, ’W’
• Hochohmige Tristate-Ausgänge: ’ Z’
• Nichtinitialisierte Signale: ’U’
• Don’t Care: ’-’
Die Signalwerte ’X’ und ’W’ stellen dabei den Zustand „unbekannt“ dar. Die Entity-Beschreibung würde
dann wie folgt aussehen:
library ieee;
use ieee.std_logic_1164.a11
ENTITY rsff IS
PORT ( s,r : IN std_logic;
datain : IN std_logic;
q,qn: OUT std_logic;
c
d
)
: std_logic_vector(7 downto 0);
: std_logic_vector(7 downto 0)
END rsff;
Listing 1.2: Entity RS-FF mit std_logic
Dabei dienen die ersten beiden Zeilen zur Einbindung und Bekanntmachung der Deklarationen in dem
Package std_logi c_1164.
4
Entity
(Beschreibung der Ein-Ausgänge eines Funktionsblocks)
1.3 Aufbau einer VHDL-Schaltungsbeschreibung
Reservierte Worte:
Dürfen nicht als frei wählbare
Namen verwendet werden
Mode: IN¦OUT¦INOUT
ENTITY rsff IS
PORT ( s,r : IN std_logic;
Name der Entity,
frei wählbar
q,qn: OUT std_logic);
END rsff;
Type: std_logic_vector¦std_logic¦unsigned
Abbildung 1.2: Syntax der Entity
1.3.2 Die Funktionsbeschreibung (Architecture)
Der zweite Teil einer Entwurfseinheit ist die sogenannte Architecture. Diese gibt die Funktion der Entwurfseinheit an, indem das Verhalten und/ oder die Struktur beschrieben wird. Als Beispiel soll hier
zunächst eine Architecture angegeben werden, die das Verhalten der Entwurfseinheit RSFF beschreibt:
ARCHITECTURE comb OF rsff IS
BEGIN
q <= not (r or qn);
qn <= not (s or q);
c(7) <= datain; --assigning a signal to a single bit of a vector
c(6 downto 0) <= c(7 downto 1);
d <= (others => ’0’); --set all bits of vector d to zero
END comb;
Listing 1.3: Funktionsbeschreibung des RS-FF
Enthält ein VHDL-Modell, wie in diesem Fall, nur eine Architecture der Entwurfseinheit RSFF, so ist
mit den beiden Objekten Entity und Architecture die Beschreibung vollständig. Die beiden hier benutzten
Operatoren or und not gehören zu den in VHDL vordefinierten Operatoren. Sind die beiden Operanden A
und B vom Typ bit, so ist das Ergebnis ebenfalls von diesem Typ. Wird jedoch wie in de zweiten Entity
das Package std_logic_1164 eingebunden, so werden durch das sogenannte Operator-Overloading die
Operatoren so erweitert, dass sie z.B. auch Signale des Typs std_logic verarbeiten können. Das Ergebnis
einer solchen Operation ist dann auch vom Typ std_logic.
5
Architecture
1 (Beschreibung
Die Hardwarebeschreibungssprache
VHDL
des Verhaltens eines Blockes)
Frei wählbarer Name
der Architektur
Name der Entity zu der
die Architektur gehört
ARCHITECTURE comb OF rsff IS
BEGIN
q
<= not (r or qn);
qn <= not (s or q);
END comb;
Inhalt der Architektur
Abbildung 1.3: Syntax der Architecture
Zu jeder Entity gehört immer eine Architektur.
Architektur und Entity treten immer als Paar auf.
VHDL unterscheidet zwei grundsätzliche Methoden der Schaltungsbeschreibung: die Verhaltensbeschreibung (Behavioral Description) und die Strukturbeschreibung (Structural Description). Bei der Verhaltensbeschreibung wird das Verhalten der Schaltung durch Boolesche Gleichungen oder durch Prozesse (z.B. für Zustands-Maschinen) beschrieben. Die Strukturbeschreibung geht davon aus, jedes System
durch Zusammenschalten von bereits definierten Blöcken (Komponenten) zu realisieren. Der Name der
Architektur ist frei wählbar, jedoch haben sich Konventionen Eingebürgert. Beschreibt die Architektur
Struktur, so nennt sie sich struct. Beschreibt sie kombinatorische Logik, so nennt sie sich comb. Beschreibt sie Register, nennt sie sich reg. Das folgende Kapitel beschäftigt sich mit Strukturbeschreibung.
1.3.3 Erzeugung einer Hierarchie durch Strukturbeschreibung
VHDL ermöglicht es komplexe Designs strukturiert aufzubauen. Ein Design kann dazu, zu Zwecken
der Übersichtlichkeit und Arbeitsteilung, in kleinere Blöcke aufgeteilt werden. Diese Blöcke wiederum
können aus Unterblöcken usw. bestehen.
1.3.3.1 Beispiel einer Strukturbeschreibung
Mit zwei Halbaddierern und einem ODER-Gatter lässt sich entsprechend Abbildung 1.4 ein Volladdierer
aufbauen. Dieser addiert die drei an seinen Eingängen anliegenden Bits A, B und C und bildet daraus
den Summenausgang SUM und den Übertrag CRY. Das entsprechende VHDL-Modell ist als 1.3.3.1
abgedruckt.
6
5.4
1.3 Aufbau
VHDLbeschreibt
Struktur
Mit zwei Halbaddierern und einem ODER-Gatter Iäßt sich entsprechend
Abbildung 5.3 ein Volladdierer aufbauen. Dieser addiert die drei an seinen
Eingängen
anliegenden Bits A, B und C und bildet daraus den Summeneiner
VHDL-Schaltungsbeschreibung
ausgan€lSUM und den Übertrag CRY. Das entsprechendeVHDL-Modell
ist als Listing 4 abgedruckt.
VOLLADD
Volladdierer
.\rchite
lahei u
\etzlist
-,,.
. g l l
\/^--
Y g l S L
' :' r r i r r i e r tD
.
.,- dek
Dit' Kom
jinitinnen
-clrr'or
Kornpo
-(nen N
t e s: o i "
. a
i r r a l eg e
losition
I r u n gd e
A
B
a
,, x_
Abb. 5.3: Struktts LlesVolladdiercrs
Abbildung 1.4: Struktur des Volladdierers
e n t i t y V 0LL A D Di s
L i s t i n g4 :
port (A,B,C:
in bjt;
ENTITY volladd IS
C R ,YS U [ 4 : o u t b i | ) ;
PORT (A,B,C:
IN std_logic;
e n dV 0 L L A D D ;
CRY,SUM: OUT std_logic);
END volladd;
's
a r c hi t e c t u r e S T R U K T oUfRV 0 L L A Dr D
s i g n a lX 1 , X 2 , X 3b :r ' t ;
ARCHITECTURE struct OF volladd
c o m pISo n e nHt A L B A D D
SIGNAL Xl,X2,X3: bit;
100
COMPONENT halbadd
PORT (A,B:
IN std_logic;
CRY,SUM: OUT std_logic);
END COMPONENT;
COMPONENT odergat
PORT (I1,I2: IN std_logic;
OUT std_logic);
OUTl:
END COMPONENT;
BEGIN
ul: HALBADD port map(
A => A,
B => B,
CRY => X1,
sum => X2);
u2: HALBADD port map(
A => X2,
B => C,
CRY => X3,
sum => SUM);
u3: ODERGAT port
map(
OUT1 => CRY,
I1 => Xl,
I2 => X3);
END struct;
Listing 1.4: Struktur des Volladierers
In Listing 1.3.3.1 wird zunächst die Entity des Volladdierers mit dem Namen V0LLADD und den Einund Ausgängen deklariert. Anschliessend folgt eine Architecture mit dem Namen struct zu dieser Entity. Es handelt sich dabei um eine reine Strukturbeschreibung. Dabei werden wie in einer Netzliste die
verwendeten Signale und Komponenten aufgelistet und deren Verschaltung angegeben.
7
5.5
Eine Ve
g n a l ea u
angege
VHDL-M
ren
Prnor
1 Die Hardwarebeschreibungssprache VHDL
Zunächst werden nach dem Schlüsselwort SIGNAL die internen Signale mit ihrem jeweiligen Modus
und Signaltyp definiert. Danach werden die benutzten Komponenten HALBADD und 0DER-GAT deklariert. Die Komponentendeklarationen sind ein Abbild der jeweiligen Entity-Definitionen. Der Name, der
nach dem Wort Component steht, muss mit dem Namen der Entity übereinstimmen. Danach folgt die
Deklarierung der Ports, welche man durch Copy-Paste direkt von der Entity übernehmen kann.
Die eigentliche Strukturbeschreibung ist zwischen den Schlüsselworten BEGIN und END zu finden. Hier
werden die zuvor deklarierten Komponenten instanziiert.
Dabei erhalten die einzelnen Instanzen einen eigenen Namen. Analog zu ICs auf einer Leiterplatten
kann man dazu U1, U2 usw. als Name wählen. Mit Hilfe des Schlüsselwortes PORTMAP werden die
internen Signale (A,B,C,CRY,SUM) der Entity V0LLADD an die Signale( X1, X2, X3) angeschlossen.
Die Zuordnung der Signale geschieht dabei durch eine Zuordnung der lokalen (OUTl, I1, I2 ) zu den
aktuellen Signalnamen (CRY ,Xl,X3). Nach dem Doppelpunkt kommt der Name des Blockes. Innerhalb
der Klammer von PORT MAP werden dann die Anschlüsse der Komponente (Linke Seite des Pfeils),
mit den Signalen innerhalb des Blockes oder der Blockaussenanschlüsse verbunden (Rechte Seite des
Pfeils).
Dies Methode zum Anschliessen von Komponenten nennt man „Named Association“ und ist die Übersichtlichste. Es gibt aber noch eine Alternative Methode, die „Positional Assocation“, welche aber leicht
zu Fehlern führt, da man die Reihenfolge der aufgeführten Signale genau einhalten muss.
PORT MAP (rx_eingang, system_clk, tx_asugang, uart_int)
Listing 1.5: Beispiel für Named Association
Die einzelnen Design Dateien selbst stehen flach in einem Sourceverzeichnis. Actung: Dem Simulator
oder Synthesizer muss man angeben, welche Entity-Architektur die höchste Hierarchiestufe hat.
Beim compilieren analysiert der Simulator oder Synthesizer beginnend von der höchsten Hierarchiestufe
anhand der Component Declaration wie die Hierarchie zusammengesetzt ist.
8
1.4 Grundelemente von VHDL
1.4 Grundelemente von VHDL
1.4.1 Identifier
Ein gültiger Bezeichner in VHDL darf Gross- und Kleinbuchstaben (A ... Z, a ... z), Ziffern (0 ... 9) und
den Unterstrich (_) enthalten. Er muss zwingend mit einem Buchstaben beginnen. Andere Zeichen sind
nicht zulässig. Der Unterstrich darf nicht am Ende eines Bezeichners stehen; ebensowenig sind zwei aufeinanderfolgende Unterstriche erlaubt. In VHDL wird generell nicht zwischen Gross- und Kleinschreibung unterschieden; die Bezeichner SignalA, signala und SIGNALA bezeichnen alle dasselbe Signal.
In VHDL existieren einige Schlüsselwörter, die, wie in anderen Programmiersprachen, nicht als Bezeichner verwendet werden dürfen (siehe Handbücher der VHDL-Compiler).
1.4.2 Kommentare
Kommentare beginnen mit zwei aufeinanderfolgenden Bindestrichen (–) und umfassen den gesamten
Rest der betreffenden Zeile. Kommentare können an jeder Stelle eines VHDL-Programmes auftreten.
Beispiele:
-- Das ist eine eigene Kommentarzeile
-- auch eine zweite Zeile muss mit "‘--"’ eingeleitet werden
ENTITY nand4 IS ( -- Kommentar bis zum Zeilenende
Listing 1.6: Kommandozeile
1.4.3 Daten-Objekte
Daten-Objekte gehören in VHDL zu einer von drei möglichen Objekt-Klassen: Konstanten, Variablen
und Signale. Wie bei modernen Sprachen üblich, müssen Daten-Objekte auch in VHDL vor ihrer Verwendung deklariert werden. Das geschieht mit folgender Syntax:
CONSTANT identifier [,
identifier
...]: TYPE
:= value;
VARIABLE identifier [,
identifier
...]: TYPE
[:= value];
SIGNAL identifier [, identifier ...]: TYPE [:= value];
Listing 1.7: Daten Objekte
In eckige Klammern ([ ]) gesetzte Ausdrücke sind bei der Eingabe nicht zwingend erforderlich, können
aber auftreten.
Die Bedeutung von Konstanten, denen übrigens bei der Deklaration ein Wert zugewiesen werden muss,
ist gleich wie in anderen Programmiersprachen.
Die wichtigste Objektklasse sind sicher die Signale, die auch eine Hardware Entsprechung haben (Leitungen, Speicherbausteine). Die Variablen haben in VHDL eher die Bedeutung von Hilfsgrössen, aber
sonst dieselben Eigenschaften wie Signale.
CONSTANT bus width: INTEGER := 8;
VARIABLE ctrl bits: std_logic_vector (7 DOWNTO 0);
SIGNAL sig1, sig2, sig3: std_logic;
Listing 1.8: Beispiele von Deklarationen
9
1 Die Hardwarebeschreibungssprache VHDL
1.4.4 Daten-Typen
Die IEEE 1164 Library unterstützt unter anderem die folgenden vordefinierten VHDL-Datentypen:
• integer
• boolean
• unsigned
• signed
• std_logic
• std_logic_vector
Eine Wertzuweisung könnte beispielsweise so aussehen: sigl <= ‘1’;
Man beachte, dass der einem Objekt des Typs „bit“ oder „std_logic“ zugewiesene Wert in einfachen
Anführungszeichen stehen muss!
Ein „std_logic_vector“ ist ein „array of bit“ in aufsteigender oder absteigender Reihenfolge. Dieser Datentyp ist besonders bequem, um Bus-Signale zu beschreiben.
SIGNAL
SIGNAL
SIGNAL
a,
c,
e:
std_logic_vector (0 TO 7);
std_logic_vector (7 DOWNTO 0);
std_logic_vector (0 TO 5);
b:
d:
Listing 1.9: Deklaration von Vektoren
Den eben deklarierten Signalen sollen nun Werte zugewiesen werden:
a
C
b
d
e
<=
<=
<=
<=
<=
"00110101";
"00110101";
x"7A"
x"7A"
0"25"
Listing 1.10: Zuweisung von Werten
Es wurden zwar hier den Signalen a und c die gleichen Werte zugewiesen (bei „std_logic_vector“ müssen
die zugewiesenen Werte in doppelten Anführungsstrichen („“) stehen), aber wegen der abweichenden
Reihenfolge der Indizierung enthalten die einzelnen Array-Elemente unterschiedliche Werte:
a(7) = ’l’
a(6) = ’0’
a(5) = ’1’
a(4) = ’0’
a(3) = ’l’
a(2) = ’l’
a(1) = ’0’
a(0) = ’0’
c(7) = ’0’
c(6) = ’0’
c(5) = ’1’
c(4) = ’l’
c(3) = ’0’
c(2) = ’l’
c(l) = ’0’
c(0) = ’1’
Ein Präfix „X“ oder „x“ bedeutet, dass der Wert in hexadezimaler Form angegeben wird; „O“ oder „o“
bedeutet eine Angabe in oktaler Form. „B“ oder „b“ stehen schliesslich für binäre Darstellung, was auch
automatisch angenommen wird, wenn kein Präfix verwendet wird. Die oktale bzw. die hexadezimale
Form der Wertzuweisung ist nur anwendbar, wenn der „std_logic_vector“ eine passende Länge aufweist
(Vielfaches von 3 bzw. von 4).
Nebst den hier beschriebenen vordefinierten Datentypen existieren noch die selbstdefinierten Typen,
unter denen der Aufzählungstyp eine besondere Bedeutung hat. Seine Deklaration lautet:
10
1.4 Grundelemente von VHDL
TYPE name IS ( value [, value ...]);
Listing 1.11: Deklarierung von eigenen Datentypen
Beispiel:
TYPE states IS (state0, statel, state2, state3);
Listing 1.12: Datentypen zum Beschreiben von Automaten
Es ist hier nicht notwendig, den Bezeichnern state0 etc. einen weiteren Typ zuzuweisen; eine Zuweisung
erfolgt automatisch durch den Compiler.
1.4.5 Operatoren
and or nand nor xor not
Innerhalb der logischen Operatoren existiert keine Hierarchie; die Reihenfolge. in der die Operationen
durchgeführt werden sollen, muss durch Klammern festgelegt werden. Beispiel:
a <= (b and c) or d
Listing 1.13: Verwendung von Operatoren
Relationale Operatoren
=
<
>
gleich
kleiner
grösser
/=
<=
>=
ungleich
kleiner gleich
grösser gleich
Addier-Operatoren
+ und - haben die gleiche Bedeutung wie in anderen Programmiersprachen, also Addition bzw. Subtraktion von Zahlen.
& ist der Verknüpfungsoperator. Die Hauptanwendung ist die Verknüpfung von String-Konstanten. Dazu
ein Beispiel:
VARIABLE c: STRING;
C:="0011001010" -- wird vor allem dann verwendet,
&"11111" -- wenn ein String zu lang für eine
& "010101"; -- Zeile ist
Listing 1.14: Verknüpfung von Strings
Zuweisungs-Operatoren
:= Zuweisung für Variablen: v:= 5;
<= Zuweisung für Signale: s <_ (a AND b) XOR (c OR d) ;
In VHDL werden für Signale und Variablen unterschiedliche Zuweisungsoperatoren verwendet.
Assoziations-Operator
Der Assoziations-Operator „=>“ stellt einen Zusammenhang zwischen verschiedenen Objekten her. Seine Anwendung kann fast nicht allgemein beschrieben werden, hingegen wird sie durch Beispiele klarer.
11
1 Die Hardwarebeschreibungssprache VHDL
1.5 Verhaltensbeschreibung in VHDL
Eine Verhaltensbeschreibung in VHDL gibt an, wie sich die Ausgangssignale aufgrund der Zustände der
Eingangssignale verhalten. Es wird nicht angegeben, wie dieses Verhalten realisiert wird. Der Aufbau
eines solchen VHDL-Modells ähnelt auf den ersten Blick einem Programm in einer höheren Programmiersprache.
Bei der Verhaltensbeschreibung unterscheidet man zwischen „gleichzeitigen“ Anweisungen (concurrent
statements, nebenläufige Anweisungen) und sequentiellen Anweisungen innerhalb von Prozessen. Beide
Anweisungstypen können innerhalb der gleichen Architekturdefinition gemischt vorkommen.
1.5.1 Nebenläufige (Concurrent) Anweisungen
Concurrent-Anweisungen existieren ausserhalb von Prozessen und können fast beliebige Arten von Ausdrücken enthalten. Sie heissen „gleichzeitig“, weil sie alle zum gleichen Zeitpunkt ausgewertet werden;
die Reihenfolge, in der die Anweisungen geschrieben werden, spielt also keine Rolle.
Beispiele:
u
v
w
x
y
z
<=
<=
<=
<=
<=
<=
a;
u;
a XOR b;
(a AND s) OR (b AND NOT(s));
‘1’ WHEN (a=’0’ AND b=’1’) ELSE ‘0’;
a WHEN (count="0010") ELSE b;
Listing 1.15: Nebenläufige Anweisungen
Die Signale a, u und v haben alle den gleichen Wert, nämlich den von a. Dies wäre auch so, wenn
die Reihenfolge der ersten beiden Zeilen umgestellt würde. Hier besteht die Möglichkeit, Denkfehler
einzubauen, weil man sich von anderen Programmiersprachen her nicht an „gleichzeitige“ Anweisungen
gewöhnt ist, sondern gedanklich alles sequentiell abarbeitet.
Am Beispiel eines 4x4 Multiplexers sollen hier einige Möglichkeiten gezeigt werden, wie man ein und
dasselbe Verhalten auf ganz verschiedene Arten beschreiben kann. Details zur Syntax müssen im jeweiligen Compiler-Handbuch nachgeschlagen werden. Im ersten Beispiel soll der Multiplexer mit logischen
Gleichungen beschrieben werden:
-- 4x4 Multiplexer mit logischen Gleichungen -- (concurrent statements)
ENTITY mux IS PORT(
a,b,c,d: IN std_logic_vector(3 DOWNTO 0);
s:
IN std_logic_vector(1 DOWNTO 0);
x:
OUT std_logic_vector(3 DOWNTO 0));
END mux;
ARCHITECTURE archmux OF
x(3) <=
(a(3) AND
OR (b(3) AND
OR (c(3) AND
OR (d(3) AND
x(2)
<=
mux IS BEGIN
NOT(s(1)) AND NOT(s(0)))
NOT(s(1)) AND s(0))
s(1) AND NOT(s(0)))
s(1) AND s(0));
...
END archmux;
Listing 1.16: Multiplexer mit logischen Gleichungen ausgedrückt
12
1.5 Verhaltensbeschreibung in VHDL
1.5.1.1 „WHEN_ELSE“-Anweisung
Die When_Else eine nebenläufige Anweisung und steht irgendwo zwischen begin und end Statement
einer Architektur. Trifft eine Zeile zu, dann werden die nachfolgenden Zeilen nicht mehr abgefragt. Die
oberen Abfragen haben demnach Priorität gegenüber den Abfragen die weiter unten vor kommen. Man
kann somit eine Logik mit Priorität aufbauen.
-- 4x4 Multiplexer mit "when-else"
-- (concurrent statements) Anweisung
ENTITY mux IS PORT(
a,b,c,d: IN std_logic_vector(3 DOWNTO
s:
IN std_logic_vector(1 DOWNTO
x:
OUT std_logic_vector(3 DOWNTO
END mux;
ARCHITECTURE archmux OF mux
x <= a WHEN (s="’00"’)
b WHEN (s="’01"’)
c WHEN (s="’10"’)
0);
0);
0));
IS BEGIN
ELSE
ELSE
ELSE
d;
Listing 1.17: Multiplexer mit WHEN-ELSE ausgedrückt
1.5.1.2 „SELECT_WHEN“-Anweisung
Die select_when Anweisung wird auch nebenläufig behandelt. Im Gegensatz zur when_else Anleitung
haben die Abfragen keine Priorität. Die Reihenfolge in der sie vorkommen ist für die Bildung der Logik
irrelevant.
ENTITY mux IS PORT(
a,b,c,d: IN std_logic_vector(3 DOWNTO 0);
s:
IN std_logic_vector(1 DOWNTO 0);
OUT std_logic_vector(3 DOWNTO 0));
x:
END mux;
ARCHITECTURE comb OF mux IS
BEGIN
with s select
x <= a WHEN "00",
b WHEN "01",
c WHEN "10",
d WHEN OTHERS;
END comb;
Listing 1.18: Multiplexer mit SELECT_WHEN ausgedrückt
1.5.2 Sequenzielle (Sequential) Statements und Prozesse
Ein Prozess enthält eine Reihe von Anweisungen, die in vertrauter Manier nacheinander, also sequentiell,
ausgewertet werden. Die Reihenfolge der Anweisungen ist hier sehr wichtig. Demgegenüber werden alle
Anweisungen, die ausserhalb eines Prozesses stehen, nebenläufig ausgeführt. Der Prozess selbst wird
zusammen mit den anderen nebenläufigen Statements in einer Architektur aber „gleichzeitig“ behandelt,
somit kann man sagen, dass der Prozess selbst ein nebenläufiges Statement ist.
Die Signale eines Prozesses werden global erst nach Beendigung des Prozesses aktualisiert während
Variablenzuweisungen sequentiell bearbeitet werden.
13
1 Die Hardwarebeschreibungssprache VHDL
Dies ist aus der Sicht eines Programmierers zunächst ungewohnt. Geht man jedoch von der Hardware aus,
so ist klar, dass dort alle Funktionseinheiten gleichzeitig, d.h. nebenläufig, arbeiten und auch die Signale
nicht nacheinander, sondern zu beliebigen Zeiten ihren Wert ändern können. Abbildung 1.5 verdeutlicht
diesen Unterschied an einem beispielhaften Vergleich.
Nebenläufige und sequentielle Ausführung
nebenläufig
sequentiell
Beginn
Beginn
Anweisung
Anweisung
Prozeß 1
Anweisung
Prozeß 2
Anweisung
Anweisung
Anweisung
Ende
Ende
Abbildung 1.5: Nebenläufige und Sequentielle Ausführung
Prozesse werden bei der Simulation eines VHDL-Modells sequentiell abgearbeitet, entweder bis zum
Prozess Ende oder bis zu einer wait-Anweisung. Diese gibt an, unter welchen Bedingungen der Prozess
erneut aktiviert werden soll.
Beispiel:
procl: PROCESS (x)
BEGIN
a <= ’0’
IF x = "1011" THEN
a <= ’1’,
END IF;
END PROCESS procl;
Listing 1.19: Sensitivity Liste
Prozesse stehen in der Architektur zwischen BEGIN und END Statement. Der Parameter (x) hinter dem
Schlüsselwort PROCESS ist eine sogenannte Sensitivity List. Das bedeutet, dass der Prozess nur ausgeführt wird, wenn sich der Wert x ändert. Falls diese Sensitivity List weggelassen wird, wird der Prozess
immer ausgeführt, wenn sich irgendein Signal ändert. Diese Liste kann auch mehrere Parameter enthalten und sollte alle Parameter enthalten die innerhalb des Prozesses abgefragt werden. Die Sensitivity
Liste ist nur für den Simulator relevant, der Synthesizer betrachtet die Sensitivity Liste nicht. Die Idee
hinter der Sensitivity Liste ist, Prozessorleistung bei der Ausführung von Simulationen zu sparen. Bei einer logischen Schaltung ändert sich das Ausgangssignal nur dann, wenn sich ein Eingangssignal ändert.
14
1.5 Verhaltensbeschreibung in VHDL
Bei D-Flip Flops sogar nur nach der Flanke des Taktsignales. Also muss ein Prozess nur dann „aufwachen“, wenn sich ein Eingangssignal auf seiner Sensitivity Liste ändert. Alle anderen Prozesse können
im „Schlafzustand“ bleiben wenn sich nichts an ihren Eingangsignalen ändert und somit wird Prozessorleistung gespart. Achtung: Aus oben genannten Gründen darf die Sensitivity Liste nicht benutzt werden
um eine bestimmte Hardwarefunktionalität zu erzeugen.
proc2: PROCESS (rst, clk)
BEGIN
IF rst=’1’ THEN q <= ’0’;
ELSIF (clk’event AND clk=’1’) THEN
q <= d;
END IF;
END PROCESS;
Listing 1.20: D-FF mit asynchronem Reset
Bei diesem Beispiel ist zu beachten, dass die Zuweisung q <= ’0’ nur erfolgt, wenn rst = ’1’ ist. Es gelten
also genau die Regeln, die von den üblichen Programmiersprachen her bekannt sind. Der Ausdruck hinter
„ELSIF“ (Aufpassen auf Schreibweise!) ist nur dann wahr, wenn eine ansteigende Taktflanke aufgetreten
ist. Der obige Prozess beschreibt übrigens das Verhalten eines positiv flankengetriggerten D-Flip-Flops
mit einem asynchronen Reset-Eingang.
Prozesse strukturieren den VHDL Kode und erleichtern das Auffinden von Problemen, da der Kompiler
Fehlermeldungen mit Hilfe von Prozessen referenziert. Um die Verständlichkeit und Übersichtlichkeit
von VHDL Kode zu gewährleisten, sollte man für jede Funktion, Signal, Signalbündel oder ähnlich
gesteuerte Signale jeweils immer einen eigenen Prozess verwenden. Kurz, man sollte nicht mit Prozessen
sparen.
1.5.2.1 „IF_ELSIF“ im Prozess
Schliesslich kann eine kombinatorische Logik auch mit Hilfe von Prozessen beschrieben werden; auch
dabei haben wir die Wahl zwischen verschiedenen Anweisungen. Zunächst die Variante mit der IF _
ELSIF-Anweisung:
ARCHITECTURE archmux OF mux
BEGIN
mx4: PROCESS (a,b,c,d,s)
BEGIN
IF
s="00" THEN x <=
ELSIF s="01" THEN x <=
ELSIF s="10" THEN x <=
ELSE x <= d;
END IF;
END PROCESS mx4;
END archmux;
IS
a;
b;
c;
Listing 1.21: Multiplexer mit IF_ELSIF ausgedrückt
Die IF_ELSIF Anweisung ist analog zur when_else Anweisung priorisierend. Trifft eine Bedingung
weiter oben zu, so kommen die nachfolgenden Bedingungen nicht mehr zur Ausführung. Die erste Zeile
hat also Priorität gegenüber den nachfolgenden. Nach der Synthese liegen die Eingangssignale der ersten
Bedingung näher am Ausgang als die der letzten Abfrage (Priorität). Das heisst es können je nach Signal
unterschiedliche Verzögerungswerte der kombinatorischen Logik entstehen.
15
1 Die Hardwarebeschreibungssprache VHDL
1.5.2.2 Die „CASE_WHEN„Anweisung im Prozess
ARCHITECTURE archmux OF mux IS
BEGIN
PROCESS (a,b,c,d,s)
BEGIN
CASE s IS
WHEN "00"
=> x <= a;
WHEN "01"
=> x <= b;
WHEN "10"
=> x <= c;
WHEN OTHERS => x <= d;
END CASE;
END PROCESS;
END archmux;
Listing 1.22: Multiplexer mit CASE Statement ausgedrückt
Die case_when Anweisung ist wieder equivalent zur with_select Anweisung, nur dass sie nur im Prozess
verwendet werden kann. Sie ist wieder nicht priorisierend, alle Abfragen werden gleich behandelt. Die
case_when Anweisung benutzt man daher gerne für Adressdekoder da alle Eingangssignale gleich behandelt werden und deshalb die Durchlaufverzögerungen von den Eingängen zu den Ausgängen für alle
Ausgangssignale weitgehend gleich sind.
1.5.2.3 Erzeugen von getakteten Flip-Flops
D-Flip-Flops unterscheiden sich von RS-Flip-Flops durch ihre Taktflankensteuerung. Zur Modellierung
muss ein Pegelübergang an einem Taktsignal erkannt werden, wozu sich das VHDL-Attribut EVENT
eignet. Dieses Attribut bezieht man auf das Taktsignal und platziert es in einem Prozess entweder in
einer WAIT- oder in einer IF-Anweisung:
ARCHITECTURE reg OF dff IS
BEGIN
PROCESS (clk)
BEGIN
IF clk’EVENT AND clk = ’1’ THEN
q <= d;
END IF;
END PROCESS;
END reg;
Listing 1.23: Erzeugen eines D-FF
Zu beachten ist, dass gewünschte asynchrone Eingänge von Speicherelementen nicht automatisch von
einem Syntheseprogramm erzeugt werden, sondern in VHDL beschrieben werden müssen. Am Beispiel
eines D-Flip-Flops mit asynchronem Rücksetzeingang sei dies gezeigt:
ENTITY dff_async_reset IS
PORT (clk,d,reset: IN std_ulogic;
q: OUT std_ulogic );
END dff_async_reset;
ARCHITECTURE reg OF dff_async_reset IS
BEGIN
PROCESS (clk,reset)
BEGIN
IF reset = ’0’ THEN -- low-aktives Reset
q <= ’0’; -- hat erste Prioritaet
ELSIF clk’EVENT AND clk = ’1’ AND -- Abfrage auf Taktfl.
clk’LAST_VALUE = ’0’ THEN -- nur, wenn kein reset
16
1.5 Verhaltensbeschreibung in VHDL
q <= d;
END IF;
END PROCESS;
END reg;
Listing 1.24: DFF mit asynchronem Reset
Zustandsdiagramm des Würfel-Zählers
1.5.2.4 Zähler in VHDL
FolgeZustand
Gegenwärtiger
Zustand
2
3
1
4
6
5
Abbildung 1.6: Zustände eines Zählers mit 6 Schritten
Zürcher Fachhochschule
16
Ein Zähler hat die Aufgabe Taktpulse zu zählen und ist mit zwei Blöcken aufgebaut. Der erste Block
ist der Zustandsspeicher, in dem der gegenwärtige Zählerwert abgespeichert wird. Der zweite Block
Prozesse Logik,
des Zählers
ist die Kombinatorischen
die aus dem gegenwärtigen Zustand den Folgezustand berechnet. Der
Folgezustand wird bei der nächsten Taktflanke in den Zustandsspeicher eingetragen. Da wir es mit zwei
Funktionsblöcken zu tun haben, einer mit kombinatorischer Logik und einer mit getakteter Logik, macht
es Sinn, diese in zwei separaten Prozessen unterzubringen.
cnt_folge
Prozess mit
Kombinatorischer
Logik
4
comb_
clk
Prozess mit
getakteter
Logik
reset
reg_
cnt_gegenwart
4
Berechnung des
Folgezustands
Zustandsspeicher
Zürcher Fachhochschule
20
Abbildung 1.7: Die zwei Prozesse des Zählers
Der Ausgang der getakteten Logik ist der gegenwärtige Zustand und dient als Eingang der kombinatorischen Logik. Der Ausgang der kombinatorischen Logik ist der Folgezustand und dient als Eingang der
getakteten Logik.
Die kombinatorische Logik ist im wesentlichen eine Rechenschaltung, die zum gegenwärtigen Zustand
17
1 Die Hardwarebeschreibungssprache VHDL
eine eins addiert. Beziehungsweise subtrahiert, wenn es sich um einen Downcounter handelt. Beliebige
Abwandlungen davon sind in der kombinatorischen Logik programmierbar.
Im folgenden VHDL Beispiel wird ein Zähler mit getrennten Prozessen gezeigt. In der Praxis findet man
häufig auch Zähler, die nur mit einem Prozess aufgebaut sind, diese sind von der Funktion und vom
Synthese Ergebnis identisch. Aus Gründen der Lesbarkeit und Klarheit des VHDL Codes, sollte man
Zähler mit getrennten Prozessen beschreiben.
LIBRARY ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
ENTITY zaehl_einfach IS
PORT( clk,reset : IN
std_logic;
cnt_out
: OUT
std_logic_vector(3 downto 0)
);
END zaehl_einfach;
signal cnt_folge:
signal cnt_gegenwart:
integer RANGE 0 to 15;
integer RANGE 0 to 15;
BEGIN
logik : PROCESS(cnt_gegenwart)
BEGIN
cnt_folge <= cnt_gegenwart + 1 ;
END PROCESS logik;
flip_flops : PROCESS(clk, reset)
BEGIN
IF reset = ’1’ THEN
cnt_gegenwart <= 0;
ELSIF clk’EVENT AND clk = ’1’ THEN
cnt_gegenwart <= cnt_folge ;
END IF;
END PROCESS flip_flops;
cnt_out <= std_logic_vector(to_unsigned(cnt_gegenwart,4));
Listing 1.25: Code Beispiel eines Zählers
1.5.2.5 Konvertierungsroutinen
Da das Rechnen mit std_logic Vektoren nicht möglich ist, muss die Addition mit Integer Zahlen durchgeführt werden. Da jedoch der Zählerwert irgendwann einmal in einen Vektor umgewandelt werden muss,
spätestens wenn man damit an die CPLD Pins gehen will, gibt es die IEEE Umwandlungsroutinen. Diese
werden vom IEEE im Packet numeric_std (für std_logic Typen) zur Verfügung gestellt.
Das folgende Beispiel wandelt einen Integer Wert cnt_gegenwart mit der Breite von 4 Bit zunächst in
einen unsigned Wert um und dann in einen std_logic Vektor:
cnt_out <= std_logic_vector(to_unsigned(cnt_gegenwart,4));
Listing 1.26: Umwandlung von Integer in std_logic_vector
Manchmal muss man einen Vektor in einen Integer umzuwandeln. Dies ist zum Beispiel nötig, um einen
Zähler mit dem Wert dieses Vektors vorzuladen. Das folgende Beispiel zeigt, wie ein Vektor zunächst in
den Typ Signed und dann in Integer übertragen wird.
18
1.5 Verhaltensbeschreibung in VHDL
Type Conversion
std_logic_vector -> unsigned
std_logic_vector -> signed
unsigned -> std_logic_vector
signed -> std_logic_vector
integer -> unsigned
integer -> signed
unsigned -> integer
signed -> integer
integer -> std_logic_vector
std_logic_vector -> integer
unsigned + unsigned -> std_logic_vector
signed + signed -> std_logic_vector
numeric_std
unsigned(arg)
signed(arg)
std_logic_vector(arg)
std_logic_vector(arg)
to_unsigned(arg,size)
to_signed(arg,size)
to_integer(arg)
to_integer(arg)
integer -> unsigned/signed ->std_logic_vector
std_logic_vector -> unsigned/signed ->integer
std_logic_vector(arg1 + arg2)
std_logic_vector(arg1 + arg2)
Resizing
unsigned
signed
resize(arg,size)
resize(arg,size)
Tabelle 1.1: Mit numeric_std zur Verfügung stehende Convertierungsroutinen
cnt <= to_integer(signed(data));
Listing 1.27: Umwandlung von std_logic_vector in Integer
1.5.2.6 Zustandsautomaten
Bei der Modellierung von endlichen Zustandsautomaten (engl: Finite State Machines) (FSM) muss man
zwischen Mealy-, Moore- und Medvedev-Automaten unterscheiden. Bei einem Mealy-Automaten hängt
der Ausgangsvektor vom momentanen Zustand und vom Eingangsvektor ab, beim Moore-Automaten
dagegen nur vom gegenwärtigen Zustand. Ein Medvedev-Automat ist dadurch gekennzeichnet, dass jeder Ausgang des Automaten mit dem Ausgang eines Zustands-Flip-Flops identisch ist. Beim werden die
Ausgangsvektoren direkt weiterverwendet, er hat also keine Ausgangslogik. Abbildung 1.8 beschreibt
ein Blockschaltbild für den Mealy-Automatentyp.
19
1 Die Hardwarebeschreibungssprache VHDL
Mealy Automat
Zustands
-speicher
Zt
Zt+1 = δ (Zt, Et)
Q
n
Et
m
Ansteuer
Logik
n
δ
!Q
n = Anzahl
der FFs
At = ω (Zt,, Et)
AusgangsLogik
ω
Takt
Et = Eingangsvektor
Z = Zustandssvektor zum gegenwärtigen Zeitpunkt t
t
Abbildung
1.8: Blockdiagram eines Mealy Automaten
Zt+1 = Zustandssvektor nach dem Taktimpuls
18
Die folgenden drei VHDL-Prozesse zeigen die prinzipielle, synthesegerechte Modellierung eines MealyAutomaten. Die Blöcke aus Abbildung 1.8 sind hier in getrennten Prozessen realisiert.
zustandsspeicher: PROCESS (clk, reset)
BEGIN
IF (reset = ’1’) THEN
zustand <= reset_zustand;
ELSIF (clk’event AND clk=’1’ AND clk’LAST_VALUE = ’0’)
THEN zustand <= folge_zustand;
END IF;
END PROCESS zustandsspeicher;
uebergangslogik: PROCESS (zustand, in1, in2, ...)
BEGIN
CASE zustand IS
WHEN zustand1 =>
IF (in1 = ... AND in2 = ... AND ...)
THEN folge_zustand <= ...;
ELSIF ...
...
WHEN zustand2 =>
...
END CASE;
END PROCESS uebergangslogik;
ausgabelogik: PROCESS (zustand, in1, in2, ...)
BEGIN
CASE zustand IS
WHEN zustand1 =>
IF (in1 = ... AND in2 = ... AND ...)
THEN out1 <= ...; out2 <= ...; ...
ELSIF ...
...
WHEN zustand2 =>
...
END CASE;
END PROCESS ausgabelogik;
Listing 1.28: Beispiel eines Mealy Automaten
Da die Prozesse zur Beschreibung der Übergangslogik und der Ausgabelogik sehr ähnlich sind, können
20
1.5 Verhaltensbeschreibung in VHDL
sie auch zusammengefasst werden. Eine mögliche Fehlerquelle hierbei ist, dass Latches für die Ausgänge
erzeugt werden, wenn diese nicht in jedem Zustand und bei jeder Kombination der Eingangssignale einen
Wert zugewiesen bekommen. Wenn man versucht, die FSM komplett in einem Prozess zu modellieren,
der lediglich vom Takt und dem Rücksetzsignal getriggert wird, werden Flip-Flops für die Ausgänge
erzeugt. Als Folgerung daraus kann man empfehlen, bei Mealy- und Moore-Automaten einen Prozess für
die Zustandsspeicherung und einen weiteren Prozess für den rein kombinatorischen Teil zu verwenden.
21
1 Die Hardwarebeschreibungssprache VHDL
1.6 VHDL Kode zum Verifizieren von Schaltungen
Gehen wir noch einmal zurück zu Kapitel 1.3.3.1 wo wir das Hierarische Design besprochen haben.
Zum Verifizieren des ganzen Designs umbaut man dieses noch einmal in einer höhere Hierarchie die wir
Testbench nennen. Die Testbench ist die höchste Hierarchiestufe in einem Design. In ihr enthalten ist
das zu testende Teil. In der Fachsprache nennt man dies „Device under test“ oder DUT. Testet man ein
ganzes System, so ist das DUT der Top Level eines Designs. Die Testbench schliesst dann direkt an die
Pins des CPLDs an. Testet man nur einen Unterblock, so ist das DUT der Unterblock.
Da die Testbench immer die höchste Hierarchiestufe ist und darüber keine weiteren Blöcke existieren,
hat die Testbench Entity auch keine Verbindungen nach aussen. Die Testbench Entity ist somit leer.
ENTITY testbench IS
END testbench;
Listing 1.29: ENtity einer Testbench
Eine Testbench die so aufgebaut ist hat den Vorteil, dass der Toplevel nach der Synthese anstelle des
unsynthetisierten Kodes eingesetzt werden kann und die Simulation damit wiederholt werden kann.
Vor der Synthese enthält die Testbench den unsynthetisierten RTL Kode. Nach der Synthese kann man
den TOP Level des unsynthetisierten RTL Kode mit dem fertig synthetisierten Kode einfach austauschen.
Die Simulationsergebnisse müssen danach gleich sein, ausser dass jetzt die Timing Informationen vorhanden sind. Dass heisst unsynthetisiertes RTL kann man mit beliebigen Taktfrequenzen laufen lassen.
Synthetisierte Designs laufen nur noch bis zu Ihrer maximalen Taktfrequenz.
Man nennt die Simulation nach der Synthese mit den Timingwerten auch Timingsimulation oder „Backannotierte“ Simulation, da die Werte für das Timing im nachhinein angefügt wurden.
1.6.1 Architecture der Testbench
Im Architecture Teil der Testbench wird der Top Level als Component deklariert, es ist also ein Block der
in der Architecture „Testbench“ verwendet wird. Da es sich um den Toplevel handelt gibt es sonst meist
keine weiteren Component. Nach dem „Begin“ der Architecture muss dann die Component Top-Level
an die Signale in der Architectur angeschlossen werden. Das geschieht mit dem Port Map. Für jeden
Anschluss an den Device under Test Component muss vor der „Begin“ Section ein Signal deklariert
werden.
Nach dem Port Map des DUT folgt die Erzeugung der Stimuli und eventuell die Assert Statements.
Um eine Dummy Tetbench Architektur herzustellen gibt es im Quartus einen Testbenchwizzard.
1.6.2 Erzeugung von Takten
Um ein Taktsignal zu erzeugen bedient man sich eines Prozesses. Da ein Prozess ohne Sensitivity Liste
immer aktiv ist, beginnt der unten gezeigte Prozess nach Ablauf der zwei WAIT statements wieder von
vorne (siehe Abschnitt 1.5.2). CLK_HALFP ist ein Signal vom Type Time.
signal clk_halfp : time := 20 nS;
BEGIN
clkgen : PROCESS
BEGIN
22
1.6 VHDL Kode zum Verifizieren von Schaltungen
WAIT FOR 1*clk_halfp;
clk <= ’0’;
WAIT FOR 1*clk_halfp;
clk <= ’1’;
END PROCESS clkgen;
Listing 1.30: Erzeugen eines Taktes
1.6.3 Assert Statements
Assertions dienen zur Überprüfung von Bedingungen und zur Ausgabe von Warnungen bzw. Fehlermeldungen. Die Syntax lautet:
[assert_label :] ASSERT condition
[ REPORT "message_string"]
[ SEVERITY severity_level] ;
Listing 1.31: Melden von Simulationsfehlern
Diese Syntax wird folgendermassen interpretiert: „Überprüfe, ob die Bedingung condition erfüllt ist; falls
nicht, erzeuge die Meldung „message_string“ und breche, abhängig von der Fehlerklasse severity_level,
gegebenenfalls die Simulation ab.“
Eine Fehlermeldung mit evtl. weiteren Konsequenzen tritt also nur auf, falls die angegebene Bedingung
(condition) den Wert false ergibt.
Ohne Angabe der Fehlermeldung wird der String „Assertion violation.“ ausgegeben. Die vier möglichen
Fehlerklassen (entsprechend dem vordefinierten Aufzähltyp severity_level) haben folgende Bedeutung:
• note dient zur Ausgabe von allgemeinen Informationen,
• warning dient zur Anzeige von möglichen unerwünschten Bedingungen,
• error zeigt an, dass eine Aufgabe mit dem falschen Ergebnis abgeschlossen wurde,
• failure zeigt an, dass eine Aufgabe nicht abgeschlossen werden
Wird in der Anweisung keine Fehlerklasse angegeben, so wird sie mit der Klasse error versehen. Die
Entscheidung, ab welcher Klasse die Simulation abgebrochen wird, legt man i.d.R. durch eine spezifische
Simulatoreinstellung fest. Zwei Beispiele zur Anzeige eines (low-aktiven) Resetsignals und zur Prüfung
auf definierten Pegel eines Signals sig_a vom Typ std_ulogic lauten:
reset_check : ASSERT sig_reset /= ’0’ REPORT "Achtung: Reset ist aktiv !"
SEVERITY note ;
Listing 1.32: Prüfen des Signals sig_reset
ASSERT (now = 0 fs) OR (sig_a /= ’U’) REPORT "sig_a ist nicht initialisiert !" ;
Listing 1.33: Unterdrückung der Fehlermeldung am Anfang der Simulation
Im zweiten Beispiel wird die Ausgabe einer Fehlermeldung zum Zeitnullpunkt unterdrückt.
23
2 CPLD Design Flow
2 CPLD Design Flow
2.1 Einrichten von Lizenzen auf Windows XP
Im Labor sind die Lizenzen bereits eingerichtet, falls sie die Lizenzen auf ihren eigenen PC installieren
wollen, verfahren sie wie folgt:
• Zunächst müssen sie eine Umgebungsvariable LM_LINCENSE_FILE auf ihrem Windows XP
einrichten:
1. Start-> Systemsteuerung -> Leistung und Wartung -> System ->Erweitert -> Umgebungsvariablen
2. Einstellen der Umgebungsvariablen LM_LICENSE_FILE 7172:rizzo.zhwin.ch; [email protected]
• Einstellen der Umgebungsvariablen zum Abfragen des Lizenzservers:
1. Einstellen zur Abfrage des Lizenz Fileservers am ModelSim
Start -> ModelSim SE 6.0B -> Licensing Wizzard -> Continue
2. Im Feld Port Nummer und Servername eingeben:
[email protected] -> OK
3. Der License Wizard wird fragen LM_LICENSE_FILE = [email protected] als Umgebungsvariable einzufügen. Dies mit „JA“ bestätigen.
4. Eine Fehlermeldung, dass der Checkout Test nicht erfogreich war könnte erscheinen, dies
kann ignoriert werden.
24
2.2 Arbeiten mit dem Mentor ModelSim Simulator
2.2 Arbeiten mit dem Mentor ModelSim Simulator
2.2.1 Anlegen einer Verzeichnissstruktur
edaverzeichnis
Projekt
simulation
source
synthese
.vhdl
modelsim
work
scripts
.do
Abbildung 2.1: Typische Unterverzeichnisse in einem Projekt
Setzen sie für jede Übung (Projekt) eine eigene Projekt Verzeichnissstruktur auf. Dies schafft Ordnung
und verhindert, dass zufällig gleiche Entity Namen von alten Projekten im Work Verzeichniss den Simulator durcheinander bringen. ACHTUNG: Dateien, Signalnamen und Verzeichnisse dürfen keine
Umlaute oder Sonderzeichen haben, da ModelSim nur auf 7-bit ASCII ausgelegt ist. Ein Projektverzeichnis könnte man in drei Unterverzeichnisse aufteilen:
• source: Hier speichern sie den VHDL Code und die Testbench ab.
• synthese: Hier speichern sie alle in Zusammenhang mit der Synthese notwendigen Verzeichnisse.
• Simulation: Hierhin legen sie alle in Zusammenhang mit der Simulation notwendigen Verzeichnisse.
• scripts: Bei der Simulation stehen hier die compile.do und wave.do. scripte welche die Kompilierung starten und die Waveform aufrufen. Bei der Synthese stehen hier die Scripts für die
Constraints und Pin Zuweisungen.
• modelsim: Hier drin „Arbeitet“ das ModelSim. Beim Einrichten eines Projektes fragt sie Modelsim nach einem Working Directory. Modelsim legt hier seine temporären Verzeichnisse ab. Es ist
gut diese Verzeichnisse nicht mit den Verzeichnissen die sie selbst generiert haben zu vermischen.
So können sie temporäre Verzeichnisse zum löschen schnell identifizieren. Ausserdem können sie
dem Check-In Tool verbieten dieses Verzeichnis mit in den Vault zu nehmen. Das spart Speicherplatz und Ein- und Auscheckzeit. Als Regel sollten alle mit den Tools Reproduzierbaren Dateien
25
2 CPLD Design Flow
nicht eingechecked werden.
• quartus: Hier drin „Arbeitet“ das Quartus. Beim Einrichten eines Projektes fragt sie Quartus nach
einem Working Directory. Quartus legt hier normalerweise die Syntheseergebnisse wie Konfigurationsdateien etc. ab. Leitet man die Syntheseergebnisse in das Verzeichniss netlist um, so kann
man durch nicht einchecken dieses Verzeichnisses Platz und Zeit sparen.
• netlist: Hier könnte man alternativ die Syntheseergebnisse ablegen. Zum Beispiel die Netzliste
zum Nachsimulieren.
26
2.2 Arbeiten mit dem Mentor ModelSim Simulator
2.2.2 Vorbereiten eines „compile.do“ files für VHDL simualtion (vor der Synthese)
Aus Gründen der Reproduzierbarkeit von Ergebnissen und einer besseren Dokumentation ist es von
Vorteil, Arbeitsabläufe in Scripten unterzubringen. Im compile.do script stehen alle Simualtorbefehle
die zum kompilieren und simulieren eines Projektes nötig sind.
Nach eingeben der Kommandozeile do compile.do im Simulator Ausgabefenster wird dann nacheinander
Kompiler, Simulator und Waveform Window aufgerufen.
Die compile.do Datei wird direkt in der Datei simulation/scripts untergebracht und ist folgendermassen
aufgebaut:
• Zunächst wird mit dem Kommando VLIB die Ziel-Library „work“ definiert. Dort legt der Kompiler
die kompilierten VHDL Dateien ab.
• Mit VCOM werden die VHDL Dateien kompiliert, der Pfad zu den VHDL source Dateien ist
relativ angegeben.
• Danach wird mit dem Kommando VSIM die Simulation gestartet. Der Simulator bezieht seine
Daten aus der Library work. Die kompilierten VHDL Verzeichnisse sind darin als
work.<testbench_architektur_name> abgelegt.
• Der wave.do file öffnet das Waveform Fenster nach der Kompilation automatisch. Das Erzeugen
der wave.do lässt man am einfachsten vom ModelSim selbst besorgen. Die Beschreibung dafür
steht in Kapitel 2.2.4
• Das „Run“ Kommando lässt den Simulator für 100ns laufen.
LUT mit zwei Eingängen
# create work library
vlib work
# compile project files
vcom -2002 -explicit -work work ../source/dff_srst.vhd
vcom -2002 -explicit -work work ../source/testbench_dff_srst.vhd
# run the simulation
#work.entityname muss mit Entity der Testbench übereinstimmen
vsim -t 1ns -lib work work.testbench_dff_srst
#Öffnen der Waveform Fenster mit den richtigen Signalnamen
do ../scripts/wave.do
run 100.0 ns
Listing 2.1: Das compile.do script
2.2.3 Aufsetzen eines ModelSim Projektes
1. Nachdem sie die notwendigen Verzeichnisse erzeugt haben, starten sie ModelSim
2. Starten sie den „new project wizard“ mit File -> New -> Project. Wählen Sie als Projekt Arbeitsverzeichnis <projekt>/simulation/modelsim.
VHDL wird ähnlich wie die C-Programmiersprache kompiliert. Aus diesem Grund gibt es bei
VHDL Quell- und Zieldateien. Die Zieldatei bei der VHDL Kompilation nennt sich die „work
library“. In der work library befinden sich die bereits kompilierten VHDL Dateien. Ändert sich
eine VHDL Datei in einem Design mit mehreren VHDL Dateien so müssen nicht alle VHDL immer wieder neu compiliert werden, sondern nur das welches sich geändert hat. Dies hat den Vorteil
von Kompilationszeitersparnis bei grösseren Designs. Die work library wird beim Aufsetzen des
27
2 CPLD Design Flow
Projektes festgelegt. ACHTUNG: Wenn sie Verschieden Übungen immer wieder in der gleichen
work library ausführen, kann es sein, dass darin noch Dateien von vorangegangen Übungen stehen, die mit den neuen Übungen interferieren. Deshalb macht es Sinn, ab und zu einmal die work
library zu löschen.
Vor der Kompilation beziehen sich die Dateinamen auf die VHDL Dateinamen. Nach der Kompilation im work Verzeichnis beziehen sich die Dateien auf den Namen der Entity/Architektur
Namen, die VHDL Dateinamen sind dann irrelevant. Dies ist eine häufige Fehlerquelle bei der
Kompilation. Damit man sich besser orientieren kann, nennt man die VHDL Dateien (.vhdl) am
besten genauso wie die Entities.
Frei wählbarer
Projektname
Pfad zu Projekt
Simulationsverzeichniss
Library Name, wohin VHDL
kompiliert wir
Abbildung 2.2: Festlegen des Arbeitsverzeichnisses in dem Modelsim läuft
28
2.2 Arbeiten mit dem Mentor ModelSim Simulator
Achtung: Beenden sie das Einrichten an dem Punkt, wo sie der Setup Wizzard nach den Source
files fragt. Laden sie keine Source VHDL files ins ModelSim, denn dies wird später von ihrem
compile.do Script automatisch erledigt.
Keine VHDL Files importieren,
sondern close drücken
Abbildung 2.3: Festlegen des Arbeitsverzeichnisses in dem Modelsim läuft
3. Nachdem Modelsim geöffnet ist, brauchen sie nur das Kommando do ../scripts/compile.do in die
Ausgabeleiste des Simulators eingeben. Beachten sie, dass sich die compile.do Datei in einem
anderen Verzeichnis als das Arbeitsverzeichnis des Simulators befindet, deshalb: do ../scripts/compile.do
4. Wenn die VHDL Dateien keine Fehler mehr haben, dann sehen die Simulatormeldungen wie unten
aus. Trotzdem erscheint nach dem Aufruf der wave.do Datei noch ein Fehler. Der Fehler rührt daher, dass beim ersten Mal noch kein wave.do Verzeichnis existiert. Als nächstes muss die wave.do
Datei wie in Kapitel 2.2.4 beschrieben erzeugt werden.
do ../compile.do
# ** Warning: (vlib-34) Library already exists at "work".
# Model Technology ModelSim SE vcom 6.1d Compiler 2006.01 Jan 23 2006
# -- Loading package standard
# -- Loading package std_logic_1164
# -- Loading package std_logic_arith
# -- Compiling entity bcd_decoder_when
# -- Compiling architecture comb of bcd_decoder_when
# Model Technology ModelSim SE vcom 6.1d Compiler 2006.01 Jan 23 2006
# -- Loading package standard
# -- Loading package std_logic_1164
# -- Compiling entity tb_bcd_decoder_when
# -- Compiling architecture struct of tb_bcd_decoder_when
# vsim -lib work -t 1ns work.tb_bcd_decoder_when
29
2 CPLD Design Flow
#
#
#
#
#
#
#
#
Loading C:\Modeltech_6.1d\win32/../std.standard
Loading C:\Modeltech_6.1d\win32/../ieee.std_logic_1164(body)
Loading work.tb_bcd_decoder_when(struct)
Loading C:\Modeltech_6.1d\win32/../ieee.std_logic_arith(body)
Loading work.bcd_decoder_when(comb)
** Error: Cannot open macro file: ../wave.do
Error in macro ./../compile.do line 11
Cannot open macro file: ../wave.do
Listing 2.2: Compilierung ist richtig, aber es fehlt noch das wave.do
2.2.4 Generieren eines wave.do files
Kompilieren sie Ihre VHDL files mit Hilfe des compile.do Scriptes wie im Kapitel 2.2.2 und ignorieren sie die Fehlermeldung über die fehlende wave.do Datei. Zunächst müssen sie die Signale, die sie
beobachten wollen, von Hand öffnen. Das geschieht indem sie die zu betrachtenden Signale im „Objects“ Fenster (Mitte oben)selektieren und danach mit der rechten Maustaste „Add to wave -> selected
signals“ anwählen. Jetzt sollte das Waveformwindow erscheinen. Falls Sie ein hierarchisches Design haben, können Sie im „Workspace“ Fenster(Oben links) auch jedes Signal der darunterliegenden Blöcke
zur Betrachtung anwählen.
Nachdem sie die gewünschten Signale angewählt haben, können sie das Waveform Fenster mit „File ->
save“als wave.do abspeichern. Legen sie wave.do im Verzeichnis simulation/scripts ab.
Starten Sie die Simulation jetzt noch einmal mit do ../compile.do jetzt wird das Waveformfenster automatisch geöffnet und die Simulation wird gestartet.
30
2.2 Arbeiten mit dem Mentor ModelSim Simulator
2.2.5 Simulationswarnungen
Erscheint die Warning: Component xyz is not bound, heisst dies, dass der Simulator die korrekt compilierten VHDL Komponenten auf einer oberen Hierarchieebene nicht miteinander verbinden konnte. Der
Bindeprozess erfolgt mit Komponenten die schon kompiliert sind, d.h. die Dateien müssen im Work Verzeichnis vorhanden sein. Die Kompilation der einzelnen VHDL Dateien war zwar erfolgreich, aber die
Komponenten passen nicht zusammen wie in der Toplevel Komponente beschrieben. Möglicherweise
gibt eine Diskrepanz bei den Entity Namen. Im Top Level wurde eine Entity definiert, diese ist aber im
Work Verzeichnis nicht oder unter einem anderen Namen vorhanden. Es kann auch sein, dass im Top
Level Signale verbunden werden, die auf Entity Ebene gar nicht existieren.
2.2.6 Backannotierte Simulation
Um backannotiert zu simulieren müssen sie wie folgt vorgehen:
1. Damit Laufzeitverzögerungen des CPLDs bei der Simulation berücksichtigt werden, benötigt der
Synthesizer zusätzlichen Dateien welche die Laufzeitverzögerungen beinhalten. Diese generiert
der Synthesizer aber nur wenn er dazu aufgefordert wird. Um den Synthezizer zu veranlassen
diese Dateien zu generieren gehen sie in: Assignmnets -> Settings.
2. Wählen sie dort den Tab: EDA Tool Settings -> Simulations
3. Dort müsssen sie drei Parameter einstellen:
• Das Simulationswerkzeug: Modelsim
• Die Sprache: VHDL
• Das Verzeichnis, wo die Ergebnisse der Synthese abgespeichert werden. Wenn sie konsequent sind und sich an Abschnitt 2.2.1 halten, dann sollten diese Verzeichnisse unter projekt/synthese/netlist abgespeichert werden.
31
2 CPLD Design Flow
Abbildung 2.4: Generieren der Delay Werte für Backannotierte Simulation
• Bereiten sie im Verzeichnis simulation/scripts Script z.B. doba.do vor, welches die Kompilationen für die backannotierte Simulation automatisch ausführt.
vlib work
#This line must be run only once
do ../script/altera.do
vcom -work work ../../synthese/netlist/lauflicht_top.vho
# Testbench
vcom -2002 -explicit -work work ../../source/tb_lauflicht_top.vhd
#simulation: back annotation
vsim -sdftyp dut=../../synthese/netlist/lauflicht_top_vhd.sdo -t 1ps work.
tb_lauflicht_top
do ../../script/wave.do
run 1000.0 ns
Listing 2.3: Script für Simulation mit Backannotation
Erklärung zum doba.do Script:
• do ../scripts/altera.do Dieses Kommando Kompiert Altera Cyclone II spezifische Libraries.
• vcom -work work ../../synthese/netlist/lauflicht_top.vho Kompiliert das Syntheseergebnis vom
Design lauflicht_top
• vcom -2002 -explicit -work work ../../source/tb_lauflicht_top.vhd Kompiliert die Testbench
von Lauflicht
• vsim -sdftyp dut=../../synthese/netlist/lauflicht_top_vhd.sdo -t 1ps work.tb_lauflicht_top Startet die Simulation unter Einbindung des Timing Delay files lauflicht_top_vhd.sdo. DUT ist
der Name für die Instanziierung des Designs.
4. Lassen sie das Script im ModelSim Command Window mit do ../script/doba.do ablaufen.
32
2.3 Aufsetzen einer CPLD Synthese mit Altera Quartus
2.3 Aufsetzen einer CPLD Synthese mit Altera Quartus
2.3.1 Aufsetzen eines Quartus Projektes
1. Erstellen sie in ihrem Projektverzeichnis, dass sie schon unter 2.2 eröffnet haben, auch ein Verzeichniss <projekt>/snthese/quartus. Das Verzeichniss quartus ist das Arbeitsverzeichniss für das
Synthesizerprogramm.
2. Starten sie Quartus und Starten sie den New Project Wizard File -> New Project Wizard. Füllen
sie die Dialogbox folgendermassen aus:
• Working Directory for the Project: <projekt>/synthese/quartus
• Name of the Project: Frei wählbarer Projektname
• What is the name of the top level of the project: VHDL File der obersten Hierarchiestufe
(aber unterhalb der Testbench, denn es macht keinen Sinn diese zu synthetisieren) aus dem
Verzeichnis <project>/vhdl.
• -> NEXT
NRD
Abbildung 2.5: Einstellen des Arbeitsverzeichnises
3. Quartus verlangt jetzt nach Ihren Source VHDL Dateien. Diese liegen in <project>/source (Die
Testbench wird nicht mit synthetisiert). -> ADD -> NEXT
4. Im nächsten Menuepunkt wird der CPLD Baustein ausgewählt. Die Grösse des CPLD, das ver-
33
2 CPLD Design Flow
wendete Gehäuse und die Betriebsspannung werden hier festgelegt. Wählen sie den CPLD Typ
EPM2210F324C3 der Max II Serie -> NEXT
Abbildung 2.6: Wählen des CPLDs
5. Die EDA Tool Settings sind wichtig, wenn sie nach der Synthese mit anderen EDA Tools weiterarbeiten wollen. Der Synthesizer erzeugt anhand dieses Formulars die Dateien die für andere EDA
tools notwendig sind. Wir wollen unser CPLD nach der Synthese mit ModelSim nachsimulieren.
Deshalb wählen wir hier: Simulation Tool: ModelSim(VHDL) -> NEXT
34
2.3 Aufsetzen einer CPLD Synthese mit Altera Quartus
Abbildung 2.7: Wählen des Mentor Graphics EDA tools
6. Im letzten Menuepunkt habe sie noch einmal die Gelegenheit alle Einstellungen zu kontrollieren
(Beachten sie bei den Dateinamen dass keine Umlaute möglich sind) dann klicken sie dann auf
-> FINISH Von jetzt ab ist dieses Projekt mit File -> Open Project immer wieder abrufbar. Die
Projekteinstellungen können immer noch jederzeit geändert werden.
2.3.2 Hinzufügen oder Entfernen von Dateien aus einem Projekt
1. Unter Assignments -> Settings Eintrag File können weitere VHDL Dateien aus dem Source Verzeichnis dazugefügt oder entfernt werden.
2. Achtung: Falls sie einen neuen Top Level File definieren, müssen sie diesen unter Assignments ->
Settings General registrieren.
2.3.3 Starten der Synthese
Wir starten unsere erste Synthese unter Processing -> Start Compilation.
Zunächst werden wir einmal ohne Constraints kompilieren, aber in der Zukunft werden wir an diesem
Punkt noch einige Einstellungen vornehmen müssen.
Nach erfolgreicher Synthese muss die Anzahl der Fehler Null sein!
35
2 CPLD Design Flow
2.3.4 Auswerten der Berichte nach Synthese Place und Route
Nach der Synthese sollten folgende Punkte überprüft werden:
• Anzahl der Errors muss null sein.
• Jede Warnung muss erklärbar sein. Gefährliche Warnungen sind Hinweise über unbeabsichtigte
Register. Fehlende Einträge in der Sensitivity Liste von Prozessen, denn dann kann die Simulation
von der tatsächliche Hardwareimplementierung abweichen.
• Prüfen sie, ob im Verzeichnis <projekt>/synthese/quartus/simulation/modelsim die datein .sdo,
.vho und .xrf vorhanden sind, diese brauchen sie um später eine backannotierte simulation durchzufühern. Falls diese nicht vorhanden sind, ist es wahrscheinlich, dass sie beim Einrichten der
Synthese keine EDA Tools angegeben haben.
• Mit dem „Resource Optimization Advisor“ in Tools können sie einen Kompilationsreport anzeigen
lassen. Vor Ihrem Design sollten sie sich immer überlegen, wie viele Flip-Flops und wie viele I/O
Pins Ihr Design benötigt, diese Zahlen können sie mit dem Resource Advisor überprüfen.
Die Ausnutzung des Bauteils ist ein Wichtiger Aspekt. Ist die Ausnutzung höher als 80%, so ist
wahrscheinlich, dass bei einer Designänderung und gelockten Pins kein Fit mehr erreicht werden
kann oder das Timing nicht mehr die erforderlichen Zeiten erfüllt.
• Mit dem „RTL Viewer“ kann ein Schaltplan dargestellt werden. Es ist ratsam den Schaltplan kurz
zu inspizieren und zu prüfen ob er im grossen und Ganzen Sinn macht.
• Im „Technology Map Viewer“ sieht man die tatsächliche Implementierung in die Logik Elemente.
2.3.5 Zuweisen von I/O Pins
Gibt man keine Pin location assignmnent Constraints an, so bestimmt das Placement Tool von selbst
welche Signale es an welche I/O Pins am besten legt. Dies ist abhängig von den eingegebenen Constraints
und an welcher Stelle sich die Funktionsblöcke im Layout befinden. Solange man die Pinzuweisung nicht
festlegt, können sich bei jeder neuen Kompilierung die Anordnung der I/O Pins verändern. Wenn die
Platine aber bereits hergestellt wurde, ist dies unakzeptabel. Deshalb ist es möglich, dem I/O Placement
Tool die Pinzuweisungen vorzugeben. Es empfiehlt sich dies aber erst möglichst nach Fertigstellung des
VHDL Designs zu machen, da sonst der Ausnutzungsgrad und das Timing beeinflusst werden kann.
Das Kommando zum Festlegen der vom Placer gefundenen Pinzuweisungen befindet sich in:
Assignments -> Backannotate Assignmnets
Bei Ausführen dieses Kommandos wird im Hintergrund zum Beispiel folgende TCL Zeile ausgeführt:
set_location_assignment PIN_Y3 -to decled[7] ausgeführt.
Selbstverständlich kann man diese Location Assignmnet Kommandi für seinen peronalisierten TCL file
übernehmen. So hat man Gelegenheit einige der PIN-Location selbst zu manipulieren, um zum Beispiel
das Platinenlayout zu vereinfachen. Dies könnte sich aber negativ auf das Timing des CPLD auswirken.
Deshalb ist es ratsam nach ändern von Pin-Locations von Hand, das CPLD Timing zu überprüfen.
36
Literaturverzeichnis
[GL94] G UNTHER L EHMANN, Manfred S.: Schaltungsdesign mit VHDL. Franzis, 1994
[Pel96] P ELLERIN, David: VHDL Made Easy. Prentice Hall, 1996. – 400 S
37