240 24 6MB
German Pages 302 [365] Year 2006
Verilog
Modellbildung für Synthese und Verifikation von Bernhard Hoppe
Oldenbourg Verlag München Wien
Die Nennung von Marken oder Titeln oder geschützten Wörtern oder Wortfolgen erfolgt in diesem Werk ohne Erwähnung etwa bestehender Marken-, Geschmacksmuster-, Gebrauchsmuster-, Titelschutzrechte oder Patente. Das Fehlen eines solchen Hinweises begründet also nicht die Annahme, ein nicht gekennzeichnetes Wort oder eine nicht gekennzeichnete Wortfolge, Ware oder Dienstleistung bzw. entsprechende Titel seien frei.
Bibliografische Information Der Deutschen Bibliothek Die Deutsche Bibliothek verzeichnet diese Publikation in der Deutschen Nationalbibliografie; detaillierte bibliografische Daten sind im Internet über abrufbar.
© 2006 Oldenbourg Wissenschaftsverlag GmbH Rosenheimer Straße 145, D-81671 München Telefon: (089) 45051-0 oldenbourg.de Das Werk einschließlich aller Abbildungen ist urheberrechtlich geschützt. Jede Verwertung außerhalb der Grenzen des Urheberrechtsgesetzes ist ohne Zustimmung des Verlages unzulässig und strafbar. Das gilt insbesondere für Vervielfältigungen, Übersetzungen, Mikroverfilmungen und die Einspeicherung und Bearbeitung in elektronischen Systemen. Lektorat: Kathrin Mönch Herstellung: Anna Grosser Satz: mediaService, Siegen Umschlagkonzeption: Kochan & Partner, München Gedruckt auf säure- und chlorfreiem Papier Gesamtherstellung: Druckhaus „Thomas Müntzer“ GmbH, Bad Langensalza ISBN 3-486-58004-3 ISBN 978-3-486-58004-4
Inhalt Vorwort des Herausgebers
XI
1
Einleitung
1
2
Electronic-Design mit Verilog HDL
5
2.1 2.1.1 2.1.2 2.1.3
Der Design-Zyklus .....................................................................................................9 Designeingabe ..........................................................................................................10 Logiksynthese...........................................................................................................12 Physikalische Implementierung................................................................................12
2.2
Verilog......................................................................................................................13
2.3 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5
Verilog im Designablauf ..........................................................................................14 Ports..........................................................................................................................15 Verhalten, Struktur und Zeitverzögerungen .............................................................15 Testbenches ..............................................................................................................16 Compiler Directives und System-Tasks ...................................................................17 SDF für Laufzeiten...................................................................................................17
2.4
Zusammenfassung....................................................................................................19
2.5 2.5.1 2.5.2
Übungsaufgaben.......................................................................................................20 Fragen.......................................................................................................................20 Wahr oder Falsch .....................................................................................................21
2.6 2.6.1 2.6.2
Antworten.................................................................................................................21 Fragen.......................................................................................................................21 Wahr oder Falsch .....................................................................................................22
3
Die Sprache Verilog
3.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9
Syntax und Semantik................................................................................................23 Kommentare .............................................................................................................24 Leerzeichen (white spaces).......................................................................................24 Bezeichner (Identifier) .............................................................................................24 Logische Zustände und Signalstärken ......................................................................25 Operatoren................................................................................................................26 Zahlen.......................................................................................................................27 Zeichenketten (strings).............................................................................................28 Datentypen ...............................................................................................................29 Deklarationen von Datentypen .................................................................................32
23
VI
Inhalt
3.1.10 3.1.11 3.1.12 3.1.13
Konstanten ............................................................................................................... 33 Verilog-Primitive ..................................................................................................... 34 Ports von Primitiven und Modulen .......................................................................... 36 Instanziierung von Primitiven .................................................................................. 36
3.2 3.2.1 3.2.2
Ausdrücke: Operatoren und Operanden ................................................................... 38 Operanden ................................................................................................................ 39 Operatoren................................................................................................................ 39
3.3 3.3.1 3.3.2
System Tasks und Compileranweisungen................................................................ 45 System-Aufgaben..................................................................................................... 45 Compileranweisungen.............................................................................................. 47
3.4
Ein einfaches Verilog-Modell mit Testumgebung ................................................... 48
3.5
Zusammenfassung.................................................................................................... 52
3.6 3.6.1 3.6.2 3.6.3
Übungsaufgaben....................................................................................................... 53 Wahr oder Falsch ..................................................................................................... 53 Fragen ...................................................................................................................... 54 Wie lautet die richtige Antwort? .............................................................................. 55
3.7 3.7.1 3.7.2 3.7.3
Antworten ................................................................................................................ 56 Wahr oder Falsch ..................................................................................................... 56 Fragen ...................................................................................................................... 57 Folgende Antwort ist richtig .................................................................................... 59
4
Modelle für Grundkomponenten
4.1 4.1.1 4.1.2 4.1.3 4.1.4
Anwenderdefinierte primitive Komponenten........................................................... 62 Unbekannte Zustände............................................................................................... 64 Sequentielle UDPs ................................................................................................... 65 Initialisierung von UDPs.......................................................................................... 70 Zellbibliotheken: Vorteile von UDPs....................................................................... 71
4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5
Signalverzögerungen und Specify-Blöcke ............................................................... 72 Ausgangspin-Delays ................................................................................................ 73 Pfadabhängige Delays.............................................................................................. 75 Zeitprüfungen für Steuer- und Taktsignale .............................................................. 79 Trägheits- und Transport-Verzögerungen ................................................................ 80 Ein kompletter Specify-Block.................................................................................. 82
4.3 4.3.1
Treiberstärken und Signalauflösung......................................................................... 85 Auflösen von Signalkonflikten................................................................................. 86
4.4
Zusammenfassung.................................................................................................... 87
4.5 4.5.1 4.5.2 4.5.3
Übungsaufgaben....................................................................................................... 88 Wahr oder Falsch ..................................................................................................... 88 Fragen ...................................................................................................................... 88 Welche Antwort ist richtig? ..................................................................................... 89
61
Inhalt
VII
4.6 4.6.1 4.6.2 4.6.3
Antworten.................................................................................................................90 Wahr oder falsch ......................................................................................................90 Fragen.......................................................................................................................91 Folgende Antwort ist richtig.....................................................................................94
5
Struktur, Hierarchie, Laufzeiten
5.1 5.1.1 5.1.2
Module als Instanzen................................................................................................96 Hierarchische Namensgebung ..................................................................................96 Generische Parameter...............................................................................................98
5.2 5.2.1 5.2.2
Rücklesen von Laufzeiten und SDF-Format ............................................................99 Struktur von SDF-Dateien......................................................................................101 SDF-Annotierungen bestehender Verilog-Konstrukte ...........................................101
5.3
Zusammenfassung..................................................................................................105
5.4 5.4.1 5.4.2
Übungsaufgaben.....................................................................................................106 Wahr oder Falsch ...................................................................................................106 Fragen.....................................................................................................................106
5.5 5.5.1 5.5.2
Antworten...............................................................................................................107 Wahr oder Falsch ...................................................................................................107 Folgende Antwort ist richtig...................................................................................107
6
Verhaltensbeschreibung
6.1
Abstraktionsebenen ................................................................................................111
6.2 6.2.1
Nebenläufigkeit ......................................................................................................112 Continuous assignment...........................................................................................113
6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5
Prozeduralblöcke....................................................................................................116 Prozedurale Zuweisungen ......................................................................................118 Kontrollstrukturen in prozeduralen Blöcken ..........................................................122 Benannte Blöcke und Unterbrechungen mit disable ..............................................129 Continous Assignments in Prozeduren (PCAs)......................................................132 Anfangswertzuweisung für Variablen ....................................................................133
6.4 6.4.1 6.4.2 6.4.3
Unterprogramme: Tasks und Functions .................................................................134 Functions ................................................................................................................134 Tasks ......................................................................................................................137 Vereinfachte Deklaration bei Verilog 2001............................................................139
6.5
Der Datentyp event.................................................................................................140
6.6 6.6.1 6.6.2
Iterative Instanziierung mit dem generate-Statement .............................................140 Generate-Schleifen .................................................................................................141 Bedingte Generierung.............................................................................................142
6.7
Zusammenfassung..................................................................................................144
6.8
Aufgaben ................................................................................................................146
95
111
VIII
Inhalt
6.8.1 6.8.2 6.8.3
Wahr oder Falsch? ................................................................................................. 146 Fragen .................................................................................................................... 146 Welche Antwort ist richtig? ................................................................................... 148
6.9 6.9.1 6.9.2 6.9.3
Antworten .............................................................................................................. 149 Wahr oder falsch .................................................................................................... 149 Fragen .................................................................................................................... 149 Folgende Antwort ist richtig .................................................................................. 152
7
Modellbildung: Logik, Speicher, Zustandsautomaten
7.1 7.1.1 7.1.2 7.1.3
Kombinatorische Logik.......................................................................................... 155 Prozedurale Blöcke ................................................................................................ 155 Nebenläufigkeit von Prozessen .............................................................................. 157 Kontinuierliche Anweisungen................................................................................ 158
7.2
RTL-Modelle in Verilog ........................................................................................ 158
7.3 7.3.1 7.3.2 7.3.3
Zustandsautomaten................................................................................................. 160 Zustandsgraphen .................................................................................................... 161 Explizite Zustandsmaschinen................................................................................. 162 Implizite Zustandsmaschinen................................................................................. 166
7.4
Speicher.................................................................................................................. 167
7.5
Bidirektionale Signale............................................................................................ 169
7.6
Zusammenfassung.................................................................................................. 170
7.7 7.7.1 7.7.2 7.7.3 7.7.4
Aufgaben................................................................................................................ 171 Wahr oder Falsch? ................................................................................................. 171 Fragen .................................................................................................................... 171 Welche Antwort ist richtig? ................................................................................... 172 Designaufgabe........................................................................................................ 173
7.8 7.8.1 7.8.2 7.8.3
Antworten .............................................................................................................. 173 Wahr oder Falsch? ................................................................................................. 173 Fragen .................................................................................................................... 174 Folgende Antwort ist richtig .................................................................................. 176
8
Logiksynthese mit Verilog
8.1 8.1.1
Verilog für die Logiksynthese............................................................................... 181 Synthesefähige Verilog-Konstrukte ....................................................................... 181
8.2 8.2.1 8.2.2 8.2.3
Hardwaredefinition mit Verilog ............................................................................. 184 Verhaltensbeschreibung von rein kombinatorischen Schaltungen ......................... 184 Unvollständige Kombinatorik und Latch Inference ............................................... 187 Flankengesteuerte Elemente und RTL-Modelle..................................................... 188
8.3
Zusammenfassung.................................................................................................. 199
8.4
Aufgaben................................................................................................................ 200
153
177
Inhalt
IX
8.4.1 8.4.2 8.4.3
Wahr oder falsch?...................................................................................................200 Fragen.....................................................................................................................200 Welche Antwort ist richtig .....................................................................................201
8.5 8.5.1 8.5.2 8.5.3
Antworten...............................................................................................................202 Wahr oder falsch?...................................................................................................202 Fragen.....................................................................................................................203 Folgende Antwort ist richtig...................................................................................203
9
Verifikation mit Verilog
9.1 9.1.1
Verifikation mit Testbenches .................................................................................206 Grenzen ..................................................................................................................210
9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5
Testbenchentwurf ...................................................................................................211 Eingabemuster und Ausgabeanalyse ......................................................................211 Selbsttestende Testbenches ....................................................................................212 Vollständige Validierung eines 4-Bit-Addierers mit parallelen Modellen .............215 Spezielle Testmuster...............................................................................................217 Top-down-Verifikation eines ASIC-Designs .........................................................223
9.3
Zusammenfassung..................................................................................................230
9.4 9.4.1 9.4.2 9.4.3
Aufgaben ................................................................................................................231 Wahr oder falsch?...................................................................................................231 Fragen.....................................................................................................................231 Ergänzen Sie...........................................................................................................231
9.5 9.5.1 9.5.2 9.5.3
Antworten...............................................................................................................232 Wahr oder falsch?...................................................................................................232 Fragen.....................................................................................................................232 Ergänzen Sie...........................................................................................................234
10
Schlussbemerkungen
235
11
Bibliografie
237
12
Glossar
239
Anhang A: Modelle aus Kapitel 9
205
243
A.1
Komplette Validierung mit Testbench für Addierer...............................................243
A.2
Wallace-Tree-Multiplizierer...................................................................................246
A.3 A.3.1
Top-down-Verifikation des 74LS299 Schieberegisters..........................................248 Die ASIC-Bibliothek cell_lib.v ..............................................................................255
Anhang B: Schlüsselworte
265
Anhang C: Verilog Quick Reference
267
X
Inhalt
C.1 Module........................................................................................................................... 267 C.2 Parallele Anweisungen .................................................................................................. 267 C.3 Daten-Typen .................................................................................................................. 268 C.4 Sequentielle Anweisungen ............................................................................................ 268 C.5 Gatter-Primitive............................................................................................................. 269 C.6 Verzögerungen (Delays)................................................................................................ 270 C.7 Operatoren ..................................................................................................................... 270 C.8 Attribute......................................................................................................................... 272 C.9 Blockierende und nicht blockierende Statements .......................................................... 272 C.10 Tasks und Functions .................................................................................................... 273 C.10.1 Task .......................................................................................................................... 273 C.10.2 Function.................................................................................................................... 273 C.11 System Tasks ............................................................................................................... 274 C.11.1 Ausgabe von Ergebnissen......................................................................................... 274 C.11.2 Simulationssteuerung................................................................................................ 274 C.11.3 Prüfen von Zeitbedingungen..................................................................................... 274 C.11.4 Lesen aus Dateien..................................................................................................... 274 C.12 Übliche Compiler-Direktiven ...................................................................................... 275 C.13 Nicht synthesefähige Verilog-Konstrukte ................................................................... 275 C.13.1 Deklarationen und Definitionen ............................................................................... 275 C.13.2 Statements................................................................................................................. 275 C.13.3 Operatoren und Sonstiges ......................................................................................... 276 C.14 Verilog 2001................................................................................................................ 276 C14.1 Ports und Datentypen................................................................................................. 276 C14.2 Tasks und Functions .................................................................................................. 277 C.14.3 Generate.................................................................................................................... 277 C.15 Vereinfachte Sensitivitätsliste ..................................................................................... 278 C.16 Potenzierungsoperator ................................................................................................. 278 C.17 Vorzeichenbehaftete Arithmetik.................................................................................. 278 C.18 Multidimensionale Felder............................................................................................ 279 Anhang D: Verilog Primitive D.1
281
Logische Gatter ...................................................................................................... 281
Anhang E: Die XILINX-Version des ModelSim-Simulators
283
Index
285
Vorwort des Herausgebers Viele technische Entwicklungen sind durch ständiges Größenwachstum der jeweiligen Systeme gekennzeichnet. Die Mikroelektronik wird hingegen durch die kontinuierliche Verkleinerung der Bauelementstrukturen vorangetrieben. Die äußeren Abmessungen der Chips und damit die Herstellkosten ändern sich kaum, die Integrationsdichte (Bauelemente/Fläche) hingegen verdoppelt sich aber etwa alle 18 Monate. So sinken die Preise für eine gegebene elektronische Funktion und das sorgt für eine ungebrochene Dynamik in den technischen und kommerziellen Möglichkeiten. Der Entwurf komplexer elektronischer Systeme stellt folglich für viele Unternehmen eine Schlüsselkompetenz dar. Obwohl die Software einen wachsenden Anteil an digitalen Systemen hat, ergibt sich häufig nicht nur für große, sondern auch für kleine und mittelständische Firmen die Notwendigkeit, digitale Hardware zu entwickeln, entweder als ASICs oder neuerdings verstärkt mit programmierbaren Logikbausteinen (CPLD, FPGA). Nur so entstehen konkurrenzfähige Produkte oder lassen sich spezifische Kundenanforderungen erfüllen. Gerade die ständig steigende Beliebtheit von CPLDs und FPGAs in der mittelständischen industriellen Anwendung gibt den Entwurfsmethoden zur Erstellung der Designdaten für die Logikbausteine auch in der Lehre an Hochschulen wachsende Bedeutung. Die wachsende Komplexität der zu entwickelnden Schaltungen stellt für die Entwickler von solchen (digitalen) mikroelektronischen Systemen eine große Herausforderung dar, die ohne Entwurfsautomatisierung mit EDA-Werkzeugen (Electronic Design Automation) nicht mehr zu bewältigen ist. Die entscheidende Rolle spielen dabei Hardware-Beschreibungssprachen (HDLs, Hardware Description Languages), die zunächst primär zur Verifikation von digitalen Schaltungsblöcken im Rahmen der Logiksimulation eingesetzt wurden. HDLs unterscheiden sich von Programmiersprachen wie FORTRAN, PASCAL oder C dadurch, dass sie nicht nur sequentielle Abläufe, sondern auch zeitlich parallel abzuarbeitende Prozesse in elektronischen Systemen (Hardware) nachbilden können. Die Beschreibungssprache Verilog, die im vorliegenden Buch behandelt wird, entstand 1983 bei der Firma Gateway Design Automation und die Sprache VHDL wenig später als Auftragsentwicklung des USamerikanischen Verteidigungsministeriums. Beide Sprachen haben sich rasch verbreitet, weil leistungsfähige Simulatoren bereit standen, mit deren Hilfe auch große Entwürfe effizient simuliert werden konnten.
XII
Vorwort
Solange Schaltungen, die aufwendig Gatter für Gatter eingegeben werden mussten, nur zeitsparend simuliert werden konnten, haben sich HDLs als primäres Definitionsmedium von elektronischen Systemen nicht durchsetzen können. Der Umbruch in der Designmethodik kam mit der Einführung kommerzieller Werkzeuge zur Logiksynthese durch die Firma Synopsys. Deren Produkt „Design Compiler“ kann abstrakte Schaltungsbeschreibungen auf der Register-Transfer-Ebene (RTL, Register Transfer Level) in eine optimierte Gatternetzliste mit Komponenten aus einer Zellenbibliothek der gewählten Herstelltechnologie erzeugen („synthetisieren“). Der Designablauf beginnt hier mit der RTL-Beschreibung des zu entwickelnden Systems in einer Hardwarebeschreibungssprache. Der Entwickler gibt nur noch die Datenflüsse zwischen Registern vor und definiert die logischen Operationen, die zwischen den Registerbänken ausgeführt werden sollen. Die detaillierte Ausarbeitung der Schaltung auf Gatterebene inklusive aller Verbindungsleitungen führt das Logiksynthesewerkzeug durch. HDLs haben also eine ähnliche Bedeutung für das Hardwaredesign wie Programmiersprachen für die Softwareentwicklung. Die Möglichkeit, Gatterschaltungen quasi automatisch zu synthetisieren, hat die Abstraktionsebene und Sichtweise beim Logikdesign verändert. Waren beim Schaltplaneditieren Kenntnisse der Booleschen Algebra und der digitalen Logik auf Gatterebene gefragt, so sind beim Digitalentwurf mit Logiksynthese abstrakte Datenflussbeschreibungen in Verhaltenssicht zu erstellen. Allerdings ist Ingenieurwissen immer noch entscheidend, denn die Synthesewerkzeuge können nicht alle Konstrukte von HDLs übersetzen und die Art und Weise, wie der HDL-Code für eine Schaltung geschrieben wird, bestimmt die Qualität der synthetisierten Gatternetzliste. Kenndaten sind hierbei Gatteraufwand, elektrische Leistungsaufnahme sowie Datendurchsatzraten. Diese Kriterien stehen miteinander in Konkurrenz, lassen sich also nicht gleichzeitig optimal gestalten. Die eigentliche Entwicklungsleistung konzentriert sich heute in der manuellen Optimierung der RTL-Beschreibung. Dieses Buch über die Hardwarebeschreibungssprache Verilog ist das dritte in einer Reihe über moderne Methoden des Elektronikentwurfs. Die Reihe begann mit Kesels und Bartholomäs Titel „Entwurf von digitalen Schaltungen und Systemen mit HDLs und FPGAs“, der sich mit den Methoden beschäftigt, die derzeit in der Industrie angewendet werden. Danach erschien das Werk von Hervé „VHDL-AMS“, das die standardisierte Erweiterung der Hardwarebeschreibungssprache VHDL von rein digitalen Systemen zu analogen, gemischt analog-digitalen und heterogenen Systemen hin behandelt. Die Simulation und Modellierung solcher Systeme, die sich weder der digitalen noch der analogen Elektronik eindeutig zuordnen lassen und verschiedene physikalische Disziplinen (Energiedomänen) umfassen, gewinnt im Zuge der Mikrosystemtechnik und Nanotechnologie immer größere technische Bedeutung. Der vorliegende Band behandelt die Beschreibung von digitalen Systemen für die Schaltungssynthese, den Test und die Verifikation mit Hilfe der Sprache Verilog. Dies war die erste Hardwarebeschreibungssprache, die in der Industrie beim Entwurf digitaler elektronischer Systeme weite Verbreitung fand. Die Sprache wurde und wird eingesetzt, um die Schaltungsvorgaben zu erfassen, das Systemverhalten zu simulieren und das erstellte Design zu verifizieren. Heute wird keine kommerzielle digitale Schaltung mehr ohne Einsatz von HDLs entwickelt und Verilog ist nach wie vor weltweit die am meisten verwendete Sprache.
Vorwort
XIII
Damit komplettiert der Titel „Verilog: Modellbildung für Synthese und Verifikation“ die Reihe, die dem Leser einen umfassenden Überblick über die aktuellen Strategien, Probleme und Verfahrensweisen des rechnergestützten Entwurfs elektronischer Systeme vermitteln soll. Da heute keine digitale Schaltung ohne Einsatz von HDL-Designmethoden entwickelt wird, sollten alle Studierenden der Elektrotechnik, die sich in Elektronik vertiefen wollen, diese Schlüsselkenntnisse mit in den Beruf nehmen. So verbessern sie ihre Beschäftigungsfähigkeit durch verkürzte Einarbeitungsphasen. Die hier mit dem Buch über Verilog inhaltlich abgeschlossene Reihe ist nicht nur als Begleitreihe zu Vorlesungen an Hochschulen und Universitäten gedacht, sondern auch zum Selbststudium, denn vielen Ingenieuren im Berufsfeld fehlen die einschlägigen Fertigkeiten, um die Vorteile des HDL-basierten Entwurfs zu nutzen. Wie erste Fachrezensionen von Kollegen belegen, wurden diese Ziele bereits von den ersten beiden Bänden der Reihe erreicht und wir haben uns bemüht, dass auch das Buch über Verilog den gleichen Gebrauchswert aufweist.
Darmstadt
Bernhard Hoppe
1
Einleitung
Hardwarebeschreibungsprachen (HDLs, Hardware Description Languages) sind Werkzeuge für den Digitalentwurf. HDLs werden beim Entwurf digitaler elektronischer Systeme eingesetzt, um die Schaltungsvorgaben zu erfassen, das Systemverhalten zu simulieren und das erstellte Design zu verifizieren. Heute wird keine digitale Schaltung mehr in der Praxis ohne Einsatz von HDLs entwickelt. Vielen Ingenieuren im Berufsfeld fehlen aber die einschlägigen Kenntnisse, um die Vorteile des HDL-basierten Entwurfs zu nutzen. Aus diesem Grund ist dieses Buch geschrieben worden und sowohl als Begleitbuch zu Vorlesungen wie auch zum Selbststudium geeignet. Es stellt die Hardwarebeschreibungssprache Verilog vor und fasst die grundlegenden Verfahren der aktuellen Designmethodik für digitale (integrierte) Schaltungen zusammen. Dabei steht die Verwendung von Verilog bei der praktischen Modellbildung stärker im Vordergrund als die rein syntaktischen Aspekte. Neben der weltweit gebräuchlichen Hardwarebeschreibungssprache Verilog, die in diesem Buch genauer vorgestellt werden soll, hat sich auch die in Europa populäre Sprache VHDL als Industriestandard etablieren können. Ob nun VHDL oder Verilog den Designer besser bei seinen Entwurfsaufgaben unterstützt, ist Ansichtssache. Beide Sprachen haben ihre Stärken und Schwächen. Verilog lässt sich leichter erlernen, ist an der Sprache C orientiert und hat nicht den komplexen theoretischen Überbau von VHDL. VHDL ist hingegen methodisch konsistenter. Es gibt aber keine Designaufgabe, die nur mit der einen und nicht mit der anderen Sprache zu bewältigen wäre. Verilog war die erste HDL, die sich in der Elektronikindustrie durchgesetzt hat. VHDL kam später, war aber von Anfang an eine genormte, frei zugängliche Sprache, während Verilog zunächst von der Firma Gateway (später Cadence) als proprietäres Tool vermarktet wurde und erst 1997 und 2001 in revidierter Form als IEEENorm 1394 erschienen ist. Statt grafischer Schaltpläne werden heute meist HDL-Netzlisten und hier insbesondere Verilog-Netzlisten zur Schaltungsdokumentation benutzt. HDLs sind genormt und können daher von jedem Tool, das die Normen erfüllt, verarbeitet werden, während Schaltpläne in der Regel in proprietären grafischen Formaten abgelegt sind. HDLs haben also die Schaltpläne als primäres Entwurfseingabemedium ersetzt. Mit diesen Sprachen können aber nicht nur logische Funktionen auf Schaltkreisebene sondern auch Systemverhalten auf höherer Abstraktionsebene modelliert werden. Verschiedene Abstraktionsebenen können gleichzeitig simuliert werden. Dies eröffnet neue Möglichkeiten, die beim Schaltplanentwurf nicht bestehen. So können verschiedene Architekturansätze mit abstrakten HDL-Verhaltensmodellen simuliert und verglichen werden. Die beste Variante wird dann ausgearbeitet und mit dem zergliedernden Entwurfsstil (Top-Down) in strukturelle Modelle auf Gatterebene umgesetzt.
2
1 Einleitung
HDL-Methoden konnten sich aber erst dann gegenüber Schaltplanentwürfen durchsetzen, als 1987 Synopsys mit dem Logiksynthesewerkzeug Design Compiler auf den Markt kam. Die Logiksynthese hat die Designverfahren revolutioniert. Ein Synthesetool analysiert das HDLModell, das das Schaltungsverhalten nur abstrakt beschreibt, setzt das Modell in eine boolesche Beschreibung um, optimiert die logische Struktur und bildet das Ergebnis auf die Komponenten einer ASIC-Bibliothek (logische Gatter, Flip-Flops, etc.) in der Zieltechnologie ab. Das Ergebnis ist eine Implementierung der gewünschten Funktion als Schaltung aus Bibliothekszellen. Diese Schaltung kann als Verilog-Netzliste oder in anderen Formaten ausgegeben werden und dient als Grundlage für den physikalischen Entwurf, bei dem aus der Schaltung eine Strukturdarstellung abgeleitet wird, die sich auf einen programmierbaren Logikbaustein übertragen lässt oder als ASIC-Layout an den Halbleiterhersteller gegeben werden kann. Die synthesebedingten Rationalisierungseffekte bei der Schaltungsdefinition haben den Schwerpunkt der Designaktivitäten verschoben. Der Designer beschäftigt sich heute fast nur noch mit der Frage, was implementiert werden soll, und überlässt die Umsetzung in eine technologienahe Gatterbeschreibung den Computer-Tools. Statt elegante und effiziente Schaltungsvarianten zu entwickeln, ist er primär damit befasst, ein synthesefähiges VerilogModell zu erstellen und dessen Übereinstimmung auf Verhaltensebene und später auf Gatterniveau mit den Vorgaben der System-Spezifikation (Lastenheft) zu verifizieren. Verifikation bleibt auch der Schwerpunkt im gesamten weiteren Entwurfsablauf: Nach der Synthese und der Umsetzung in die Zieltechnologie folgen zusätzliche Verifikationsschritte, die dann auch Laufzeiten durch die eingesetzten Gatter berücksichtigen. Auch bei der Verifikation bieten HDL-Modelle Vorteile. Statt die Testsignale per Hand in den Simulator einzugeben und die Ergebnisse als Wellenzüge mit bloßem Auge zu analysieren, kann man so genannte Testbench-Modelle mit HDLs entwickeln, die diese Aufgaben automatisch erledigen und selbständig die Verifikationsaufgaben abarbeiten. Im vorliegenden Buch werden die sprachlichen Konstrukte und Möglichkeiten von Verilog im Hinblick auf die einzelnen Designschritte dargestellt. Bei dieser Einführung in Verilog wird unterstützend auf ähnliche oder entsprechende Anweisungen in den verwandten Sprachen VHDL als Hardwarebeschreibungssprache und C als prozedurale Sprache Bezug genommen. Das Buch ist folgendermaßen aufgebaut: Nachdem in Kapitel 2 die Grundlagen der HDL-Designmethoden gelegt wurden, folgen in Kapitel 3 die syntaktischen und semantischen Regeln als allgemeine Vorgaben des VerilogStandards. Der Unterschied zwischen prozeduralen Computersprachen und HDLs liegt in der Einbeziehung der zeitlichen Nebenläufigkeit, mit der Hardware und damit auch HDLModelle Informationen verarbeiten, während Software die Instruktionen stets sequentiell Instruktion für Instruktion angeht. In Kapitel 4 modellieren wir mit Verilog die Grundkomponenten elektronischer Schaltungen (logische Gatter und Flip-Flops) und beschäftigen uns mit Laufzeiteffekten in Schaltungen. In Kapitel 5 stehen strukturelle Modelle mit instanziierten Modulen und Primitiven im Vordergrund und es wird auf das Standard-Delay-Format (SDF) eingegangen. Nachdem der gatterbasierte Entwurf abgehandelt ist, wenden wir uns in Kapitel 6 den Verhaltensmodellen zu, mit denen Schaltungseigenschaften auf höherer Abstraktionsebene definiert werden kön-
Einleitung
3
nen. Die Verilog-Konstrukte für diese Aufgabe sind den Anweisungen von prozeduralen Sprachen wie C sehr ähnlich. Wichtig ist aber, dass der Designer bei der abstrakteren Modellbildung nicht vergisst, dass Verilog nebenläufiges Hardwareverhalten beschreibt und keine reinen Computeralgorithmen. Mit diesem Kapitel sind die grundlegenden Konzepte erarbeitet und wir können uns in Kapitel 7 der Modellierung spezieller Hardwarekomponenten wie Speichern, kombinatorischer Logik und Zustandsautomaten zuwenden. Kapitel 8 behandelt die Logiksynthese, bei der Sprache in Hardware übersetzt wird. Es sind nicht alle Verilog-Anweisungen synthetisierbar, denn nicht jedes sprachliche Konstrukt hat seine Entsprechung in Hardwarekomponenten. Die Qualität des Syntheseergebnisses hängt stark von der zugrunde liegenden Verilog-Beschreibung ab. Implikationen des VerilogCodes und die reduzierte Syntax werden systematisch vorgestellt und an Beispielen verdeutlicht. Im Kapteil 9 wird die Verifikation mit Verilog-Testbenches diskutiert. Als Testbench (engl. für Prüfumgebung) wird ein HDL-Modell bezeichnet, das eine bestimmte Abfolge von Signalen erzeugt, mit denen das zu verifizierende Modell angesteuert werden kann. Es ist auch möglich, mit Hilfe des Testbench-Modells die Ausgabesignale des zu testenden Modells aufzunehmen, abzuspeichern oder automatisiert zu überprüfen (selbsttestende Testbench). Die verschiedenen Strategien für die automatische Design-Verifikation werden erläutert und mit Anwendungsbeispielen illustriert. Kapitel 10 fasst zusammen und gibt einen Ausblick auf aktuelle Entwicklungen der Sprache Verilog. In den Anhängen finden sich eine Verilog Quick Reference, ein Glossar mit den wichtigsten Begriffen aus dem Designbereich und Beispiele sowie Ergänzungen zu den einzelnen Kapiteln. Zur besseren Lesbarkeit sind alle Verilog-Schlüsselwörter im Text fett gedruckt, die Schlüsselwörter des SDF-Standards und von VHDL in GROSSBUCHTSTABEN und alle stehenden Begriffe, die im Rahmen des HDL-Designs verwendet werden, kursiv. Mein besonderer Dank für die Unterstützung beim Schreiben des Buches gebühren Frau Mönch vom Oldenbourg Verlag, Herrn Jens Hüttemann und der Firma Mentor Graphics für die Überlassung der Daten des Verilog-Trainings-Kurses und Herrn Karthikeyan Balasubramanian (M.Sc.) für viele anregenden Diskussionen und Hilfe bei der Erstellungen der Grafiken im Buch.
Inhalt Vorwort des Herausgebers
XI
1
Einleitung
1
2
Electronic-Design mit Verilog HDL
5
2.1 2.1.1 2.1.2 2.1.3
Der Design-Zyklus .....................................................................................................9 Designeingabe ..........................................................................................................10 Logiksynthese...........................................................................................................12 Physikalische Implementierung................................................................................12
2.2
Verilog......................................................................................................................13
2.3 2.3.1 2.3.2 2.3.3 2.3.4 2.3.5
Verilog im Designablauf ..........................................................................................14 Ports..........................................................................................................................15 Verhalten, Struktur und Zeitverzögerungen .............................................................15 Testbenches ..............................................................................................................16 Compiler Directives und System-Tasks ...................................................................17 SDF für Laufzeiten...................................................................................................17
2.4
Zusammenfassung....................................................................................................19
2.5 2.5.1 2.5.2
Übungsaufgaben.......................................................................................................20 Fragen.......................................................................................................................20 Wahr oder Falsch .....................................................................................................21
2.6 2.6.1 2.6.2
Antworten.................................................................................................................21 Fragen.......................................................................................................................21 Wahr oder Falsch .....................................................................................................22
3
Die Sprache Verilog
3.1 3.1.1 3.1.2 3.1.3 3.1.4 3.1.5 3.1.6 3.1.7 3.1.8 3.1.9
Syntax und Semantik................................................................................................23 Kommentare .............................................................................................................24 Leerzeichen (white spaces).......................................................................................24 Bezeichner (Identifier) .............................................................................................24 Logische Zustände und Signalstärken ......................................................................25 Operatoren................................................................................................................26 Zahlen.......................................................................................................................27 Zeichenketten (strings).............................................................................................28 Datentypen ...............................................................................................................29 Deklarationen von Datentypen .................................................................................32
23
VI
Inhalt
3.1.10 3.1.11 3.1.12 3.1.13
Konstanten ............................................................................................................... 33 Verilog-Primitive ..................................................................................................... 34 Ports von Primitiven und Modulen .......................................................................... 36 Instanziierung von Primitiven .................................................................................. 36
3.2 3.2.1 3.2.2
Ausdrücke: Operatoren und Operanden ................................................................... 38 Operanden ................................................................................................................ 39 Operatoren................................................................................................................ 39
3.3 3.3.1 3.3.2
System Tasks und Compileranweisungen................................................................ 45 System-Aufgaben..................................................................................................... 45 Compileranweisungen.............................................................................................. 47
3.4
Ein einfaches Verilog-Modell mit Testumgebung ................................................... 48
3.5
Zusammenfassung.................................................................................................... 52
3.6 3.6.1 3.6.2 3.6.3
Übungsaufgaben....................................................................................................... 53 Wahr oder Falsch ..................................................................................................... 53 Fragen ...................................................................................................................... 54 Wie lautet die richtige Antwort? .............................................................................. 55
3.7 3.7.1 3.7.2 3.7.3
Antworten ................................................................................................................ 56 Wahr oder Falsch ..................................................................................................... 56 Fragen ...................................................................................................................... 57 Folgende Antwort ist richtig .................................................................................... 59
4
Modelle für Grundkomponenten
4.1 4.1.1 4.1.2 4.1.3 4.1.4
Anwenderdefinierte primitive Komponenten........................................................... 62 Unbekannte Zustände............................................................................................... 64 Sequentielle UDPs ................................................................................................... 65 Initialisierung von UDPs.......................................................................................... 70 Zellbibliotheken: Vorteile von UDPs....................................................................... 71
4.2 4.2.1 4.2.2 4.2.3 4.2.4 4.2.5
Signalverzögerungen und Specify-Blöcke ............................................................... 72 Ausgangspin-Delays ................................................................................................ 73 Pfadabhängige Delays.............................................................................................. 75 Zeitprüfungen für Steuer- und Taktsignale .............................................................. 79 Trägheits- und Transport-Verzögerungen ................................................................ 80 Ein kompletter Specify-Block.................................................................................. 82
4.3 4.3.1
Treiberstärken und Signalauflösung......................................................................... 85 Auflösen von Signalkonflikten................................................................................. 86
4.4
Zusammenfassung.................................................................................................... 87
4.5 4.5.1 4.5.2 4.5.3
Übungsaufgaben....................................................................................................... 88 Wahr oder Falsch ..................................................................................................... 88 Fragen ...................................................................................................................... 88 Welche Antwort ist richtig? ..................................................................................... 89
61
Inhalt
VII
4.6 4.6.1 4.6.2 4.6.3
Antworten.................................................................................................................90 Wahr oder falsch ......................................................................................................90 Fragen.......................................................................................................................91 Folgende Antwort ist richtig.....................................................................................94
5
Struktur, Hierarchie, Laufzeiten
5.1 5.1.1 5.1.2
Module als Instanzen................................................................................................96 Hierarchische Namensgebung ..................................................................................96 Generische Parameter...............................................................................................98
5.2 5.2.1 5.2.2
Rücklesen von Laufzeiten und SDF-Format ............................................................99 Struktur von SDF-Dateien......................................................................................101 SDF-Annotierungen bestehender Verilog-Konstrukte ...........................................101
5.3
Zusammenfassung..................................................................................................105
5.4 5.4.1 5.4.2
Übungsaufgaben.....................................................................................................106 Wahr oder Falsch ...................................................................................................106 Fragen.....................................................................................................................106
5.5 5.5.1 5.5.2
Antworten...............................................................................................................107 Wahr oder Falsch ...................................................................................................107 Folgende Antwort ist richtig...................................................................................107
6
Verhaltensbeschreibung
6.1
Abstraktionsebenen ................................................................................................111
6.2 6.2.1
Nebenläufigkeit ......................................................................................................112 Continuous assignment...........................................................................................113
6.3 6.3.1 6.3.2 6.3.3 6.3.4 6.3.5
Prozeduralblöcke....................................................................................................116 Prozedurale Zuweisungen ......................................................................................118 Kontrollstrukturen in prozeduralen Blöcken ..........................................................122 Benannte Blöcke und Unterbrechungen mit disable ..............................................129 Continous Assignments in Prozeduren (PCAs)......................................................132 Anfangswertzuweisung für Variablen ....................................................................133
6.4 6.4.1 6.4.2 6.4.3
Unterprogramme: Tasks und Functions .................................................................134 Functions ................................................................................................................134 Tasks ......................................................................................................................137 Vereinfachte Deklaration bei Verilog 2001............................................................139
6.5
Der Datentyp event.................................................................................................140
6.6 6.6.1 6.6.2
Iterative Instanziierung mit dem generate-Statement .............................................140 Generate-Schleifen .................................................................................................141 Bedingte Generierung.............................................................................................142
6.7
Zusammenfassung..................................................................................................144
6.8
Aufgaben ................................................................................................................146
95
111
VIII
Inhalt
6.8.1 6.8.2 6.8.3
Wahr oder Falsch? ................................................................................................. 146 Fragen .................................................................................................................... 146 Welche Antwort ist richtig? ................................................................................... 148
6.9 6.9.1 6.9.2 6.9.3
Antworten .............................................................................................................. 149 Wahr oder falsch .................................................................................................... 149 Fragen .................................................................................................................... 149 Folgende Antwort ist richtig .................................................................................. 152
7
Modellbildung: Logik, Speicher, Zustandsautomaten
7.1 7.1.1 7.1.2 7.1.3
Kombinatorische Logik.......................................................................................... 155 Prozedurale Blöcke ................................................................................................ 155 Nebenläufigkeit von Prozessen .............................................................................. 157 Kontinuierliche Anweisungen................................................................................ 158
7.2
RTL-Modelle in Verilog ........................................................................................ 158
7.3 7.3.1 7.3.2 7.3.3
Zustandsautomaten................................................................................................. 160 Zustandsgraphen .................................................................................................... 161 Explizite Zustandsmaschinen................................................................................. 162 Implizite Zustandsmaschinen................................................................................. 166
7.4
Speicher.................................................................................................................. 167
7.5
Bidirektionale Signale............................................................................................ 169
7.6
Zusammenfassung.................................................................................................. 170
7.7 7.7.1 7.7.2 7.7.3 7.7.4
Aufgaben................................................................................................................ 171 Wahr oder Falsch? ................................................................................................. 171 Fragen .................................................................................................................... 171 Welche Antwort ist richtig? ................................................................................... 172 Designaufgabe........................................................................................................ 173
7.8 7.8.1 7.8.2 7.8.3
Antworten .............................................................................................................. 173 Wahr oder Falsch? ................................................................................................. 173 Fragen .................................................................................................................... 174 Folgende Antwort ist richtig .................................................................................. 176
8
Logiksynthese mit Verilog
8.1 8.1.1
Verilog für die Logiksynthese............................................................................... 181 Synthesefähige Verilog-Konstrukte ....................................................................... 181
8.2 8.2.1 8.2.2 8.2.3
Hardwaredefinition mit Verilog ............................................................................. 184 Verhaltensbeschreibung von rein kombinatorischen Schaltungen ......................... 184 Unvollständige Kombinatorik und Latch Inference ............................................... 187 Flankengesteuerte Elemente und RTL-Modelle..................................................... 188
8.3
Zusammenfassung.................................................................................................. 199
8.4
Aufgaben................................................................................................................ 200
153
177
Inhalt
IX
8.4.1 8.4.2 8.4.3
Wahr oder falsch?...................................................................................................200 Fragen.....................................................................................................................200 Welche Antwort ist richtig .....................................................................................201
8.5 8.5.1 8.5.2 8.5.3
Antworten...............................................................................................................202 Wahr oder falsch?...................................................................................................202 Fragen.....................................................................................................................203 Folgende Antwort ist richtig...................................................................................203
9
Verifikation mit Verilog
9.1 9.1.1
Verifikation mit Testbenches .................................................................................206 Grenzen ..................................................................................................................210
9.2 9.2.1 9.2.2 9.2.3 9.2.4 9.2.5
Testbenchentwurf ...................................................................................................211 Eingabemuster und Ausgabeanalyse ......................................................................211 Selbsttestende Testbenches ....................................................................................212 Vollständige Validierung eines 4-Bit-Addierers mit parallelen Modellen .............215 Spezielle Testmuster...............................................................................................217 Top-down-Verifikation eines ASIC-Designs .........................................................223
9.3
Zusammenfassung..................................................................................................230
9.4 9.4.1 9.4.2 9.4.3
Aufgaben ................................................................................................................231 Wahr oder falsch?...................................................................................................231 Fragen.....................................................................................................................231 Ergänzen Sie...........................................................................................................231
9.5 9.5.1 9.5.2 9.5.3
Antworten...............................................................................................................232 Wahr oder falsch?...................................................................................................232 Fragen.....................................................................................................................232 Ergänzen Sie...........................................................................................................234
10
Schlussbemerkungen
235
11
Bibliografie
237
12
Glossar
239
Anhang A: Modelle aus Kapitel 9
205
243
A.1
Komplette Validierung mit Testbench für Addierer...............................................243
A.2
Wallace-Tree-Multiplizierer...................................................................................246
A.3 A.3.1
Top-down-Verifikation des 74LS299 Schieberegisters..........................................248 Die ASIC-Bibliothek cell_lib.v ..............................................................................255
Anhang B: Schlüsselworte
265
Anhang C: Verilog Quick Reference
267
X
Inhalt
C.1 Module........................................................................................................................... 267 C.2 Parallele Anweisungen .................................................................................................. 267 C.3 Daten-Typen .................................................................................................................. 268 C.4 Sequentielle Anweisungen ............................................................................................ 268 C.5 Gatter-Primitive............................................................................................................. 269 C.6 Verzögerungen (Delays)................................................................................................ 270 C.7 Operatoren ..................................................................................................................... 270 C.8 Attribute......................................................................................................................... 272 C.9 Blockierende und nicht blockierende Statements .......................................................... 272 C.10 Tasks und Functions .................................................................................................... 273 C.10.1 Task .......................................................................................................................... 273 C.10.2 Function.................................................................................................................... 273 C.11 System Tasks ............................................................................................................... 274 C.11.1 Ausgabe von Ergebnissen......................................................................................... 274 C.11.2 Simulationssteuerung................................................................................................ 274 C.11.3 Prüfen von Zeitbedingungen..................................................................................... 274 C.11.4 Lesen aus Dateien..................................................................................................... 274 C.12 Übliche Compiler-Direktiven ...................................................................................... 275 C.13 Nicht synthesefähige Verilog-Konstrukte ................................................................... 275 C.13.1 Deklarationen und Definitionen ............................................................................... 275 C.13.2 Statements................................................................................................................. 275 C.13.3 Operatoren und Sonstiges ......................................................................................... 276 C.14 Verilog 2001................................................................................................................ 276 C14.1 Ports und Datentypen................................................................................................. 276 C14.2 Tasks und Functions .................................................................................................. 277 C.14.3 Generate.................................................................................................................... 277 C.15 Vereinfachte Sensitivitätsliste ..................................................................................... 278 C.16 Potenzierungsoperator ................................................................................................. 278 C.17 Vorzeichenbehaftete Arithmetik.................................................................................. 278 C.18 Multidimensionale Felder............................................................................................ 279 Anhang D: Verilog Primitive D.1
281
Logische Gatter ...................................................................................................... 281
Anhang E: Die XILINX-Version des ModelSim-Simulators
283
Index
285
Vorwort des Herausgebers Viele technische Entwicklungen sind durch ständiges Größenwachstum der jeweiligen Systeme gekennzeichnet. Die Mikroelektronik wird hingegen durch die kontinuierliche Verkleinerung der Bauelementstrukturen vorangetrieben. Die äußeren Abmessungen der Chips und damit die Herstellkosten ändern sich kaum, die Integrationsdichte (Bauelemente/Fläche) hingegen verdoppelt sich aber etwa alle 18 Monate. So sinken die Preise für eine gegebene elektronische Funktion und das sorgt für eine ungebrochene Dynamik in den technischen und kommerziellen Möglichkeiten. Der Entwurf komplexer elektronischer Systeme stellt folglich für viele Unternehmen eine Schlüsselkompetenz dar. Obwohl die Software einen wachsenden Anteil an digitalen Systemen hat, ergibt sich häufig nicht nur für große, sondern auch für kleine und mittelständische Firmen die Notwendigkeit, digitale Hardware zu entwickeln, entweder als ASICs oder neuerdings verstärkt mit programmierbaren Logikbausteinen (CPLD, FPGA). Nur so entstehen konkurrenzfähige Produkte oder lassen sich spezifische Kundenanforderungen erfüllen. Gerade die ständig steigende Beliebtheit von CPLDs und FPGAs in der mittelständischen industriellen Anwendung gibt den Entwurfsmethoden zur Erstellung der Designdaten für die Logikbausteine auch in der Lehre an Hochschulen wachsende Bedeutung. Die wachsende Komplexität der zu entwickelnden Schaltungen stellt für die Entwickler von solchen (digitalen) mikroelektronischen Systemen eine große Herausforderung dar, die ohne Entwurfsautomatisierung mit EDA-Werkzeugen (Electronic Design Automation) nicht mehr zu bewältigen ist. Die entscheidende Rolle spielen dabei Hardware-Beschreibungssprachen (HDLs, Hardware Description Languages), die zunächst primär zur Verifikation von digitalen Schaltungsblöcken im Rahmen der Logiksimulation eingesetzt wurden. HDLs unterscheiden sich von Programmiersprachen wie FORTRAN, PASCAL oder C dadurch, dass sie nicht nur sequentielle Abläufe, sondern auch zeitlich parallel abzuarbeitende Prozesse in elektronischen Systemen (Hardware) nachbilden können. Die Beschreibungssprache Verilog, die im vorliegenden Buch behandelt wird, entstand 1983 bei der Firma Gateway Design Automation und die Sprache VHDL wenig später als Auftragsentwicklung des USamerikanischen Verteidigungsministeriums. Beide Sprachen haben sich rasch verbreitet, weil leistungsfähige Simulatoren bereit standen, mit deren Hilfe auch große Entwürfe effizient simuliert werden konnten.
XII
Vorwort
Solange Schaltungen, die aufwendig Gatter für Gatter eingegeben werden mussten, nur zeitsparend simuliert werden konnten, haben sich HDLs als primäres Definitionsmedium von elektronischen Systemen nicht durchsetzen können. Der Umbruch in der Designmethodik kam mit der Einführung kommerzieller Werkzeuge zur Logiksynthese durch die Firma Synopsys. Deren Produkt „Design Compiler“ kann abstrakte Schaltungsbeschreibungen auf der Register-Transfer-Ebene (RTL, Register Transfer Level) in eine optimierte Gatternetzliste mit Komponenten aus einer Zellenbibliothek der gewählten Herstelltechnologie erzeugen („synthetisieren“). Der Designablauf beginnt hier mit der RTL-Beschreibung des zu entwickelnden Systems in einer Hardwarebeschreibungssprache. Der Entwickler gibt nur noch die Datenflüsse zwischen Registern vor und definiert die logischen Operationen, die zwischen den Registerbänken ausgeführt werden sollen. Die detaillierte Ausarbeitung der Schaltung auf Gatterebene inklusive aller Verbindungsleitungen führt das Logiksynthesewerkzeug durch. HDLs haben also eine ähnliche Bedeutung für das Hardwaredesign wie Programmiersprachen für die Softwareentwicklung. Die Möglichkeit, Gatterschaltungen quasi automatisch zu synthetisieren, hat die Abstraktionsebene und Sichtweise beim Logikdesign verändert. Waren beim Schaltplaneditieren Kenntnisse der Booleschen Algebra und der digitalen Logik auf Gatterebene gefragt, so sind beim Digitalentwurf mit Logiksynthese abstrakte Datenflussbeschreibungen in Verhaltenssicht zu erstellen. Allerdings ist Ingenieurwissen immer noch entscheidend, denn die Synthesewerkzeuge können nicht alle Konstrukte von HDLs übersetzen und die Art und Weise, wie der HDL-Code für eine Schaltung geschrieben wird, bestimmt die Qualität der synthetisierten Gatternetzliste. Kenndaten sind hierbei Gatteraufwand, elektrische Leistungsaufnahme sowie Datendurchsatzraten. Diese Kriterien stehen miteinander in Konkurrenz, lassen sich also nicht gleichzeitig optimal gestalten. Die eigentliche Entwicklungsleistung konzentriert sich heute in der manuellen Optimierung der RTL-Beschreibung. Dieses Buch über die Hardwarebeschreibungssprache Verilog ist das dritte in einer Reihe über moderne Methoden des Elektronikentwurfs. Die Reihe begann mit Kesels und Bartholomäs Titel „Entwurf von digitalen Schaltungen und Systemen mit HDLs und FPGAs“, der sich mit den Methoden beschäftigt, die derzeit in der Industrie angewendet werden. Danach erschien das Werk von Hervé „VHDL-AMS“, das die standardisierte Erweiterung der Hardwarebeschreibungssprache VHDL von rein digitalen Systemen zu analogen, gemischt analog-digitalen und heterogenen Systemen hin behandelt. Die Simulation und Modellierung solcher Systeme, die sich weder der digitalen noch der analogen Elektronik eindeutig zuordnen lassen und verschiedene physikalische Disziplinen (Energiedomänen) umfassen, gewinnt im Zuge der Mikrosystemtechnik und Nanotechnologie immer größere technische Bedeutung. Der vorliegende Band behandelt die Beschreibung von digitalen Systemen für die Schaltungssynthese, den Test und die Verifikation mit Hilfe der Sprache Verilog. Dies war die erste Hardwarebeschreibungssprache, die in der Industrie beim Entwurf digitaler elektronischer Systeme weite Verbreitung fand. Die Sprache wurde und wird eingesetzt, um die Schaltungsvorgaben zu erfassen, das Systemverhalten zu simulieren und das erstellte Design zu verifizieren. Heute wird keine kommerzielle digitale Schaltung mehr ohne Einsatz von HDLs entwickelt und Verilog ist nach wie vor weltweit die am meisten verwendete Sprache.
Vorwort
XIII
Damit komplettiert der Titel „Verilog: Modellbildung für Synthese und Verifikation“ die Reihe, die dem Leser einen umfassenden Überblick über die aktuellen Strategien, Probleme und Verfahrensweisen des rechnergestützten Entwurfs elektronischer Systeme vermitteln soll. Da heute keine digitale Schaltung ohne Einsatz von HDL-Designmethoden entwickelt wird, sollten alle Studierenden der Elektrotechnik, die sich in Elektronik vertiefen wollen, diese Schlüsselkenntnisse mit in den Beruf nehmen. So verbessern sie ihre Beschäftigungsfähigkeit durch verkürzte Einarbeitungsphasen. Die hier mit dem Buch über Verilog inhaltlich abgeschlossene Reihe ist nicht nur als Begleitreihe zu Vorlesungen an Hochschulen und Universitäten gedacht, sondern auch zum Selbststudium, denn vielen Ingenieuren im Berufsfeld fehlen die einschlägigen Fertigkeiten, um die Vorteile des HDL-basierten Entwurfs zu nutzen. Wie erste Fachrezensionen von Kollegen belegen, wurden diese Ziele bereits von den ersten beiden Bänden der Reihe erreicht und wir haben uns bemüht, dass auch das Buch über Verilog den gleichen Gebrauchswert aufweist.
Darmstadt
Bernhard Hoppe
1
Einleitung
Hardwarebeschreibungsprachen (HDLs, Hardware Description Languages) sind Werkzeuge für den Digitalentwurf. HDLs werden beim Entwurf digitaler elektronischer Systeme eingesetzt, um die Schaltungsvorgaben zu erfassen, das Systemverhalten zu simulieren und das erstellte Design zu verifizieren. Heute wird keine digitale Schaltung mehr in der Praxis ohne Einsatz von HDLs entwickelt. Vielen Ingenieuren im Berufsfeld fehlen aber die einschlägigen Kenntnisse, um die Vorteile des HDL-basierten Entwurfs zu nutzen. Aus diesem Grund ist dieses Buch geschrieben worden und sowohl als Begleitbuch zu Vorlesungen wie auch zum Selbststudium geeignet. Es stellt die Hardwarebeschreibungssprache Verilog vor und fasst die grundlegenden Verfahren der aktuellen Designmethodik für digitale (integrierte) Schaltungen zusammen. Dabei steht die Verwendung von Verilog bei der praktischen Modellbildung stärker im Vordergrund als die rein syntaktischen Aspekte. Neben der weltweit gebräuchlichen Hardwarebeschreibungssprache Verilog, die in diesem Buch genauer vorgestellt werden soll, hat sich auch die in Europa populäre Sprache VHDL als Industriestandard etablieren können. Ob nun VHDL oder Verilog den Designer besser bei seinen Entwurfsaufgaben unterstützt, ist Ansichtssache. Beide Sprachen haben ihre Stärken und Schwächen. Verilog lässt sich leichter erlernen, ist an der Sprache C orientiert und hat nicht den komplexen theoretischen Überbau von VHDL. VHDL ist hingegen methodisch konsistenter. Es gibt aber keine Designaufgabe, die nur mit der einen und nicht mit der anderen Sprache zu bewältigen wäre. Verilog war die erste HDL, die sich in der Elektronikindustrie durchgesetzt hat. VHDL kam später, war aber von Anfang an eine genormte, frei zugängliche Sprache, während Verilog zunächst von der Firma Gateway (später Cadence) als proprietäres Tool vermarktet wurde und erst 1997 und 2001 in revidierter Form als IEEENorm 1394 erschienen ist. Statt grafischer Schaltpläne werden heute meist HDL-Netzlisten und hier insbesondere Verilog-Netzlisten zur Schaltungsdokumentation benutzt. HDLs sind genormt und können daher von jedem Tool, das die Normen erfüllt, verarbeitet werden, während Schaltpläne in der Regel in proprietären grafischen Formaten abgelegt sind. HDLs haben also die Schaltpläne als primäres Entwurfseingabemedium ersetzt. Mit diesen Sprachen können aber nicht nur logische Funktionen auf Schaltkreisebene sondern auch Systemverhalten auf höherer Abstraktionsebene modelliert werden. Verschiedene Abstraktionsebenen können gleichzeitig simuliert werden. Dies eröffnet neue Möglichkeiten, die beim Schaltplanentwurf nicht bestehen. So können verschiedene Architekturansätze mit abstrakten HDL-Verhaltensmodellen simuliert und verglichen werden. Die beste Variante wird dann ausgearbeitet und mit dem zergliedernden Entwurfsstil (Top-Down) in strukturelle Modelle auf Gatterebene umgesetzt.
2
1 Einleitung
HDL-Methoden konnten sich aber erst dann gegenüber Schaltplanentwürfen durchsetzen, als 1987 Synopsys mit dem Logiksynthesewerkzeug Design Compiler auf den Markt kam. Die Logiksynthese hat die Designverfahren revolutioniert. Ein Synthesetool analysiert das HDLModell, das das Schaltungsverhalten nur abstrakt beschreibt, setzt das Modell in eine boolesche Beschreibung um, optimiert die logische Struktur und bildet das Ergebnis auf die Komponenten einer ASIC-Bibliothek (logische Gatter, Flip-Flops, etc.) in der Zieltechnologie ab. Das Ergebnis ist eine Implementierung der gewünschten Funktion als Schaltung aus Bibliothekszellen. Diese Schaltung kann als Verilog-Netzliste oder in anderen Formaten ausgegeben werden und dient als Grundlage für den physikalischen Entwurf, bei dem aus der Schaltung eine Strukturdarstellung abgeleitet wird, die sich auf einen programmierbaren Logikbaustein übertragen lässt oder als ASIC-Layout an den Halbleiterhersteller gegeben werden kann. Die synthesebedingten Rationalisierungseffekte bei der Schaltungsdefinition haben den Schwerpunkt der Designaktivitäten verschoben. Der Designer beschäftigt sich heute fast nur noch mit der Frage, was implementiert werden soll, und überlässt die Umsetzung in eine technologienahe Gatterbeschreibung den Computer-Tools. Statt elegante und effiziente Schaltungsvarianten zu entwickeln, ist er primär damit befasst, ein synthesefähiges VerilogModell zu erstellen und dessen Übereinstimmung auf Verhaltensebene und später auf Gatterniveau mit den Vorgaben der System-Spezifikation (Lastenheft) zu verifizieren. Verifikation bleibt auch der Schwerpunkt im gesamten weiteren Entwurfsablauf: Nach der Synthese und der Umsetzung in die Zieltechnologie folgen zusätzliche Verifikationsschritte, die dann auch Laufzeiten durch die eingesetzten Gatter berücksichtigen. Auch bei der Verifikation bieten HDL-Modelle Vorteile. Statt die Testsignale per Hand in den Simulator einzugeben und die Ergebnisse als Wellenzüge mit bloßem Auge zu analysieren, kann man so genannte Testbench-Modelle mit HDLs entwickeln, die diese Aufgaben automatisch erledigen und selbständig die Verifikationsaufgaben abarbeiten. Im vorliegenden Buch werden die sprachlichen Konstrukte und Möglichkeiten von Verilog im Hinblick auf die einzelnen Designschritte dargestellt. Bei dieser Einführung in Verilog wird unterstützend auf ähnliche oder entsprechende Anweisungen in den verwandten Sprachen VHDL als Hardwarebeschreibungssprache und C als prozedurale Sprache Bezug genommen. Das Buch ist folgendermaßen aufgebaut: Nachdem in Kapitel 2 die Grundlagen der HDL-Designmethoden gelegt wurden, folgen in Kapitel 3 die syntaktischen und semantischen Regeln als allgemeine Vorgaben des VerilogStandards. Der Unterschied zwischen prozeduralen Computersprachen und HDLs liegt in der Einbeziehung der zeitlichen Nebenläufigkeit, mit der Hardware und damit auch HDLModelle Informationen verarbeiten, während Software die Instruktionen stets sequentiell Instruktion für Instruktion angeht. In Kapitel 4 modellieren wir mit Verilog die Grundkomponenten elektronischer Schaltungen (logische Gatter und Flip-Flops) und beschäftigen uns mit Laufzeiteffekten in Schaltungen. In Kapitel 5 stehen strukturelle Modelle mit instanziierten Modulen und Primitiven im Vordergrund und es wird auf das Standard-Delay-Format (SDF) eingegangen. Nachdem der gatterbasierte Entwurf abgehandelt ist, wenden wir uns in Kapitel 6 den Verhaltensmodellen zu, mit denen Schaltungseigenschaften auf höherer Abstraktionsebene definiert werden kön-
Einleitung
3
nen. Die Verilog-Konstrukte für diese Aufgabe sind den Anweisungen von prozeduralen Sprachen wie C sehr ähnlich. Wichtig ist aber, dass der Designer bei der abstrakteren Modellbildung nicht vergisst, dass Verilog nebenläufiges Hardwareverhalten beschreibt und keine reinen Computeralgorithmen. Mit diesem Kapitel sind die grundlegenden Konzepte erarbeitet und wir können uns in Kapitel 7 der Modellierung spezieller Hardwarekomponenten wie Speichern, kombinatorischer Logik und Zustandsautomaten zuwenden. Kapitel 8 behandelt die Logiksynthese, bei der Sprache in Hardware übersetzt wird. Es sind nicht alle Verilog-Anweisungen synthetisierbar, denn nicht jedes sprachliche Konstrukt hat seine Entsprechung in Hardwarekomponenten. Die Qualität des Syntheseergebnisses hängt stark von der zugrunde liegenden Verilog-Beschreibung ab. Implikationen des VerilogCodes und die reduzierte Syntax werden systematisch vorgestellt und an Beispielen verdeutlicht. Im Kapteil 9 wird die Verifikation mit Verilog-Testbenches diskutiert. Als Testbench (engl. für Prüfumgebung) wird ein HDL-Modell bezeichnet, das eine bestimmte Abfolge von Signalen erzeugt, mit denen das zu verifizierende Modell angesteuert werden kann. Es ist auch möglich, mit Hilfe des Testbench-Modells die Ausgabesignale des zu testenden Modells aufzunehmen, abzuspeichern oder automatisiert zu überprüfen (selbsttestende Testbench). Die verschiedenen Strategien für die automatische Design-Verifikation werden erläutert und mit Anwendungsbeispielen illustriert. Kapitel 10 fasst zusammen und gibt einen Ausblick auf aktuelle Entwicklungen der Sprache Verilog. In den Anhängen finden sich eine Verilog Quick Reference, ein Glossar mit den wichtigsten Begriffen aus dem Designbereich und Beispiele sowie Ergänzungen zu den einzelnen Kapiteln. Zur besseren Lesbarkeit sind alle Verilog-Schlüsselwörter im Text fett gedruckt, die Schlüsselwörter des SDF-Standards und von VHDL in GROSSBUCHTSTABEN und alle stehenden Begriffe, die im Rahmen des HDL-Designs verwendet werden, kursiv. Mein besonderer Dank für die Unterstützung beim Schreiben des Buches gebühren Frau Mönch vom Oldenbourg Verlag, Herrn Jens Hüttemann und der Firma Mentor Graphics für die Überlassung der Daten des Verilog-Trainings-Kurses und Herrn Karthikeyan Balasubramanian (M.Sc.) für viele anregenden Diskussionen und Hilfe bei der Erstellungen der Grafiken im Buch.
2
Electronic-Design mit Verilog HDL Rem tene, verba sequuntur Halte dich an die Tatsachen, die Worte werden folgen Cato der Ältere
In den letzten Jahrzehnten haben sich die Möglichkeiten, die integrierte Schaltungen ICs beim Elektronikentwurf bieten, rapide entwickelt. Bestanden die ersten ICs aus wenigen digitalen logischen Gattern, die zu einem Bauteil zusammengefasst wurden, so brachte Anfang der 70er Jahre des 20. Jahrhunderts die Firma INTEL den ersten (4-Bit-)Mikroprozessor und den ersten 1-kBit-Halbleiterspeicher auf den Markt, bei denen einige Tausend Transistoren in einem Chip integriert waren (Large Scale Integration, LSI). Heute haben diese mikroelektronischen Komponenten 64-Bit-Wortbreiten oder 512 MBit Speicherkapazität und bestehen aus Millionen von Transistoren (Very Large Scale Integration, VLSI). Um mit diesem immensen Anstieg der Designkomplexität umzugehen, haben sich die Designmethoden in ähnlicher Weise entwickelt. LSI-Schaltungen wurden mit wenig durchgängigen und einfachen Methoden entwickelt. Teildesigns (weniger als 100 Transistoren) wurden mit Schaltkreissimulatoren (wie SPICE) simuliert. Es wurden diskrete Probeaufbauten aus logischen Gattern der 74000er Serie durchgeführt, um die Gesamtfunktionalität zu verifizieren (Breadboarding). Das Chiplayout, in dem die geometrische Beschreibung für die Produktionsvorgaben für den Halbleiterhersteller festgelegt sind, wurde per Hand Transistor für Transistor auf Millimeterpapier gezeichnet und dann am Zeichentisch digital erfasst oder man gab das Layout mit GeometrieEditoren auf Spezialcomputersystemen ein. Dieses umständliche Vorgehen konnte mit der Fortentwicklung der Halbleitertechnologie nicht Schritt halten. Beim Übergang von der LSI zur VLSI-Phase verlor der Einzeltransistor seine Funktion als grundlegendes Bauelement an das logische Gatter als Basiskomponente. Gleichzeitig wurde als erster Schritt zur Entwurfsautomatisierung die Layoutsynthese eingeführt, bei der Layoutblöcke für die einzelnen Gattertypen aus einer Bibliothek von so genannten Standardzellen automatisch von Spezialsoftwaretools zusammengesetzt und mit Leiterbahngeometrien nach den Vorgaben des Schaltplans (Schematic) verbunden wurden. Zur Schaltungseingabe von Standardzellschaltungen verwendete man Schaltplaneditoren und zur Simulation Logiksimulatoren, die nicht mehr mit Strömen und Spannungen rechneten, wie beispielsweise
6
2 Electronic-Design mit Verilog HDL
SPICE, sondern die logische Funktion eines Gatters mit den Zuständen „0“ und „1“ nachbildeten. Solche Simulationen auf Gatterebene waren viel effizienter, da man sich bei digitalen Schaltungen nicht für die Details der Signalübergänge, sondern nur für die angenommenen Zustände interessiert. Gleichzeitig boten die Schaltplaneditoren die Möglichkeit, Grundschaltungen aus Gattern zu Blöcken zusammenzufassen und so eine Schaltungshierarchie zu schaffen, mit der auch komplexe Designs übersichtlich dargestellt werden können. Ausgehend von den Designprimitiven, den Gattern, setzte man den Hierarchiesierungsprozess bis zur obersten Hierarchieebene fort (Top-Level), auf der der Entwurf nur noch über ein einziges Symbol als Black-Box mit allen Ein- und Ausgangsverbindungen der Schaltung erscheint. Die Logiksimulation wurde aufgrund der zunehmenden Designkomplexität zum entscheidenden Faktor im Bemühen, die technologischen Fortschritte und die damit verbundene Steigerung des Integrationsgrads auch tatsächlich auf der Designseite nutzen zu können. Logiksimulationen ermöglichen umfassende Funktionstests. So können Fehlfunktionen bereits in der Designphase korrigiert werden, vor der Fabrikation und der Vermessung von Prototypen. Jeder unentdeckte Designfehler erfordert nämlich nach der Korrektur einen neuen, langwierigen und kostspieligen Fabrikationsdurchlauf. Deshalb wurden Logiksimulatoren immer weiter entwickelt und mit speziellen Hardwarebeschleunigern ausgestattet. In diesem Wettlauf kam 1985 die Firma Automated Integrated Design Systems, die sich ein Jahr später in Gateway Design Automation umbenannte, mit dem Simulator Verilog auf den Markt. Dieser Simulator war das erste Werkzeug, das nicht nur logische Schaltungen, sondern auch parallel dazu abstrakte Verhaltensbeschreibungen simulieren konnte, die in einer Cähnlichen Sprache vorgegeben werden konnten. So ließen sich verschiedene Architekturvarianten im Design ausprobieren, ohne dass man jede Version bis auf Gatterebene ausdetaillieren musste. Vorher wurden Architektur und laufzeitbehaftetes, taktgesteuertes Gatterverhalten mit inkompatiblen Werkzeugen getrennt voneinander analysiert. Gleichzeitig entwickelte Gateway den schnellen XL-Algorithmus zur Ausführung des Simulationsprogramms und Verilog-XL wurde zur leistungsfähigsten Simulationssoftware, die damals verfügbar war. Der Simulator Verilog erfasste die Struktur einer Schaltung über Sprachkonstrukte in Form von Netzlisten. Das besondere an einer solchen Hardwarebeschreibungssprache im Vergleich zu einer herkömmlichen sequentiellen Programmiersprache wie PASCAL, C oder Fortran liegt in der nebenläufigen Erfassung von Prozessaktivitäten. Diese Nebenläufigkeit, also das zeitlich parallele Abarbeiten von Abläufen, ist das Kennzeichen der Informationsverarbeitung in elektronischen Schaltungen, in denen verschiedene Funktionsblöcke gleichzeitig unterschiedliche Prozesse bearbeiten können (Bild 2.1). Neben Verilog wurde 1987 die Sprache VHDL noch im Auftrag des US-amerikanischen Verteidigungsministeriums entwickelt und von der Ingenieursvereinigung IEEE genormt (IEEE-1076-2005), um die Elektronik in militärischer Ausrüstung dokumentieren und herstellerunabhängig simulieren zu können. Mittlerweile ist auch Verilog standardisiert (IEEE 1394-2001).
2 Electronic-Design mit Verilog HDL
a
7
out1
out2
b
c
out3
out3
Abb. 2.1 Nebenläufige Ausführung in elektronischen Schaltungen. Ein Wechsel des Signals b kann eine gleichzeitige, nebenläufige Änderung aller Ausgänge out1 bis out4 bewirken. In sequentiellen Softwarebeschreibungen der gezeigten logischen Verknüpfungen, würde sich erst ein Ausgang und dann nacheinander alle weiteren Ausgangswerte ändern.
War das ursprüngliche Ziel, mit HDLs komplexe Schaltungen zu erfassen und simulieren, so ergaben sich vollständig neue Möglichkeiten, als Ende der 80er Jahre Logiksynthesewerkzeuge bereitstanden. Diese Tools können so genannte RTL-Beschreibungen (Bild 2.2) von Schaltungen (Register Transfer Level), die eine geeignete Untermenge der möglichen HDLKonstrukte benutzen, automatisch in Gatternetzwerke überführen. Auf RTL-Ebene gibt der Entwerfer nur noch den Datenfluss zwischen Registern vor und spezifiziert die Datenverarbeitung zwischen den Registerstufen. Alle weiteren Designschritte bis zur fertigen Gatterschaltungen inklusive der Optimierung erledigt das Synthesewerkzeug.
8
2 Electronic-Design mit Verilog HDL
*
* D
SET
CLR
*
Q
D
Q
SET
CLR
Q
D
Q
SET
CLR
Q Q
Takt
D
SET
Q
D
SET
Q
Schaltwerk
Schaltwerk CLR
Q
CLR
Q
Takt
Abb. 2.2 RTL-Schaltung: oben digitaler Filter als RTL-Schaltung und unten schematisch der Aufbau aus Schaltwerken mit zwischengeschalteten Registern. Solche Strukturen können auch in HDLs mit Texteingaben spezifiziert werden. Die Schaltwerke werden mit Prozessen beschrieben, die von steigenden Flanken des gemeinsamen Taktes ausgelöst werden, und die Register durch implizite Zuweisung von speichernden Elementen (Siehe 7.2)
Diese Form der Entwurfsautomatisierung erschloss Designkomplexitäten, die vorher völlig unzugänglich erschienen. 100.000-Gatter-Designs waren kein Problem mehr. Außerdem konnten aufgrund der inhärenten modularen Struktur von HDL-Beschreibungen einzelne Blöcke aus fertigen und verifizierten Entwürfen herausgelöst und als Intellectual Property (IP) wieder verwendet werden. Dies beschleunigte den Design-Prozess weiter. Heute sind Chips mit Millionen von Gattern keine Seltenheit mehr. Bild 2.3 zeigt die Entwicklung der Designmethodik in den letzten Jahrzehnten.
2.1 Der Design-Zyklus
2.1
9
Der Design-Zyklus
Der typische Designzyklus für ein elektronisches System beginnt mit der Erfassung der Anwenderforderungen, also welche Funktion soll dargestellt werden, welche Eingangs- und Ausgangssignale sind gegeben, usw. Aus den Kundenwünschen wird zuerst ein Systemkonzept erstellt, das als Lastenheft (Spezifikation) schriftlich fixiert wird. In der Konzeptphase werden die gewünschten Funktionen in Hard- und Softwareanteile zerlegt und es wird geprüft, an welchen Stellen kundenspezifische Lösungen (ASIC oder anwenderspezifisch programmierbare Logikbausteine, CPLD oder FPGA) Vorteile bieten. Dann folgt für jede kundenspezifische Komponente wieder eine Konzeptphase, in der die Eigenschaften der VLSISchaltung für sich genommen spezifiziert werden. Ob am Ende des Prozesses ein ASICoder ein CPLD-Design stehen, spielt so lange im Entwurfsablauf keine Rolle, bis die Umsetzung des verifizierten Designs in ein Chiplayout oder Programmierdaten für den feldprogrammierbaren Baustein anstehen (Backend).
Design Reuse
sig De Gatter Transistoren Geometrien
1975
om nk
ple
t xitä RTL
Systemdesign
Logiksynthese
Platzieren und Verdrahten
Einsatz von HDLs (Verilog, VHDL)
Maskenlayout
1980
1985
1990
1995
2000
2005
Abb. 2.3 Entwicklung der Designmethodik seit 1975 ermöglicht immer höhere integrierte Entwürfe. Seit zwei Jahrzehnten sind Hardwarebeschreibungssprachen die Basis des Entwurfs.
10
2.1.1
2 Electronic-Design mit Verilog HDL
Designeingabe
Mit HDLs lassen sich mikroelektronische Systeme aus verschiedenen Blickwinkeln beschreiben. Nach Gasky und Kuhn [GAK] gibt es drei Sichtweisen. In der strukturellen werden elektronische Systeme aus elektrisch verbundenen Komponenten wie in einem Schaltplan aufgebaut. Die Verhaltenssicht beschreibt das System als Black-Box, mit Eingangs- und Ausgangssignalen, die von der Schaltung ineinander transformiert werden. Zu diesen beiden Sichten tritt beim Elektronikentwurf noch die geometrische Sicht hinzu. Damit ist die Beschreibung des elektronischen Systems über grafische Daten für das Chiplayout, die Leiterplattenverdrahtung oder die Zuordnung von Verbindungsleitungen und Logikzellen in einem CPLD gemeint. Diese dritte Beschreibungsart spielt hier aber keine Rolle. Details finden sich in der Literatur [JAN]. Die drei Sichtweisen gliedern die Entwurfsaufgabe horizontal. Da der Entwurf elektronischer Systeme trotz HDLs und Logiksynthese eine immer komplexer werdende Aufgabe darstellt, werden Hierarchien zur Verbesserung der Übersichtlichkeit eingeführt. Die verschiedenen Hierarchieebenen gliedern den Entwurf vertikal, genau wie die drei Sichtweisen das Design horizontal strukturieren. Jeder Entwurf (Bild 2.4) beginnt mit einer als Text vorliegenden Spezifikation. Der nächste Schritt des Designablaufs setzt die Spezifikation in eine HDL-Verhaltensbeschreibung um, die man dann in ein RTL-Design überführt. Bei der so genannten High-Level-Synthese [KEB] wird die Verhaltensbeschreibung automatisch in RTL-Code umgewandelt. Stehen hierfür geeignete Werkzeuge nicht zur Verfügung, dann wird das Verhaltensmodell in geeigneter Weise manuell umgeschrieben. Synthesewerkzeuge unterstützen diesen Prozess durch Analysemodule, die alle nicht synthetisierbaren Konstrukte anzeigen. Die HDL-Verhaltensbeschreibung beschreibt das funktionale Verhalten des Systems abstrakt mit mathematischen Formeln und boolescher Algebra. Die Systemdynamik ist über die Zahl der bei der RTL-Umsetzung eingefügten Registerstufen zu beeinflussen. Die Verhaltensbeschreibung wird mit Simulationen getestet, um so früh wie möglich festzustellen, ob das HDL-Design die geforderten Funktionen korrekt erfasst. Das RTL-Design wird simuliert, um zu prüfen, ob das Verhalten der Verhaltensbeschreibung 1:1 umgesetzt wurde. Dabei dient das Verhaltensmodell als Referenz. Mit diesem verzahnten Vorgehen können sehr früh im Entwurfszyklus grundlegende Designfehler beseitigt und Missverständnisse zwischen Systemdesigner und Konzeptentwickler korrigiert werden. RTL-Design und Verhaltensbeschreibung sind technologieunabhängig. Erst im nächsten Schritt, der Logiksynthese, erfolgt die Zuordnung eines spezifischen Herstellverfahrens und damit einhergehend werden elektronischen Funktionen spezifische Signallaufzeiten zugewiesen. Wenn sich später die Technologie zu noch schnelleren Schaltzeiten, geringerer Verlustleistung und kleinerem Ressourcenbedarf weiterentwickelt, kann die Logiksynthese die existierende RTLSchaltung für die neue Technologie aufbereiten und anpassen, ohne dass das grundlegende Design geändert werden müsste. Bei der Designeingabe mit HDLs verfährt man genau wie beim Schreiben von Computerprogrammen. Eine komplexe Funktion kann häufig mit wenigen HDL-Zeilen definiert werden. Die Multiplikation von zwei 32-Bit-Zahlen, ein komplexes Schaltwerk aus vielen Gatterkomponenten, lässt sich z.B. in nur einer Zeile Verilog-Code ausdrücken. Die Textbe-
2.1 Der Design-Zyklus
11
schreibung in HDL-Syntax mit Kommentaren ist dann viel leichter lesbar als ein Gatterschaltplan mit vielen Komponenten, zahllosen Verbindungsleitungen und einer vielschichtigen Schaltungshierarchie. Spezifikation
Verhaltensmodell Manuelles Umsetzen
RTL-Modell
Simulation
Testen auf Übereinstimmung
Logiksynthese Zielbibliothek Gatternetzliste
Simulation
Testen auf Übereinstimmung
Layousynthese / Place & Route Leitungslaufzeiten
Physikalisches Design
Simulation
Testen auf Übereinstimmung
Fertiger Entwurf
Abb. 2.4 Designablauf als Flussdiagramm: Alle Schritte bis einschließlich der Erstellung der Gatternetzliste werden als Frontend bezeichnet, die physikalische Realisierung als Backend. Simulationen stellen die funktionale Übereinstimmung der verschiedenen Abstraktionsebenen des Designs von Stufe zu Stufe sicher.
12
2 Electronic-Design mit Verilog HDL
Effizienz, Lesbarkeit und Portierbarkeit auf neue Technologien sind die primären Vorteile von HDLs als Designeingabemedium. Dies wird auch in Zukunft so bleiben, denn auch die fertigen Reuse-Blöcke, die man kaufen oder aus eigenen Entwicklungen recyceln kann, sind meist HDL-Blöcke, die sich am einfachsten wieder in HDL-Design einpassen lassen.
2.1.2
Logiksynthese
Der nächste Schritt im Designablauf ist das Starten der Logiksynthese. Unter einem Syntheseprozess versteht man die automatische Transformation einer Beschreibung von einer Abstraktionsebene in die nächst tiefer liegende, wobei tiefer liegend technologienäher bedeutet. Bei der Logiksynthese wird eine HDL-Beschreibung auf RTL-Ebene zunächst analysiert und in boolesche Gleichungen, mathematische oder logische Operatoren und Speicher übersetzt. Diese Beschreibung ist noch generisch, also noch nicht technologiebezogen. Dann wird die generische Beschreibung optimiert. Dabei werden Redundanzen beseitigt und die Zahl der logischen Verknüpfungen wie bei einem Karnaugh-Diagramm minimiert. Abschließend bilden die Synthesewerkzeuge die generische Netzliste auf die zur Verfügung stehende Gatterbibliothek ab und versuchen durch Einfügen von Treibern die bestehenden Laufzeitanforderungen zu erfüllen. Als Ergebnis entsteht eine Gatternetzliste aus Elementen der Zielbibliothek des ASICHalbleiterherstellers oder CPLD-Produzenten, die neben der logischen Funktion der Gatter auch deren Signalverzögerungen erfasst. Diese Netzliste wird wieder per Simulation mit dem Verhalten der RTL-Beschreibung verifiziert, um zu testen, ob die Umsetzung korrekt erfolgt ist, und um zu prüfen, ob die Schaltung auch mit den jetzt erstmalig einbezogenen Gatterlaufzeiten die Designvorgaben erfüllt. Gatterlaufzeiten sind eine hardwarespezifische Eigenschaft, die auf RTL-Ebene nicht einbezogen werden. Auf der RTL-Ebene arbeiten die Schaltwerke zwischen den Registerstufen unverzögert. Ein RTL-Design kann daher im Prinzip mit beliebig hoher Taktfrequenz betrieben werden. Auf Gatterebene nach der Synthese kann man bestimmen, welche Verzögerungszeit ein Schaltnetz zwischen zwei Registern aufweist und welche minimale Periodendauer der Takt nicht unterschreiten darf.
2.1.3
Physikalische Implementierung
Die Gatternetzliste aus der Synthese wird im Backendbereich des Designzyklus in eine physikalische Realisierung umgesetzt. Die Gatterschaltung wird automatisch mit so genannten Layoutsynthese-Tools in ein Layout (geometrische Sicht) überführt, das aus Layoutblöcken der einzelnen Instanzen besteht, die mit Leiterbahnen verbunden sind. Dabei treten als weiteres Korrektiv die Leitungslaufzeiten zu den Gatterverzögerungen hinzu. Diese sind von der Leiterbahnführung und der Leiterbahnlänge bestimmt und damit Informationen, die erst dem fertigen Layout entnommen werden können. Die Laufzeiten werden aus dem Layout mit geeigneten Tools extrahiert und in die Gatternetzliste eingebunden. Dann erfolgt die abschließende Post-Layout-Simulation, die im Zeitverhalten dem später realisierten System entsprechen sollte.
2.2 Verilog
13
Die Umsetzung des RTL-Designs in ein CPLD ist sehr ähnlich: die Logiksynthese liefert eine Netzliste aus Gattern aus der Zielbibliothek für den gewählten programmierbaren Baustein. Software-Tools (sog. Platzier- und Verdrahtungswerkzeuge, Place & Route) bilden die Gatterschaltung optimal auf die interne Struktur des CPLDs ab und schalten die nötigen Verbindungen in der Leitungsmatrix des programmierbaren Chips frei. Alle Laufzeiten werden erfasst und zur Nachsimulation der Gatternetzliste ausgegeben.
2.2
Verilog
Hardwarebeschreibungssprachen (HDLs) ersetzen in den 80er Jahren des 20. Jahrhunderts Schaltplaneditoren, weil die Designs die fortschreitenden Weiterentwicklungen der Herstellverfahren für Integrierte Schaltkreise dazu geführt haben, dass bereits damals sehr komplexe Systeme auf einem Stück Silizium integriert werden konnten. Der INTEL 486-Prozessor beispielsweise kam 1989 auf den Markt und bestand aus über 1 Mio. Transistoren. Schaltpläne konnten für diese Komplexitäten nicht mehr sinnvoll zur Designeingabe herangezogen werden und Simulationen auf Bauelementebene mit SPICE als dem Standardwerkzeug waren nur noch für sehr beschränkte Teilbereiche möglich (damals max. 100 Transistoren)! Verilog war die erste Sprache des ersten Logiksimulators, der die Verwendung von Hochsprachenkonstrukten und Gatterbeschreibungen zuließ. Vorher gab es viele Logiksimulatoren auf Gatterebene und verschiedene Simulatoren, die das abstrakte Verhalten von Schaltungen simulieren konnten, aber es waren stets Schnittstellen zwischen den Ebenen zu bedienen. Die nötigen Umformatierungen erschwerten den Ablauf erheblich. Gleichzeit mit Verilog kam der EDA-Hersteller Gateway mit dem schnellen XL-Algorithmus für die Logiksimulation auf Gatterebene auf den Markt. Das Produkt Verilog-XL stellte damals den schnellsten Logiksimulator überhaupt dar. Die Simulationszeiten auf den damals noch sehr langsamen Rechnern lagen sogar unter denen der damals gebräuchlichen Hardware-Beschleunigern. Verilog kann als Hardwarebeschreibungssprache in drei Bereiche gegliedert werden: 1. die eigentliche Beschreibungssprache, mit der Verhalten oder Struktur von Modellen eingegeben werden kann, 2. die Schnittstelle zu anderen Programmiersprachen (Programming Language Interface, PLI), über die Software-Tools beispielsweise mittels C-Code auf Modelle zugreifen oder den Simulator steuern können, 3. das Standard Delay Format (SDF) als genormtes Format zur Darstellung von Verzögerungszeiten in Modellen. Mit SDF-Dateien können Laufzeiten für Modelle, die sich erst aus Entwurfsschritten ergeben, die nach der Simulation erfolgen, wieder in das Ausgangsmodell eingebunden werden. So werden Post-Layout- oder Post-Place&RouteSimulation zur Verifikation von ASIC- oder CPLD-Designs unterstützt. Verilog ist eine sehr populäre HDL und hat sich als Quasi-Standard zur Hardwarebeschreibung entwickelt. Diese Sprache ist weniger formal als VHDL und kann deshalb leichter erlernt werden. Die Syntax ist zudem stark an die bekannte Sprache C angelehnt. Designer
14
2 Electronic-Design mit Verilog HDL
mit C-Erfahrung können sich deshalb schnell einarbeiten. Verilog-HDL wird von allen gebräuchlichen Synthesewerkzeugen unterstützt und fast alle Halbleiterhersteller bieten Verilog-Bibliotheken für ihre Standardzell- oder CPLD-Prozesse an. Folglich besteht für ein Verilog-Design die größtmögliche Auswahl an Implementierungstechnologien. In Verilog lassen sich alle Abstraktionsebenen des Hardwareentwurfs gleichzeitig verwenden. Schaltungen und Systeme können bei der Modellbildung aus Transistorschaltern, primitiven Gattern, RTL-Beschreibungen oder aus Verhaltensbeschreibungen zusammengesetzt werden. Die Sprache unterstützt die strukturelle Modellierung, was die Verifikation über so genannte Test-Bench-Modelle erleichtert. Die in Verilog definierten System-Tasks ermöglichen außerdem den unkomplizierten Datentransfer zwischen Modellen und Dateien auf der Festplatte.
2.3
Verilog im Designablauf
Verilog-Modelle werden durch Module repräsentiert. Ein Modul hat 4 Bestandteile: • • • •
den Modul-Namen, die Ports des Moduls, die Port- und die Datentyp-Deklarationen und die funktionale Beschreibung auf Verhaltens- bzw. Strukturebene.
Die Ports bilden die Schnittstelle nach außen, während sich der funktionale Teil im Modulinneren befindet. Ein komplexes Design kann aus vielen Modulen bestehen, die über Ports miteinander verbunden sind. Somit stellen Module einer niederen Ebene ihre Funktionen Modulen einer höheren Ebene über ihre Ports zur Verfügung, ohne dabei Funktionsdetails erkennen zu lassen. Die Modulsyntax liest dich wie folgt: module ();
...
... endmodule
2.3 Verilog im Designablauf
S
SET
Q
Clk
R
CLR
Q
15 module rsff (s, r, clk, clr, q, q_not) input s, r, clk, clr; output q, q_not; wire s, r, clk, clr, q, q_not; Funktionsbeschreibung mit Zeitverhalten endmodule
Abb. 2.5 Schaltplansymbol und Verilog-Modell: rsff ist der Modulname, danach folgt in Klammern die Portliste des Moduls. In Zeile 2 und 3 werden die Signalflussrichtungen der Ports definiert: input (Eingang) bzw. output (Ausgang), in Zeile 4 wird der Datentyp der Signale definiert: wire. Die Funktionsbeschreibung kann entweder mit einem Verhaltensmodell oder strukturell erfolgen.
2.3.1
Ports
Die Ports eines Moduls beschreiben zusammen mit den Portdeklarationen die Signale, die die Eingangsgrößen bzw. Ausgangsgrößen eines Modells darstellen. Hier besteht eine enge Analogie zu den Pins eines integrierten Schaltkreises oder den Anschlüssen einer Leiterplatte. Je nach Signalflussrichtung werden drei verschiedene Porttypen unterschieden: Eingänge (input), Ausgänge (output) und bidirektionale Ports (inout). Diese dienen zur Kommunikation mit anderen Modulen oder der Außenwelt, auch hier sind wieder Parallelen zu VHDL offensichtlich. Der Datentyp legt fest, welche Anschlüsse an die jeweiligen Ports zulässig sind. Der wire-Typ bildet z.B. elektrische Verbindungsleitungen nach, die Signale von anderen Modulen zuführen oder an diese weiterleiten.
2.3.2
Verhalten, Struktur und Zeitverzögerungen
Die Verhaltensbeschreibung im Verilog-Modul beschreibt mit den Anweisungen der Sprache, wie sich die zu entwerfende Schaltung verhalten soll. Diese Beschreibung kann auf zweierlei Weise erfolgen: funktional oder strukturell. Bei funktionalen Verilog-Modellen wird noch zwischen Datenfluss und algorithmischen Modellen unterschieden. Datenflussmodelle stellen die Funktion relativ schaltungsnah mit Hilfe von Registern und asynchronen logischen Funktionen dar. Algorithmische Modelle beschreiben die Funktionen eines Systems losgelöst von jedweden Hardwarebezogenheiten über algorithmische Transformationen der Eingangssignale in die Ausgangsgrößen. Das System wird als Black-Box modelliert, die zwischen die Eingangs- und Ausgangsports geschaltet ist. Ein funktionales Verilog-Modell beschreibt das Verhalten mit Hilfe von kontinuierlichen Zuweisungen oder prozeduralen Anweisungen. Bei der kontinuierlichen Zuweisung handelt es sich um Gleichungen, bei denen der Operand auf der linken Seite, in Abweichung von gewöhnlichen Computersprachen, erst dann das aktualisierte Ergebnis der rechten Seite über-
16
2 Electronic-Design mit Verilog HDL
nimmt, wenn dort mindesten ein Operand seinen Zustand geändert hat. Die Zuweisung erfolgt also synchron zu einem Ereignis (Event). Diese Form der Ereignissteuerung ist in VHDL mit dem Signalzuweisungsoperator implementiert. Prozedurale Anweisungen hingegen verhalten sich wie die Anweisungen in normalen Programmiersprachen. Die Anweisungen werden nicht ereignisgesteuert, sondern nach ihrer Reihenfolge ausgeführt. Die Anbindung an die für Hardware typische Zeitstruktur erfolgt über Sensitivitätslisten, in denen die Variablen aufgeführt sind, die die Prozedur nach einem Event anstoßen. Ein Strukturmodell besteht in Verilog aus verbundenen Komponenten, die für sich jeweils das Verhalten eines Teilsystems beschreiben. Bei den Komponenten kann es sich um umfangreiche Verilog-Module, wie beispielsweise einen Mikroprozessorkern, oder um VerilogPrimitive handeln, die nur ein einzelnes logisches Gatter nachbilden. Bestimmte primitive Elemente sind in Verilog vordefiniert. Das Zeitverhalten des Modells berücksichtigt, dass in realen Systemen zwischen einer Signaländerung an einem Eingang bis zur Änderung des Ausgangssignals eine Signallaufzeit vergeht. Signalverzögerungen können direkt in Verilog-Modulen definiert werden oder erst später im Designzyklus eingefügt werden. Die Beschreibung der Funktion und des Zeitverhaltens wird in Verilog-Modulen häufig vermischt. Nicht jedes Verilog-Modell hat ein explizit definiertes Zeitverhalten. Manche Modelle sind rein funktional und berücksichtigen die Signallaufzeiten nicht oder nur implizit.
2.3.3
Testbenches
Ein zentrales Mittel bei der Verifikation von komplexen elektronischen Entwürfen sind Testbenches (Prüfstände). Dabei handelt es sich um Verilog-Module, die in die das zu testende neue Modell (DUT: Design Under Test) eingebunden werden. Die Testbench erzeugt mit Signalgeneratoren geeignete Eingangssignalmuster, die alle Aspekte der Funktionalität des DUT während der Simulation aktivieren. Monitormodelle prüfen, ob die erzeugten Ausgangssignalfolgen den Vorgaben der Spezifikation genügen. Im Prinzip enthält eine vollständige Testbench alle Informationen, die in der Spezifikation in Textform aufgeführt sind, und stellt folglich eine simulierbare Variante der Spezifikation dar. Verilog unterstützt das Testbenchdesign durch viele verifikationsorientierte System-Tasks, mit denen das dynamische Verhalten des DUT verifiziert werden kann. Das Design muss auf jeder Abstraktionsebene mit der Testbench verifiziert werden, zuerst das Verhaltensmodell, dann das RTL-Modell, anschließend die Gatternetzliste und schließlich die rückübersetzte Verilog-Version des physikalischen Entwurfs. Erst wenn die korrekte Funktion einer Variante sichergestellt ist, kann mit der nächsten Verfeinerung der Designs begonnen werden, denn bekanntermaßen steigen die Kosten, die die Beseitigung eines Designfehlers verursacht, von Abstraktionsebene zur nächst niederen Abstraktionsebene um eine ganze Größenordnung!
2.3 Verilog im Designablauf
2.3.4
17
Compiler Directives und System-Tasks
Eine Compiler-Anweisung (Compiler Directive) steuert die Übersetzung eines VerilogModells. Solche Direktiven wirken sogar über File-Grenzen hinweg, bis sie durch andere Anweisungen überschrieben werden. Beispiel sind etwa eine `include-Anweisung, die den Compiler dazu veranlasst, den Inhalt eines bestimmten Files in den Code eines VerilogModells einzubetten, oder `timescale, eine Steueranweisung, die die Zeitskala für die Simulation eines Modells festlegt. Mit Verilog-System-Funktionen (System-Tasks) können Simulationsergebnisse dargestellt, externe Dateien beschrieben oder gelesen werden, die Zeitskala ausgegeben sowie Flanken, Periodendauern und andere dynamischen Aspekte eines Modells im Hintergrund während der Simulation überprüft werden. Diese direkt in Sprache integrierten Möglichkeiten werden in VHDL umständlich mit Hilfe von externen Modellen (Packages) implementiert. Deshalb lassen sich gerade Testbenches leichter in Verilog als in anderen HDLs modellieren.
2.3.5
SDF für Laufzeiten
Bei modernen Herstelltechnologien, deren Strukturen im tiefen Submikrometerbereich liegen (90 nm bei aktuellen CPLD-Bausteinen), spielen die Gatterverzögerungen, die bei Design und Simulation mit Verilog-Modellen leicht erfasst werden können, nicht mehr die allein entscheidende Rolle. Leitungslaufzeiten und Eingangskapazitäten, die von Gatterausgängen wie Leitungen geladen und entladen werden müssen, sind zu berücksichtigen. Diese Zusatzeffekte können erst am Ende des Designablaufs in das dynamische Verhalten des Systems eingebunden werden, weil erst dann die Schaltungstopologie auf Gatterebene sowie die geometrische Anordnung der Zellen festliegt. Zur Einbindung der Laufzeiten in bestehende Verilog-Modelle steht das genormte Standard Delay Format (SDF) zur Verfügung (IEEE Std. 1497-1999). SDF ist ein Bestandteil der Sprache Verilog, wird aber auch als Format bei der Nachsimulation von VHDL-Designs verwendet. Backannotation Die Laufzeitinformationen, die sich nach dem physikalischen Design ergeben und sich als SDF-Datei einbinden lassen, werden mit EDA-Tools aus dem Backend des Design Flows berechnet und berücksichtigen die Leitungslängen, die Verdrahtungsebenen und die für parasitäre Kapazitäten und Widerstände relevanten Technologieparameter. Diese Daten werden in die Verilog-Netzliste eingepflegt, die mit einem Logiksynthesewerkzeug aus Bibliothekszellen der Zieltechnologie erzeugt wurde. Dieser Prozess heißt Rückannotierung (Backannotation) und dabei werden die Laufzeitinformationen im Verilog-Design um die Leitungseffekte ergänzt. Da wir es mit komplexen Designs mit Tausenden von Verbindungsleitungen zu tun haben, muss dies automatisch erfolgen. Auch dies wird durch das genormte SDFFormat erleichtert. Die meisten Verilog-Simulatoren sind in der Lage, Delay-Files zu lesen und die einzelnen Verzögerungen den Netzen in der zugrunde liegenden Verilog-Netzliste zuzuordnen.
18
2 Electronic-Design mit Verilog HDL
Leitungsverzögerungen Leitungen in einem ASIC oder in einem CPLD tragen deshalb zur Gesamtsignallaufzeit bei, weil sie widerstandsbehaftet sind und Koppel- und Substratkapazitäten darstellen. Die resultierenden RC-Delays der Leitungen haben einen Anteil an der gesamten Laufzeit von 25%, wenn Technologien mit minimalen Strukturbreiten von 0,5µm zum Einsatz kommen, und dieser Anteil steigt auf über 80% bei moderneren Technologien mit Strukturen im 100Nanometer-Bereich. Wenn also moderne Technologien zum Einsatz kommen, hängen die Laufzeiten immer mehr von den Signalverzögerungen auf den Verbindungsleitungen ab, deren genaue Größe erst nach dem Platzieren und Verdrahten im Backend, also am Ende des Entwurfszyklus bekannt ist. Stellen sich nach der Post-Layout- oder Post-Place&RouteSimulation Laufzeitfehler ein, dann muss das Design nochmals überarbeitet werden, indem z.B. stärkere Treiber für die Leitungen vorgesehen werden, die im Layout dann besonders lang ausfallen. Die backannotierte Netzliste gibt das Verhalten des physikalischen Entwurfs so exakt wie möglich wieder und die Simulation dieser Netzliste stellt die abschließende und entscheidende Prüfung des Designs vor der Implementierung in Hardware dar. Fan-Out-Delays von Logikgattern Leitungslaufzeiten treten auch schon als Schätzgrößen bei der Synthese auf. Das Synthesetool erzeugt aus einer RTL-Beschreibung des Designs eine Verilog-Netzliste aus Bibliothekselementen der verwendeten Zieltechnologie (ASIC-Prozess oder CPLD-Familie). Je nach der erwarteten Chipgröße, die das Synthesewerkzeug aus der Zahl der verwendeten Gatter abschätzt, und den daraus folgenden kapazitiven Belastungen der einzelnen Netze werden zusätzliche Delay-Werte für die Verbindungen während der Synthese errechnet. Gleichzeitig hängen die Gatterdelays wesentlich von der zu treibenden Ausgangslast ab, die von den Eingangskapazitäten der Folgegatter gebildet wird. Dieser Fanout-Effekt kann ebenfalls erst nach der Umsetzung in eine technologiespezifische Gatternetzliste, also nach der Synthese erfasst werden. Post-Synthese-Simulation Fanout-Delays und abgeschätzte Leitungslängen werden bei der Optimierung der Gatternetzliste berücksichtigt. Ob das Syntheseergebnis die Spezifikationen erfüllt, wird mit der PostSynthesis-Simulation überprüft. Dazu wird die synthetisierte Verilog-Netzliste simuliert, wobei das entsprechende Delay File im SDF-Format mit einbezogen wird. Als Beispiel für die Auswirkungen von Signalverzögerungen nach der Synthese wird ein Design betrachtet, das die Zustandsmaschine aus Bild 2.5 beschreibt. Die Maschine kann vier Zustände S0 bis S3 annehmen, welcher Zustand realisiert wird, hängt von den Eingängen y und z ab.
2.4 Zusammenfassung
S0
y = 1; z = 0
19
S1
y = 1; z = 0
S2
y = 1; z = 0
S3
y = 1; z =1
Abb. 2.5 Zustandsdiagram eines Zustandsautomaten mit den Zuständen S0 bis S3 und den Eingängen y und z. Synchron zum nicht gezeigten Taktsignal clk wechselt der Zustand. Das ebenfalls nicht gezeigte rst-Signal setzt die Schaltung in den Zustand S3.
Die Simulation des Verhaltensmodells, in dem die vier Zustände als zweistellige Binärzahl mit den Ziffern out1 und out2 dargestellt sind, zeigt die Zustandswechsel gleichzeitig mit der steigenden Taktflanke. Nach der Synthese hingegen treten Signalverzögerungen zwischen Taktflanke und Zustandswechsel auf, die von der gewählten Zieltechnologie abhängen. Die Layouteffekte werden den zeitlichen Versatz noch weiter steigern.
Abb. 2.6 Simulation des Zustandsautomaten auf Verhaltens- und Gatterebene vor bzw. nach der Synthese. Im Verhaltensmodell folgen die Ausgänge unmittelbar dem rst-Signal bzw. der steigenden clk-Flanke. In der synthetisierten Netzliste hingegen treten erhebliche Signalverzögerungen auf, die fast die Taktperiode überschreiten!
2.4
Zusammenfassung
In diesem Kapitel haben wir uns mit dem generellen Ablauf eines Designs mit Hilfe der Hardwarebeschreibungssprache Verilog beschäftigt. Das klassische Vorgehen bei Designs vergangener Jahrzehnte bestand aus der Umsetzung der als Text vorliegenden Spezifikation, die manuell per Schaltplaneingabe in eine strukturelle Beschreibung umgesetzt wurde, deren Übereinstimmung mit den Vorgaben mittels Simulationen anhand von ausgedruckten Signalverläufen verifiziert wurde. Heutige Designs lassen sich aufgrund der gestiegenen Komplexität weder per Hand beschreiben, noch ohne Automatismen in Schaltpläne umsetzen, geschweige denn durch Augenschein verifizieren.
20
2 Electronic-Design mit Verilog HDL
Die nötige Designautomation wird nur mit HDLs wie Verilog oder VHDL möglich: Verhaltensmodelle werden in RTL-Beschreibungen umgesetzt, dann synthetisiert und die sich ergebenden Netzlisten aus Komponenten der Bibliotheken des verwendeten Zielprozesses können per Layoutsynthese in ein physikalisches Design umgeformt werden. Verilog war die erste Hardwarebeschreibungssprache, die sowohl die digitale Simulation von Gatterdesigns wie auch gleichzeitig die Funktionsbeschreibung und Simulation von Verhaltensmodellen auf höherer Abstraktionsebene ermöglichte. Verilog unterstützt die Designeingabe durch strukturelle oder funktionale Modellierung der Schaltungsfunktionen. Eingebaute primitive logische Komponenten erlauben die effiziente Simulation komplexer Strukturen. Mit System-Tasks kann der Verifikationsablauf systematisch strukturiert werden und fast vollständig ohne Eingriffe des Anwenders ablaufen, wenn Testbenches geschrieben werden, die sowohl das eingesetzte zu prüfende Design stimulieren, wie auch die Ausgabesignale des zu testenden Moduls analysieren. Das Einbinden von Signallaufzeiten nach der Logiksynthese oder der Layouterzeugung wird durch das eigene SDF-Format in Verilog besonders einfach. Verilog beschleunigt den Designprozess also in drei Dimensionen: Durch Simulation auf Verhaltensebene können verschiedene Architekturvarianten ausprobiert werden. Das Verilog-Modell dokumentiert das Design in simulierbarer Form, wobei aufgrund der Standardisierung der Austausch und die Wiederverwendung von Modellen zwischen verschiedenen Anwendern sicher gestellt sind. Synthesewerkzeuge, die Verilog-Code in boolesche Gatter und speichernde Elemente übersetzen, das Ergebnis anschließend optimieren und auf die Gatterbibliotheken einer ASIC- oder CPLD-Technologie abbilden können, verkürzen die zeitaufwendige Umsetzung von Spezifikationen in Schaltpläne auf einige Mausklicks.
2.5
Übungsaufgaben
2.5.1
Fragen
1. 2. 3. 4. 5.
Wodurch unterscheiden sich HDLs von anderen Software-Programmiersprachen? Worin liegen die Vorteile des HDL-basierten Entwurfs im Vergleich zur Schaltplaneingabe? Beschreiben Sie das Vorgehen beim Top-Down-Design und beim Bottom-UpDesign! Was verstehen Sie unter Abstraktionsniveaus in VLSI-Designs? Lesen Sie diesen Verilog-Code und beantworten Sie die folgenden Fragen! module adder(inA,inB,out); input inA,inB; output [0:1]out; assign out = inA+ inB; endmodule
2.6 Antworten • • •
2.5.2 1. 2. 3. 4. 5.
Wie heißt das Modul? Wie viele Ports sind vorgesehen? Welche Wortbreite hat der Ausgangsport?
Wahr oder Falsch Nebenläufige Anweisungen (concurrent statements) sind einer der wesentlichen Unterschiede zwischen HDLs und „normalen“ Programmiersprachen. (wahr/falsch) HDLs können am effektivsten auf niedrigen Abstraktionsstufen (also auf dem Gatter- oder Transistor-Niveau) eingesetzt werden. (wahr/falsch) HDLs benötigen keine Compiler wie andere Programmiersprachen. (wahr/falsch) Verilog-AMS oder VHDL-AMS können bei der Modellbildung von analogen oder gemischt analog-digitalen Schaltungen eingesetzt werden. (wahr/falsch) Die Syntax der Verilog-HDL ist der von „C“ sehr ähnlich. (wahr/falsch)
2.6
Antworten
2.6.1
Fragen
1.
2.
3.
21
HDLs unterscheiden sich von anderen Software-Programmiersprachen dadurch, dass sie kombinatorische Logik, flanken- oder pegelgesteuerte Speicherelemente und insbesondere das zeitlich nebenläufige Verhalten von elektronischer Hardware in einfacher Weise und unterstützt durch spezifische Sprachkonstrukte beschreiben können. Vorteile des HDL-basierten Entwurfs im Vergleich zur Schaltplaneingabe liegen darin, dass aufgrund der Normung HDL-Beschreibungen leicht portierbar sind und von anderen gelesen werden können ohne dass spezifische Werkzeuge benötigt werden. Die Schaltungseingabe mittel HDLs ist meist effizienter als der grafische Entwurf mit Schaltplaneditoren. HDLs unterstützen darüber hinaus verschiedene Abstraktionsebenen und Modellierungsstile, wie Verhaltensmodelle und strukturelle Beschreibungen. Top-down und Bottom-up sind Begriffe, die den zergliedernden bzw. den aufbauenden Entwurfsstil bezeichnen. Bei Top-down beginnt das Design auf der höchsten Abstraktionsebene. Das Gesamtsystem wird als Blackbox mit Ein- und Ausgängen beschrieben. Dann wird die Funktion dieser Blackbox Hierarchiestufe für Hierarchiestufe nach unten immer detaillierter ausgefüllt. Diese Vorgehensweise ist bei komplexen digitalen Designs üblich. Bei Bottom-up beginnt der Designzyklus auf niedrigem Abstraktionsniveau, z.B. auf Transistorebene. Aus den Transistoren werden Grundschaltungen, wie Gatter, Operationsverstärker, Flip-Flops, Strom- und Spannungsreferenzen, Komparatoren etc. aufgebaut. Diese Komponenten werden in der nächsten Stufe zu kleineren Funktionsblöcken zusammengefasst und so entsteht
22
2 Electronic-Design mit Verilog HDL
4.
5.
2.6.2 1. 2. 3. 4. 5.
Schritt für Schritt die Gesamtschaltung. Diese Methode spielt im Analog und Mixed-Signal-Design eine wichtige Rolle. In Gegensatz zum Top-down-Verfahren kann hier aber die Verifikation des Gesamtkonzeptes erst am Schluss des Designzyklus erfolgen. Verschiedene Konzepte können deshalb nur eingeschränkt miteinander vergleichen werden! Unter Abstraktionsniveaus in VLSI-Designs versteht man die verschiedenen Detaillierungsgrade einer Designbeschreibung. Wie in Frage 3 schon erwähnt, kann z.B. eine Schaltung auf Transistorniveau also strukturiert und so genau an der Hardwareimplementierung wie möglich dargestellt werden oder rein auf Verhaltensebene, also abstrakt und von der Hardwaresicht losgelöst, beschrieben sein. Zwischen der Struktur- und der Verhaltensicht existieren in der Praxis zahlreiche Mischformen, die unterschiedlich starken Abstraktionen entsprechen. Das oben angegebene Modul heißt „adder“, hat drei Ports (inA, inB, out), die Wortbreite des Ausgangsports beträgt 2 bit.
Wahr oder Falsch Nebenläufige Anweisungen (concurrent statements) sind einer der wesentlichen Unterschiede zwischen HDLs und „normalen“ Programmiersprachen. (wahr/falsch) HDLs können am effektivsten auf niedrigen Abstraktionsstufen (also auf dem Gatter- oder Transistor-Niveau) eingesetzt werden. (wahr/falsch) HDLs benötigen keine Compiler wie andere Programmiersprachen. (wahr/falsch) Verilog-AMS oder VHDL-AMS können bei der Modellbildung von analogen oder gemischt analog-digitalen Schaltungen eingesetzt werden. (wahr/falsch) Die Syntax der Verilog-HDL ist der von „C“ sehr ähnlich. (wahr/falsch)
3
Die Sprache Verilog
Ein Verilog-Modell besteht aus eine Liste von Anweisungen, die die Schnittstellen des Modells zur Außenwelt definieren und alle Beziehungen der einzelnen Signale innerhalb des Modells festlegen. Ein Verilog-Modell beginnt mit dem Schlüsselwort module und endet mit dem Schlüsselwort endmodule. Verilog-Modelle werden deswegen im Weiteren häufig als Modul bezeichnet. Jede Anweisung wird im Text des Moduls mit einem Semikolon „;“ abgeschlossen. In Verilog können im Gegensatz zu VHDL auch direkt Anweisungen für die Steuerung der Kompilation und der Simulation als System Tasks und Compiler Directives in die Modul-Datei eingebettet werden. In diesem Kapitel werden die sprachlichen Grundlagen für die Entwicklung von Modellen auf Basis von Verilog behandelt. Dazu gehören Sprachregeln, lexikalische Konventionen, die Definitionen von Datentypen und Operatoren, sowie der anderen grundlegenden Konstrukte. In Verilog sind bestimmte Schlüsselwörter vorgegeben. Die zugehörigen Bezeichner dürfen für keine weiteren Zwecke benutzt werden. Im Text und in allen Programmbeispielen sind die Schlüsselwörter fett gedruckt. Im Anhang A findet sich eine Liste aller Schlüsselworte.
3.1
Syntax und Semantik
Die lexikalischen Konventionen der Sprache Verilog erinnern stark an die der Programmiersprache C. Verilog unterscheidet im Gegensatz zu VHDL Groß- und Kleinschreibung (case sensitive). Alle Verilog-Schlüsselwörter werden klein geschrieben. Schlüsselwörter (z.B. module) haben eine vordefinierte Bedeutung. Die wichtigsten Vereinbarungen und Regeln werden im Folgenden beschrieben. Schreibweisen für grammatische Regeln Die Gebrauchsanweisung für eine Sprache wie Verilog wird in Form von grammatischen Regeln präsentiert. Diese Regeln haben einen Namen (auf der linken Seite von ::=) und werden als Funktion anderer Regeln oder mit Marken (Endzeichen) ausgedrückt. Folgende Konventionen werden hier verwendet: modul
Schlüsselwörter fett
::=
Zuweisung einer Regel zu ihrem Namen
[xx]
Der Teil xx ist optional
24
3 Die Sprache Verilog
{yy}
Der Teil yy wird N-mal wiederholt, wobei N auch Null sein kann
x ⏐y
wähle x oder y
3.1.1
Kommentare
Kommentare verbessern die Lesbarkeit eines Modells. In Verilog können einzelne Zeilen und ganze Blöcke als Kommentare verwendet werden. Eine Kommentarzeile beginnt mit einem Doppel-Schrägstrich „//“. Die gesamte so gekennzeichnete Zeile wird dann als Erläuterung aufgefasst und beim Kompilieren übersprungen. Kommentare über mehrere Zeilen (Blöcke) starten mit einem Schrägstrich gefolgt von einem Stern „/*“ und werden mit den gleichen Symbolen in umgekehrter Reihenfolge „*/“ beendet. Im unten stehenden Fenster werden die Möglichkeiten aufgezeigt. Zusätzlich können auch bestimmte Bereiche einer Zeile für Kommentierungen genutzt werden (siehe letztes Beispiel). A = B + C ;// zeilenweiser Kommentar /* Kommentar über zwei Programmzeilen */ module /*Kommentar mitten in einer Zeile */ sum(a,b); Damit der Modellcode übersichtlich bleibt, sind zeilenweise Kommentare sinnvoller als Kommentarblöcke. Block-Kommentare werden häufig Modellen vorangestellt, um das Modell textlich kurz zu beschrieben, den Autor zu benennen etc.
3.1.2
Leerzeichen (white spaces)
Leerzeichen, Tabulator-Einschübe, Zeileneinzug, Returnsymbole für eine neue Zeile und das Ende einer Datei (File, End of File, EOF) sind spezielle ASCII-Zeichen, die auf dem Bildschirm nicht angezeigt werden und die von Verilog beim Kompilieren ausgelassen werden. Verilog ist eine formatfreie Sprache. Mit Leerzeichen können wir frei den Modelltext formatieren, um eine bessere Lesbarkeit zu erreichen. Wichtig ist aber, dass Leerzeichen weder im Bezeichnern also in Namen von Objekten (Identifier) noch in Zahlen oder Schlüsselwörtern auftreten dürfen.
3.1.3
Bezeichner (Identifier)
Jedes Objekt (Modul, Signal, Variable, ...) wird in Verilog über einen Bezeichner angesprochen. Verilog-Bezeichner sind eine Folge von groß- oder kleingeschriebenen Buchstaben (a – z, A – Z), den Ziffern von 0 bis 9 und den Sonderzeichen „_“ und „$“, ohne eingeschobene Leerzeichen. Jeder Bezeichner muss mit einem Buchstaben oder dem Unterstrich „_“ anfangen. Die Maximallänge eines Namens beträgt 1024 Zeichen. Ein Name endet beim ersten
3.1 Syntax und Semantik
25
Leerzeichen. Selbstverständlich können Schlüsselwörter, wie module, nicht als Namen vergeben werden. Es ist wichtig, sich daran zu erinnern, dass die Sprache zwischen Groß- und Kleinschreibung (case sensitivity) unterscheidet. „abc“ und „aBc“ sind also zwei verschiedene Bezeichner. Verilog interpretiert die beiden Zeichenfolgen als unterschiedliche Namen! Das $-Zeichen spielt eine Sonderrolle. Namen, die mit einem Dollar-Zeichen beginnen, kennzeichnen eine Systemfunktion, mit der beispielsweise die Simulation beendet werden kann ($finish), oder Ergebnisse über das Display ausgegeben werden können ($display). Erweiterte Namen, so genannte escaped identifiers, können aus beliebigen ASCII-Zeichenfolgen bestehen und die Regel für diese Bezeichner lautet, dass der Name mit einem Backslash „\“ beginnen muss. Die gleiche Konvention wird auch innerhalb der Sprache VHDL verwendet, um beispielsweise in dieser nicht case-sensitiven Sprache Großschreibung bei Bezeichnern herauszustellen. Die erweiterten Namen ermöglichen die Synchronisation unterschiedlicher Namenskonventionen. Dies ist nötig, weil im Design-Ablauf verschiedene CAE-Werkzeuge zum Einsatz kommen, wie z.B. Synthese-Tools oder Schaltplaneditoren, die sich in der Namensgebung nicht notwendigerweise nach den Regeln des generischen Verilogs richten. Im folgenden Kasten sind Beispiele für typische Verilog-Identifier aufgeführt. Korrekt: Verilog Namen: Q, abc, Q_, ls74, Input, input, c_out Erweiterte Verilog Bezeichner: \74ls, \Q~, \reset*, \1,2,3 Fehlerhaft: $true // Bezeichner dürfen nicht mit einem $-Symbol anfangen reg // Bezeichner dürfen nicht mit Verilog-Schlüsselwörtern übereinstimmen
3.1.4
Logische Zustände und Signalstärken
Wird eine digitale Simulation durchgeführt, dann werden die Zustände der einzelnen Knoten der Schaltung nicht mehr mit Strömen und Spannungen wie in der Schaltkreissimulation beschrieben, sondern es werden zunächst nur die beiden logischen Zuständen „wahr“ und „falsch“ bzw. die beiden Ziffern „0“ und „1“ berücksichtigt, die im Datentyp Bit (0,1) zusammengefasst werden. Häufig ist diese Abstraktion realer Signale in elektronischen Systemen zu stark. Logische Nullen und Einsen sind nicht geeignet, um zum Beispiel einen Kurzschluss oder einen Ausgang mit hoher Impedanz darzustellen. Um solche relevanten Phänomene beschreiben zu können, wird in Verilog eine vierwertige Logik (0, 1, x, z) verwendet. x bezeichnet dabei einen unbekannten Zustand, der entweder „0“ oder „1“ sein kann, und „z“ den hochohmigen Zustand, der von einer abgeschalteten Leitung angenommen wird (engl. Tri-State). Statt des Buchstabens z ist es alternativ auch möglich, das Fragezeichen „?“ zu verwenden. Den logischen Zuständen 0 und 1 sowie dem x-Zustand sind in Verilog jeweils 8 Signalstärken zugeordnet. Signalstärken regeln, wie Signalkonflikte zu lösen sind. Diese Konflikte
26
3 Die Sprache Verilog
entstehen, wenn ein Signal aus mehreren Quellen gespeist wird und diese Quellen unterschiedliche Pegel ausgeben. In realen elektronischen Schaltungen ist dies sehr häufig der Fall. Außer Gattern, die unterschiedliche logische Signale auf eine Leitung senden, gibt es dort z.B. Busleitungen, die von Tristate-Ausgängen oder offenen Kollektor-Anschlüssen getrieben werden. Verilog benutzt ein definiertes Verfahren zur Auflösung von solchen widersprüchlichen Zuweisungen. Die verschiedenen Signalstärken sind in folgender Tabelle aufgeführt. Tab. 3.1 Treiberstärken in Verilog
Stärke
Typ
Stärkegrad
supply
treibend, wie eine direkte Verbindung zur Versorgung (= 1) bzw. Masse (=0)
am stärksten
strong
treibend, wie ein aktives Gatter
pull
treibend, wie ein Widerstand gegen Versorgung oder Masse (pull-up, pull-down)
large, medium und small
speichernd, wie eine „große“, „mittlere“ bzw. „kleinere“ Kapazität, relevant für tristate-fähige Signalleitungen, die umgeladen werden müssen
weak
treibend, schwach wie ein hochohmiger Widerstand gegen Versorgung oder Masse (pull-up, pull-down)
highz
Hohe Impedanz, abgeschaltet
Am schwächsten
Es gibt insgesamt 25 Kombinationen aus Zustand und Signalstärke in Verilog: alle acht Stärken für 0, 1 und x, aber nur die highz-Stärke für den z-Zustand.
3.1.5
Operatoren
Operatoren verknüpfen Objekte oder wirken auf Objekte (Operanden) mit dem Ziel, einzelne oder mehrere Größen zu verändern oder aus Größen neue Größen zu gewinnen. Zur Klassifizierung werden Operatoren danach eingeteilt, ob sie auf einen Operanden, zwei Operanden
3.1 Syntax und Semantik
27
oder sogar drei Operanden wirken. Ein Operator, der auf eine Größe wirkt (unary operator), ist beispielsweise der logische Inversionsoperator „!“. Wie bei jeder Programmiersprache sind auch für Verilog zahlreiche binäre Operatoren (binary operator) definiert, die zwei Operanden verknüpfen. Ein Beispiel ist der Additionsoperator „+“, der zwei Größen addiert: a + b. Verilog setzt auch „ternäre“ Operatoren (ternary operator) ein, die drei Größen zueinander in Beziehung setzen. a = ^in;
// ^ ist ein unary operator, „in” ist der Operand
out = a + b;
// + ist ein binärer Operator, a und b sind Operanden
out = in ? a : b; // ?: leitet einen Ausdruck mit einem ternären Operator ein, //in, a, b sind die Operanden
3.1.6
Zahlen
Zahlen werden im Binärformat im Speicher des Rechners abgelegt, auf dem eine VerilogSimulation durchgeführt wird. Jede ganze Zahl besteht in der Algebra aus Ziffern, die mit der von der Position abhängigen Potenz der Zahlenbasis zu multiplizieren sind. Je nach Basis spricht man von Binär-, Dezimal- oder anderen Zahlen. Verilog verwendet bei den ganzen Zahlen (Integers) vier verschiedene Zahlensysteme. Spezielle Bezeichner geben die Basis des jeweiligen Zahlensystems vor, legen also fest, wie eine Zahl zu interpretieren ist: dezimal (d oder D, Basis 10), hexadezimal (h oder H, Basis 16), oktal (o oder O, Basis 8) und binär (b oder B, Basis 2). Wird keine Basis vorgegeben, liegt die Voreinstellung auf dem Dezimalsystem. In Verilog kann nicht nur die Basis des Zahlensystems, sondern auch die Wortbreite der binären Darstellung der Zahl auf dem verwendeten Rechner vorgegeben werden (sized numbers). So wird z.B. die Zahl 8’hFF als 8-Bit-Wort 1111_1111 abgelegt. Der Unterstrich „_“ kann dabei beliebig zwischen die Ziffern gesetzt werden, um die Zahlendarstellung klarer zu strukturieren. Der Wert der Zahl wird dadurch nicht verändert. Ist keine Breite des Speicherworts vorgegeben, dann wird die Zahl auf dem Rechner als 32-Bit-Göße abgelegt (unsized numbers). Das allgemeine Format für eine ganze Zahl in Verilog sieht also folgendermaßen aus: ’>. Bei der Zahl 16’H11FF handelt es sich also um die Hexadezimalzahl 0001_0001_1111_1111, die als 16-Bit-Wort gespeichert wird. Wenn Zahlen ohne Größen- und Zahlensystemangabe definiert werden, interpretiert sie der VerilogKompiler stets als Dezimalzahlen. In dieser aus Informatiksicht ungewöhnlichen Aufteilung in sized- und unsized-numbers zeigt sich, dass Verilog eine hardware-orientierte Sprache ist. In elektronischen digitalen Schaltungen, die Algorithmen mit ganzen Zahlen verarbeiten sollen, ist die Wortbreite, in der die Zahlen zu speichern bzw. darzustellen sind, ein zentraler Parameter. Dies zeigen schon die Bezeichnungen 8-Bit-Mikrokontroller, 16-Bit-Multiplizierer usw. Wenn ein VerilogModell für die Logik-Synthese geschrieben wird, ist klar, dass nur sized-numbers Verwendung finden sollten, damit später nicht alle Zahlenoperationen mit der voreingestellten Wortbreite von 32 Stellen implementiert werden, auch wenn das vom möglichen Wertebereich
28
3 Die Sprache Verilog
nicht nötig ist. Geht es nur um eine Verhaltensdarstellung eines Systems, dann bedarf es natürlich keiner Festlegung der Wortbreiten, es sei denn, es sollen Rundungs- oder Abschneideeffekte bei numerischen Verfahren untersucht werden. Benötig ein Zahlenwert bei einer sized-number nicht alle Stellen zur Darstellung dann werden die überzähligen Stellen aufgefüllt (Stellenerweiterung). Wie erweitert wird, hängt vom Wert der am weitesten links stehenden Ziffer der Zahl (MSB, Most Significant Bit) ab: • Ist diese Ziffer eine „0“ oder eine „1“, dann wird mit Nullen aufgefüllt. • Ist der Wert der am weitesten links stehenden Stelle ein „x“ oder ein „z“, dann wird die notwendige Zahl an x- bzw. z-Symbolen eingefügt. • Ist der Zahlenwert größer als die angegebene Stellenzahl, werden die nicht ins Format passenden Ziffern mit den kleinsten Gewichten abgeschnitten. In der folgenden Liste finden sich einige Beispiele für ganze Zahlen: 8’hFF // 8 Bit breite Hexadezimalzahl 4’b1110 // 4 Bit breite Binärzahl 8’x10 // Binärzahl mit 8 Stellen, die ersten Stellen sind unbestimmt „x“: xxxxxx10 3’b8 // Abschneidoperation: 1000 ¢ 100 ’o12 // Oktalzahl mit 32 Bit-Darstellung ’d45 // Dezimalzahl mit 32 Bit-Darstellung Negative Zahlen beginnen mit dem Vorzeichen „-“ (z.B. –8’d6) werden in der Zweierkomplementdarstellung binär abgespeichert (für das Beispiel: 1111_1010). Reelle Zahlen kennzeichnet der Dezimalpunkt. Es gibt zwei Darstellungsmöglichkeiten: . oder E. Auch das kleine e ist als wissenschaftliche Notation erlaubt. In reellen Zahlen dürfen x und z nicht auftreten. Eine reelle Zahl ist nur dann zulässig, wenn beiderseits des Dezimalpunkts ein Wert steht. Die Mantisse bei der Exponentialdarstellung ist reell, der Exponent stets eine ganze Zahl. Beispiele: 1.2 0.6
// entsprechen 1,2 bzw. 0,6
3.2E6 3.2e-6
// entsprechen 3.200.000,0 bzw. 0,0000032
3.1.7
Zeichenketten (strings)
Ein String ist eine Folge aus Zeichen (characters), die von Anführungsstrichen eingeschlossen ist. Eine solche Kette darf sich nur über eine Zeile erstrecken. Sobald ein Zeilenwechsel eingegeben wird (Return), wird die Zeichenkette unterbrochen.
3.1 Syntax und Semantik
29
“Verilog – easy to learn” // eine Zeichenkette “Verilog IEEE-1394”
3.1.8
// auch eine Zeichenkette
Datentypen
In Hardwarebeschreibungssprachen treten zu den Variablen, die wir aus den üblichen Programmiersprachen kennen, noch die Signale hinzu. Damit können Verzögerungseffekte in elektronischen Komponenten beschrieben werden und es wird möglich, die in Hardwarekomponenten übliche zeitlich parallele Ausführung von Aktionen zu erfassen. Bei Signalen handelt es sich um Größen, die nicht nur einen (Zahlen-)wert repräsentieren, sondern auch mit einer Zeitbasis verknüpft sind. Signale transportieren Information zwischen Funktionsblöcken, wie z. B. logischen Gattern. Variablen halten den Wert, den sie einmal zugewiesen bekommen haben, bis zur nächsten Zuweisung. Signale müssen hingegen dauerhaft durch ein logisches Gatter oder einen anderen Treiber auf einem Zustand gehalten werden, ansonsten geht diese Information verloren und das Signal nimmt wieder den hochohmigen Zustand z an. Signale und Variablen sind per Voreinstellung skalare Größen (Breite: 1 bit). Sollen vektor-wertige Größen verwendet werden, dann wird an die Signalnamen der Indexbereich in eckigen Klammern angehängt: in_put[7:0] ist z.B. eine Vektor-Größe mit 8 bit Breite. Über den Indexwert können einzelne Komponenten des Vektor-Signals angesprochen werden. in_put[7] ist bspw. das Signal, das die höchstwertige Stelle (most significant bit) darstellt. in_put[3:0] spricht die niederwertigsten drei Stellen des Vektors an. Variablen werden hingegen stets als Ganzes angesprochen. Wenn out_put eine 8 bit breite Variable ist, dann kann man out_put nicht stellenweise sondern nur als Vektor adressieren. In Verilog werden zwei Gruppen von Datentypen unterschieden die net- und die regDatentypen, die sich im Wesentlichen dadurch unterscheiden, wie den zugehörigen Objekten Werte zugewiesen werden und wie diese Werte gehalten werden: • Die Klasse der net-Datentypen (Netze) repräsentiert die „elektrische“ Verbindungsstruktur zwischen den Komponenten einer Schaltung. Netze halten, wie Leitungen in realen Schaltkreisen, ihren Wert nur dann, wenn dieser von einem Treiber dauerhaft eingeprägt wird. • Die Klasse der Register-Datentypen (reg), in die die Variablen eines Modells fallen, die in prozeduralen Blöcken von Verhaltensmodellen Daten speichern. Variablen kann man als Verallgemeinerung von speichernden Elementen ansehen. Register-Typen halten also zugewiesene Werte, bis diese durch Zuweisung wieder geändert werden. Dieser Datentyp wird bei der Logiksynthese nicht direkt durch eine Registerschaltung ersetzt. Dafür ist eine explizite Modellierung des Registerverhaltens nötig. Für die Simulation müssen die Datentypen aller Größen festliegen, die im Modul verwendet werden. Nur so ist klar, wie die jeweiligen Größen verarbeitet und gespeichert werden sollen. Der jeweilige Datentyp kann explizit in dem Modul vorgegeben werden, in dem die betreffende Größe verwendet wird. Wird keine explizite Typzuweisung definiert, dann ist net voreingestellt. Alle Größen, die in einem Strukturmodell Komponenten (Gatter oder instanziierte Module) über Ports verknüpfen, erhalten einen net-Typ zugewiesen, denn diese Ver-
30
3 Die Sprache Verilog
bindungen entsprechen elektrischen Leitungen. Für Variablen in einem Verhaltensmodell hingegen ist keine Voreinstellung vereinbart. Hier sind explizite Deklarationen erforderlich. Netze und Register können als skalare Größen oder als Vektoren deklariert werden. net-Typen In Verilog existieren verschiedene vordefinierte Netz-Typen. Jedem Netz-Typ ist eine eigene Auflösungsfunktion zugeordnet, die das Verhalten von verschiedenen Logikfamilien als Hardwareimplementierungen nachbildet. Eine Auflösungsfunktion legt das Verhalten des Netzes fest, wenn kein Treiber für das Netz existiert oder wenn verschiedene Treiber unterschiedliche Signalwerte zuführen. Tab. 3.2 Vordefinierte Netz-Daten-Typen
Netz Daten-Typ
Nachgebildete Funktionalität
wire
tri
wire: Verbindungsleitung, keine spezielle Auflösungsfunktion tri: wie wire, aber dieser Typ hat stets Tristatefähigkeit, kann also von Treibern hochohmig getrennt werden
wor
trior
wor: Ausgänge verodert (über ODER-Gatter verschaltet) – entspricht ECL-Logik, trior wie wor, aber tristatefähig.
wand
triand
wand: Ausgänge verundet (über UND-Gatter verschaltet) – entspricht Open-Collector-Logik, triand wie wand, aber tristatefähig.
tri0
tri1
Tristate-Netz wird im z-Zustand über einen Widerstand nach Masse bzw. Versorgungspotential verschaltet (Pull-down oder Pull-up)
supply0
supply1
Netz liegt konstant auf Masse- bzw. Versorgungspotential als stärkster logischer „0“ oder „1“
trireg
Speichert den letzten Wert im Tristatefall, wenn das Netz nicht mehr angesteuert wird – bildet eine physikalische Leitungskapazität nach
Der wire-Datentyp, wird als einfachster Verbindungstyp am häufigsten in der Praxis verwendet. Register-Typen Register sind speichernde Elemente in einer Schaltung und halten den zuletzt zugewiesenen Wert bis zur nächsten Zuweisung. Variablen mit Typen aus der Registerklasse werden in der Modellierung auf Verhaltensebene verwendet (siehe Kapitel 6). In Verilog sind fünf Registertypen vordefiniert: reg, integer, time, real und event. Der am meisten verwendete Typ ist reg.
3.1 Syntax und Semantik
31
Die Register-Datentypen können wie auch die Netze als skalare oder vektorielle Größen deklariert werden. Register-Datentypen werden nicht im Zuge der Logiksynthese des Designs in Hardeware-Register umgesetzt. Vielmehr wird mit diesen Datentypen die Datenspeicherung in den Kapazitäten oder Speicherelementen von elektronischen Schaltungen nachgebildet. reg-Typen sind aber nicht nur auf speichernde Elemente beschränkt, sondern können auch bei der Modellierung kombinatorischer Logik verwendet werden. Im Gegensatz zu net-Größen werden aber alle angenommenen Werte auch bei abgeschalteten Treibern gehalten. Logische Größen können also nicht nur mit einem net-Typ, sondern auch mit regoder integer-Typen deklariert werden. Neben der Nachbildung von Hardwareeigenschaften können Variablen auch für weitere Zwecke in Verilog-Modellen benutzt werden. Dazu gibt es in Verilog neben dem Typ reg die Typen integer, time, real, realtime und event, die in der Tabelle 3.3 kurz charakterisiert werden. Tab. 3.3 Vordefinierte Reg-Datentypen
Daten-Typ
Funktionalität
reg
Vorzeichenlose Größe mit beliebiger Wortbreite, die Voreinstellung ist eine Breite von einem Bit und ein Initialwert x bei einer Simulation.
integer
Vorzeichenbehaftete ganze Zahl für numerische Berechnungen mit 32Bit-Darstellung. Eine negative Integer-Größe wird im 2er-Komplement abgespeichert. In Modellen stellen integer Größen abstrakte Objekte dar, die keine direkte Beziehung zu elektronischen Schaltungen haben. Ein Beispiel sind Schleifenindizes in Verhaltensmodellen.
time
Eine Variable dieses Typs wird als 64-Bit-Größe gespeichert und repräsentiert die physikalische Größe Zeit, z.B. die Simulationszeit oder eine Verzögerungszeit eines Gatters. Variablen dieses Typs sind vorzeichenlose ganze Zahlen größer oder gleich Null.
real
Diese Variablen werden doppelt genau mit 64 bit abgelegt, können in wissenschaftlicher und dezimaler Notation angegeben werden und haben den Default-Wert 0,0.
realtime
Diese Variablen werden wie real-Größen doppelt genau mit 64 bit abgelegt, können in wissenschaftlicher und dezimaler Notation angegeben werden und haben den Default-Wert 0,0. Mit diesem Typ können Zeitwerte als reelle Zahl abgespeichert werden.
event
Hier handelt es sich um einen abstrakten Datentyp, der zur Kennzeichnung von Ereignissen (engl. events), d.h. Zustandswechsel von logischen Signalen verwendet wird.
32
3.1.9
3 Die Sprache Verilog
Deklarationen von Datentypen
Der Datentyp von Größen in einem Modul wird über folgende Angabe festgelegt: . Bei Vektoren ist nach dem Datentyp in eckigen Klammern der Indexbereich anzugeben: < Datentyp> [MSB:LSB] . MSB und LSB sind ganze Zahlen und bezeichnen die Position des höchstwertigen bzw. des niederwertigsten Bits. Der Bereich zwischen MSB und LSB legt die Zahl der Komponenten des Vektors fest. Wie bei den Signalen können auch hier einzelne Stellen (Bits) oder bestimmte Abschnitte eines Vektors angesprochen werden. Mehrdimensionale Felder Der Verilog-Standard von 1995 lies nur eindimensionale Arrays zu. Verilog 2001 hingegen erlaubt mehrdimensionale Felder von Netz- und Registertypen. Die Indexdefinitionen werden nach dem Array-Namen eingegeben. Auch in mehrdimensionalen Feldern können einzelne Komponenten oder Teilbereiche (nicht für real- oder realtime-Objekte) direkt angesprochen werden, indem für das Feld ein Index für jede Dimension und eine Komponentenoder Bereichsspezifikation vorgegeben wird. Statt fester Vorgaben können auch Bits oder Teilbereiche eines vorgegebenen Feldes in veränderlicher Form adressiert werden, Statt einer konstanten Indexvorgabe dürfen Ausdrücke verwendet werden. Hierzu führt Verilog 2001 die Operatoren „+:“ und „-:“ ein und gibt die Syntax [-:] bzw. [+:] vor. Start_Bit gibt die am weitesten links oder rechts stehende Stelle an, von der ab der zu selektierende Bereich beginnt, und Breite die Anzahl der auszuwählenden Komponenten. Beispiele: wire a, b, c; // skalare (1 Bit) wire-Größen reg sum, co; // skalare Register-Variable wire [31:0] busA // 32-Bit-Bus reg [31:24] high_byte // 8-Bit-Register-Größe integer J, K, //ganze Zahlen in 32-Bit-2er-Komplement-Darstellung real y, z; // Reelle Zahlen integer integer_feld [1:64]; // lineares Feld aus 64 ganzen Zahlen reg [15:0] daten [0:127] [0:127][ [0:127]; // 3dimensionales Feld von 16-Bit-Worten wire Index [7:0][63:0]; // zweidimensionales Feld aus ganzen Zahlen wire [15:0] daten_w [2] [1][ [0]; // daten_w ist ein bestimmtes 16-Bit-Wort aus dem Feld „daten“ wire [7:0] daten_byte [31][15] [7]; // daten_byte ist ein bestimmtes Byte aus dem Feld „daten“ wire daten_bit [31][15] [7]; // daten_bit ist ein bestimmtes einzelnes Bit aus dem Feld „daten“ wire busA [K+:3]; // 3-Bit-Vektor mit den Komponenten busA [K+2], busA [K+1], busA [K]
3.1 Syntax und Semantik
33
Implizite Deklarationen Ist keine explizite Deklaration vorhanden, dann werden für nicht deklarierte Bezeichner implizite Typvereinbarungen getroffen. Tritt der Bezeichner in einer Port-Deklaration auf, dann wird diesem der Typ wire zugewiesen. Findet sich der unbekannte Bezeichner in der Anschlussliste eines Moduls oder einer primitiven Komponente, die in einem strukturellen Modell eingesetzt werden soll, dann wird ein skalares Netz vom voreingestellten Netztyp (default net type) angenommen. Die Voreinstellung kann mit einer Kompileranweisung (`default_nettype) für alle Module, die in einer Datei aufgeführt sind, übergreifend vorgenommen werden (siehe Abschnitt 3.3.2). Der voreingestellten Netztyp wird auch implizit vereinbart, wenn eine Größe auf der linken Seite einer Zuweisung auftritt und diese Größe vorher nicht deklariert wurde.
3.1.10
Konstanten
Konstanten ändern sich ihrer Natur gemäß während der Simulation eines Modells nicht, sind also keine Variablen. In Verilog werden konstante Größen als Parameter bezeichnet, die einem festen Wert einen eindeutigen Namen zuordnen. Als Konstanten können neben numerischen oder physikalischen Größen (integer, real bzw. time) auch Zeichenketten (string) als symbolische Namen für bestimmte Zustände von Variablen im Modell vereinbart werden. Dies vereinfacht Abänderungen des Modells und verbessert die Lesbarkeit. In Verilog können zwei Arten von Konstanten benutzt werden: • parameter: Dabei handelt es sich um Konstanten, die für ein Modell vereinbart werden. Bei jeder Instanziierung dieses Moduls in einem strukturellen Verilog-Modell können die Konstanten neu vereinbart werden (entsprechend einer generischen Konstanten GENERIC in VHDL), und • specparam: diese Parameter werden in dem Bereich eines Moduls vorgegeben, in dem Deklarationen vorgenommen werden können (specify block). Diese Konstanten legen das dynamische Verhalten der jeweiligen Module fest (Timing). Diese wesentlichen Eigenschaften werden bei jeder Instanziierung eines Moduls übernommen. Definiert man zum Beispiel eine feste Busweite mit parameter buswidth = 10, dann kann überall im Modell buswidth eingesetzt werden. Soll das Modul in einem Strukturmodell eingesetzt werden und ist es nötig, Busse mit einer anderen Weite zu verwenden, dann kann dieser Parameter mit der defparam-Anweisung lokal für die betrachtete Instanz modifiziert werden. Es ist daher nicht nötig, aufwendig die Weite aller Busse als Zahlenwert an allen Stellen im Modul zu korrigieren!
34
3 Die Sprache Verilog
Beispiele für Parameter: parameter id_name = 12; parameter width = 234; parameter [8*13:0] str = “Hi Verilog”; Beispiel für die Parameterzuweisung specparam: module \74ls74 (q, qb, ck, d, rst, pst); // Moduldeklaration mit Ports in Klammern ......
// Anweisungen
specify
// Specify Block: Anfang
specparam t_setup = 7.4; // Set-up-Zeit wird auf 7.4 Zeiteinheiten gesetzt .......
// Anweisungen
end specify; // Specify Block: Ende
3.1.11
Verilog-Primitive
Die Sprache verfügt über 26 vordefinierte funktionale Modelle (Tabelle 3.4) für die gebräuchlichsten digitalen Gatter (gates), Treiber (buffer) und Schaltermodelle (switches) für Transistoren als sog. primitive Elemente (primitives). Mit diesen vordefinierten Modellen lassen sich auf einfachste Weise kleinere logische Schaltungen in Form einer Netzliste nachbilden. Verilog unterstützt so die strukturelle Modellbildung auf hardwarenaher Ebene. Digitale Schaltungen werden deshalb häufig von EDA-Werkzeugen als Verilog-Netzlisten ausgegeben, die aus diesen Primitiven bestehen. Tab. 3.4
Verilog-Primitive
Logische Gatter (Gates) and nand Treiber (Buffer) buf not pulldown Schaltermodelle (Transistor-switches) nmos rnmos tran rtran
or nor
xor xnor
bufif0 notif0 pullup
bufif1 notif1
pmos rpmos tranif0 rtranif0
cmos rcmos tranif1 rtrabif1
3.1 Syntax und Semantik
35
Die Primitiven and, or, xor, nand, nor und xnor repräsentieren logische Gatter, wobei hier zwei oder mehr Eingänge zugelassen sind, aber nur ein Ausgang. Bei den Treibern (buf bis notif1) ist es umgekehrt, hier ist die Zahl der Eingänge fest (ein Eingang) und die Zahl der Ausgänge als die getriebenen Leitungen variabel. pulldown und pullup sind Elemente, die eine einzelne Leitung auf Masse bzw. Versorgungsspannung ziehen. Diese Komponenten haben dementsprechend keinen Eingang sondern nur einen Ausgang. Die verbleibenden Primitiven stellen uni- und bidirektionale MOS-Transistorschalter für die switch-level Simulation (Simulation mit Schaltermodellen) von Schaltungen auf Bauelementebene dar. Eine genauere Beschreibung der Primitiven mit Wahrheitstabellen und Schaltplansymbolen findet sich in einem gesonderten Anhang (D). Generell stehen in der Portliste der Primitiven die Ausgänge jeweils am weitesten links, also am Anfang, dann folgen die Eingänge und am Schluss werden die Kontrollsignale aufgeführt (falls vorhanden), die das primitive Element aktivieren oder abschalten. Die relevanten logischen Werte für die Kontrollanschlüsse kann man am Namen ablesen: bufif0 ist z.B. ein Tristate-Treiber, der von einer logischen Null („0“) am Kontrolleingang angeschaltet wird und notif1 ist ein invertierender Tristate-Treiber, der mit einer logischen Eins („1“) aktiviert wird. Während die Schaltermodelle eine jeweils genau festgelegte Anzahl von Ein- und Ausgängen aufweisen, stehen die aufgeführten primitiven Gatter- und Treiberelemente jeweils für ganze Familien von Objekten (siehe Abb. 3.1). Das Schalterelement cmos, bei dem es sich um ein CMOS-Transfergatter handelt (siehe Abb. 3.1) hat beispielsweise stets drei Eingänge (input, n-gate, p-gate) und einen Ausgang (output). Bei Gattern und Treibern unterscheiden wir zwischen Primitiven mit n-Eingängen (n-input primitves) und primitiven Elementen mit n-Ausgängen (n-output primitves). Bei den Mehrfach-Primitiven ändert sich das Schlüsselwort, das den Gattertyp definiert, nicht. Die jeweils aktuelle Zahl der Ein- oder Ausgänge wird vom Compiler anhand der Portliste erkannt. Beim Vergleich mit einer Standardzellbibliothek oder einem Katalog für die TTL-Gatter der 74xxx-Reihe stellt man fest, dass viele elementare Komponenten nicht als Verilog-Primitive vordefiniert sind. Beispiele sind Multiplexer oder Flip-Flops. Hier bietet die Sprache aber die Möglichkeit, vom Anwender definierte Primitive zusätzlich zu deklarieren (UDPs, user defined primitives, siehe Abschnitt 4.1). p_enable
input
output
in_1 in_2
out
in_1 in_2 in_3 in_4
out
n_enable cmos(output, input, n_enable, p_enable)
and(out, in_1, in_2)
Abb. 3.1 CMOS-Transfergatter und das AND-Gatter mit 2 und 4 Eingängen.
and(out, in_1, in_2, in_3, in_4)
36
3 Die Sprache Verilog
Beispiele: nand (out, in1, in2); and (out, in1, in2, in3, in4); buf (out_1, out_2, in);
3.1.12
// NAND-Gatter mit den 2 Eingängen in1, in2 // AND-Gatter mit den 4 Eingängen in1, in2, in3, in4 // Treiber buf mit einem Eingang und zwei Ausgängen i
Ports von Primitiven und Modulen
Wie bereits in Kapitel 2 diskutiert, werden Verilog-Module über Schnittstellen oder Ports mit der Außenwelt verbunden. An einen Port können analog zu den Pins eines elektronischen Bauelements nur Signale über net-Datentypen angelegt werden, denn an die Anschlüsse eines elektronischen Bauteils werden die Signale über elektrische Leitungen geführt. Eingabegrößen können einem Modul nur über Eingangsleitungen (input) vom Typ wire zugeführt werden. An Ausgabe-Schnittstellen (output) können analog von außen nur wires angeschlossen werden. Von innen können die Signale, die zu den Ausgangsports führen, auch vom Typ reg sein, wenn die Ausgabegrößen gehalten werden sollen (registered outputs). Ports vom Typ inout sind bidirektional. Daten können über diese Schnittstellen in beide Richtungen weitergeleitet werden. Da hier gleichzeitig die gleichen Einschränkungen bzgl. der angeschlossenen Verbindungen gelten wie bei input- und output-Ports, sind inoutSchnittstellen vom Modul her und zum Modul hin mit wire-Typen zu verbinden.
3.1.13
Instanziierung von Primitiven
Der Begriff „Instanziierung“ ist nicht verilog-spezifisch. Instanziiert werden auch grafische Symbole von Komponenten in elektronischen Schaltplänen. Eine Instanz ist eine Kopie eines Bibliothekelements. Bei Schaltplandesigns handelt es sich um eine Komponente aus der Bauteilbibliothek, die u. U. nicht nur einmal sondern mehrfach in einen Schaltplan (Bild 3.2) eingesetzt wird. In einem strukturellen HDL-Design hingegen werden Modelle (bei Verilog Module) aus einer Modell-Bibliothek in ein anderes Modell instanziiert oder im objektorientierten Sinn referenziert.
3.1 Syntax und Semantik
37
a
out sel b
Abb. 3.2
Schaltplan eines 2:1 Multiplexers. Das Bibliothekselement „AND-Gatter“ ist zweimal eingesetzt
Die strukturelle Verilog-Netzliste des Multiplexers, der in Bild 3.2 als Schaltung vorliegt, hat ausgedrückt mit Hilfe von Verilog-Primitiven die folgende Form: module mux(out, a, b, sel); output out; input a,b, sel; not i1 (sel_n, sel); and i2 (sel_a, a, sel); and i3 (sel_b, sel_n, b); or i4 (out, sel_a, sel_b); endmodule Die Schlüsselworte module und endmodule stehen am Anfang und am Ende des Modells. Der Modulname ist hier „mux“, die Ports heißen out, a, b, und sel. In der zweiten Anweisung wird out als Ausgang und a, b, und sel werden als Eingänge definiert. Dann werden die benötigten primitiven Gatterelemente not (Inversion), and (Verundung) und or (Veroderung) eingesetzt. Die vier Instanzen, die den vier Gattern im Schaltplan entsprechen, können individuell über die Namen i1 bis i4 angesprochen werden. Damit sind mehrfach auftretende gleiche Primitive unterscheidbar. Für jede Instanz werden in Klammern die gewünschten Signalverknüpfungen vorgenommen, wobei interne Signale (sel_n, sel_a, sel_b), die nicht als Port auftreten, implizit als Netze (siehe 3.1.9, `default_nettype) definiert sind. Die allgemeine Syntax für die Instanziierung von Primitiven ist: PRIMITIVE_TYPE [Stärke] [#Delay] [Instanzen_name] (Liste der Anschlüsse); Wir sehen, dass gegenüber dem mux-Beispiel noch weitere optionale Vorgaben beim Einsetzen einer primitiven Verilog-Komponente möglich sind: Jeder Instanz kann eine Ausgangstreiberstärke [Stärke] zugewiesen werden. Da logische Gatter, Treiber und Pull-up- bzw. Pull-down-Widerstände am Ausgang nur voll regenerierte Logikpegel liefern, sind nur Treiberstärken (siehe Abschnitt 3.1.4, Tabelle 3.1) für die logische „0“ und die logische „1“ anzugeben (stärke_der_0 und stärke_der_1). Bei Pull-up-
38
3 Die Sprache Verilog
bzw. Pull-down-Widerständen hingegen ist der Ausgang fest die „1“ bzw. die „0“ und die Angabe der entsprechenden Stärke genügt. Bei den in Frage kommenden Signalstärken ist highz ausgeklammert: Stärke_der_1::= supply1⎟ strong1⎟ pull1⎟ weak1 Stärke_der_0::= supply0⎟ strong0⎟ pull0⎟ weak0 Für Transistorschalter, wie z.B. das in Bild 3.1 gezeigte Transfergatter, können keine Signalstärken vorgegeben werden, denn im Gegensatz zu Gattern oder Treibern verstärken solche Schaltelemente die logischen Zustände nicht. Die Signallaufzeit durch das primitive Element kann optional als Delay nach einem #-Symbol eingegeben werden. Dabei sind Laufzeiten für steigende, fallende oder abschaltende Ausgänge möglich, wobei zusätzlich noch minimale, maximale und typische Verzögerungen je nach Technologievariante spezifiziert werden können. Wird kein Laufzeitwert eingetragen, erfolgt die Signalweitergabe von Eingang nach Ausgang unverzögert. Über den Instanzennamen [Instanzen_name] werden primitive Komponenten unterscheidbar. Jeder Bezeichner ist als Name zugelassen. Beispiele: not #2.5 (a, b, c); // invertierender Tristate-Treiber not mit den beiden Ausgängen a und b als Eingang // #2.5 spezifiziert eine Gatterverzögerungszeit von 2.5 Zeiteinheiten and (strong0, weak1) #3.2 u1 (out, in1, in2); // 2fach-AND mit starker 0 und schwacher 1, 3.2 Zeiteinheiten Verzögerung, // der Instanzennamen ist u1
3.2
Ausdrücke: Operatoren und Operanden
Ein Ausdruck (in Englisch expression) besteht aus Operanden, die mit Hilfe von Operatoren zu neuen Operanden verknüpft werden. Die Werte der neuen Operanden richten sich nach dem semantischen Gehalt des Operators und den Werten der verwendeten Operanden. Wir unterscheiden zwischen skalaren und verktoriellen Ausdrücken, wobei skalare Ausdrücke ein skalares (ein-bittiges) Ergebnis haben, während Vektor-Ausdrücke einen Ergebnisvektor liefern. Neben den in der Norm vordefinierten Operatoren kann der Anwender auch Funktionen einführen, die aus Eingabe-Operanden Ergebnisse, also andere Operanden produzieren.
3.2 Ausdrücke: Operatoren und Operanden
3.2.1
39
Operanden
Ein Operand im Rahmen von Verilog ist entweder: • • • •
eine konstante Zahl, ein Netz (net), eine Variable vom Typ reg, integer, real, time und realtime, ein selektierter Bereich von einer oder mehreren Stellen (bit- oder part-select) aus einem Netz oder aus einer Variablen der Klassen reg, time und integer, • eine Element eines Feldes (array) oder • ein Aufruf einer Funktion, die einen der in dieser Liste bisher angegebenen Typen liefert.
3.2.2
Operatoren
In der Verilog-Hardware-Beschreibungssprache stehen alle Operatoren zur Verfügung, die man auch von gewöhnlichen Programmiersprachen kennt. Die Abkürzungen und Symbole für die verschiedenen arithmetischen und logischen Verknüpfungsoperatoren erinnert stark an die Notationen der Sprache C. Die Operatoren können wie in 3.1.5 angesprochen in unary-, binary- und ternary-Operatoren aufgeteilt werden, je nachdem wie viele Operanden (ein, zwei oder drei) verknüpft werden. Arithmetische Operatoren Natürlich stehen im Rahmen von Verilog alle üblichen arithmetischen Operatoren für die Addition, Subtraktion, Division, die Modulo-Bildung und die Multiplikation zur Verfügung. Die Symbole zeigt der folgende Kasten. +
Addition
-
Subtraktion
/
Division
% Modulo *
Multiplikation
** Potenzierung Wenn bei einer arithmetischen Operation auch nur eine Stelle (Bit) eines Operanden unbekannt ist (x-oder z-Zustand), dann ist auch das Resultat dieser arithmetischen Operation unbekannt. Divisionsoperatoren schneiden Nachkommastellen ab, wenn die deklarierte Stellenzahl für das Netz oder die Variable, die das Ergebnis zugewiesen bekommen soll, nicht ausreichend ist. Das Vorzeichen des Ergebnisses einer solchen Operation wird vom ersten Operanden übernommen. Werden ganze Zahlen dividiert, werden alle entstehenden Nachkommastellen abgeschnitten. Ist der zweite Operand bei einer Division oder Modulobildung eine 0, dann ist das Ergebnis in beiden Fällen unbestimmt (x). Die Modulo-Bildung y % z ergibt den Restwert, den die Division y / w liefern würde. Folglich stimmen Divisionsergebniss und Modulobildung überein, wenn w ein Teiler von y ist.
40
3 Die Sprache Verilog
Der Minus-Operator kann nicht nur in Subtraktionen verwendet werden, sondern als unaryOperator auch zur Vorzeichenumkehr. Die Potenzierung liefert kein konkretes Ergebnis, wenn der erste Operand (a in a**b) null oder der zweite Operand (b) negativ ist, oder wenn a negativ und b keine ganze Zahl ist. Im Folgenden sieht man einige Anwendungen arithmetischer Operatoren. m = 5;
p = 2.0;
n=2
q = 4’b010z;
m + n ergibt 7
m / n ist 2
m % n ergibt 1
m – n ergibt 3
m / p ist 2.5
m + q ist 4’bxxxx
Vergleichende Operatoren Diese Operatoren vergleichen zwei Operanden. Je nachdem wie dieser Vergleich ausfällt wird die skalare Größe „0“ (nicht zutreffend) oder „1“ (zutreffend) ausgegeben. Wir können die üblichen Relationen „größer als“, „kleiner als“, „größer gleich“ oder „kleiner gleich“ abprüfen. >
größer als
= größer als oder gleich groß wie > oder > oder 2 ist 4’b1110
p >> 2
m >> n ist 4’b0001
ist 4’b0010
Bedingungs- oder Conditional-Operator Dieser Operator mit dem Symbol „?:“ ist der einzige Operator in Verilog, der auf drei Operanden (Variable oder Ausdrücke) wirkt: Bedingungsoperator ::= expression_1 ?: expression_2 : expression_3; Der Operator wählt einen der der Ausdrücke expression_2 oder expression_3 aus, je nachdem wie das boolesche Äquivalent des ersten Operanden ausfällt: bei true wird „expression_2“ ausgeführt und bei false „expression_3“. Der Operator wirkt wie eine logische Verzweigung (if then else). So können mit einer Programmzeile z.B. 2-zu-1-Muliplexer oder Tristate-Treiber beschrieben werden. Reduziert sich expression_1 zu einer unbestimmten Größe (x oder z), dann werden die einzelnen Stellen der beiden anderen Operanden bitweise verglichen, gemäß der folgenden Wahrheitstabelle verknüpft und das Ergebnis zugewiesen. Ist einer der beiden zu vergleichenden Operanden länger, wird der kürzere von rechts her so lange mit Nullen aufgefüllt, bis die Stellenzahl übereinstimmt. Tab. 3.5 Auflösung von mehrdeutigen Zuordnungen beim ?:-Operator
?:
0
1
x
z
0
0
x
x
x
1
x
1
x
x
x
x
x
x
x
z
x
x
x
x
Beispiele out = (sel = = 1’b1)? a : b;
// 2:1-Multiplexer
y = en? data_bus : 32’bz;
// 32-Bit Tristate-Buffer mit active-high enable-Signal:
// en = 1, dann wird der Zustand von data_bus auf den y-Bus gelegt // en = 0, dann wird der y-Bus mit z-Bits belegt // ist en x oder z, dann wird der Bus mit x-Bits beschrieben
44
3 Die Sprache Verilog
Verkettungsoperator und Replikationsoperator Der Verkettungsoperator (engl. concatenate operator) verbindet mehrere Ausdrücke. Der eigentliche Operator besteht aus zwei geschweiften Klammern {operand1, operand2}, welche die zu verbindenden, durch Kommata abgetrennten Operanden einschließen. Die Operanden werden in Verilog von links nach rechts zusammengefasst. Der Replikationsoperator (Wiederholungsoperator) ist eine Variante des Verkettungsoperators und hier wird ein Operand n-mal mit sich selbst verkettet: {n{operand}}. Beispiele a = 1'b1; b = 2'b00; {a, b} // ergibt 100 {4{a}} // ergibt 1111 Operator-Rangfolge Werden in einem Ausdruck verschiedene Operatoren benutzt, dann ist das Endergebnis häufig von der Reihenfolge der Abarbeitung bestimmt. Deshalb ist in der Norm eine feste Rangfolge für die verschiedenen Operatoren genau wie in der Algebra („Punktrechnung vor Strichrechnung“) festgelegt (Tabelle 3.6). Tab. 3.6 Operator-Rangordnung (operator precedence)
Rang
Symbol
Operator
Hoch
+ - ! ~
unitär
**
Pontenzierung
* / %
Multiplikation, Division, Modulo
+ -
Addition, Subtraktion
> >
Schieboperatoren
< >=
Vergleiche
= = != = = = ! = =
Gleichheit
& ~&
Reduktion
^ ^~ ~^ | ~| && ||
Logik
?:
Bedingungsoperator
Niedrig
3.3 System Tasks und Compileranweisungen
3.3
45
System Tasks und Compileranweisungen
Im Verilog-Standard sind nicht nur Konstrukte definiert, mit denen Simulationsmodelle geschrieben werden können, sondern auch so genannte System-Aufgaben (system tasks) und Compiler-Direktiven (compiler directives). Mit den System-Funktionen können während der Simulation Ergebnisse auf dem Bildschirm angezeigt werden oder andere Routineoperationen ausgeführt werden. Mit Direktiven für den Compiler können wir z.B. vor der Simulation die Zeitauflösung des Simulators einstellen oder wie bereits erwähnt, den default-nettype vorgeben. System-Tasks und Compiler-Anweisungen haben mit dem eigentlichen Modell nichts zu tun. Sie beginnen mit einem $- bzw. einem ′-Zeichen. Neben den vordefinierten tasks und directives können EDA-Werkzeuge auch noch weitere Anweisungen beinhalten.
3.3.1
System-Aufgaben
Alle System-Tasks haben die Form $Schlüsselwort. Hier werden nur die gebräuchlichsten vorgestellt. Eine komplette Liste der standardisierten Tasks steht im Verilog HDL Language Reference Manual (LRM). Die für ein Tool spezifischen Anweisungen findet man in der Gebrauchsanleitung des jeweiligen Simulators. Systemanweisungen zur Textausgabe Mit diesen Kommandos können Werte von Operanden während der Simulation ausgegeben werden. Die Anweisungen $display, $strobe und $monitor haben eine einheitliche Syntax und geben einen formatierten Text zur Simulationszeit auf den Bildschirm. Die allgemeine Form von $display ist beispielsweise $display([Formatvorgabe], [operand_1], [operand_2], … ); Die einfachste Möglichkeit etwas auszugeben besteht darin, einen Text in Hochkommata zu setzen. $display und $strobe geben den Text aus, wenn das Statement ausgeführt wird. $strobe unterscheidet sich von $display dadurch, dass hier erst der Text am Ende des aktuellen Simulationszeitschritts auf dem Bildschirm erscheint, wenn alle Signale im aktuellen stabil sind. $monitor hingegen reagiert auf jede Änderung der überwachten Signale und druckt dann immer alle Werte, die in der Operandenliste stehen, als Bildschirmtext. So können sehr viele Ausgabedaten anfallen. Die Signalwerte werden von allen drei Anweisungen in der Reihenfolge ausgegeben, in der sie in der $display-, $monitor- oder $strobe-Anweisung stehen. Verilog beschränkt die Textlänge einer Ausgabeanweisung auf eine Zeile. $write ist eine Variante von $display, die sich dadurch unterscheidet, dass $write nicht wie $display eine neue Zeile vor dem Schreibvorgang öffnet. Mit Erweiterungen b, h oder o können die Formate der auszugebenden Größen festgelegt werden: $displayb gibt im Binär$displayo im Oktal- und $displayh im Hex-Format aus. Wird kein Format angegeben, werden alle Werte als Dezimalzahlen ausgegeben.
46
3 Die Sprache Verilog
Sollen in einer Textzeile verschieden Formate benutzt werden, kann dies mit Formatspezifikatoren festgelegt werden, die die gleiche Form haben wie in der Programmiersprache C oder C++ (printf -Funktion). Diese Spezifikatoren legen fest, an welcher Stelle in der Ausgabezeile welcher Wert in welcher Zahlendarstellung erscheinen soll. Es ist zu beachten, dass immer nur eine $monitor-Anweisung im Modell aktiv sein darf. Mit $monitoron und $monitoroff kann eine Monitoranweisung ein- bzw. ausgeschaltet werden. Formatangaben %d oder %D dezimale Ausgabe %h oder %H hexadezimale Ausgabe %b oder %B binäre Ausgabe %o oder %O Ausgabe im Oktalformat %c oder %C Ausgabe als ASCII-Zeichen %s oder %S Ausgabe als Zeichenkette %t oder %T zeige die Zeit an %f oder %F Ausgabe als Dezimalzahl Spezielle Zeichen: \t
setzt einen Tabulator
\n
erzeugt eine neue Zeile
\\
druckt ein „\“-Zeichen
\“
druckt ein doppeltes Hochkomma
Weitere wichtige Systemfunktionen sind $time, $stime und $realtime, mit denen die aktuelle Simulationszeit als 64-Bit-Integer, 32-Bit-Integer bzw. als Realzahl ausgegeben werden kann. Textausgabefunktionen und Ausgabe des jeweiligen Simulationszeitpunkts können kombiniert werden und so können die zeitlichen Entwicklungen im Modell als Liste am Bildschirm dargestellt werden. Neben der Bildschirmausgabe besteht die Möglichkeit, Texte auch in Dateien zu schreiben. $fopen und $fclose öffnen und schließen die gewünschte Datei. Statt $display-, $monitorusw. heißen die datei-bezogenen Befehle $fdisplay-, $fmonitor- oder $fstrobe bzw. $fwrite. Maximal dürfen in Verilog 31 Dateien gleichzeitig geöffnet sein. Alle Dateien werden am Ende der Simulation automatisch wieder geschlossen.
3.3 System Tasks und Compileranweisungen
47
Beispiele: $display(“Verilog mach Spass“); // druckt Verilog mach Spass Formate: wire bus[3:0]; bus = 3’d10; $display (“bus = %d or %h or %b” ,bus, bus, bus); // gibt aus: bus = 10 or A or 1011 $time und $monitor: $monitor ($time, “reset: %b load %b: up_down %b data %h”, reset, ld, d_out); // Ausgabe könnte folgendermaßen aussehen: 100 reset: 1 load: 1 up_down: 0 data 01FF Weitere System-Tasks $reset setzt die Simulation auf den Zeitpunkt null zurück und $stop hält die Simulationszeit an und man kann in einem interaktiven Modus das Programm Schritt für Schritt austesten (debugging). Mit $finish wird eine laufende Simulation beendet und der Simulator verlassen. Im Language Reference Manual [LRM] können alle standardisierten System-Tasks nachgesehen werden.
3.3.2
Compileranweisungen
Diese Anweisungen (compiler-directives) steuern den Verilog-Compiler. Diese Anweisungen beginnen mit dem `-Zeichen („accent grave“ im Französischen), nicht zu verwechseln mit einem einzelnen Hochkomma (’). Dann folgt ein Bezeichner für die CompilerAnweisung. Im Folgenden werden die gebräuchlichsten Anweisungen vorgestellt. Es ist zu beachten, dass Compileranweisungen nicht durch das Erreichen einer endmodule-Anweisung oder eines FileEndes (end of file) beim Kompilieren deaktiviert werden. Diese Anweisungen wirken auf alle Dateien und Module, die nach dem Einlesen einer Direktive übersetzt werden und bleiben so lange aktiv, bis die Compileranweisung geändert oder rückgesetzt wird (mit `resetall). `define Dieser Befehl veranlasst den Compiler, eine bestimmte Zeichenfolge (Namen) immer wenn diese im Programmtext auftritt durch einen vorher definierten Text (Makro) zu ersetzen. Die Syntax liest sich wie folgt: `define Name_des_Makros Text_des_Makros Die Anweisung wird nicht mit einem Semikolon abgeschlossen und darf nicht länger als eine Zeile sein. Die Anweisung kann sowohl innerhalb als auch außerhalb von Moduldefinitionen verwendet werden. Wie alle Compiler-Anweisungen sollte auch `define möglichst außerhalb von Modulen vereinbart werden.
48
3 Die Sprache Verilog
`include Mit dieser Anweisung wird der Compiler dazu veranlasst, den Inhalt eines Files in den Code eines Verilog-Modells einzubetten. Überall im Quellcode, wo das `include-Statement auftritt, wird dieses Statement durch den Inhalt des Files ersetzt. `timescale Diese Steueranweisung legt die Zeitskala für die Simulation fest. Der abstrakten Simulationszeit in Timesteps wird eine physikalische Zeit (z.B. in ns) zugeordnet. Die `timescaleSteueranweisung definiert nicht nur, welche Zeitspanne einer Zeiteinheit der Simulationszeit entspricht, sondern auch wie genau physikalische Zeiten aufzulösen sind. Timescale-Steueranweisung ::= `timescale Zeiteinheit Basis_1 / Zeitauflösung Basis_2 Die Zeiteinheit ist die Zahl von Zeiteinheiten (Basis_1) auf der physikalischen Zeitskala, die einer Einheit der Simulationszeit entsprechen soll, und die Zeitauflösung legt fest, mit welcher Genauigkeit (in Zeitschritten der Basis_2) die physikalischen Zeiten erfasst werden sollen. Mögliche Zeitbasen in der `timescale-Anweisung sind Sekunden (s), Millisekunden (ms), Mikrosekunden (µs), Nanosekunden (ns), Picosekunden (ps) oder Femtosekunden (fs). Findet sich keine `timescale-Anweisung in einem Modell, dann sind Signalverzögerung lediglich ganze Zahlen ohne Zeitbezug. Eventuell auftretende Nachkommastellen werden angeschnitten. Beispiele: `define WIDTH 10 // Name: WIDTH, Text der eingefügt werden soll: 10 module decode () output dec1[WIDTH-1:0]; …… // dec1 ist ein Vektor mit dem tatsächlichen Indexbereich 9 : 0 endmodule `include “one_bit_adder.v” // das Modul one_bit_adder.v wird eingefügt `timescale 1 ns / 10 ps // eine Simulationszeiteinheit entspricht 1 ns, Zeiten werden bis // zur zweiten Dezimalstelle (0,01 ns = 10 ps) berücksichtigt
3.4
Ein einfaches Verilog-Modell mit Testumgebung
Das bisher Dargestellte reicht zur Modellierung und Simulation eines ersten Beispielmodells bereits aus. Es handelt sich um einen Volladdierer, dessen Schaltplan in Bild 3.1 gezeigt ist. Dieser Schaltplan lässt sich mit Hilfe von Verilog-Primitiven leicht 1:1 in ein HDL-Modell umwandeln.
3.4 Ein einfaches Verilog-Modell mit Testumgebung
a b
49
sum
n1
n3
ci n2
Abb. 3.3 Volladdierer mit den Eingängen a, b und ci (carry in für Übertragsbit) sowie sum und co (carry out für Übertragsbit-Ausgabe)
Das Modell besteht aus 5 Gatterprimitiven (XOR, AND, ODER), 3 internen Leitungen (n1, n2, n3) sowie aus 3 Eingangsports (a, b, ci) und 2 Ausgängen (sum und co). Eine realistische Zeitskala für integrierte Schaltungen sind Vielfache von 1 ns. Dann kann folgendes VerilogModell aufgestellt werden und unter full_adder.v (mit der nicht vorgeschriebenen, aber praktischen Dateierweiterung .v) abgespeichert werden. `timescale 1ns / 1ns module f_add (a, b, ci, sum, co); input a, b, ci; output sum, co; wire a, b, ci, sum, co, n1, n2, n3; xor (n1, a, b); xor (sum, n1, ci); and (n2, a, b); and (n3, n1, ci); or (co, n2, n3); endmodule Bevor wir das Modell simulieren können, muss es als zu testendes Design (Unit Under Test, UUT, oder Design under Verification, DUV) in eine abgeschlossene Testumgebung (Testbench) eingebettet werden. Eine Testbench ist ein Modell, das ein anderes Modell automatisch testet (siehe Kapitel 9). Üblicherweise haben Testbench-Modelle keine Ports, sondern umschließen das zu prüfende Modell vollständig. Viele Simulationsumgebungen können nur Modelle verarbeiten, die in eine Testbench eingebettet sind, die zumindest die nötigen Eingangssignale für das eigentlich interessierende UUT-Modell erzeugt. In diesem Buch sind alle Beispiele mit dem Tool MODELSIM von Mentor Graphics simuliert worden, für das auch eine kostenlose Version mit reduziertem Funktionsumfang im Internet geladen werden kann (siehe Anhang C). Hier sind Testbenches nicht unbedingt notwendig, weil Stimuli auch über sog. forces direkt an die Eingangsports des Modells gelegt werden können. In der Praxis kommt man aber bei der HDL-Modellierung in der Regel nicht ohne Testbenches aus.
50
3 Die Sprache Verilog
Zum Test des Volladdierermoduls wird daher das Modell in die Testbench instanziiert, wobei seine Anschlüsse mit den Teilen des Testbenchmodells Modell verbunden werden, die Signalgeneratoren für die Eingangsmuster realisieren und die Ausgänge mit den Anweisungen der Testbench, die Ausgangssignale speichern, ausgeben oder sogar auswerten (Bild 3.4). Über die Testbench können neben der Funktionalität auch alle dynamischen Eigenschaften des zu testenden Modells geprüft werden. Damit ist in der Testbench das gesamte Verhalten des zu prüfenden Modells kodiert. Manche bezeichnen daher die Testbench auch als ausführbare Spezifikation, wobei sich der Begriff „ausführbar“ auf die Möglichkeit der Auswertung per Simulationswerkzeug bezieht. Eine Testbench für den Volladdierer sollte alle logischen Eingabekombinationen aus den Signalen a, b und ci generieren und nacheinander anlegen. Damit die Eingangsignale ihren zugewiesenen Zustand bis zum nächsten Signalwechsel behalten, verwenden wir für a, b und ci den reg-Datentyp. Wir betrachten dabei nur den einfachsten Fall, bei dem diese Größen nacheinander auf „0“ und „1“ gesetzt werden, und lassen undefinierte Zustände oder andere Permutationen der Eingangszustände weg. Zur Auswertung genügt es im Prinzip, die Ausgabesignale mit den zugehörigen Eingabesignalen mit der $monitor-Funktion auf dem Bildschirm auszugeben. Die sequentielle Signalgenerierung können wir mit Hilfe des Verzögerungsoperators „#“ und mit direkten Signalzuweisungen realisieren: # 10 a = 1; setzt das Signal a nach 10 Zeiteinheiten auf den Wert „1“. Um die Eingabestimuli zu generieren, verwenden wir im Vorgriff auf das Kapitel 5 (Verhaltensmodellierung), eine Prozedur, die mit dem Schlüsselwort initial gestartet wird. Diese Prozeduren werden während einer Simulation genau einmal am Beginn (Simulationszeit 0) ausgeführt. Die mit dem #-Operator erzeugten zeitlichen Verzögerungen werden bei initial-Prozeduren relativ zur Ausführungszeit der vorherigen Anweisung gezählt. Mehrere Signalverzögerungen addieren sich also. Zur Instanziierung des Addierermoduls f_add verwenden wir die gleiche Notation wie beim Instanziieren von Verilog-Primitiven (siehe Abschnitt 3.1.13): auf den Modulnamen folgt der Instanzbezeichner (hier i1) und die aktuelle Portliste (hier a, b, ci, sum und co). Dass die Ports dieselben Namen tragen wie im Modul f_add ist nicht unbedingt nötig, beziehen sich diese Namen doch auf Netze, die im übergeordneten Testbenchmodul zu definieren sind. Die Eingabesignale a, b und ci sind dabei als reg-Typen zu deklarieren, damit sie die jeweiligen Signalzustände bis zum nächsten Zustandswechsel halten. Die Zuordnung zwischen den Testbenchsignalen und den lokalen Signalen im zu testenden Modul erfolgt über die Reihenfolge in der Portliste der Instanz.
3.4 Ein einfaches Verilog-Modell mit Testumgebung
51
Generatoren für Eingangssignale
Zu testendes Modell: module mein_design (ports); //Deklarationen und funktionale Beschreibung endmodule;
Überwachung, Ausgabe und Auswertung der Ausgangssignale
Abb. 3.4 Struktur einer Testbench mit eingesetztem zu testendem Modell.
Das Testbenchmodell mit eingesetztem Addierer hat dann folgende Form: `timescale 1ns / 1ns // Zeitskala auf 1 ns ohne Dezimalstellen module testbench; reg a, b, ci; // Eingangssignale wire sum, co; // Ausgnagssignale f_add i1 (a, b, ci, sum, co); // Volladdierer als Instanz i1 in der Testbench initial // Prozess für Eingabesignale begin a = 0; // Anfangsbelegung a, b, ci = 0, 0, 0 b = 0; ci = 0; #10 a = 1; // a nach 1: es liegt 1,0,0 an, // Ergebnis: sum = 1 co = 0 #10 b = 1; // b nach 1: es liegt 1,1,0 an, // Ergebnis: sum = 0 co = 1 #10 ci = 1; // ci nach 1: es liegt 1,1,1 an, // Ergebnis: sum = 1 co = 1 #10 $stop; // Simulationsende bei 40 ns $finish; // Simulator wird verlassen end // Prozess wird beendet initial // zweiter parallel laufender Prozess // erzeugt Ausdruck auf Bildschirm begin $monitor ("Bei %0d: \t a=%b b=%b ci=%b sum=%b co=%b",
52
3 Die Sprache Verilog
$time, a, b, ci, sum, co); // druckt Simulationszeit, a, b, ci, sum und co als Binärzahl // bei jeder Zustandsänderung der überwachten Signale aus end endmodule Als Ergebnis der Simulation erzeugt die $monitor-Systemfunktion folgenden Ausdruck auf dem Bildschirm: Bei 0: a=0 b=0 c=0 sum=0 co=0 Bei 10:
a=1 b=0 ci=0 sum=1 co=0
Bei 20:
a=1 b=1 ci=0 sum=0 co=1
Bei 30:
a=1 b=1 ci=1 sum=1 c0=1
$stop called at simulation time 40 ns Mit Simulationswerkzeugen wie MODELSIM können die Ergebnisse auch grafisch als Kurvenzüge (waves) ausgegeben werden. Das folgende Bild zeigt das wave-window des Simulators.
Bild 3.5 Wellenzugdarstellungen der Simulationsergebnisse für die Testumgebung des Volladdierers
3.5
Zusammenfassung
In diesem Kapitel sind die grundlegenden Konzepte der Verilog-HDL vorgestellt worden. Es fällt auf, dass sich die Sprache an C anlehnt und dass bei der Entwicklung von Verilog stets die Modellbildung für elektronische Schaltungen im Blickpunkt stand. Es können verschiedene Datentypen verwendet werden. Für die Logiksimulation stellt Verilog einen eigene 4-wertige Logik bereit, die als Signalzustände die logische „1“, die logische „0“, den unbekannten logischen Zustand x und den hochohmig getrennten Zustand z zulässt. Den einzelnen Zuständen können verschiedene Treiberstärken zugeordnet werden, damit
3.6 Übungsaufgaben
53
sich Zuweisungskonflikte auflösen lassen. Neben diesem Datentyp mit engem Hardwarebezug stehen auch Typen wie integer und real, physikalische Größen wie time, Zeichenfolgen (strings) usw. zur Verfügung. Verilog unterscheidet drei Klassen von Größen: Konstanten, die hier parameter heißen, Variablen (reg) und Netze (net). Netze entsprechen elektrischen Verbindungsleitungen, die logische Signale zwischen Komponenten eines Systems transportieren. Netze haben kein Gedächtnis, sondern vergessen ihren Zustand, wenn dieser nicht permanent von einem treibenden Gatter vorgegeben wird. net-Typen ist in Verilog also eine wesentliche Eigenschaft von elektronischen Systemen aufgeprägt worden. Variablen in üblichen Computersprachen unterscheiden sich im Verhalten dahingehend, dass hier ein zugewiesener Zustand so lange gehalten wird, bis eine neue Zuweisung erfolgt. Dieses Verhalten zeigen in Verilog die reg- oder Register-Datentypen. Die Hardware-Analogie ist hier ein speicherndes Element, das Register. Aus allen Datentypen in Verilog können nicht nur skalare Größen, sondern auch Vektoren oder mehrdimensionale Felder gebildet werden. Verilog unterstützt die Simulation auf Gatter- und Transistorebene mit vordefinierten primitiven Elementen. Diese können auf einfache Weise in Netzlisten zusammengeschaltet und als digitale Gatter-Modelle simuliert werden. Für Simulationen auf noch niedrigerem Abstraktionsniveau stellt Verilog spezielle Leitungstypen mit kapazitiven Eigenschaften und Transistorprimitive mit einfachen Schaltermodellen bereit. So können Systeme aus Netzen, Kapazitäten und Transistoren aufgebaut und simuliert werden. Zur Verknüpfung von Größen sind in Verilog viele logische und arithmetische Operatoren definiert. Auch hier wird wieder der Bezug zur digitalen Hardware deutlich. Beispiele sind hierfür die arithmetischen Schiebeoperatoren, die Verkettungsoperatoren zum Zusammenfassen von skalaren Größen zu Vektoren für Busoperationen oder der ternäre Auswahloperator. Im Verilog-Standard sind nicht nur Konstrukte definiert, mit denen Simulationsmodelle geschrieben werden können, sondern auch system tasks und compiler directives. Mit den System-Funktionen können während der Simulation Ergebnisse auf dem Bildschirm angezeigt werden ($display) oder Simulationen gestoppt oder der Simulator verlassen werden ($finish). Mit Direktiven für den Compiler können wir z.B. vor der Simulation die Zeitauflösung des Simulators einstellen oder mit `include andere Verilog-Dateien in ein Modul einbinden.
3.6
Übungsaufgaben
3.6.1
Wahr oder Falsch
1. 2. 3. 4.
Leerzeichen dürfen in Bezeichnern für Variablen verwendet werden. (wahr/falsch) Im Rahmen der Verilog-HDL wird nicht zwischen Groß- und Kleinschreibung unterschieden. (wahr/falsch) Es gibt keine Zeichenketten in Verilog. (wahr/falsch) “3out_” ist ein gültiger Verilog-2001-Bezeichner. (wahr/falsch)
54
3 Die Sprache Verilog 5. 6. 7.
Primitive Gatter können mehr als einen Ausgangsport aufweisen. (wahr/falsch) Alle Input-Ports sind als reg-Variablen zu deklarieren. (wahr/falsch) Der Leitungs-Datentyp trireg behält den letzten zugewiesenen Wert bei, wenn die Leitung mit einem z-Signal angesteuert wird. (wahr/falsch) 8. # kennzeichnet Delays in Verilog. (wahr/falsch) 9. Mit der Kompiler-Direktive `timescale kann die Zeitskala bei der Simulation festgelegt werden. (wahr/falsch) 10. Das endmodule Schlüsselwort wird mit einem Semikolon abgeschlossen. (wahr/falsch)
3.6.2 1. 2.
Fragen Was ist der kennzeichnende Unterschied der Datentypen wire und reg? Finden Sie alle Fehler im folgenden Modell! module mux(a,b,sel,out); input a,b,sel; output out; reg a,b,c,out; always @ (a,b,sel) begin out = sel ? a :b ; end endmodule;
3.
Worin besteht der Unterschied zwischen den beiden Vergleichsoperatoren “= = =” und “= =” ?
4.
Entwerfen Sie ein Modell eines Halbaddierers mit Verilog-Primitiven!
5.
Welche Rolle spielen parameter in Verilog?
6.
Geben Sie vier compiler directives in Verilog an und beschreiben Sie deren Eigenschaften und Wirkungen!
7.
Worin besteht der Unterschied zwischen der bitweisen Veroderung mit or und dem wor-Operator?
8.
Schreiben Sie Modelle für die folgende Schaltung: •
unter Verwendung von Verilog-Primitiven,
3.6 Übungsaufgaben •
9.
55
bzw. mit Verilog-Operatoren und assign-Statements.
Was unterscheidet die System-Tasks $monitor und $display?
10. Schreiben Sie alle Port-Typen auf, die in Verilog verfügbar sind!
3.6.3 1.
2.
3.
Wie lautet die richtige Antwort? Wird die auf das if-Statement folgende Anweisung im folgenden Code-Fragment ausgeführt? Was ist das Ergebnis der Vergleichsoperation?
a.
a = 3’b0x1 b = 3’b1x0 if (a===b)…… 0
b.
1
c.
x
d.
z
Welche der folgenden Bezeichner sind unzulässig? a.
cB124
b.
output
c.
select_
d.
\74$clk\
Welchem Datentyp können weder zu speichernde Werte noch logische Zustände zugeordnet werden? a.
reg
b.
wire
56
3 Die Sprache Verilog
4.
c.
event
d.
integer
Welche Binärzahl d ergibt sich aus folgender Verkettung (Konkatenierung) a = 2’b00 ; b=1’b1 c=4’b110 d = 2{{b,a},2{b},{b,c}} a. 100111010011111110
5.
b.
100111111010011110
c.
111010011110011110
d.
100111110100111110
Welche der folgenden System-Tasks wird den Wert einer Variablen nur immer dann anzeigen, wenn dieser sich während der Simulation ändert? a.
$monitor
b.
$displayb
c.
$finish
d.
$writememh
3.7
Antworten
3.7.1
Wahr oder Falsch
1. 2. 3. 4. 5. 6.
Leerzeichen dürfen in Bezeichnern für Variablen verwendet werden. (wahr/falsch) Im Rahmen der Verilog-HDL wird nicht zwischen Groß- und Kleinschreibung unterschieden. (wahr/falsch) Wir können keine Zeichenketten in Verilog definieren. (wahr/falsch) “3out_” ist ein gültiger Verilog-2001-Bezeichner. (wahr/falsch) Namen in Verilog dürfen nur mit einem Unterstrich oder einem Buchstaben beginnen! Primitive Gatter können mehr als einen Ausgangsport aufweisen. (wahr/falsch) Nur Primitive der Typen buf oder not können mehr als einen Ausgangsport zugeordnet bekommen, logische Gatter aber nicht! Alle Input Ports sind als reg-Variablen zu deklarieren. (wahr/falsch). Das trifft nur auf die Ausgangsports zu!
3.7 Antworten
57
7.
Der Leitungs-Datentyp trireg behält den letzten zugewiesenen Wert bei, wenn die Leitung mit einem z-Signal angesteuert wird. (wahr/falsch) 8. # kennzeichnet Delays in Verilog. (wahr/falsch) 9. Mit der Kompiler-Direktive `timescale kann die Zeitskala bei der Simulation festgelegt werden. (wahr/falsch) 10. Das ‘endmodule’ Schlüsselwort wird mit einem Semikolon abgeschlossen. (wahr/falsch)
3.7.2
Fragen
1.
Der kennzeichnende Unterschied zwischen wire und reg besteht darin, dass wireDatentypen (Netze) strukturelle Verbindungen in Modulen darstellen und regGrößen Variablen definieren, die Daten speichern können. In Verilog ist vorgeschrieben, dass die linken Seiten von prozeduralen Anweisungen stets regVariablen sein müssen. Sonst können Netze eingesetzt werden.
2.
Das Modell module mux(a,b,sel,out); input a,b,sel; output out; reg a,b,sel,out; always @ (a,b,sel) begin out = sel ? a :b ; end endmodule; hat 2 Fehler: Der Ausgangsport out ist als reg deklariert und nach dem endmoduleStatement steht ein Semikolon.
3.
Der Unterschied zwischen den beiden Vergleichsoperatoren „= = =” und „= =” besteht darin, dass „= =“ der logische Vergleichsoperator ist, der logische Zustände 0 und 1 vergleicht und „= = =“ der Identitätsoperator, der die Werte 0, 1, x und z der einzelnen Stellen der Operanden vergleicht. Wenn z.B. a = 2’b0x und b=2’0x gilt, gibt der Identitätsoperator a = = = b den logischen Wert 1 (Identität) aus und der logische Vergleichsoperator a = = b liefert den Wert x. Bei a = 2’b01 und b=2’00 stellen beide Operatoren übereinstimmend den logischen Wert 0 (falsch) fest.
58
3 Die Sprache Verilog 4.
Das Modell eines Halbaddierers mit Verilog-Primitiven kann grafisch durch den Schaltplan X
SUM
Y CARRY
und in Verilog durch module Half_adder (X,Y,SUM,CARRY); input X,Y; output SUM,CARRY; xor(SUM,X,Y); and(CARRY,X,Y); endmodule dargestellt werden. 5.
Mit Parametern kann man in Verilog-Modellen Konstanten definieren, die vor einer Simulation und während einer Simulation verändert werden können. So können Modelle geschrieben werden, die leicht zu konfigurieren, besser lesbar, leicht erweiterbar und portierbar sind.
6.
Beispielsweise kommen die folgenden Direktiven in Frage: `include: Mit dieser Anweisung können wir ein komplettes Verilog Source File bei der Kompilation eines Modells einschließen. `timescale: Diese Anweisung legt die Zeitskala bei der Simulation fest. `ifdef schließt Programmzeilen in ein Modell während der Simulation ein. `define wird zur Erstellung von Textmakros genutzt.
7.
Bei der bitweisen Veroderung mit or wird jede Stelle des einen Operanden mit der entsprechenden Stelle des anderen Operanden verodert, z.B. 2’b01 or 2’b00 ergibt 2’b01. Bei einem Wired-Or handelt es sich um einen Netzdatentyp, mit dem Netze beschrieben werden können (vgl. Abschnitt 3.1.8), die von mehreren Signalen getrieben werden. Das Netz gibt bei Datenkonflikten den veroderten Wert der Treibersignale aus.
3.7 Antworten 8.
59
Das Modell mit den Primitiven bzw. das Verhaltens-Modell haben folgende Gestalt: module Primitive_model(a,b,s,o); input a,b,s; ouput o; not(s_not, s); and(p1,a,s_not) ; and(p2,s,b); or(o,p1,p2); endmodule module Behav_model(a,b,s,o) input a,b,s; ouput o; assign o = (s ? a : b); endmodule
9.
$display gibt während der Simulation den Wert der in der Parameterliste festgelegten Größen immer dann auf dem Bildschirm aus, wenn auf diese Größen zugegriffen wird, $monitor tut dies nur, wenn sich diese Größen während der Simulation ändern.
10. Die Verilog-Port-Typen sind: input, output, inout.
3.7.3
Folgende Antwort ist richtig
1.
Die Anweisung nach dem if-Statement wird nicht ausgeführt, denn das Ergebnis der Vergleichsoperation ist 0 (Antwort a)
2.
Der Bezeichner output ist als Verilog-Schlüsselwort nicht zulässig (Antwort b)
3.
Dem Datentyp event können weder zu speichernde Werte noch logische Zustände zugeordnet werden (Antwort c).
4.
Die Verkettung von a = 2’b00 ; b=1’b1 c=4’b110 nach der Vorschrift d = 2{{b,a},2{b},{b,c}} ergibt die Antwort d 100111110100111110
5.
Die System Task $displayb zeigt den Wert einer Variablen nur bei jeder Änderung dieses Wertes an (Antwort b).
4
Modelle für Grundkomponenten
Verilog unterstützt, wie sich schon am Vorhandensein von Gatter- und Transistorprimitiven zeigt, die hardwarenahe Modellierung in besonderer Weise. Diese Art der Modellierung ist sehr detailliert, spiegelt den Aufbau der zu simulierenden Schaltung auf Hardwarebene weitestgehend wieder und entspricht der Netzlistendarstellung eines Schaltplanentwurfs. Da die vordefinierte Menge an Gattermodellen und Transistoren nicht immer ausreicht, ist es in Verilog möglich, zusätzliche primitive Elemente einzuführen (user defined primitives, UDPs). Aus Verilog-Primitiven und UDPs lassen sich bereits komplexe Modelle aufbauen. Indem man Netzlisten aus Primitiven als Module definiert und diese Module wieder in andere Module einsetzt, entsteht eine aufbauende Schaltungshierarchie. Diesen Entwurfsstil bezeichnet man wie beim Schaltplandesign als aufbauenden Entwurf (Bottom-up-Design), siehe Bild 4.1.
Abb. 4.1 Aufbauende Hierarchie: aus vordefinierten Gattern werden Halbaddierer, aus diesen Voll-Addierer und aus diesen Komponenten und anderen Gattern wird ein 32-Bit-Addierer zusammengesetzt.
62
4 Modelle für Grundkomponenten
Der Nachteil des Bottom-up-Designs liegt darin, dass zum einen die Komponenten auf jeder Hierarchiestufe simuliert werden müssen und dass das Verhalten der Gesamtschaltung erst am Ende des Entwurfsprozesses kontrolliert werden kann. Folglich ist es nicht ohne weiteres möglich, verschiedene Varianten oder Schaltungsarchitekturen zu vergleichen. Dafür ist der zergliedernde Entwurfsstil (Top-down-Entwurf) viel besser geeignet, der von Verhaltensmodellen für das Gesamtsystem auf hoher Abstraktionsebene ausgeht. So können verschiedene Alternativen im Vorfeld leicht analysiert und bewertet werden. Mittels Synthese werden dann die einzelnen Komponenten der gewählten Implementierung konkretisiert und bis zur Gatterebene hinaus entwickelt. Der Bottom-up-Stil war zu der Zeit, als Verilog entwickelt wurde, sehr verbreitet. Damals waren die Synthesewerkzeuge noch in den Anfängen und die Komponentenbibliotheken der Halbleiterhersteller noch sehr unvollständig. Deshalb musste man zu Beginn des Entwurfsprozesses erst selbst auf Transistorniveau die nötigen Zellen definieren. Das ist heute nicht mehr so. Synthese ist ein Standardverfahren und die Herstellerbibliotheken beinhalten Hunderte von Gattern, Registern, usw. Die wichtigste Anwendung der strukturellen Modellierung auf Gatterebene liegt heute nicht mehr im Systementwurf, sondern in der Verifikation von Ergebnissen der Logiksynthese als Gatternetzliste bei der Post-Synthesis-Verifikation, bei der gegen das bereits verifizierte Verhaltensmodell geprüft wird, bzw. in der Post-LayoutSimulation, bei der der komplette physikalische Entwurf inklusive aller Verbindungsleitungen verifiziert werden muss. Bei der Nachsimulation der synthetisierten Netzliste werden die Laufzeiten der Gatter und abgeschätzte Verzögerungszeiten der Verbindungsleitungen bereits berücksichtigt, um die Funktion der synthetisierten Schaltung gemäß Spezifikation sicherzustellen, noch bevor aufwendige Layouts erstellt oder komplexe Platzierungs- und Verdrahtungsarbeiten durchgeführt wurden. Die Post-Layout-Simulation verwendet extrahierte Leitungskapazitäten und ist die letzte Prüfung, bevor Prototypen der Schaltung gefertigt werden. In diesem Kapitel wird gezeigt, wie man technologiebezogene Zellbibliotheken aufbaut, indem anwenderdefinierten primitiven Elemente (UDPs) entwickelt werden, in denen Signallaufzeiten und Treiberstärken der einzelnen Zellen berücksichtigt sind, damit eine Simulation auf Gatterebene möglichst genaue Ergebnisse liefert. Besonderes Gewicht wird dabei auf die verschiedenen Möglichkeiten in Verilog gelegt, wie Signalverzögerungen nachgebildet werden können und wie zeitliche Bedingungen in Schaltungsmodellen bei der Simulation mit timing checks automatisch auf Einhaltung geprüft werden können.
4.1
Anwenderdefinierte primitive Komponenten
Die vordefinierten Standardkomponenten in Verilog umfassen weder Multiplexer, noch Kombinationsgatter (z.B. AND-OR-Gatter mit Inversion), noch Flip-Flops. Diese Komponenten finden sich in fast jeder Standardzell- oder CPLD-Bibliothek. Verilog bietet die Möglichkeit, anwenderdefinierte Grundkomponenten zu definieren, die wie die VerilogPrimitiven verwendet werden können. Diese Komponenten sind in sich abgeschlossen. Es müssen keine anderen Module oder Primitive eingesetzt werden. Das Verhalten der Kompo-
4.1 Anwenderdefinierte primitive Komponenten
63
nenten wird mittels Wahrheitstabellen nachgebildet. Wenn dabei einige Vorgaben eingehalten werden, heißen die Modelle UDPs (User Defined Primitives). Verilog unterscheidet zwei Typen von UDPs: • Kombinatorische UDPs: Hier ist der Ausgangswert eine logische Kombination der Eingangsgrößen. Ein Beispiel ist ein Multiplexer, der eine von zwei Eingangsgrößen nach Maßgabe eines Steuerbits als Ausgangsgröße ausgibt. • Sequentielle UDPs: Hier hängt der nächste Ausgangswert sowohl von den Eingangsvariablen wie auch vom aktuellen Ausgangszustand ab, der als interner Zustand eines sequentiellen UDPs gespeichert ist. Beispiele für diese Kategorie sind Register oder FlipFlops. Der Vorteil von UDPs liegt darin, dass sie von einem Simulator schnell ausgewertet werden können und dabei nur wenig Speicherplatz benötigen. Wird ein Multiplexer bspw. aus Verilog-Primitiven aufgebaut, dann zeigt Bild 3.2 bereits, dass wir 2 AND-, 1 OR- und 1 Invertergatter benötigen. Mit folgender einfachen Wahrheitstabelle (Tab. 4.1) lässt sich die gleiche Funktion viel kompakter darstellen. Tab. 4.1 Wahrheitstabelle eines 2:1-Multiplexers mit sel als Auswahlbit, a und b als Eingangssignale und y als Ausgangssignal
sel
a
B
y
0
0
0⏐1
0
0
1
0⏐1
1
1
0⏐1
1
0
1
0⏐1
1
1
Diese Tabelle kann leicht in eine UDP-Definition übertragen werden. Die Schlüsselwörter, mit denen eine UDP-Definition beginnt bzw. abgeschlossen wird, sind primitive bzw. endprimitive. Nach primitive wird der Name des neuen primitiven Elements vereinbart (z. B. mux_p), dann folgt die Portliste, in der Ausgänge wie bei den Verilog Primitiven zuerst aufgeführt werden. Dann folgen die Eingangs- und Ausgangssignale und die Schlüsselwörter table und endtable schließen die Wahrheitstabelle ein. Für den Multiplexer ergibt sich diese UDP-Deklaration: primitive mux_p (y, a, b, sel); //Schlüsselwort: primitive input sel, b, a; // Eingangssignale output y; // Ausgangssignal table // a 0 1
b ? ?
// Anfang der Wahrheitstabelle sel :y 0 :0; 0 :1;
64
4 Modelle für Grundkomponenten
? 0 ? 1 endtable endprimitive
1 1
:0; :1;
Die Reihenfolge der Eingangsports in der Portliste bestimmt die Reihenfolge der Spalten für die Eingangssignale in der Wahrheitstabelle. Ein Doppelpunkt trennt die Eingangsgrößen von der Ausgangsgröße (hier y). Das Fragezeichen („?“) in der Tabelle ist eine Kurzschreibweise für die drei Zustände (0, 1, x) und zeigt an, dass es für den Ausgangswert unmaßgeblich ist, welcher logische Zustand am entsprechenden Port anliegt (don’t care). Wie erwähnt, gelten einige Einschränkungen bei der UDP-Definition. Eine benutzerdefinierte primitive Komponente darf nur einen Ausgang besitzen, muss aber mindestens einen bzw. darf höchstens zehn Eingänge aufweisen. In den Wahrheitstabellen ist der z-Zustand verboten, nur die logischen Zustände 0, 1 und x (sowie Übergänge zwischen Zuständen) sind erlaubt. Sollte ein Eingang einer UDP-Komponente den Zustand z annehmen, wird dieser als x interpretiert. Signal-Verzögerungen können nicht schon bei der Definition eines UDPs, sondern erst bei der Instanziierung vorgegeben werden (siehe folgendes Beispiel). UDPs können wie Verilog-Primitive in Netzlisten-Modelle eingefügt werden: `timescale 1ns / 100ps // Zeitskala 1 ns, eine Dezimalstellen module mux (a, b, sel, y); input a, b, sel; // Eingangssignale output y; // Ausgangssignal mux_p #4.3(y, a, b, sel); //UDP-Instanz mit 4.3 ns delay endmodule
4.1.1
Unbekannte Zustände
In UDPs kann der unbekannte logische Zustand x sowohl in den Tabellen als auch als Wert für Eingangssignale auftreten. Dann folgt aber nicht zwingend, dass der Ausgangszustand des UDP ebenfalls ein x-Zustand ist. Bei logischen Gattern oder anderen Schaltungen ist es unter bestimmten Umständen möglich, dass ein unbestimmter Zustand an einem der Eingänge einen definierten logischen Pegel am Ausgang zur Folge haben kann. Dies lässt sich bei der Definition der entsprechenden UDPs nachempfinden, indem die entsprechenden Signalkombinationen in der Tabelle berücksichtigt werden. Als Beispiel dient wieder der oben definierte Multiplexer. Hier erscheint, wenn der Auswahleingang unbestimmt ist (sel = x) und die Dateneingänge a und b den gleichen logischen Zustand (0 oder 1) aufweisen, der Wert von a und b am Ausgang y. Sind hingegen a und b in verschiedenen logischen Zuständen, dann ist keine eindeutige Entscheidung über den Wert von y zu treffen (y = x). Da den Ausgangszuständen von UDPs bei nicht in der Tabelle berücksichtigten Signalkombinationen stets x-Zustände zugewiesen werden, lässt man den Eintrag in der Wahrheitstabelle weg. Die erweiterte Deklaration des Multiplexers hat dann folgende Form:
4.1 Anwenderdefinierte primitive Komponenten
65
primitive mux_p (y, a, b, sel); //Schlüsselwort: primitive input sel, b, a; // Eingangssignale output y; // Ausgangssignal table // Anfang der Wahrheitstabelle // a b sel :y 0 ? 0 :0; 1 ? 0 :1; ? 0 1 :0; ? 1 1 :1; 0 0 x :0; 1 1 x :1; // bei gleichen Eingängen kommt es nicht auf den Zustand des // Auswahlsignals an endtable endprimitive Modelle, die auch bei undefinierten Eingangssignalen soweit möglich, sinnvolle Ausgangszustände zuweisen, heißen „optimistische“ Modelle. Modelle, die stets bei x-Zuständen am Eingang auch einen x-Zustand zurückgeben, sind „pessimistisch“.
4.1.2
Sequentielle UDPs
Da in Verilog weder Flip-Flops noch Register als vordefinierte Primitive existieren, können speichernde Elemente nur als UDPs eingeführt werden. Solche sequentielle Schaltungen sind dadurch gekennzeichnet, dass sich der aktuelle Ausgabewert von intern gespeicherten Werten, also von vorherigen Ausgabezuständen, ableitet. Deshalb wird in der Wahrheitstabelle in der UDP-Deklaration eine zusätzliche Spalte für den vorherigen Zustand aufgenommen. Die Einträge in dieser Spalte werden wieder durch einen Doppelpunkt von den Eingangsgrößen abgetrennt. Bei sequentiellen Komponenten haben außerdem nicht immer alle Eingangssignale einen Einfluss auf den Ausgangswert. In den Fällen, in denen sich trotz Wechseln der Eingangswerte der Ausgangszustand nicht ändert, wird ein „-“-Symbol in die Ausgabespalte der Wahrheitstabelle eingetragen. Dann bleibt der letzte gespeicherte Ausgabewert weiterhin am Ausgang aktiv. Damit der aktuelle Ausgabewert für den oder die nächsten Zustandswechsel während der Simulation gespeichert wird, ist die Ausgangsgröße eines sequentiellen UDPs als reg-Datentyp zu definieren. Ein erstes Beispiel für sequentielle UDPs ist das folgende Modell eines S-R-Flip-Flops: primitive SR_p (Q, S_, R_); input S_, R_; // Eingangssignale output Q; // Ausgangssignal reg Q; // Ausgang Q wird als reg-Typ gespeichert table // // S_ R_ : gesp. Zustand : nächster Zustand 0 1 : ? : 1; // gesetzt 1 0 : ? : 0; // rückgesetzt
66
4 Modelle für Grundkomponenten
1 1 : ? : -; // kein Wechsel // gespeicherter Zustand bleibt Ausgangszustand endtable endprimitive Sequentielle UDPs können wie die oben eingeführten kombinatorischen UDPs wieder in strukturelle Modelle eingefügt werden und dabei Signalverzögerungszeiten zugewiesen bekommen: `timescale 1ns / 100ps // Zeitskala 1 ns, eine Dezimalstellen module srff (s_, r_, q); input s_, r_; // Eingangssignale output q; // Ausgangssignal wire s_, r_, q; // Anschlüsse des Latches sind wires SR_p #2.2(q, s_, r_); //Latch-Instanz mit 2.2 ns delay endmodule In diesem Beispiel haben wir es mit einem pegelsensitiven Latch zu tun. Der Ausgang Q bzw. q im instanziierten Fall kann sich ändern, wenn neue Eingangszustände angelegt werden und dies nach der Wahrheitstabelle zu einem neuen Ausgangszustand führt. In den meisten digitalen Systemen werden aber flankensensitive speichernde Elemente eingesetzt. In solchen synchronen Schaltungen wechseln die Zustände der speichernden Elemente synchron zu einer steigenden oder fallenden Taktflanke. Dies verbessert die Testbarkeit, weil die Synchronisation ein klar definiertes Zeitverhalten der Systeme zu Folge hat. Synchrones Verhalten kann ebenfalls in die UDP-Definition aufgenommen werden. Reagiert bspw. ein flankengesteuertes Flip-Flop auf die steigende Flanke des Taktsignals clk, dann findet sich in der Wahrheitstabelle als entsprechender Eintrag in der Spalte des clk-Signals (01). UDPs können auf beliebige Zustandsübergänge sensibilisiert werden, indem einfach der alte und der neue Zustand in Klammern nacheinander angegeben werden: (Zustand_alt Zustand_neu). Deshalb kann auch auf weitere steigende Übergänge (0x) und (x1) oder auch auf fallende Flanken (10), (1x) oder (0x) getriggert werden. Verilog stellt auch zwei eingebaute Funktionen bereit, um Signalflanken zu festzustellen: negedge (negative edge, fallende Flanke) oder posedge (positive edge, positive Flanke). Wie erwähnt, erzeugt jeder nicht in der Wahrheitstabelle aufgeführte Signalwechsel den unbestimmte Ausgangszustand x. Bei Flip-Flops sollte sich aber nur bei der vorgegebenen Taktflanke der Ausgang ändern. Bei allen anderen Übergängen des Taktsignals sollte hingegen der gespeicherte Zustand am Ausgang erhalten bleiben. Dies muss in der Wahrheitstabelle Berücksichtigung finden. Da neun Übergangsmöglichkeiten zwischen den drei relevanten Pegeln (0, 1, x) existieren, wären neun zusätzliche Zeilen in der Wahrheitstabelle notwendig. Kompakter ist es, den „don’t care“-Zustand „?“ einzusetzen, der elegante Möglichkeiten zur Zusammenfassung bietet. Beispielsweise erfasst (?0) alle fallende Flanken und mit (??) kann man alle Übergänge eines Signals abdecken.
4.1 Anwenderdefinierte primitive Komponenten
67
In der Wahrheitstabelle eines sequentiellen UDPs können Flanken- und Pegelsensitivität gleichzeitig auftreten. So kann synchrones Verhalten mit asynchroner Setzbarkeit oder Rücksetzbarkeit (Set und Reset) kombiniert werden. Da in Verilog die Tabellen von oben nach unten abgearbeitet werden, erhält das Set- oder Reset-Verhalten dadurch Priorität, dass diese pegelgesteuerten Einträge vor den flankengesteuerten in der Tabelle stehen. Die folgenden Beispiele, ein D-Flip-Flop und ein JK-Flip-Flop, die synchron zur steigenden Taktflanke schalten und asynchron setz- und rücksetzbar sind, zeigen die vorgestellten Möglichkeiten.
d
q D-FF
clk
pre
J
pre
q_out K
JK-FF
rst clk
clear
Abb. 4.2 D-Flip-Flop und JK-Flip-Flop (synchron zur steigenden Flanke von clk). Die Preset- (pre-) und Reset(rst-)Signale des D-FF sowie die Preset- und Clear-Signale des JK-FF sind active low.
primitive dff_q (q, d, clk, rst, pre); output q; input d, clk, rst, pre; reg q; // reg-Typ speichert den internen Zustand table //d clk rst pre : gesp.:nächster Zustand 0 (01) 1 1 : ? : 0; // 0 eingesp. 1 (01) 1 1 : ? : 1; // 1 eingesp. ? ? 0 ? : ? : 0;// auf 0 rückgesetzt ? ? 1 0 : ? : 1;// auf 1 gesetzt // rst (reset) hat höhere Prioritaet als pre (preset) (??) ? 1 1 : ? : -; // Flanken von d werden ignoriert ? (1?) 1 1 : ? : -; // Fallende Flanken von clk werden ignoriert ? ? (?1) 1 : ? : -;
68 ? ? 1 0 (0x) 1 1 (0x) 1 // steigende Flanken endtable endprimitive
4 Modelle für Grundkomponenten (?1) : ? : -; 1 : 0 : -; 1 : 1 : -; von rst und pre werden ignoriert
// JK-Flip-Flop in Verilog 2001 primitive jk_prim; output reg q; input clk, j, k, pre, clear; // kompaktere Schreibweise für Ein- und Ausgangsports table // clk j k pre // Setzen des JK-FFs ? ? ? 0 ? ? ? * // Rücksetzen ? ? ? 1 ? ? ? 1 // Normalbetrieb r 0 0 0 r 0 0 1 r 0 1 1 r 1 0 1 r 1 1 1 r 1 1 1 f ? ? ? // j und k b * ? ? b ? * ? // optimistisches Modell p 0 0 1 p 0 ? 1 p ? 0 ? (?0) ? ? ? (1x) 0 0 1 (1x) 0 ? 1 (1x) ? 0 ? x * 0 ? x 0 * 1 endtable endprimitive
clear
:gesp. :nächster Zustand
1 1
: ? : 1
: :
1; 1;
0 *
: ? : 0
: :
0; 0;
0 1 1 1 1 1 ?
: : : : : : :
0 ? ? ? 0 1 ?
: : : : : : :
1; -; 0; 1; 1; 0; -;
? ?
: ? : ?
: :
-; -;
1 ? 1 ? 1 ? 1 1 ?
: : : : : : : : :
: : : : : : : : :
-; -; -; -; -; -; -; -; -;
? 0 1 ? ? 0 1 1 0
4.1 Anwenderdefinierte primitive Komponenten
69
Bei dem JK-Flip-Flop hängt definitionsgemäß der Zustand am Ausgang von j und k ab. Wenn pre und clear beide inaktiv sind (also nicht im Zustand 0), ändert sich der Ausgang bei der nächsten steigenden clk-Flanke in folgender Weise. Gilt j = k = 0, dann wird q = 0 zugewiesen. Bei j = k = 1 wechselt q bei jeder steigenden clk-Flanke zwischen den logischen Zuständen 0 und 1. j = 0 und k = 1 bedingt q = 1 und j = 1 und k = 0 hat q = 0 zur Folge. In diesem Modell haben wir auch die kompaktere Syntax von Verilog 2001 benutzt, nach der wir die Portliste weglassen und die reg-Deklaration mit der Definition des Ausgangssignals einschließen können. Der folgende Kasten zeigt den Vergleich von Verilog 1995 und 2001 für das D-FF-Modell. Verilog 1995: primitive dff_q (q, d, clk, rst, pre); output q; input d, clk, rst, pre; reg q; // reg-Typ speichert den internen Zustand table ... Verilog 2001 primitive dff_q; output reg q; input d, clk, rst, pre; reg q; // reg-Typ speichert den internen Zustand table ... Da die verschiedenen Signalübergänge und -kombinationen zu sehr langen Tabellen in UDPs führen können, wurden noch weitere in Verilog zulässigen Kurznotationen für die Fallunterscheidungen in den Wahrheitstabellen der Flip-Flops benutzt (siehe Tabelle 4.2).
70
4 Modelle für Grundkomponenten
Tab. 4.2 Symbole für UDP-Tabellen
Symbol Bedeutung
Kommentar
0
Logische Null
1
Logische 1
x
Unbekannter Zustand
Darf in den Eingangsfeldern aller UDPs und im Feld für den aktuellen Zustand von sequentiellen UDPs auftreten
?
Durchlaufen der 3 Zustände 0, 1, x
Darf nicht in Ausgangsfeldern aller UDPs auftreten
b
Durchlaufen der 2 definierten Zustände Darf in den Eingangsfeldern aller 0, 1 UDPs; aber nicht in den Ausgangsfeldern auftreten, außerdem im Feld für den aktuellen Zustand von sequentiellen UDPs erlaubt.
-
kein Zustandwechsel
Darf nur in Ausgangsfeldern sequentieller UDPs auftreten
(vw)
Zustandwechsel von „v“ nach „w“
„v“ und „w“ sind entweder 0, 1, x, ? oder b und dieses Symbol ist nur in Eingangsfeldern erlaubt.
*
Durchlaufen aller Zustandswechsel
Gleichbedeutend mit (??), nur bei Eingangsfeldern
r
Steigende Eingangsflanke
Gleichbedeutend mit (01)
f
Fallende Eingangsflanke
Gleichbedeutend mit (10)
p
Durchlaufen von (01),(0 x) und (x1)
positive Flanke
n
Durchlaufen von (10),(x0) und (1x)
4.1.3
Initialisierung von UDPs
Bei kombinatorischen UDPs und den vordefinierten Verilog-Primitiven sind zu Beginn einer Simulation (Simulationszeit T = 0) alle Ausgänge im Zustand x. Ein definierter Ausgangszustand stellt sich erst ein, wenn nach der Auswertung der Eingangssignale ein logischer Zustand mit den definierten Verzögerungen zu den Ausgängen der primitiven Komponenten propagiert ist. Bei sequentiellen UDPs besteht aber die Möglichkeit, die Ausgangswerte bei T = 0 vorzugeben. Diese Initialisierung erfolgt mit der initial-Anweisung. Nach dem Schlüsselwort folgt die Zuweisung des Anfangszustands für das reg-Ausgangssignal des UDPs. Es
4.1 Anwenderdefinierte primitive Komponenten
71
sind nur Zuweisungen für das Ausgangssignal erlaubt. Da die Ausgangwerte von UDPs skalare Größen sind, kommen nur folgende Anfangszustände in Frage: 0, 1, 1`b1, 1`b0 oder 1`bx. Am Beispiel des diskutierten D-Flip-Flops wird gezeigt, wie der Ausgangszustand mit „0“ initialisiert werden kann: // D-Flip-Flop primitive dff_q (q, d, clk, rst, pre); output q; input d, clk, rst, pre; reg q; // reg-Typ speichert den internen Zustand initial q = 0; // setzt den Startwert des Flip-Flops auf 0 table .... Die initial-Anweisung in UDPs setzt nur den Zustand zum Startzeitpunkt T = 0 fest. Es ist nicht erlaubt, durch ein Delay diese Initialisierung zu verzögern.
4.1.4
Zellbibliotheken: Vorteile von UDPs
UDPs werden vorwiegend bei der Erstellung von Modellen für technologiespezifische Zellbibliotheken für das CPLD-Design oder ASIC-Entwicklungen verwendet. In Verilog können die Zellen nicht nur mit UDPs, sondern auch mit den eingebauten Primitiven modelliert werden. Mit primitiven Komponenten könnte das Verhalten von Flip-Flops, Registern, Multiplexern usw. ebenfalls nachgebildet werden, indem man die Komponenten aus den relevanten logischen Gattern aufbaut. Bild 4.3 zeigt dies am Beispiel des bereits diskutierten D-FlipFlops.
D D
CLK
DFF CLK
Q
Q
_ Q
_ Q
Abb. 4.3 D-Flip-Flop als Symbol und Gatterschaltplan: Das Verilog-Modell aus Primitiven hat fünf Instanzen.
Dies hat aber folgende Nachteile. Nur zwei Instanzen des oben vorgestellten UDPs dff_q und des leicht abgeänderten Modells dff_qb mit invertierten Ausgangszuständen in den ersten beiden Tabellenzeilen, stellen die gleiche Funktion dar:
72
4 Modelle für Grundkomponenten
`timescale 1ns / 100ps // Zeitskala 1 ns, eine Dezimalstellen module dff (q, qb, clk, d, rst, pre); input clk, d, rst, pre; // Eingangssignale output q, qb; // Ausgangssignal dff_q (q, clk, d, rst, pre); dff_qb (qb, clk, d, rst, pre); endmodule UDPs verringern also, wie das Beispiel zeigt, deutlich die Zahl der eingesetzten Primitiven. Dies beschleunigt die Simulation, denn weniger Instanzen heißt weniger Speicherbedarf, weniger (interne) Signale und damit weniger Ereignisse, die verwaltet werden müssen. Dies ist besonders wichtig, wenn synthetisierte Designs auf Zellebene nachsimuliert werden müssen. Hier hat man es auch bei kleineren Designaufgaben schnell mit Tausenden bis Hunderttausenden von Bibliothekselementen zu tun! Die benutzerdefinierten Primitiven bilden außerdem nur das Verhalten der Komponenten nach und zeigen den internen Aufbau aus Logikgattern nicht. Sie tun dies zudem genauer, weil auch undefinierte Eingangssignalkombinationen mit x-Zuständen zu definierten Ausgangswerten führen können. UDPs abstrahieren vollständig von der zugrunde liegenden Hardwareimplementierung. Bei der Modellierung von herstellerspezifischen Zellbibliotheken werden so keine technologischen Details weitergegeben.
4.2
Signalverzögerungen und Specify-Blöcke
Bisher wurden bei den diskutierten Primitiven keine Signal-Verzögerungen berücksichtigt. Per Voreinstellung wird in Verilog die Signallaufzeit zwischen den Eingängen und den Ausgängen gleich null gesetzt (zero delay). Im Rahmen dieser Vereinfachung übernimmt der Ausgang einer Komponente sofort die Änderungen der Eingangssignale. Bei reellen Schaltkreisen ist dies nicht der Fall. Jedes logische Gatter und jeder komplexere Schaltkreis erzeugt ein gültiges Ausgangssignal erst nach einer spezifischen Verzögerungszeit (Bild 4.4). Laufzeiten werden in den heute maßgeblichen CMOS-Schaltungen im Wesentlichen von den Umladezeiten der internen kapazitiven Lasten der Gatter (Gateoxidkapazitäten, Verbindungsleitungen) und den zu treibenden Ausgangskapazitäten bestimmt.
4.2 Signalverzögerungen und Specify-Blöcke
73
Vout
Vin
V
tr
tf
t Abb. 4.4 Signallaufzeiten in realen Schaltungen: Ein mit einer kapazitiven Ausgangslast versehener Inverter wird von einer Eingangspannung (strichliniert) mit Stufencharakteristik angesteuert. Die Ausgangsspannung Vout (durchgezogen) folgt der Eingangsspannung (Vin) invertiert und zeitverzögert. Die Ausgangsanstiegsdelayzeit tr (Ausgangsfalldelayzeit tf ) wird zwischen den 50% Pegeln der Ein- und Ausgangssignale gemessen.
4.2.1
Ausgangspin-Delays
In Verilog kann man jedem Modul Verzögerungszeiten (signal delay times) zuweisen, die das analoge Lade- und Entladeverhalten an den Ausgängen nachbilden. Da es bei den Verzögerungen auf die Ausgangsbelastung ankommt, also auf die Schaltungsumgebung, in die eine Komponente eingebettet ist, werden in Verilog diese Verzögerungszeiten erst bei der Instanziierung definiert. Die Verzögerungen können weiterhin von der Art des Signalwechsels (siehe Bild 4.4), von der Umgebungstemperatur, der zur Verfügung stehenden Betriebsspannung und anderen Einflüssen abhängen. Deshalb stellt die Sprache bis zu 9 verschiedene Signalverzögerungen pro Ausgangsport zur Verfügung. Man unterscheidet in Verilog zwischen folgenden Fällen: •
zero-delays (unverzögert) bei funktionalen Modellen (Ausgangssignal ändert sich zeitgleich mit Eingangssignalen)
•
Verzögerungen fall_delay),
•
Verzögerungen für das Abschalten von Ausgängen (toZ-delay),
•
Minimale und maximale Verzögerungswerte für alle Übergänge,
•
Verschiedene Minimal- und Maximaldelays für steigende bzw. fallende Ausgänge, und
•
Unterschiedliche minimale bzw. maximale Laufzeiten für steigende und fallende Übergänge sowie Abschaltverzögerungen.
für
fallende
und
steigende
Ausgangssignale
(rise_delay,
74
4 Modelle für Grundkomponenten
Bild 4.5 verdeutlicht die Signalverläufe bei Zustandswechseln von Ausgangssignalen.
1,x,z
1
0
0,x,z
Fallzeit
Anstiegszeit
1,x
z
z
toZ_delay
0,x
toZ_delay
Abb. 4.5 Verzögerungszeiten für steigende (rise_delay) bzw. fallende Ausgangsflanken (fall_delay) bzw. für die Abschaltung eines logischen Signals (toZ_delay). Von Anstiegszeiten spricht man, wenn der Endzustand eine logische „1“ ist, und von Fallzeiten, wenn das Signal einen „0“-Zustand annimmt. Die jeweils möglichen Ausgangszustände sind links an den Signalverläufen angetragen.
Laufzeiten werden in Verilog durch das „#“-Symbol gekennzeichnet. Eine Abschaltverzögerung (toZ_delay) tritt auf, wenn der Ausgang in den z-Zustand wechselt. Für jeden möglichen Übergang kann eine eigene Verzögerungszeit definiert werden. Wird nur eine Zeit angegeben, dann gilt diese für alle drei Übergangsarten. Bei zwei Angaben beziehen sich die Zeiten auf das Anstiegsdelay und Verzögerung für fallende Ausgänge. Erst bei drei Angaben wird mit dem letzten Eintrag die Abschaltverzögerung definiert. Wenn der Ausgang in den unbestimmten Zustand x wechselt, wird die kleinste der drei verschiedenen Verzögerungszeiten verwendet. Beipiele für 1, 2 und 3 Delay-Angaben in Zeiteinheiten and # (10) a1 (out, in1, in2);
// eine Laufzeit für alle Übergänge
and # (10,12) a2 (out, in1, in2)
// Anstiegs- und Abfallverzögerung von 10 bzw. 12
and # (7,10,14) a3 (c, a, b);
// rise_delay = 7, fall_delay = 10, toZ_delay = 14 // beim Übergang nach z beträgt das delay 7
Um Technologievariationen, Schwankungen der Betriebstemperatur und der Versorgungsspannung zu berücksichtigen, können Delay-Triplets für die minimale, typische und maxi-
4.2 Signalverzögerungen und Specify-Blöcke
75
male Laufzeit angegeben werden (min:typ:max), wobei min ≤ typ ≤ max gelten muss. Wie das folgende Beispiel zeigt, kommen dann bis zu 9 verschiedene Laufzeiten zum Tragen. Beispiel min:typ:max delays bufif0 # (5:7:9, 8:10:12, 15:18:21) b1 (io1, io2, dir); // min., typische und max. Delays für Anstiegs-, Abfall- bzw. Abschaltverzögerung
4.2.2
Pfadabhängige Delays
Bisher wurden nur Ausgangsverzögerungen betrachtet, die unabhängig davon sind, von welchem Eingang die Daten zum Ausgang propagieren, und die bei der Instanziierung festgelegt werden. Pfadabhängige Delays sind hingegen generische Eigenschaften der Module selbst. Tabelle 4.3 zeigt zur Verdeutlichung der signalpfadabhängigen Laufzeiten einen Auszug aus dem Datenblatt einer Standardzellbibliothek, der anhand von Testchips gemessene Laufzeiten zwischen den verschiedenen Pins eines Komplexgatters (AND-OR-INV, Bild 4.6) auflistet. Wir erkennen, dass die Laufzeiten durch eine Schaltung davon abhängen, an welchem Eingangspin sich der Zustand geändert hat. So ist z.B. die Verzögerung bei einer Signaländerung am a-Eingang, die zu einem steigenden Übergang des Ausgangssignals o führt, typischerweise 2,4 ns. Erzeugt ein Signal an d den gleichen Ausgangssignalwechsel, dann beträgt das Delay 2,5 ns. Diese Unterschiede resultieren aus der verwendeten Schaltungstechnik. Bei CMOS-Gattern haben NMOS- und PMOS-Transistoren unterschiedliche Treiberstärken, die im Pull-down-Pfad (NMOS) bzw. im Pull-up-Pfad (PMOS) zu verschiedenen Lade- bzw. Entladezeiten des Ausgangsknotens führen. Dazu kommen noch unterschiedliche Verdrahtungslängen und damit Lastkapazitäten für die verschiedenen Signalpfade im Gatter. Zustandsabhängige Pfadverzögerungen Pin-abhängige Laufzeiteffekte werden im Folgenden am Beispiel eines Komplexgatters behandelt. Die unten abgebildete Implementierung des AND-OR-INVERT-Gatters ist im Übrigen nur schematisch zu sehen. Auf Transistorebene werden meist effizientere Strukturen verwendet, um Chipfläche zu sparen. Dies ist ein weiteres Argument, das die Modellierung von Komplexgattern über Tabellen mit UDPs stützt.
a b o c d
Abb. 4.6 Schematische Darstellung des AND-OR-INVERT-Komplexgatters
76
4 Modelle für Grundkomponenten
Die Signalverzögerungen dieses Gatters sind in folgender Tabelle festgelegt, die z.B. aus den Designunterlagen für den Standardzellenentwurf mit einer bestimmten Technologie stammen könnte. Tab. 4.3 Signalverzögerungen in ns für das AND-OR-INVERT-Gatter
Steigende Übergänge
Fallende Übergänge
Delaypin_zu_pin
min.
typ.
max.
min.
typ.
max.
ta_o
2,2
2,4
2,7
1,6
1,8
2,0
tb_o
2,1
2,3
2,6
1,5
1,7
1,8
tc_o
2,3
2,5
2,8
1,8
2,0
2,1
td_o
2,3
2,5
2,8
1,8
2,0
2,1
Die eingangspinspezifischen Delays können in Verilog in Specify-Blöcken vorgegeben werden. Ein Specify-Block beginnt mit dem Schlüsselwort specify und endet mit end specify. Im Specify-Block können außer Pfad-Delays auch Parameter zugeordnet (z.B. Fläche oder Ausgangslast, die von Synthesewerkzeugen gelesen werden) oder, wie wir weiter unten sehen werden, auch Timing Checks definiert werden, die während der Simulation durchgeführt werden (beispielsweise Setz- und Halte-Zeiten von Flip-Flops).
Parallele Verb.(=>)
inout/output Ports
Inout/input Ports
Inout/input Ports
inout/output Ports
Die Signalpfade in einem Modul heißen in der Verilog-Norm module paths. Die Norm unterscheidet zwischen full module paths und parallel module paths. Bei parallelen Verbindungen wird der Operator „=>“ und im anderen Fall (full) der Operator „*>“ benutzt. ParallelVerbindungen liegen vor, wenn jeder Eingang bitweise mit einem entsprechenden Ausgang verbunden ist. Bei vollen Verbindungen hingegen führt jedes Eingangssignal zu jedem Ausgangssignal. Hier ist es im Gegensatz zur Parallelverbindung möglich, unterschiedlich breite Eingangs- und Ausgangsvektoren zu verbinden. Den Unterschied der beiden Versionen zeigt die folgende Grafik (Bild 4.7).
Vollst. Verbindung
Abb. 4.7 Parallele und vollständige Verbindung im Vergleich: Im ersten Fall existierten bei N=4 Eingängen und N=4 Ausgängen auch vier parallel Pfade, während im zweiten Fall 16 (NxN) Verbindungen möglich sind.
4.2 Signalverzögerungen und Specify-Blöcke
77
Das Komplexgattermodell AND-OR-INVERT mit den Signalverzögerungen aus Tabelle 4.3 mit Specify-Block bei der Instanziierung (full module paths) hat in Verilog die folgende Form: primitive aoi_p (o, a, b, c, d); //UDP fuer AND_OR_INVERT input a, b, c, d; // Eingangssignale output o; // Ausgangssignal table // a b 0 0 1 0 1 1 ……… endtable endprimitive
// Anfang der Wahrheitstabelle c d :y 0 0 :1; 0 0 :1; 0 0 :0;
module aoi (o, a, b, c, d); //Modul mit Komplexgatter input a, b, c, d; // Eingangssignale output o; // Ausgangssignal aoi_p (o, a, b, c, d); // UDP fuer AND_OR_INVERT eingesetzt specify (a *> o) (b *> o) (c, d *> o) endspecify endmodule
// Anfang des Specify-Blocks = (2.2:2.4:2.7, 1.6:1.8:2.0); = (2.1:2.3:2.6, 1.8:2.0:2.1); = (2.3:2.5:2.8, 1.8:2.0:2.1);
Flankenabhängige Verzögerungen Laufzeiten werden für flankengetriggerte speichernde Elemente, wie Flip-Flops, relativ zu einem Zustandswechsel eines Taktes angegeben. Das Taktsignal, auf dessen Flanke es ankommt, muss als Eingangsport deklariert sein. In der Norm heißen flankenabhängige Pfade edge-sensitive-paths. Um eine flankenanhängige Verzögerung festzulegen, ist zuerst mit posedge oder negedge eine Triggerung auf steigende bzw. fallende Flanken festzulegen. Dann wird das auf Flanken zu überwachende Signal definiert, z.B. den Takt clk bei einem DFlip-Flop. Als Letztes gibt man an, welches Eingangssignal (beim D-FF d) verzögert am Ausgang (im Beispiel q) erscheinen soll. Mit einem Polaritätsoperator (+ oder -) kann spezifiziert werden, ob der betrachtete Datenpfad nicht invertierend bzw. invertierend ausgelegt ist. Der folgende Kasten enthält drei Beispiele. (posegde clk => (q+: d)) = (4.4:4.8:5.4, 3.8:4.1:4.6); (negedge clk => (q- : d)) = (10, 8); (clk => (q : d)) = (10,8);
78
4 Modelle für Grundkomponenten
Im ersten Beispiel dauert es nach einer steigenden Taktflanke je nach Technologievariante und je nachdem ob wir einen fallenden oder steigenden Signalwechsel am Ausgang q beobachten zwischen 3,8 und 5,4 Zeiteinheiten, bis der nicht invertierte Eingang d am Ausgang erscheint. Das zweite Beispiel zeigt eine Sensitivität auf die fallende Flanke von clk. Der Verzögerungspfad von d nach q ist invertierend und nach der Flanke beträgt die Anstiegsverzögerung 10 und Abfallverzögerung 8 Zeiteinheiten. Fehlt die Flankendefinition, wie im dritten Beispiel, dann wird bei jedem Wechsel von clk die Übergabe von d nach q mit einer Laufzeit von 10 bzw. 8 Zeiteinheiten beaufschlagt. Bedingte Signalverzögerungen Sollen Verzögerungen pegelabhängig definiert werden oder sollen bestimmte Laufzeiten nur unter bestimmten Bedingungen wirksam werden, dann ist vor dem path delay eine ifBedingung für das relevante Eingangssignal zu definieren, die erfüllt (true) oder nicht erfüllt (false) sein kann: Bedingte-Signalverzögerung ::= if (input_condition) path_delay. Als Beispiele betrachten wir das D-FF mit den low-aktiven Reset- (rst)- und Preset- (pre)Eingängen aus Abschnitt 4.1.2 (siehe erste Zeile im folgenden Kasten). Nur wenn rst und pre beide inaktiv sind also den Wert „1“ annehmen, dann ist das Flip-Flop speicherbereit und eine flankensensitive Signalverzögerung macht Sinn. Das zweite Beispiel im Kasten ist ein Modell eines Exklusiv-Oder-Gatters, bei dem abhängig von den Pegeln der Eingänge a und b verschiedene Verzögerungen bis zum Ausgang out zugewiesen werden: Invertiert das Gatter den sich ändernden Eingangspegel, dann gelten die beiden Anstiegs- und Abfallzeiten invertrise und invertfall. Wird der Eingangszustand nach dem Wechsel an den Ausgang unverändert weitergegeben, dann gelten die anderen beiden Laufzeiten. if (rst == 1’b1 && pre == 1’b1 ) (posegde clk => (q+: d)) = (4.4:4.8:5.4, 3.8:4.1:4.6); module XORgate (a, b, out); input a, b; output out; xor x1 (out, a, b); specify specparam noninvrise = 1, noninvfall = 2 specparam invertrise = 3, invertfall = 4; if (a) (b => out) = (invertrise, invertfall); if (b) (a => out) = (invertrise, invertfall); if (~a) (b => out) = (noninvrise, noninvfall); if (~b) (a => out) = (noninvrise, noninvfall); endspecify endmodule
4.2 Signalverzögerungen und Specify-Blöcke
4.2.3
79
Zeitprüfungen für Steuer- und Taktsignale
Mit bestimmten Anweisungen (timing checks) im specify block kann man überprüfen, ob das erstellte Design während der Simulation bestimmte Zeitvorgaben einhält. So sind beispielsweise für Flip-Flops bestimmte Zeitintervalle zu beachten, damit die korrekten Daten übernommen werden. Vor der Taktflanke muss das Eingangssignal d schon eine gewisse Zeit, die setup-Zeit, stabil anliegen und darf sich auch nach der Flanke erst nach der Haltezeit (hold time) wieder ändern. Bei der Post-Layout-Simulation von synthetisierten Netzlisten mit annotierten Verdrahtungslaufzeiten ist eine typische Aufgabe zu prüfen, ob unter allen Bedingungen die in den Datenblättern spezifizierten setup- und hold-Zeiten für alle Flip-Flops eingehalten werden, obwohl unterschiedliche Taktleitungslängen die Flanken verschleifen. Verilog timing checks können in zwei Gruppen eingeteilt werden: •
Prüfung, ob ein Signal über ein Zeitintervall stabil bleibt ($setup, $hold, $setuphold) und
•
Prüfung von Zeitintervallen zwischen zwei Ereignissen bei Takt- und Steuersignalen ($skew, $width, $period).
Obwohl hier ein $-Zeichen am Anfang steht, handelt es sich bei diesen Zeitprüfungen nicht um System Tasks! Das $-Symbol stammt noch aus den ersten Sprachvarianten vor der Zeit der systematischen Normung. Jede der Prüfungen bezieht sich auf ein Referenzereignis und ein auszuwertendes Ereignis. Zur Auswertung werden die Simulationszeitpunkte des Referenzereignisses und des Auswerteevents als time stamp bzw. time check gespeichert. Das minimal zulässige oder nicht zu überschreitende Zeitlimit (einzelnes Zeitintervall oder min:typ:max-Delay) in der jeweiligen Prüfung wird mit der Differenz aus time check und time stamp verglichen. Wahlweise kann eine Variable bei Zeitverletzungen gesetzt werden (notifier, reg-Datentyp). Die Setup- und die Holdprüfung überwachen in der Regel ein Datensignal mit einer Taktflanke als Referenz. Ein Wechsel des Datums dient bei $setup als time stamp und die Taktflanke stellt das Referenzereignis dar. Bei $hold ist es umgekehrt. $setuphold fasst die Setup und Hold-Prüfung in einer Anweisung zusammen. $setup( d, posedge clk, 3.0, set_up_violation); // Setup-Zeit von d bzgl. clk 3.0 $hold(posedge clk, d, 2.0, hold_up_violation); // Hold-Zeit von d bzgl. clk 2.0 $setuphold(posedge clk, d, 3.0, 2.0, set_up_and_hold_violation); // set_up_violation, hold _violation, set_up_and_hold_violation sind die Variablen, die // bei der entsprechenden Verletzung gesetzt werden, also den Wert „1“ annehmen.
80
4 Modelle für Grundkomponenten
Bei der zweiten Art von timing-check-Prüfungen bei Steuer- und Taktsignalen werden Mindestabstände zwischen zwei Ereignissen bei einem oder zwei Signalen überwacht. Mit $skew können Zeitverschiebungen zwischen Flanken untersucht werden. Sobald dieser Versatz oberhalb einer Schwelle liegt, wird ein Fehler gemeldet. Mit der $width-Anweisung können wir Mindest-Pulsbreiten untersuchen. Hier wird als Time-Check-Zeitmarke das nächste Ereignis auf dem Referenzsignal mit umgekehrter Polarität heran gezogen. Bei einer Messung mit der $period-Anweisung sucht der Simulator die nächste gleichartige Flanke des Referenzsignals und bestimmt so die Periodendauer. Bei $width können wir zusätzlich eine Zeitschwelle setzen, unterhalb derer kurzzeitige Signalwechsel (Glitches) bei der Weitenmessung ausgeblendet werden. Wenn wir eine Nachricht (notifier) verwenden wollen, müssen wir diese Schwelle zusätzlich angegeben. $skew ( posedge clk1, posedge clk2, 0.5, skew_violation); // Taktverschiebung zwischen clk1 und clk2 max. 0.5 $width(negedge rst, 2, 0, rst_violation); // Low-aktiver Reset muss 2 Zeiteinheiten anliegen, keine Ausnahme für Glitches $period(posedge clk, 3.0, clk_violation); // Taktperiode 3.0 Zeiteinheiten // skew_violation, rst_violation, clk_violation sind die Variablen, die bei der // entsprechenden Verletzung gesetzt werden, also den Wert „1“ annehmen.
4.2.4
Trägheits- und Transport-Verzögerungen
Bei einer digitalen Simulation werden Verzögerungen den Komponenten des Modells einfach zugewiesen und nicht wie bei der analogen Schaltkreissimulation aus den Differentialgleichungen, die das System aus Bauelementen und Verbindungsleitungen beschreiben, errechnet. Da bei der digitalen Modellbildung die Naturgesetze der Elektrodynamik nicht eingehen, wird nicht von der Physik entschieden, wie kurz ein Eingangspuls sein darf, damit er noch am Ausgang der Komponente als Signalwechsel sichtbar wird. Da intuitiv klar ist, dass nicht beliebig schnell wechselnde Eingangssignale verarbeitet werden können, werden bei der Logiksimulation zwei Arten von Verzögerungen verwendet, das so genannte InertialDelay (träge Verzögerung) und das Transport-Delay. Die beiden Formen unterscheiden sich in der Behandlung von Pulsen, deren Breite kleiner als der spezifizierte Verzögerungswert ist: •
Ein Inertial-Delay filtert alle Pulse aus, die kürzer als die Verzögerungszeit der Komponente ausfallen (Bild 4.8), und
•
die Transport-Verzögerung gibt jeden Signalwechsel am Eingang an den Ausgang mit der definierten Verzögerungszeit weiter.
4.2 Signalverzögerungen und Specify-Blöcke
81
input
output
input
output
10
20
30
40
50
60
70
80
100
ns
Abb 4.8 Intertial-Verzögerung eines OR-Gatters, das als Treiber geschaltet ist, mit 10 ns Delay. Bei einer Transport-Verzögerung würde der 5 ns breite Puls des Input-Signals am Ausgang (output) von 60 bis 65 ns erscheinen. Die gezeigte Inertial-Verzögerung blendet den Puls aus.
Die Inertial-Verzögerung berücksichtigt, dass kurze Signaländerungen an Eingangsports, wie sie in realen Schaltungen aufgrund von transienten Signalwechseln (Glitches, Spikes) während der Einschwingphase vor Erreichen des stabilen Zustands häufig auftreten, keinen Einfluss auf den Ausgangszustand haben können, weil in der Regel eine logische Schaltung aufgrund ihrer Eingangskapazitäten bestimmte Ladezeiten benötigt, bevor sie Eingangssignalkombinationen verarbeiten kann (siehe Setup- und Hold-Zeiten). Ein konservatives Maß für die Trägheit eines Gatters oder einer Schaltung ist ihre Signalverzögerung. Glitches, die kürzer als die Signalverzögerung sind, werden also ignoriert. Natürlich ist das nur eine Näherung, denn die Ladezeiten an den Eingängen, die die Trägheit verursachen, sind nur ein Teil der gesamten Verzögerung. Glitches werden hier also stärker unterdrückt als dies in der Realität der Fall ist. Bei der Transportverzögerung hingegen, reichen auch noch so kurze Spikes an den Eingängen aus, um zu entsprechenden Signaländerungen an den Ausgängen zu führen. Dies ist natürlich genauso wenig physikalisch. Hier werden die Einflüsse von Glitches überschätzt. Da man es bei Modellen für Grundkomponenten oder bei Verilog-Primitiven mit Strukturen zu tun hat, die sich eng an das Verhalten elektronischer Schaltungen anlehnen, ist klar, dass es sinnvoll ist, in Verilog-Modellen aus Primitiven für Pfad- und Ausgangsdelays nur Inertial-Delays zuzulassen. Transport-Verzögerungen können erst im Rahmen von den abstrakteren Verhaltensmodellen verwendet werden.
82
4 Modelle für Grundkomponenten
4.2.5
Ein kompletter Specify-Block
Im folgenden Beispiel werden noch einmal die Möglichkeiten eines Specify-Blocks aufgezeigt. Das Modul beschreibt das bereits diskutierte D-Flip-Flop als UDPs mit low-aktiven Reset- und Preset-Eingängen und vollständiger Timing-Information für alle Signalverzögerungen inklusive einer Prüfung der Setup- und Hold-Zeit. D-Flip-Flop mit vollständiger Laufzeitinformation: module dff (q, qb, clk, d, rst, pre); input clk, d, rst, pre; // Eingangssignale output q, qb; // Ausgangssignale wire q, qb, clk, d, rst, pre; reg t_error; // notifier flag dff_q one(q, d, clk, rst, pre, t_error); dff_qb two(qb, d, clk, rst, pre, t_error); // in den UDPs dff_q und dff_qb wird zusätzlich ein // Eingang t_error definiert, der im Zustand 1 das D-FF // in den Zustand X versetzt specify specparam t_set_up =3.0, t_hold = 1.2; (rst, pre *> q, qb) = (2.2:2.3:2.5, 2.0:2.2:2.4); if(rst == 1 && pre == 1) (posedge clk => (q+:d))=(4.4:4.8:5.4, 3.8:4.1:4.6); if(rst == 1 && pre == 1) (posedge clk => (q-:d))=(4.1:4.5:5.2, 3.5:3.8:4.3); $setuphold(posedge clk, d,t_set_up, t_hold, t_error); endspecify endmodule Modelle der eingesetzten Flip-Flop-UDPs: primitive dff_q (q, d, clk, rst, pre,t_error); output q; input d, clk, rst, pre, t_error; reg q; // reg-Typ speichert den internen Zustand table //d clk rst pre t_error : gesp.:nächster Zustand 0 (01) 1 1 ? : ? : 0; // 0 eingesp. 1 (01) 1 1 ? : ? : 1; // 1 eingesp. ? ? 0 ? ? : ? : 0; // auf 0 rück-
4.2 Signalverzögerungen und Specify-Blöcke
83
//setzt ? ? 1 0 ? : ? : 1;// auf 1 gesetzt // rst (reset) hat höhere Prioritaet als pre (preset) (??) ? 1 1 ? : ? : -; // Flanken von d werden ignoriert ? (1?) 1 1 ? : ? : -; // Fallende Flanken von clk werden ignoriert ? ? (?1) 1 ? : ? : -; ? ? 1 (?1) ? : ? : -; 0 (0x) 1 1 ? : 0 : -; 1 (0x) 1 1 ? : 1 : -; ? ? ? ? (??) : ? : x; // steigende Flanken von rst und pre werden ignoriert endtable endprimitive Modell des Flip-Flops mit invertiertem Ausgang: primitive dff_qb (q, d, clk, rst, pre,t_error); output q; input d, clk, rst, pre, t_error; reg q; // reg-Typ speichert den internen Zustand table //d clk rst pre t_error : gesp. :nächster Zustand 0 (01) 1 1 ? : ? : 1;// 0 ein//gesp. 1 (01) 1 1 ? : ? : 0;// 1 //eingesp. ? ? 0 ? ? : ? : 1;// auf 0 //rückgesetzt ? ? 1 0 ? : ? : 0;// auf 1 ge//setzt // rst (reset) hat höhere Prioritaet als pre (preset) (??) ? 1 1 ? : ? : -; // Flanken von d werden ignoriert ? (1?) 1 1 ? : ? : -; // Fallende Flanken von clk werden ignoriert ? ? (?1) 1 ? : ? : -; ? ? 1 (?1) ? : ? : -; 0 (0x) 1 1 ? : 0 : -; 1 (0x) 1 1 ? : 1 : -; ? ? ? ? (??) : ? : x; // steigende Flanken von rst und pre werden ignoriert endtable endprimitive
84
4 Modelle für Grundkomponenten
Die folgenden Simulationen zeigen das modellierte zeitliche Verhalten des Moduls (Bild 4.9), wenn es mit der Testbench module tb_dff; reg clk,pre,d,rst; always #4 clk = ~clk; initial begin clk = 1'b0; rst = 1'b0; pre = 1'b1; d = 1'b0; # 9 rst = 1'b1; # 8 pre = 1'b0; # 7 pre = 1'b1; #2 d=1; #18 d=0; #20; end dff ins1(.q(q), .qb(qb), .clk(clk), .d(d), .rst(rst), .pre(pre)); endmodule angesteuert wird.
Abb. 4.9 Zeitliches Verhalten des D-FFs mit Timing Checks
Auf dem Display werden folgende Messages ausgegeben, wenn die setup- bzw. die hold-Zeit verletzt wird: # ** Error: C:/Dokumente und Einstellungen/schumann/Desktop/urgent/dff.v(49): $setup( d:26 ps, posedge clk:28 ps, 3 ps ); # ** Error: C:/Dokumente und Einstellungen/schumann/Desktop/urgent/dff.v(49): $hold( posedge clk:44 ps, d:44 ps, 1 ps );
4.3 Treiberstärken und Signalauflösung
4.3
85
Treiberstärken und Signalauflösung
Verilog kann den logischen Zuständen eines Netzes, den Ports von UDPs oder VerilogGatterprimitiven verschiedene Treiberstärken zuordnen. So können die Eigenschaften bestimmter Hardwarefamilien nachgebildet werden. Zur Erinnerung, die logischen Werte sind 1, 0, X, Z. Unter Ausnutzung der Signalstärken können auch Signalkonflikte aufgelöst werden. Die verschiedenen Stärken sind nochmals in Tabelle 4.4 aufgelistet. Tab. 4.4
Signalstärken in Verilog
Name
Abkürzung
Stärke in Zahlen
supply0
Su0
7
strong0
St0
6
pull0
Pu0
5
large0
La0
4
weak
We0
3
medium0
Me0
2
small0
Sm0
1
highz0
Hiz0
0
highz1
Hiz1
0
small1
Sm1
1
medium1
Me1
2
weak1
We1
3
large1
La1
4
pull1
Pu1
5
strong1
St1
6
supply1
Su0
7
In TTL-Gattern sind z.B. wegen der offenen Kollektorausgänge die logischen Nullen an den Ausgängen stärker als die logischen Einsen (strong0 und pull1). Die Eingänge von dieser Gatterfamilie werden bei hochohmig abgeschalteten Signalen mit einem Pullup-Widerstand gegen die Versorgungsspannung gezogen und können deshalb mit tri1-Netzen nachgebildet werden. Das Verilog-Modell eines TTL-NAND-Gatters (74LS01) hat daher die folgende Form:
86
4 Modelle für Grundkomponenten
`timescale 1ns / 100ps // Zeitskala 1 ns, eine Dezimalstellen module LS01 (a, b, y); input a, b; // Eingangssignale output y; // Ausgangssignale tri a, b; // TTL Eingänge wire y; // nand (strong0, pull1) #(12:17:32, 10:15:28) (y, a, b); endmodule Die Stärke der Ausgangssignale kann wie in Abschnitt 3.1.13 erläutert, vor der Delay-Definition bei der Instanziierung der primitiven nand-Komponente definiert werden.
4.3.1
Auflösen von Signalkonflikten
Bei der Simulation von elektronischen Systemen entsteht oft die Situation, dass zwei Signale mit verschiedenen Pegeln an demselben Netzknoten anliegen. Zur Vermeidung solcher Uneindeutigkeiten werden solche Pegelkonflikte mit Hilfe der Signalstärken aufgelöst, um aus zwei verschiedenen Signalen ein eindeutiges Ergebnis zu ermitteln. Zwei Fälle sind von Interesse, wenn zwei Signale zusammengeführt werden: 1.
Die beiden Signale haben verschiedene Stärken und den gleichen oder verschiedene logische Pegel. Als Ergebnis nimmt der Ausgangsknoten den gleichen logischen Pegel an, wie er bei beiden Einzelsignalen vorliegt bzw. übernimmt den logischen Pegel des stärkeren Signals. Die Stärke dieses neuen Signals entspricht dem stärkeren der beiden Eingangssignale (Bild 4.10). supply1 supply1
pull1
Abb. 4.10 Signalkonflikt bei verschiedenen Stärken, aber gleichem Pegel
2.
Die Signale haben die gleiche Stärke, sind aber logisch unterschiedlich. Dies führt zu einem Signal, das den Stärkewert der beiden Eingangssignale annimmt und dessen logischer Pegel unbekannt ist (x), siehe Bild 4.11.
4.4 Zusammenfassung
87
pull1 pullx
pull0 Abb. 4.11 Signalkonflikt bei gleichen Stärken und verschiedenen Pegeln
4.4
Zusammenfassung
In diesem Kapitel wurde die Modellierung von Grundkomponenten für die Logiksimulation von Systemen mit Netzlisten behandelt. Solche Grundmodelle finden sich in den VerilogBibliotheken von Standardzell-Technologien oder CPLD-Familien. Mit Verilog werden Netzlisten aus solchen Bibliothekselementen nach der Synthese und am Ende des DesignProzesses simuliert. Ziel ist dabei die Überprüfung der Syntheseergebnisse bzw. die abschließenden Verifikation des physikalischen Entwurfs im Rahmen der Post-Layout- bzw. Post-Place-Route-Simulationen. Das Verhalten der Bibliothekselemente, die nicht von den Verilog-Primitiven abgedeckt sind, wird mit Wahrheitstabellen in einer bestimmten Syntax modelliert (UDPs: user defined primitives). Nach der Erfassung der logischen Funktionalität, die in den Tabellen mit einer Vielzahl von Kürzeln für Zustandswechsel oder Zustandsgruppen effizient dargestellt werden kann, erfolgt die Anbindung an die verwendete Technologie über die Vorgabe von Signalstärken und Laufzeiten bei der Instanziierung der UDPs in strukturellen, netzlistenartigen Gesamtmodellen. Signalstärken spiegeln die Treiberstärke der Ausgangstransistoren der primitiven Komponenten wieder. Große Transistoren produzieren mehr Ladestrom als kleine und werden deshalb die Signale schwächerer Gatter überschreiben. Verilog kann Gattern und UDPs bis zu acht unterschiedliche Treiberstärken zuordnen und es gibt Regeln, wie Signalkonflikte sinnvoll aufgelöst werden können. Für Laufzeiten sind ebenfalls detaillierte und spezifische Vorgaben möglich. Verilog kennt Ausgangs- und Pfadverzögerungen. Bei den Ausgangssignalverzögerungen wird zwischen Anstiegs-, Abfall- und Abschaltverzögerungen unterschieden, wobei jede Verzögerungsart wieder in typische, minimale und maximale Laufzeiten untergliedert werden kann. Zusätzlich lassen sich Signalpfade von Eingangsports zu Ausgängen individuell oder global für eine Komponente mit Pfadverzögerungszeiten beaufschlagen. Solche Verzögerungen können auch zwischen Signalflanken und Ausgangssignalwechseln von flankensensitiven Pfaden vorgegeben werden.
88
4 Modelle für Grundkomponenten
Verilog erlaubt bei dieser hardwarenahen Modellierung nur das träge Inertialdelay, das Signalwechsel an Eingängen mit einer Periode kürzer als die definierte Signalverzögerungszeit ausblendet. Damit bleiben kurzzeitige Signalwechsel (glitches) während des Einschwingverhaltens von treibenden Gattern an den Eingängen der betrachteten Komponente wirkungslos, was bei realen Schaltungen nicht immer der Fall ist und deshalb eine optimistische Modellannahme darstellt. Das andere Extrem, das Transportdelay, bei dem sich jeder Signalwechsel am Eingang auch im Ausgangsverhalten widerspiegelt, übersteigert die die Wirkung der glitches, ist deshalb auf Gatterebene unrealistischer und in Verilog nur bei Verhaltensmodellen zulässig. Je näher man dem physikalischen Entwurf kommt, desto stärker verschieben sich die spezifizierten Laufzeiten aufgrund der Leitungsbeiträge. Deshalb ist es sehr hilfreich, dass Verilog mit timing checks die Verifikation dahingehend unterstützt, dass Pulsbreiten, Taktperioden, Setup- und Haltezeiten usw. während der Simulation abgeprüft und die Einhaltung der Vorgaben protokolliert wird.
4.5
Übungsaufgaben
4.5.1
Wahr oder Falsch
1. Man kann innerhalb von UDPs Laufzeitinformationen vorgeben. (wahr/falsch) 2. UDPs können innerhalb eines Modells mit definiert werden. (wahr/falsch) 3. In einem sequentiellen UDP kann sowohl pegel- wie auch gleichzeitig flankensensitives Verhalten nachgebildet werden. (wahr/falsch) 4. In der UDP-Tabelle dürfen inout-Variablen auftreten (wahr/falsch) 5. In der UDP-Tabelle müssen alle Eingangssignalkombinationen abgedeckt werden. (wahr/falsch) 6. Die Hauptaufgabe von specify-Blöcken besteht in der Festlegung von Signalpfaden zwischen Ein- und Ausgängen des betrachteten Moduls. (wahr/falsch) 7. Die voreingestellte Laufzeit von Signalen durch ein primitives Verilog-Element ist 0. (wahr/falsch) 8. Verilog-Primitive verwenden das Trägheitsdelay (inertial delay). (wahr/falsch) 9. Verilog verfügt über Konstrukte, mit denen sich unterschiedliche Hardwaretechnologien nachbilden lassen, wie CMOS, ECL, TTL etc. (wahr/falsch) 10. specify-Blöcke stehen stets außerhalb der Modul-Definition. (wahr/falsch)
4.5.2
Fragen
1. Welche Porttypen dürfen unter welchen Bedingungen für UDPs verwendet werden? 2. Beschreiben Sie, was unter einer kombinatorischen, einer pegelgesteuerten und einer flankengetriggerten UDP-Komponnete zu verstehen ist, und geben Sie jeweils ein Beispiel an!
4.5 Übungsaufgaben
89
3. Beschreiben Sie einen Halbaddierer mit Hilfe von zwei UDPs für den Summen- bzw. den Übertragspfad. 4. Erstellen Sie ein Modell für zweifaches AND-Gatter (Ausgang y, Eingänge m und n) unter Verwendung des primitiven AND-Gatters, welches die Laufzeiten aus dem folgenden Datenblatt nachbildet: Low to High min :6 typ :7 max : 8 High to Low min :5 typ :6 max : 8 To high impedance min :8 typ :9 max :11 5. Finden Sie alle Fehler in folgendem Modell module what_is_wrong(out_c,in_a,in_b); output out_c; input ina,in_b; not #(2:2:3,2:3:3,2:4:5) (in_a, in_b, y_out); endmodule 6. Welcher Simulationszeit entspricht das Statement #6, wenn die Zeitskala auf 10ns / 1 ps festgesetzt wurde? 7. Lesen Sie den folgenden Verilog-Code und beantworten Sie folgende Fragen: (a,b,c *> y1,y2) = (3:4:6, 7:9:10); a. Wie groß ist das max rising delay von a nach y2? b. Wie groß ist das typische falling delay von c nach y1? c. Wie viele Signalpfade beschreibt die obige Verilog-Zeile? 8. Geben Sie alle Signalstärken an, die in Verilog zur Verfügung stehen! 9. Wodurch unterscheiden sich das Inertial- und das Transport-Delay?
4.5.3
Welche Antwort ist richtig?
1. Welcher Typ gehört nicht zu den Verilog-Netzen (net)? a. tri1 b. wire c. supply1 d. wor 2. Wie viele Signalpfade beschreibt der folgende Verilog-Code? wire [0:1] m, n; wire [0:1] p, q ; (m, n *>p, q) = 2; a. 4 b. 8 c. 12 d. 16
90
4 Modelle für Grundkomponenten
3. Welche der folgenden Signalstärken treibt am stärksten? a. strong0 b. pull1 c. highz1 d. large1 4. Welches Ausgangssignal wird angenommen? La0 Output ? We0
a.
We0
b.
La0
c.
Wex
d.
HiZ
10. Der __________Timing Check sucht Verletzungen der Setup-Zeit. a. $setup b.
$hold
c.
$setuphold
d.
$period
4.6
Antworten
4.6.1
Wahr oder falsch
1. Man kann innerhalb von UDPs pfadabhängige Laufzeitinformationen mit specifyBlöcken vorgeben. (wahr/falsch) 2. UDPs können innerhalb eines Moduls neu definiert werden. (wahr/falsch) 3. In einem sequentiellen UDP kann sowohl pegel- wie auch gleichzeitig flankensensitives Verhalten nachgebildet werden. (wahr/falsch) 4. In der UDP-Tabelle dürfen inout-Variablen auftreten (wahr/falsch) 5. In der UDP-Tabelle müssen alle Eingangssignalkombinationen abgedeckt werden. (wahr/falsch) 6. Die Hauptaufgabe von specify-Blöcken besteht in der Festlegung von Signalpfaden zwischen Ein- und Ausgängen des betrachteten Moduls. (wahr/falsch) Die wichtigste Aufgabe dieser Blöcke besteht in der Festlegung von Laufzeiten!
4.6 Antworten
91
7. Die voreingestellte Laufzeit von Signalen durch ein primitives Verilog-Element ist 0. (wahr/falsch) 8. Verilog-Primitive verwenden das Trägheitsdelay (inertial delay). (wahr/falsch) 9. Verilog verfügt über Konstrukte, mit denen sich unterschiedliche Hardwaretechnologien nachbilden lassen, wie CMOS, ECL, TTL etc. (wahr/falsch) 10. specify-Blöcke stehen stets außerhalb der Module Definition. (wahr/falsch)
4.6.2
Fragen
1. UDPs dürfen nur einen einzigen Ausgangsport besitzen und müssen mindestens einen und dürfen maximal zehn Eingangsports aufweisen. Bidirektionale Ports (inout) sind nicht erlaubt. 2. Kombinatorische UDPs beschreiben das Verhalten von kombinatorischen logischen Schaltungen. Ein Beispiel ist ein Multiplexer, der zwei Eingänge wahlweise auf einen Ausgang schaltet: primitive mux(mux_out,select,a,b); output mux_out; input select, a, b; table // select a b : mux_out 0 0 ? : 0 0 1 ? : 1 1 ? 0 : 0 1 ? 1 : 1 ? 0 0 : 0 ? 1 1 : 1 endtable endprimitive Pegelgesteuerte UDPs modellieren Schaltungen mit Aktivierungssignalen (enable). Das typische Beispiel ist hier das Register mit enable (Latch): primitive latch (q_out, enable, data); input enable, data; output q_out; reg q_out; table // enable 1 1 0 endtable endprimitive
data 1 0 ?
: state : q_out/n_state : ? : 1; : ? : 0; : ? : -;
92
4 Modelle für Grundkomponenten Ändern sich die Zustände der zu modellierenden Einheit synchron mit den Flanken eines Eingangssignals, dann haben wir es mit flankengetriggertem Verhalten zu tun. Ein Beispiel ist das D-Flip-Flop: primitive d_ff(q_out,clk,data); input clk, data; output q_out; reg q_out; table // clk data (01) 0 (01) 1 (0?) 1 (?0) ? ? (??) endtable endprimitive
3.
: : : : : :
state ? ? 1 ? ?
: : : : : :
q_out/n_state 0 1 1 -
Ein Halbaddierer aus den beiden UDPs s und c hat folgenden Aufbau: // Top Level module half_adder(inA,inB,sum,carry); input inA,inB; output sum,carry; s(sum,inA,inB); c(carry,inA,inB); endmodule // Summenbildung primitive s(sum,a,b); input a,b; output sum; table // a b : sum 1 0 : 1; 1 1 : 0; 0 1 : 1; 0 0 : 0; endtable endprimitive // Übertragsberechnung
4.6 Antworten
93
primitive c(carry,a,b); input a,b; output carry; table // a b : sum 1 1 : 1; 1 0 : 0; 0 b : 0; endtable endprimitive 4.
Das AND-Gatter mit den angegebenen Laufzeiten kann mit folgender Verilog-Anweisung implementiert werden: and #(5:6:8, 6:7:8, 8:9:11)
5.
(y,m,n);
Das Modell hat folgende Fehler: Der Name des Eingangsports in_a wird einmal falsch geschrieben (ina) und der erste Port in der Portliste der instanziierten Primitiven Komponente ist der Ausgangsport: input in_a, in_b not #(2:2:3,2:3:3,2:4:5) (out_c, in_a, in_b);
6.
Das Delay beträgt 60 ns.
7.
Im folgenden Beispiel (a,b,c *> y1,y2) = (3:4:6, 7:9:10); beträgt das max rising delay von a nach y2 sechs Zeiteinheiten, ist das typische falling delay von c nach y1 neun Zeiteinheiten und es existieren sechs Signalpfade.
8.
Die Signalstärken von Verilog sind: supply0 strong0 pull0 large0 weak0 medium0 small0 highz0
9.
supply1 strong1 pull1 large1 weak1 medium1 small1 highz1
Das träge oder Inertial-Delay beschreibt wie das Transport-Delay (nicht träges Delay) Signalverzögerungen von Eingängen zu Ausgängen. Der Unterschied der beiden Formen drückt sich in der Behandlung von Störimpulsen aus. Störimpulse (spikes, glitches) tre-
94
4 Modelle für Grundkomponenten ten als Folge von Laufzeitunterschieden in Schaltungen auf. Treffen nicht alle Eingangssignale zeitgleich an den Eingängen eines Moduls ein, dann kann kurzeitig ein ungewolltes Schalten des Ausgangs zustande kommen. Der fehlerhafte Zustand wird aber, nachdem alle gültigen Signalwerte an den Eingängen anliegen, wieder zurückgenommen. Dieser transiente Fehlzustand erreicht das nächste Gatter und kann hier ebenfalls einen kurzeitigen falschen Ausgangswert provozieren, der sich dann wieder fortpflanzen kann und so weiter. Ob ein kurzer Eingangspuls tatsächlich am Ausgang einer Komponente sichtbar wird, hängt davon ab, ob die getriebenen Instanzen solche Spikes aufgrund ihrer Eingangskapazitäten absorbieren oder nicht. Jede elektronische Schaltung benötigt eine gewisse Zeit (Haltezeit), um einen Zustand am Eingang zu übernehmen. Verändert sich der Signalwert am Eingang während dieser Trägheitsphase, hat der kurzzeitig anliegende Zustand keine Auswirkungen auf den Ausgang. Beim trägen Delay wird die Haltezeit mit der Signalverzögerung vom Eingang zum Ausgang gleich gesetzt. Im Rahmen dieser Näherung propagieren alle Signalwechsel am Eingang nicht zum Ausgang, die kürzer als das vorgegebene Delay sind. Spikes werden also vollständig unterdrückt. Beim nicht trägen Transport-Delay wird die Haltezeit auf 0 gesetzt, also wird jeder auch noch so kurze Signalwechsel an einem Eingang auch am Ausgang sichtbar.
4.6.3
Folgende Antwort ist richtig
1. supply1 ist eine Signalstärke und gehört folglich nicht zu den Verilog-Netzen (Antwort c) 2. Es werden vier Pfade definiert (Antwort a) 3. strong0 treibt am stärksten. (Antwort a) 4. La0 ist der Ausgangszustand. (Antwort b) 5. Mit $setup finden wir die gesuchte Zeitverletzung. (Antwort a)
5
Struktur, Hierarchie, Laufzeiten
Mit HDLs lassen sich mikroelektronische Systeme aus verschiedenen Blickwinkeln beschreiben. Nach Gasky und Kuhn [GAK] gibt es drei Sichtweisen: • die in diesem Kapitel im Vordergrund stehende strukturelle Sicht, die elektronische Systeme als Netzwerke aus verbundene Komponenten auffasst, • die Verhaltenssicht, die sich nur für die Funktion des Systems interessiert und • die geometrische Sicht, in der das Design über grafische Daten, z.B. das Chiplayout, dargestellt wird. Da der Entwurf elektronischer Systeme trotz HDLs und Logiksynthese eine immer komplexer werdende Aufgabe darstellt, werden Hierarchien zur Verbesserung der Übersichtlichkeit eingeführt. Die verschiedenen Hierarchieebenen gliedern den Entwurf vertikal, genau wie die drei Sichtweisen das Design horizontal strukturieren. Hierarchien in Designs lassen sich mit einem Schaltplanentwurf (schematic design) veranschaulichen. Hier werden Schaltplänen aus Bibliothekselementen Symbole mit Ports zugeordnet, die den Ein- und Ausgängen des zugrunde liegenden Schaltplans entsprechen. Diese Symbole können dann wieder in neue Schaltpläne instanziiert werden, aus denen wieder neue Symbole generiert werden usw. Bild 5.1 zeigt dieses Vorgehen schematisch am Beispiel eines 4-Bit-Registers.
Abb. 5.1 Schaltplandarstellung und Komponenten-Symbol eines 4-Bit Registers aus 4 D-FFs.
96
5 Struktur, Hierarchie, Laufzeiten
In analoger Weise lassen sich Hierarchien in Verilog-Modellen einführen, indem Module, Verilog-Primitive oder UDPs in andere Module eingesetzt werden.
5.1
Module als Instanzen
Module auf einer niedrigeren Hierarchieebene können Instanzen in Modulen auf höheren Hierarchieebenen sein. Das Modul entspricht dabei dem Schaltplan und das instanziierte Verilog-Modul repräsentiert die auf höherer Ebene eingesetzte Instanz des grafischen Symbols des Schaltplans. Da ein Modul mehrfach in einer Netzliste auf gleicher oder in verschiedener Hierarchiestufe eingesetzt sein kann, muss jede Instanz eines Moduls über einen eigenen Namen individuell ansprechbar sein. Bei primitiven Komponenten ist es dem Anwender freigestellt, die Instanzen gesondert zu bezeichnen.
5.1.1
Hierarchische Namensgebung
In einem großen Design trägt jede Instanz und jede Leitung einen eigenen hierarchischen Namen, damit sich einzelne Objekte im Gesamtdesign identifizieren lassen. Das folgende Diagramm zeigt als Beispiel einen 8-Bit-Addierer, die sich aus zwei Instanzen eines 4-BitAddierer-Moduls zusammensetzen, welche wiederum aus je vier Volladdierern bestehen.
Abb. 5.2 Modellhierarchie eines 8-Bit-Addierers, der aus zwei 4-Bit-Addierern besteht, die aus jeweils vier Instanzen eines Volladdierermoduls (1 bit adder) bestehen.
Verilog verwendet eine Punktnotation, um jeder Instanz bzw. jedem Signal im Design einen eindeutigen Namen zuzuweisen. Alle Module, Register (reg) und Verbindungen (wire) sind
5.1 Module als Instanzen
97
im Modul über die hierarchische Reihenfolge der Modulnamen zugänglich. Die folgenden beiden Beispiele zeigen, wie man die Leitung w1 im untersten Volladdierer des linken bzw. rechten 4-Bit-Addierers anspricht. ins4b0.ins1b3.w1 ins4b1.ins1b3.w1 Die Anschlussbelegung bei Instanzen kann wie auch in VHDL implizit oder explizit vereinbart werden. Bei der impliziten Belegung werden die Signale der höheren Hierarchiestufe gemäß der Reihenfolge der Ports des jeweiligen Modul-Modells zugeordnet. Soll ein Port des Moduls beim Einsetzen nicht angeschlossen werden, dann macht man das durch zwei Kommas ohne Signalnamen dazwischen kenntlich. Als Alternative können auch die relevanten Signale in expliziter Form bestimmten Ports zugewiesen werden: (.port_name_1(signal_name_1), port_name_2(signal_name_2)). Nicht angeschlossene Ports tauchen dann in der Anschlussliste entweder gar nicht auf oder der Port wird aufgeführt, aber keinem Signal zugeordnet (.port_name). Das folgende Modell zeigt die beiden Versionen. Hier wird das DFF-Modul als Basiskomponente aus Abschnitt 4.2.5 viermal instanziiert. // 4-Bit-Register aus D-Flip-Flops mit Reset `timescale 1ns / 100ps // Zeitskala 1 ns, eine Dezimalstelle module register (r, clk, d, ld, rst); output [3:0] r; // gespeicherte Signale input [3:0] d; // Eingangsdaten input clk, ld, rst; // Steuersignale wire [3:0] d, r; // interne Verbindungsleitungen pullup (nc); // Pull-Up-Widerstand dff In1 (.clk(ld), .rst(rst), .pre(nc), .q(r[0]), .d(d[0])); // explizite Liste: qb Eingang des DFF fehlt dff In2 (r[1], , load, d[1], rst, nc); // implizite Liste: qb Eingang des DFF fehlt: , ,! dff In3 (.clk(ld), .rst(rst), .pre(nc), .q(r[2]), .d(d[2]), .qb()); // explizite Liste: qb Eingang des DFF ist explizit // nicht angeschlossen! dff In4 (r[3], , load, d[3], rst, nc); // implizite Liste endmodule
98
5.1.2
5 Struktur, Hierarchie, Laufzeiten
Generische Parameter
Das Beispiel zeigt, dass in Verilog die Signalverzögerungen nicht bei der Instanziierung definiert werden, sondern in den zugrunde liegenden Modulen. Die Sprache VHDL unterstützt sog. GENERICs. Dabei handelt es sich um Konstanten, die bei der Elaboration des Modells vor der Simulation mit ihren aktuellen Werten übergeben werden. In Verilog können ebenfalls flexible Modelle geschrieben werden, die sich unter geänderten Randbedingungen und mit anderen Eigenschaften einsetzen lassen als diejenigen, die bei der Modelldefinition Gültigkeit hatten. Diese Möglichkeit sollte man intensiv nutzen, fördert sie doch die Wiederverwendbarkeit einmal entwickelter Modelle (Design Reuse, [JAN]). In Verilog müssen bei generischen Modellen die Delays, die Datenwortbreiten und Ähnliches in den Modulen mit Verilog-Parametern (Datentyp parameter) und nicht mit festen Werten definiert werden. Diese Parameter sind, wie in Abschnitt 3.1.10 erklärt, eigene Datentypen, die ihren Wert während einer Simulation nicht ändern. Als Parameter können in einem Modul ganze Zahlen (Integers), reelle Zahlen (Real-Größen), min:typ:max-Laufzeiten und ASCII-Zeichenketten abgelegt werden. Im folgenden Beispiel werden für ein BufferModul mit dem Parameter N die Wortbreite und mit dem Parameter delay die Signalverzögerung des Buffers festgelegt. Bei der Parameterdefinition sind auch geeignete Defaultwerte anzugeben, im Beispiel N = 8 und delay = 2:3:4. `timescale 1ns / 100ps // Zeitskala 1 ns, eine Dezimalstellen module NbitBuffer (Y, A); parameter N = 8; // Voreingestellte Bufferbreite 8 output [N-1:0] Y; input [N-1:0] A; wire [N-1:0] Y, A; parameter delay = 2: 3: 4; // Voreingestellte Laufzeit buf #delay i[N-1:0] (Y, A); // Verilog-Primitiver Buffer // mit Instanzennamen i7, i6, …, I0 endmodule Die voreingestellten Werte der Verilog-Parameter können bei jeder Instanziierung eines Moduls überschrieben werden. Die Neudefinition wird während der Kompilierung durchgeführt. Nachdem die aktuellen Werte zugeordnet sind, bleiben diese konstant (run time constants). Die Zuweisung von aktuellen Parametern erfolgt mit der defparam-Anweisung. In dieser Anweisung wird der hierarchische Name des zu ändernden Parameters verwendet, bei dem über eine Punktnotation die einzelnen Hierarchiestufen angegeben werden, die für den Bezeichner relevant sind. `timescale 1ns / 100ps // Zeitskala 1 ns, eine Dezimalstellen module gener (………); …….. NbitBuffer In1 (out1, in1); // Voreinstellung N = 8, delay = 2:3.4
5.2 Rücklesen von Laufzeiten und SDF-Format
99
NbitBuffer In2 (out2, in2); defparam In2.delay = 5; // Delay wird überschrieben: delay ≡ 5 defparam In2.N = 16; // Wortbreite N ≡ 16 NbitBuffer In3 (out3, in3); defparam In3.N = 4; // Wortbreite N ≡ 16, delay bleibt auf 2:3:4 Die Moduleinsetzung und die Parameterfestlegung lassen sich auch in einer Anweisung kompakter zusammenfassen. Dies wird dann als implizite Parameterfestlegung bezeichnet. Die gültigen Parameterwerte können nach dem #-Symbol, das außerhalb einer Modul-Instanziierung stets Laufzeiten kennzeichnet, der Reihenfolge nach eingegeben werden. Bei dieser impliziten Methode können keine Parameter ausgelassen, also auf den Defaultwerten belassen werden. Soll ein Parameter geändert werden, dann müssen alle im Modul vorher definierten Parameter in der Liste nach dem # erscheinen, und sei es mit ihren voreingestellten Werten. Die expliziten Parameterzuweisungen des vorherigen Beispiels haben in impliziter Form folgende Gestalt: NbitBuffer In1 (out1, in1); // Voreinstellung N = 8, delay = 2:3.4 NbitBuffer #(16,5) In2 (out2, in2); // und Delay als zweiter Parameter auf delay ≡ 5 // gesetzt NbitBuffer #(4) In3 (out3, in3); // N als erster Parameter wird auf 4 gesetzt
5.2
Rücklesen von Laufzeiten und SDF-Format
Bei der Logiksynthese eines Verilog-Designs erzeugt das Synthesetool aus einer Beschreibung auf Verhaltensebene (siehe Kapitel 6) eine Verilog-Netzliste aus Bibliothekselementen (Gatter, Flip-Flops etc.) der verwendeten Zieltechnologie (ASIC-Prozess oder CPLDFamilie). Die Ausgänge der einzelnen Gatter sind dabei unterschiedlich belastet, je nachdem wie viele Eingänge von Folgegattern angeschlossen sind (fan out) und wie lang die Leitungen zu diesen Kapazitäten ausfallen. Das Synthesetool optimiert die Schaltung so lange, bis alle Zeitvorgaben aus der Spezifikation erfüllt sind. Je nach der erwarteten Chipgröße, die das Synthesewerkzeug aus der Zahl der verwendeten Gatter abschätzt, werden Delay-Werte für die Verbindungen errechnet. Auch die Auffächerung der Ausgangsleitungen der einzelnen Komponenten im Design ist vor der Synthese unbekannt und kann deshalb bei der Verilog-Simulation des Verhaltensmodells noch nicht berücksichtigt werden. Die Eingangslastdelays und die Leitungsverzögerungen gehen wesentlich in die Optimierung der Gatternetzliste während des Syntheseprozesses ein. Das
100
5 Struktur, Hierarchie, Laufzeiten
Synthesewerkzeug ermittelt aber die Laufzeiten im System nicht mit einer ereignisgesteuerten Logiksimulation von Verilog-Modellen, sondern benutzt ein vereinfachtes Verfahren, die statische Timinganalyse [JAN, KEB]. Deshalb kann es sein, dass das Synthesewerkzeug eine Schaltung liefert, die in statischer Analyse die zeitlichen Randbedingungen der Spezifikation erfüllt, ohne dass dies bei der genaueren Logiksimulation noch der Fall sein muss. Um zu testen, ob das Syntheseergebnis die vorgegebenen Spezifikationen (Verhalten und Dynamik) erfüllt, wird deshalb die Post-Synthesis-Simulation durchgeführt. Dazu wird die synthetisierte Verilog-Netzliste dynamisch simuliert, wobei die eingerechneten Netzlaufzeiten wie auch die fan-out-Verzögerungen als Delay File mit einbezogen werden. Bei der Verwendung von Submikrometer-Zieltechnologien hängen die Laufzeiten zwischen den Komponenten sehr stark von den Signalverzögerungen auf den Verbindungsleitungen ab. Deshalb genügt es für eine endgültige Verifizierung nicht, nur die bei der Logiksynthese abgeschätzten Leitungslängen zu berücksichtigen. Die exakten Leitungslängen und -verläufe liegen erst nach dem Platzieren und Verdrahten im physikalischen Design am Ende des Entwurfszyklus fest. Deshalb ist es sehr wichtig, dass das Design nach Platzieren und Verdrahten unter Berücksichtigung der dann genau bekannten Leitungseffekte nochmals mit Verilog nachsimuliert wird, um das Designrisiko zu minimieren (Post Layout Simulation).
Abb. 5.3 SDF-Einträge können Delay-Parameter und Prüfbedingungen in Verilog-Modellen ändern oder neue Parameter bzw. Bedingungen einsetzen
Das Problem bei diesen Nachsimulationen liegt in der Einbindung der umfangreichen Laufzeitinformation (Delay-Files) in die Verilog-Netzliste aus Bibliothekselementen. Die meisten Verilog-Simulatoren können für die Post-Synthesis- und die Post-Layout-Verifikation DelayFiles einarbeiten, die in dem genormten Standard Delay Format (SDF) geschrieben sind
5.2 Rücklesen von Laufzeiten und SDF-Format
101
(IEEE Std. 1497-1999). SDF-Dateien enthalten Werte, mit denen Leitungsverzögerungen, specparam-Werte für Gatterlaufzeiten und Zeitbedingungen zusätzlich festgelegt oder entsprechende Parameter in der Ausgangsnetzliste überschrieben werden können. Der Prozess der Zuordnung von Delays zu Instanzen und Verbindungen heißt Backannotation (nachträgliche Eintragung). Bei der Backannotierung von Verilog-Modellen werden die Werte aus den SDF-Dateien in die jeweiligen Verilog-Modelle übernommen (Bild 5.3).
5.2.1
Struktur von SDF-Dateien
Bei einer SDF-Datei handelt es sich um geschachtelte Klammerausdrücke mit spezifischen SDF-Schlüsselworten, die im Folgenden mit Großbuchstaben angegeben werden. Auf jedes Schlüsselwort folgen Werte in Form von Text Werte-Tripletts oder weiteren Schlüsselwörtern. Jedes SDF-File beginnt mit einigen Kopfzeilen (Header-Section). Hier werden SDF-Version (SDFVERSION), der Designname (DESIGN), die Zeitauflösung (TIMESCALE), technologische Parameter (VOLTAGE, PROCESS, TEMPERATURE) und verschiedene andere allgemeine Informationen mitgeteilt. An die Header-Section schließen sich die ZellenDeklarationen (CELL) an, die sich auf die einzelnen Zellen des Chip-Layouts oder des platzierten und verdrahteten CPLD-Designs beziehen. In jeder Deklaration wird der Zellentyp (z.B. NAND2, INV, TRIBUF aus der zugrunde liegenden Bibliothek aufgeführt (CELLTYPE), danach die Instanzenkennung (z.B. INSTANCE NAND2_23). Dann folgen die Timingparameter nach dem Schlüsselwort DELAY, die neuen zeitlichen Bedingungen (TIMINGCHECK) und nach dem Schlüsselwort LABEL neue Werte für specparams.
5.2.2
SDF-Annotierungen bestehender Verilog-Konstrukte
Es gibt verschiedene SDF-Konstrukte, die DELAY genauer spezifizieren [LRM]. So gibt z.B. IOPATH ein Delay vor, das eine entsprechende Laufzeitvorschrift im entsprechenden Specify-Block ersetzt. Alle Beispiele im Folgenden stammen aus der Norm und sollen die Möglichkeiten des SDF-Formats illustrieren. Steht im SDF-File: (IOPATH sel zout (1.3) (1.7)) und im Verilog-Specify-Block (sel => zout) = 0; dann werden dem Pfad von sel nach zout Anstiegs-/Abfall-Delays von 1.3 bzw. 1.7 Zeiteinheiten zugeordnet. Ein bedingtes IOPATH-Delay (zu erkennen am Schlüsselwort COND) wird nur dem Pfad im Specify-Block zugewiesen, für den die vorgegebene Bedingung gilt.
102
5 Struktur, Hierarchie, Laufzeiten
Ein Eintrag (COND mode (IOPATH sel zout (1.3) (1.7))) im SDF-File, der sich den specify-Pfaden if (!mode) (sel => zout) = 0; if (mode) (sel => zout) = 0; zuordnen lässt, wird nur für die zweite Anweisung wirksam, in der die Bedingung mode in nicht invertierter Form auftritt. Die erste Anweisung wird nicht annotiert. Nicht nur Laufzeiten, sondern auch Zeitbedingungen lassen sich über SDF-Dateien aktualisieren. Nach dem Schlüsselwort TIMINGCHECK folgen die Zuweisungen von Setup- und Holdzeiten (SETUP, HOLD), Pulsbreiten (WIDTH), Flankenverschiebungen (SKEW) etc., für die sich Entsprechungen in den Verilog-Modellen der Zellen finden müssen. Mit diesem Eintrag im SDF File: (SETUPHOLD data clk (3) (4)) werden die folgenden Verilog-Timing-Checks in Bezug auf die Setup- und Holdzeit (von 1 nach 3, bzw. 1 nach 4) abgeändert: $setuphold (posedge clk&&& mode, data, 1, 1, ntfr); $setuphold (negedge clk&&&!mode, data, 1, 1, ntfr); Die SDF-Anweisung (SETUPHOLD data (posedge clk) (3) (4)) wirkt sich nur auf die erste Verilog-Timing-Prüfung aus, auf die zweite wegen der dort verwendeten fallenden Flanke (negedge) nicht: $setuphold (posedge clk&&& mode, data, 1, 1, ntfr); $setuphold (negedge clk&&&!mode, data, 1, 1, ntfr); Im folgenden Beispiel (SETUPHOLD data (COND !mode (posedge clk)) (3) (4)) wird keine der beiden Verilog-Prüfung annotiert, weil hier mode statt !mode und negedge statt posedge auftreten. $setuphold (posedge clk&&& mode, data, 1, 1, ntfr); $setuphold (negedge clk&&&!mode, data, 1, 1, ntfr); Mit dem Label-Schlüsselwort können Verilog-Modell-Parameter (specparams) überschrieben werden. Das folgende Beispiel zeigt dies für ein Taktgenerierungs-Modul, in dessen
5.2 Rücklesen von Laufzeiten und SDF-Format
103
Verilog-Code die High- und Low-Zeiten des Taktsignals über die specparams dlow und dhigh definiert sind. module clock(clk); output clk; reg clk; specparam dhigh=0, dlow=0; initial clk = 0; always begin #dhigh clk = 1; #dlow clk = 0; end endmodule Im SDF-File finden sich die folgenden Einträge: (LABEL (ABSOLUTE (dhigh 60) (dlow 40))) Nach der Annotierung beträgt die Zeit, die das clk-Signal im Low-Zustand (Zustand „0“) bleibt, bevor es in den High-Zustand („1“) wechselt, 60 Zeiteinheiten. Der Taktwechsel nach Low wird um 40 Einheiten verzögert. Somit beträgt die Taktperiode 100 Zeitschritte. SDF Interconnect Delays Diese Laufzeiten in SDF-Dateien unterscheiden sich von den bisher besprochenen Konstrukten dadurch, dass diese nicht mit Verilog-Modell-Anweisungen im ursprünglichen Gatteroder Verhaltensmodell zusammenhängen. Physikalisch entsprechen INTERCONNECTDelays den Leitungslaufzeiten zwischen den Pins der Komponenten in der Schaltung. Im zugrunde liegenden Verilog-Design stellen die INTERCONNECT-Delays Laufzeiten zwischen dem Ausgangsport eines Moduls und den Eingangsports eines anderen Moduls bzw. zwischen zwei bidirektionalen Ports verschiedener Instanzen in der Netzliste dar. Neben dem INTERCONNECT-Delay können auch PORT-Delays (module input port delays, MIPD) und NET-Delays in SDF-Files auftreten. Mit INTERCONNECT-Laufzeiten werden individuelle Verbindungsleitungen zwischen zwei oder mehreren Ports nachgebildet, d. h. eine Verbindung zwischen einem treibenden Port und einem getriebenen Port wird mit einer Verzögerungszeit belegt. PORT-Delays hingegen werden einzelnen Ports zugewiesen und gehen somit in die Laufzeit aller Netze ein, die an den annotierten Port angeschlossen sind. Anders ausgedrückt, ein PORT-Delay hält jedes Signal, das an den annotierten Port gelangt, um die definierte Verzögerungszeit auf. Bei NET-Delays wird unterschieden, ob die Laufzeit einem Port oder einem Netz (net) zuge-
104
5 Struktur, Hierarchie, Laufzeiten
ordnet werden kann. Bei einem Port wird wie beim PORT-Delay verfahren, bei einem Netz wird das Delay allen Ports, die an diesem Netz angeschlossen sind, zugewiesen. Ein Beispiel: (INTERCONNECT i14/u5/out i53/selmode (1.43) (2.17)) Hier wird dem Netz zwischen dem treibenden Pin out der Instanz u5 im eingesetzten Modul i14 und allen Eingangsports in der selmode-Instanz I53 ein Delay zugewiesen. Bei steigenden bzw. fallenden Signalwechseln beträgt die Verzögerung 1,43 bzw. 2,17 Zeiteinheiten. Die hierarchischen Namen im SDF-Format werden anders als bei Verilog-Netzlisten mit Schrägstrichen „/“ statt mit Punkten gegliedert. Mehrfachannotierungen Die SDF-Verarbeitung erfolgt geordnet. Die einzelnen im SDF-File definierten Zuweisungen von Laufzeiten zu einem Design-Objekt werden gemäß ihrer Reihenfolge verarbeitet. Dabei können vorhandene Annotierungen additiv oder subtraktiv verändert (INCREMENT) oder überschrieben werden (ABSOLUTE). Das folgende Beispiel zeigt dies anhand eines IOPATH-Delays: (DELAY (ABSOLUTE (PATHPULSE A Z (2.1) (3.4)) (IOPATH A Z (3.5) (6.1)) Hier wird dem Pfad von A nach Z eine Pulsbreite zugewiesen und dann der gesamte Pfad mit einer Laufzeit für steigende oder fallende Events von 3,5 bzw. 6,1 versehen. Diese Zuweisungen überschreiben aber die gerade vorher zugewiesenen Pulsbreiten. Dies passiert nicht, wenn im zweiten SDF-Statement leere Klammern eingefügt werden, die die aktuellen Pulsweiten übernehmen: DELAY (ABSOLUTE (PATHPULSE A Z (2.1) (3.4)) (IOPATH A Z ((3.5) () ()) ((6.1) () ()) ) Die beiden Zuweisungen wirken sich genauso aus wie die folgenden Annotierungen: (DELAY (ABSOLUTE (IOPATH A Z ((3.5) (2.1) (3.4)) ((6.1) (2.1) (3.4)) )
5.3 Zusammenfassung
5.3
105
Zusammenfassung
In diesem Kapitel wurden hierarchische Strukturmodelle besprochen und gezeigt, wie Laufzeitinformationen, die sich im Verlauf des Designprozesses ergeben, in den Verifikationsprozess einbezogen werden können. Strukturmodelle können aus instanziierten Modulen, Verilog-Primitiven oder UDPs aufgebaut werden. Charakteristisch für eine Schaltungshierarchie ist Reduktion des Detaillierungsgrads mit aufsteigender Hierarchiestufe. Um einzelne Komponenten oder Leitungen in einem hierarchischen Verilog-Modell zu identifizieren, wird eine Punktnotation verwendet, bei der die einzelnen Hierarchiestufen durch Punkte getrennt werden. Damit Verilog-Designs später leichter wieder verwendet werden können, sollten die Module weitgehend mit Hilfe von generischen Parametern (Wortbreiten, Laufzeiten etc.) entworfen werden. Dazu werden die Konstanten in Modellen nicht direkt und unveränderlich definiert, sondern mit param-Anweisungen nur als Konstanten gekennzeichnet. Der dabei zu definierende Vorzugswert (default) kann bei Bedarf mit der defparam-Anweisung bei der Instanziierung überschrieben werden. In der defparam-Anweisung wird bei hierarchischen Modellen der hierarchische Name des zu ändernden Parameters verwendet. Eine zentrale Rolle bei der Verifizierung von Designs spielen parasitäre Laufzeiteffekte, die sich erst zum Ende des Designprozesses hin konkretisieren. Da im Laufe des Designs verschiedene CAD-Tools für die Logiksynthese und das Platzieren und Verdrahten der Bibliothekselemente zum Einsatz kommen, müssen die Laufzeitinformationen wieder in die Verilog-Netzliste zurückgespiegelt werden (Backannotation). Das Einfügen neuer oder das Überschreiben vorhandener Laufzeitparameter wird durch das in Verilog genormte SDF-Format erleichtert. Bei einer SDF-Datei handelt es sich um geschachtelte Klammerausdrücke mit spezifischen SDF-Schlüsselworten (SDF-Schlüsselworte in Großbuchstaben). Das relevante Schlüsselwort für Laufzeiten ist DELAY. Signalverzögerungen auf einzelnen Signalleitungen zwischen zwei Ports werden nach DELAY mit INTERCONNECT gekennzeichnet. PORTDelays hingegen werden einzelnen Ports zugewiesen und ein PORT-Delay hält jedes Signal, das an den annotierten Port gelangt, um die definierte Verzögerungszeit auf. Bei NETDelays wird unterschieden, ob die Laufzeit einem Port oder einem Netz (net) zugeordnet werden kann. Bei einem Port wird wie beim PORT-Delay verfahren, bei einem Netz wird das Delay allen Ports, die an diesem Netz angeschlossen sind, zugewiesen. Vorhandene Delayparameter können mit anderen Schlüsselworten aktualisiert werden, z.B. mit IOPATH kann ein Delay vorgegeben werden, das eine entsprechende Laufzeitvorschrift im entsprechenden Specify-Block ersetzt.
106
5 Struktur, Hierarchie, Laufzeiten
5.4
Übungsaufgaben
5.4.1
Wahr oder Falsch
1. Ports von Verilog-Modulen können unangeschlossen bleiben, ohne dass dies zu einer Fehlermeldung führt. (wahr/falsch) 2. Die explizite Portzuordnung (über Namen) ist weniger fehleranfällig als die implizite Zuordnung über die Reigenfolge. (wahr/falsch) 3. Verilog-Module können wie Verilog-Primitive unter Angabe von Verzögerungszeiten instanziiert werden. (wahr/falsch) 4. SDF-Vorgaben überschreiben die Timing Parameter in einem Verilog-Modell. (wahr/falsch) 5. Die specparam-Werte eines specify-Blocks sind außerhalb des Blocks sichtbar. (wahr/falsch)
5.4.2
Fragen
1. Was verstehen Sie unter dem Begriff Hierarchie im Zusammenhang mit VerilogModellen? 2. Das unten grafisch dargestellte Modul top( ) enthält sehr viele eingesetzte Module. Die einzelnen Modulnamen finden sich hinter den Instanzennamen Ins1, Ins2, … In jedem Modul gibt es einige reg-Variablen, die beschrieben oder gelesen werden sollen.
ins1 b(); Ins2 a(); top(); l,m
n
o,p
Ins3 c();
q,r
s
Ins4 d();
• Geben Sie an, wie man die reg-Variablen im Modul d( ) vom Top-Level aus ansprechen kann! • Geben Sie weiterhin an, wie man der Variablen n im Modul b( ) den Wert von r aus dem Modul c( ) hierarchisch zuweisen kann
5.5 Antworten
107
3. Diskutieren Sie die Vor- und Nachteile von Modellen mit Hierarchie! 4. Gegeben sind die beiden folgenden Modul-Deklarationen. Diese beiden Module sollen in ein neues Toplevel-Modul connect( ); instanziiert werden, und zwar einmal per expliziter und einmal per impliziter Portzuweisung. Die zu instanziierenden Module sind: module con_test1(inB,inA,inC,out1,out2); module con_test2(inF,inE,out5,out4,out3); Die gewünschte Portzuordnung ist die folgende: inB => out4, inA => out3, inC => out5, out1 =>inF, out2 => inE 5. Was verstehen Sie unter dem Begriff SDF?
5.5
Antworten
5.5.1
Wahr oder Falsch
1. Ports von Verilog-Modulen können unangeschlossen bleiben, ohne dass dies zu einer Fehlermeldung führt. (wahr/falsch) 2. Die explizite Portzuordnung (über Namen) ist weniger fehleranfällig als die implizite Zuordnung über die Reigenfolge. (wahr/falsch) 3. Verilog-Module können wie Verilog-Primitive unter Angabe von Verzögerungszeiten instanziiert werden. (wahr/falsch) 4. SDF-Vorgaben überschreiben die Timing Parameter in einem Verilog-Modell. (wahr/falsch) 5. Die specparam-Werte eines specify-Blocks sind außerhalb des Blocks sichtbar. (wahr/falsch)
5.5.2
Folgende Antwort ist richtig
1. Die Hierarchie in einem Modell entsteht, wenn Module in anderen Modulen als Instanz verwendet werden und wenn Module mit Instanzen selbst als Instanz in Module auf höherer Ebene eingesetzt werden. So können aus einfachen Basismodulen durch fortgesetzte Instanziierung komplex gegliederte Modelle generiert werden. Genauso kann man in abstrakten Beschreibungen die Module immer detaillierter ausgestalten, indem man Untermodule einsetzt, die näher an einer strukturellen Implementierung sind. In beiden Fällen entsteht eine Hierarchie im Modell, die von hardwarenaher Modellierung auf den niedrigen Hierarchieebenen zu abstrakteren Beschreibungen auf höheren Hierarchieebenen führt. 2. Die Syntax zum Ansprechen der reg-Variablen im Modul d( ) vom Top-Level aus ist ins2.ins3.ins4.s;
108
5 Struktur, Hierarchie, Laufzeiten Die Anweisung assign n = top.ins2.ins3.r;
weist der Größe n im Modul b( ) den Wert von r aus dem Modul c( ) zu. 3. Die Vorteile des hierarchischen Modellierens liegen in • der einfacheren und schnelleren Verifikation und Simulation des Modells, • der Möglichkeit, das Gesamtdesign auf verschiedene Entwickler aufzuteilen und so die einzelnen Module im Gesamtkonzept unabhängig voneinander bearbeiten zu können, • in der Möglichkeit, einzelne Module im hierarchischen Entwurf aus anderen Designs zu übernehmen und so wieder zu verwenden. Dies steigert die Effizienz der Entwicklungstätigkeit insgesamt. • der besseren Gliederung hierarchischer Entwürfe, die diese leichter lesbar macht. • der effizienten Steuerung des Designablaufs. Als Nachteil kommt in Betracht: • Wenn das Design punktuell geändert wird, dann muss man für alle Instanzen eines veränderten Moduls prüfen, ob die angestrebte Funktionalität im jeweiligen Kontext immer noch gegeben ist. 4. Der Verilog-Code zur Instanziierung der beiden Module con_test1 und con_test2 in das Modul connect liest sich wie folgt: module connect(); …… …… // explizites Port Mapping con_test1 ins1 (.inB(out4),.inA(out3),.inC(out5),.out1(inF),.out2(inE)) ; con_test2 ins2 (.inF(out1),.inE(out2),.out5(inC),.out4(inB),.out3(inA)) ; endmodule module connect(); …… …… // Implizites Port Mapping
5.5 Antworten
109
con_test1
ins1 (out4,out3,out5,inF,inE);
con_test2
ins2 (out1,out2,inC,inB,inA);
endmodule 5. Mit SDF-Dateien können wir Delay-Informationen, die erst beim physikalischen Design des Systems oder nach der Logiksynthese vorliegen, in das ursprüngliche Modell übernehmen (Backannotation) und so eine Post-Layout- oder Post-Synthesis-Simulation vornehmen. SDF-Dateien enthalten Werte, mit denen Pfadverzögerungen, specparamWerte, Zeitbedingungen und Leitungslaufzeiten neu festgelegt werden können. Dabei überschreiben die SDF-Einträge die Timing-Parameter (falls vorhanden)in der ursprünglichen Verilog-Netzliste.
6
Verhaltensbeschreibung
Bisher haben wir Verilog-Modelle behandelt, die sich sehr eng an spätere Hardware-Implementierungen anlehnen. Diese Vorgehensweise erschließt aber nicht den Abstraktionsgrad, der zur Untersuchung von komplexeren Systemeigenschaften nötig ist, noch werden bei der Schaltungseingabe mit Verilog die Systeme so generisch beschrieben, dass Synthesewerkzeuge nennenswerte Optimierungsmöglichkeiten finden. Die strukturelle Modellierung unter Verwendung von primitiven Komponenten ist im Prinzip nichts anderes als der herkömmliche grafische Schaltplanentwurf abgebildet auf die sprachliche Ebene. Was Verilog aber als erste verbreitete Hochsprache beim Elektronikdesign so populär gemacht hat, ist die Fähigkeit der Sprache auch abstraktere Modellierungsarten zu integrieren, insbesondere die Modellbildung auf Verhaltensebene. In der Vor-Verilog-Zeit existierten zwar auch Simulatoren auf digitaler Ebene, die auf Schaltplandesigns aufsetzten, und es waren auch Verhaltenssimulationen auf Hochsprachenebene z.B. mit C üblich, um das Systemverhalten zu analysieren. Die Durchgängigkeit von der abstrakten Verhaltensbeschreibung bis hinunter zur Implementierung mit Bibliotheksprimitiven wurde aber erstmalig von Verilog und den zugehörigen Simulatoren unterstützt. In diesem Kapitel werden wir die prozeduralen Verilog-Konstrukte vorstellen, mit deren Hilfe abstrakte Modelle ohne direkten Bezug zur Implementierung geschrieben werden können. Ohne abstraktere Modelle können komplexe Systeme wie komplette Mikroprozessoren nicht modelliert und untersucht werden.
6.1
Abstraktionsebenen
Beim Elektronikentwurf wird zwischen strukturellen Modellen sowie funktionalen Modellen (Behavioural Models) unterscheiden. Die Verhaltensmodelle lassen sich noch in algorithmische Modelle und Datenflussbeschreibungen unterteilen. Bei den algorithmischen Modellen wird das System als Black Box aufgefasst, die die Eingangssignale in die Ausgangssignale transformiert. Die Datenflussmodelle beschreiben das System über logische Transformationen zwischen Registerstufen (Register-Transfer-Ebene, RTL-Modelle). Bild 6.1 verdeutlicht dies grafisch. Alle Verhaltensmodelle verwenden die gleichen sprachlichen Konstrukte. RTL-Beschreibungen sind Ausgangspunkt für die Logiksynthese und deshalb schon etwas enger an Hardwarestrukturen angelehnt. Algorithmische funktionale Modelle sind abstrakter.
112
6 Verhaltensbeschreibung
Strukturmodell: Funktion und Vernetzung
R
SET
CLR
Q Q
RTL-Modell: Funktion und Registerstruktur at every edge of clock res_register = a + b + carry;
Abstraktionsgrad
S
Verhaltensmodell: nur Funktion if enable is true for (i=0; i trig; #450 -> trig; #300 -> trig; #100 -> ev1; end initial begin // fork join Beispiel repeat (2)
132
6 Verhaltensbeschreibung
fork begin : event_expr @ev1; repeat (3)begin @trig; end #10 a = b + c; end wait (reset) disable event_expr; join end endmodule Die Simulationsergebnisse sehen wir in Bild 6.5:
Abb. 6.5 Simulation des asynchronen Verhaltens des fork-join-Beispiels. Die Symbole bei ev1 und trig markieren die events. Der Reset deaktiviert den event_expr-Block und deshalb behält a den alten Wert „1“.
6.3.4
Continous Assignments in Prozeduren (PCAs)
Bisher haben wir zwei Arten von Zuweisungen kennen gelernt: die prozedurale Zuweisung als Zuweisung wie in einer prozeduralen Computersprache und die kontinuierliche Zuweisung (continuous assignment), die während der gesamten Simulationsdauer aktiv ist und sich wie Signalzuweisungen in kombinatorischen Schaltungen verhält. Prozedurale kontinuierliche Zuweisungen (PCAs) sind eine Mischform aus diesen beiden Typen. Diese neue Form verhält sich wie ein continuous-assignment, mit dem Unterschied, dass prozedurale kontinuierliche Zuweisungen in einer Prozedur aktiviert (mit dem Schlüsselwort assign) und auch wieder deaktiviert werden können (mit dem Schlüsselwort deassign). Weitere Unterschiede zwischen PCAs und continuous-assignments sind: • continuous-assignments werden automatisch ab Simulationszeit „0“ aktiviert, PCAs müssen innerhalb einer Prozedur erreicht und ausgeführt werden und sind erst dann aktiv; • für continuous-assignments existiert kein deassign-Statement, sie bleiben stets aktiv;
6.3 Prozeduralblöcke
133
• bei kontinuierlichen Anweisungen wird auf net-Typen, bei PCAs auf RegisterDatentypen zugewiesen. Wird einer Variablen mit einem PCA per assign ein Wert zugewiesen, dann behält sie diesen dauerhaft, genauer, bis die Variable mit deassign wieder freigegeben und über eine prozedurale Zuweisung geändert wird oder mit einer weiteren assign-Anweisung einen anderen Wert erhält. Das assign-Statement überschreibt also alle Zuweisungen innerhalb des prozeduralen Blocks. Mit PCAs können wir das pegelgesteuerte Verhalten von speichernden Elementen (Latches), kombinatorischer Logik oder die asynchrone Steuerung von sequentiellen Logikblöcken modellieren. Unser Beispiel ist eine D-Flip-Flop mit preset- und clear-Eingängen. module dff (q, d, clear, preset, clock); output q; input d, clear, preset, clock; reg q; always @(clear or preset) if (!clear) assign q = 0; else if (!preset) assign q = 1; else deassign q; always @(posedge clock) q = d; endmodule Wird das Flip-Flop asynchron gesetzt (preset = 0) oder rückgesetzt (= 0), wird der Ausgang q vom assign-Statement fest auf dem entsprechenden Pegel „0“ oder „1“ gehalten. Positive Taktflanken (posedge clock) können keine Zuweisung des Eingangszustandes d auf den Ausgang bewirken. Das Flip-Flop kann erst dann das Datum d taktsynchron speichern, wenn sowohl das preset- als auch clear-Signal beide nicht mehr aktiv sind. Dieser Zustand wird mit der elseVerzweigung abgefragt: Sobald preset und clear gesetzt sind, wird q freigegeben (deassign) und kann bei der nächsten positiven Taktflanke den Zustand von d übernehmen. Neben assign und deassign bietet Verilog noch eine auf Netze und Register erweiterte Form von PCAs, die force- und die release-Anweisung. Mit diesen Anweisungen können sogar assign- und deassign -Anweisungen überschrieben werden.
6.3.5
Anfangswertzuweisung für Variablen
Verilog initialisiert wire- und reg-Datentypen per Voreinstellung mit dem Wert x. Variablen vom Typ integer oder time werden anfänglich auf 0 gesetzt, realtime- und real-Größen auf 0.0. In der alten Norm von 1995 konnten diese Defaults nur mit Zuweisungen in initialSchleifen überschrieben werden. In Verilog 2001 hingegen kann für Größen der Typen reg, integer, time, real und realtime wie auch in VHDL der Anfangswert zusammen mit der
134
6 Verhaltensbeschreibung
Typdeklaration festgelegt werden. wires hingegen können nach wie vor nur über eine explizite Zuweisung während der Simulation aus dem Anfangszustand x herausgebracht werden. Das folgende Modell zeigt die neuen Möglichkeiten: // 2001 module clock_gen #(parameter delay = 5) (output reg clock = 0) initial forever #delay clock = ~clock; endmodule // 1995 module clock_gen (clock) parameter delay = 5; output clock; reg clock; initial begin clock = 0; forever #delay clock = ~clock; end endmodule
6.4
Unterprogramme: Tasks und Functions
Unterprogramme in Verilog heißen tasks und functions. Mit diesen Programmen können bestimmte Abläufe einmal vorgegeben und an verschiedenen Stellen innerhalb eines Verhaltensmodells aktiviert und ausgeführt werden. Der Aufruf einer task oder einer function ersetzt im Modul viele Zeilen Code. Unterprogramme verkürzen nicht nur den Text des Verilog-Modells, sondern strukturieren komplexe Verhaltensmodelle genau wie instanziierte Module in Strukturmodellen Übersichtlichkeit schaffen. Diese Programme verbessern die Lesbarkeit der Modellbeschreibungen, vereinfachen die Fehlersuche bei der Programmentwicklung und erleichtern Wartung und Portierung von umfangreicheren Modellen. Im Folgenden werden die Unterschiede zwischen tasks und functions erläutert und das Vorgehen bei Definition und Aufruf dieser Unterprogramme wird angegeben und mit praktischen Beispielen erläutert.
6.4.1
Functions
Eine Verilog-function ist ein Unterprogramm, das eine bestimmte Folge von sequentiellen Anweisungen ausführt und einen einzelnen Wert zurückgibt. Diese Funktionen werden in dem Modul definiert, in dem sie auch benutzt werden sollen. functions sind lokale auf ein bestimmtes Modul bezogene Unterprogramme. Globale Verfügbarkeit von Unterprogrammen wie in VHDL über so genannte PACKAGEs ist in Verilog nicht vorgesehen. In functi-
6.4 Unterprogramme: Tasks und Functions
135
ons können alle Verilog-Operatoren oder Anweisungen benutzt werden. Anweisungen, die Einfluss auf den zeitlichen Ablauf der Funktion haben könnten (wie #, @, wait), sind aber verboten, denn eine Funktion muss in Verilog ohne Zeitverzug in null Einheiten Simulationszeit abgearbeitet werden können. Die Funktionsdeklaration folgt der Vorgabe: Function_declaration ::= function [ automatic ] [ signed ] [ range_or_type ] function_name; input_port declaration; ... statements; ... endfunction [ range_or_type ]::= real| integer| time| realtime mit Wortbreite [m:n] functions geben in jedem Fall einen Wert zurück, dessen Wortbreite range_or_type [m:n] in der function-Deklaration festgelegt werden muss (Default-Breite: 1 Bit). Außer Variablen des vierwertigen Verilog-Standarddatentyps sind noch die Typen integer, real und realtime zulässig, die aber explizit benannt werden müssen. Der Rückgabewert wird auf eine Pseudovariable übertragen, die über den Funktionsnamen angesprochen werden kann. Außer dieser Rückgabemöglichkeit sind weitere Ausgabe-Ports in functions verboten. Wenn von den vektorwertigen Rückgabegrößen abgesehen wird, haben Verilog-functions die gleiche Funktionalität wir VHDL-FUNCTIONs, die nur skalare Funktionsergebnisse zulassen. Verilog schreibt vor, dass jede Funktion mindestens eine Eingabegröße (input) besitzt. functions können von jedem initial- oder always-Block aus aufgerufen werden oder auch von continuous-assignments. In kontinuierlichen Anweisungen stehen die Funktionen auf der rechten Seite und werden immer dann ausgeführt, wenn sich eine der Eingangsgrößen der function ändert. Im folgenden Beispiel wird ein 2-zu-1-Multiplexer mit Hilfe einer Funktion modelliert: module fun_mux(sel,a,b,out); input [7:0]a,b; // Wortbreite der Ein- und Ausgänge: 8-Bit input sel; // sel ist das Auswahlbit output [7:0] out; reg [7:0] out; always @(sel,a,b) out = mux(sel,a,b); endmodule function [7:0]mux; // Wortbreite des Rückgabewertes mux: // 8-Bit input sel;
136
6 Verhaltensbeschreibung input [7:0]a,b; case (sel) 1'b0 : mux = a; 1'b1 : mux = b; default : mux = 7'bx; endcase endfunction
Wie das Beispiel zeigt, kann die Funktionsdeklaration an jeder Stelle des Moduls vorgenommen werden. Es ist nicht wie in VHDL nötig, die Funktion vor dem ersten Aufruf zu deklarieren. Die Wortbreite des Ausgabewertes der Funktion wird in der Funktionsdeklaration angegeben, hier [7:0]. Die Funktion mux gibt also ein 8-Bit-Wort zurück. Die Zuweisung des auszugebenden Wertes (hier auf mux) ist die letzte Anweisung in der Funktionsbeschreibung vor dem abschließenden endfunction-Statement. Die Eingangsgrößen für eine Funktion werden genauso definiert, wie die Input-Ports in Modulen. Die Zuordnung der Übergabewerte im Funktionsaufruf erfolgt gemäß der Reihenfolge der input-Deklarationen in der Funktionsbeschreibung. Im Beispiel wird zuerst sel übergeben, dann a und b. Eingabeparameter werden nicht wie in VHDL explizit in der Funktionsdeklaration vereinbart! Erweiterungen im 2001er Standard: Rekursive und konstante Funktionen Mit dem neuen Standard von 2001 wurden die Möglichkeiten erweitert: rekursive Funktionen können nun mit dem Schlüsselwort automatic definiert werden und während in Verilog 1995 in Funktionen nur skalare vorzeichenbehaftete integer-Größen (Schlüsselwort signed in der Deklaration) verarbeitet und ausgegeben werden konnten, sind jetzt auch vorzeichenbehaftete Bitvektoren zulässig. Ein Beispiel für rekursive Funktionen ist die Berechnung der Fakultät einer Zahl: function automatic [63:0] fakul input [31:0] N; if (N == 1) fakul = 1; else fakul = N * fakul (N-1); //rekursiver Aufruf der Funktion fakul endfunction Der 1995er Standard lässt nur Funktionen zu, die variable Größen berechnen und ausgeben. Mit der 2001-Norm lassen sich auch Konstanten für die Simulation berechnen, wenn die Funktionen während der Elaboration des Modells ausgeführt werden. In diese Funktionen dürfen nur konstante Ausdrücke übergeben werden. Sie haben keine Auswirkungen auf variable Größen und hängen auch nicht von diesen ab. In der der Norm [LRM] ist folgendes Beispiel für diesen Funktionstyp zu finden: module RAM_model (address, write, chip_select, data); parameter data_width = 8; parameter ram_depth = 256; // Parameter der aus einem anderen Parameter berechnet
6.4 Unterprogramme: Tasks und Functions
137
// wird: localparam adder_width = clogb2(ram_depth); input [adder_width - 1:0] address; input write, chip_select; inout [data_width - 1:0] data; // Definition der clogb2 function function integer clogb2; input [31:0] value; for (clogb2=0; value>0; clogb2=clogb2+1;) value = value>>1; endfunction reg [data_width - 1:0] data_store[0:ram_depth - 1]; //weitere Anweisungen für das RAM Model folgen Dieses Beispiel ist ein Auszug aus einem Modell für einen Speicher (RAM). Hier wird die Wortbreite adder_width über eine konstante Funktion aus dem Parameter ram_depth berechnet, indem der duale Logarithmus gebildet wird. Wird im Modell die Speichertiefe bei der Instanziierung geändert, dann führt die Funktion den Parameter adder_width während der Elaboration automatisch nach. Dieses Modell kann als 32*421-RAM mit folgender Anweisung instanziiert werden, ohne dass adder_width explizit angegeben werden muss: ram_model #(32,421) ram_a0(a_addr,a_wr,a_cs,a_data); Konstante Funktionen vereinfachen also die Parametrisierung und damit die Skalierung von Modellen, da sie flexibler eingesetzt werden können als Verilog-Parameter.
6.4.2
Tasks
Verilog unterstützt als zweite Klasse von Unterprogrammen sog. tasks (task, die Aufgabe). tasks entsprechen den PROCEDURES in VHDL und „Subroutines“ in anderen Programmiersprachen. Im Gegensatz zu functions sind hier alle Verilog-Anweisungen inklusive zeitliche Vorgaben zugelassen und in der Regel werden mehrere Ergebniswerte zurückgegeben. Deshalb ersetzen tasks im Prinzip nur Programmteile in den Prozeduren, die tasks aufrufen. Wie functions sind tasks lokal in dem Modul zu deklarieren, das diese Unterprogramme verwenden will. Die Deklaration kann dabei an beliebiger Stelle vor oder nach dem ersten Aufruf erfolgen. Tasks werden über statements und nicht wie functions als Bestandteil von Ausdrücken aktiviert. In dieser Anweisung werden die Eingangsparameter für das Unterprogramm als Argumente übergeben und die berechneten Ergebnisse entgegengenommen. Die Reihenfolge der Portdeklarationen in der Definition des Unterprogramms gibt hier wie bei functions die Reihenfolge vor. tasks können andere tasks aufrufen. Das rufende Programm übernimmt erst dann wieder die Steuerung des Simulationsablaufs, wenn alle aktivierten tasks abgearbeitet sind.
138
6 Verhaltensbeschreibung
Die allgemeine Syntax zur Deklaration einer task ist: task_declaration ::= task [ automatic ] task_name; declarations; ... statements; ... endtask Declarations in tasks können sein: • • • •
Eingangsgrößen (inputs) Ausgangsgrößen (outputs) bidirektionale Größen (inouts) und alle Datentypen als lokale Variablen, die auch in prozeduralen Blöcken Verwendung finden können.
Als Statements kommen wie erwähnt alle Verilog-Anweisungen in Frage mit der Einschränkung, dass ein solches Unterprogramm sich nur dann selbst aufrufen kann, wenn die Option automatic gesetzt ist. Solche rekursiven Aufrufe werden wie bei functions erst von Verilog 2001 unterstützt. Der erweiterte Sprachumfang erlaubt es, die zugeordneten Speicherbereiche für die Variablen der tasks dynamisch zuzuordnen (allocate) und freizugeben (deallocate). Tasks ohne die automatic-Option verhalten sich statisch, d. h. alle Variablen behalten ihre Werte zwischen den Aufrufen. Da tasks nebenläufig abgearbeitet werden, kann es zu Zugriffskonflikten kommen, wenn mehrere Prozesse die gleiche task parallel zueinander aufrufen. Das folgende Beispiel zeigt die Verwendung eines task-Unterprogramms in einem Modul, das einen synchronen Addierer beschreibt: module task_add(data_1,data_2,out); input [1:0]data_1,data_2; output [2:0]out; reg [2:0]out; always@(data_1 or data_2) add(data_1,data_2,out); task add; input [1:0]a; input [1:0]b; output [2:0]c; c = a + b; endtask endmodule
6.4 Unterprogramme: Tasks und Functions
139
Beim Aufruf des Unterprogramms werden die Eingangsvektoren data_1 und data_2 den lokalen Variablen a und b zugewiesen, das Ergebnis c berechnet und über den output-Port der task an das rufende Modul übertragen.
6.4.3
Vereinfachte Deklaration bei Verilog 2001
In der Sprache VHDL können die Argumente von FUNCTIONs und PROCEDUREs direkt nach Definition des Funktionsnamens mit Typ, Modus und Wortbreite vorgegeben werden. Dies ist ab dem 2001er-Standard auch in Verilog möglich. Statt der function- bzw. taskDeklaration in den beiden Beispielen function [7:0]mux;
bzw.
input sel; input [7:0]a,b; case (sel)
// Wortbreite des Rückgabewertes mux: // 8-Bit
task add; input [1:0]a; input [1:0]b; output [2:0]c; können wir nun die kompaktere und besser lesbare Notation function [7:0]mux (input sel, input [7:0]a,b); bzw. task add (output [2:0]c, input
[1:0]a,b);
verwenden. Der Datentyp der Ein- und Ausgänge wird automatisch auf reg gesetzt. Andere Datentypen müssen deklariert werden: function real real_sum (input real a,b) real_sum = a + b; endfunction Im 1995er Standard entspricht dies: function real real_sum input real a,b; real_sum = a + b; endfunction
140
6.5
6 Verhaltensbeschreibung
Der Datentyp event
In Verilog steht ein spezieller, abstrakter Datentyp event zur Verfügung. Dieser Typ ist abstrakt, weil Variablen dieses Typs kein Wert zugewiesen werden kann. Mit dem Operator „->“ kann ein event-Typ aktiviert werden. Dies hat auf den flankensensitiven Operator @ die gleiche Wirkung wie ein Ereignis, das einen event auslöst. Mit solchen benannten Ereignissen können verschiedene Prozesse, die unabhängig voneinander ablaufen, synchronisiert werden. Dies zeigt das folgende Beispiel: module serial_out (….); … event data_ready, data_sent; always @ (data_ready) begin for (i = 0; i data_sent; end always @ (data_sent) begin wait (opcode == ‘send) data_out = data_bus[address]; -> data_ready; end Der erste always-Block gibt asynchron den Wert eines 16-Bit-Registers über einen seriellen 1-Bit-Ausgang aus. Der zweite asynchrone Prozess lädt Daten, die seriell ausgegeben werden sollen, in das 16-Bit-Register. Die beiden always-Blöcke müssen aufeinander synchronisiert werden, damit die richtigen Daten in der richtigen Reihenfolge ausgegeben werden, denn das Register darf nicht mit einem neuen Vektor geladen werden, bevor der alte Registerstand komplett abgearbeitet worden ist. Eine neue serielle Ausgabesequenz darf erst gestartet werden, wenn ein neuer Wert in das Register geladen worden ist. Die Freigabe des Registers wird über das data_sent -Ereignis gemeldet. Der Abschluss des Ladevorgangs für das Register wird über ein data_ready-Event angezeigt.
6.6
Iterative Instanziierung mit dem generateStatement
Das generate …. endgenerate Statement kann Instanzen wiederholt einsetzen, wobei die konkrete Anzahl der Instanzen flexibel gestaltet werden kann. Verilog-2001 erweitert den Anwendungsbereich des generate …. endgenerate- Konstrukts auf weitere Code-Segmente, wie Netzdeklarationen, reg-Deklarationen, kontinuierliche Zuweisungen, tasks und functions, sowie always- und initial-Blöcke.
6.6 Iterative Instanziierung mit dem generate-Statement
141
Der Vervielfachungsfaktor wird als positive ganze Zahl vorgegeben, die zum neuen Datentyp genvar gehört. Im Gegensatz zu integer-Konstanten sind genvars nur während der Elaboration des Verilog-Modells definiert und können während der Simulation nicht mehr angesprochen werden. Sobald eine Stelle einer genvar x oder z annimmt, wird ein Fehler gemeldet und die Elaboration abgebrochen. Generate-Statements befördern die Entwicklung parametrisierbarer und damit leicht wiederverwendbarer Modelle, insbesondere wenn generate-Konstrukte mit konstanten Funktionen zur flexiblen Parameterzuweisung kombiniert werden. Replizierte Instanziierungen können mit generate-Schleifen (generate-loop), bedingten generates (generate if-else) oder mit generates mit Fallunterscheidung (generate-case) vorgenommen werden.
6.6.1
Generate-Schleifen
Diese Konstruktion ermöglicht die wiederholte Einsetzung von Variablendeklarationen, Modulen, Primitiven, kontinuierlichen Anweisungen, initial- und always-Blöcken, wobei die Zahl der Instanzen über eine for-Schleife gesteuert wird. Der Schleifenindex wird als genvar deklariert. Die erste Anweisung in der Schleife darf den so definierten Schleifenindex nicht auf der rechten Seite verwenden. Als Beispiel [LRM] betrachten wir einen Umsetzer zwischen Gray-Code und Binärdarstellung. In diesem Modell wird das generate-Statement benutzt, um kontinuierliche Anweisungen mehrfach zu erzeugen. module gray2bin1 (bin, gray); parameter SIZE = 8; // SIZE :generischer Parameter output [SIZE-1:0] bin; input [SIZE-1:0] gray; genvar i; generate for (i=0; i> bewirkt, bei der die binäre Darstellung von 2: 0010 um 2 Stellen nach links geschoben wird: 0010 ¢ 0000. 3. Die beiden Varianten des Multiplexer-Designs sind: module mux_if_else(mux_out,dataA,dataB,select); input dataA,dataB,select; output mux_out; reg mux_out; always @ (select, dataA, dataB) begin if (select) mux_out = dataA; else mux_out = dataB; end endmodule module mux_assign_ter(mux_out,dataA,dataB,select); input dataA,dataB,select; output mux_out; wire mux_out; assign mux_out = select ? dataA : dataB ; endmodule 4. functions und tasks sind beides Unterprogramme, unterscheiden sich aber in mehreren Punkten: In functions können alle Verilog-Operatoren oder Anweisungen benutzt werden, aber Anweisungen, die Einfluss auf den zeitlichen Ablauf der Funktion haben könnten (wie #, @, wait), sind verboten, denn eine Funktion muss in Verilog ohne Zeitverzug in null Einheiten Simulationszeit abgearbeitet werden können. Eine Funktion hat mindestens einen Eingangsparameter, der beim Aufruf gesetzt wird. Ausgangs- oder bidirektionale Größen dürfen in der Parameterliste der Funktion nicht auftreten. Functions geben einen einzigen Wert zurück. Im Gegensatz zu functions sind in tasks alle VerilogAnweisungen inklusive zeitlicher Vorgaben zugelassen. Die Parameterliste bei tasks unterliegt weder vom Modus (in, out, inout) nach von der Anzahl der Parameter irgendwelchen Beschränkungen. Die Liste kann sogar leer sein. Tasks werden über statements und nicht wie functions als Bestandteil von Ausdrücken aktiviert. Tasks können functions oder andere tasks aufrufen. Funktionen dürfen hingegen keine tasks aufrufen.
6.9 Antworten
151
5.
Der Unterschied zwischen den beiden Verilog-Codes c = foo ? a : b; und if (foo) c = a; else c = b; besteht in der Behandlung von unbestimmten Werten in der Auswahlgröße foo. Gilt foo = x oder foo = z, dann werden die einzelnen Stellen der beiden anderen Operanden bitweise verglichen und gemäß der Tabelle 3.4 verknüpft. Ist einer der beiden zu vergleichenden Operanden länger, wird der kürzere von rechts her so lange mit Nullen aufgefüllt, bis die Stellenzahl übereinstimmt. Gilt foo = 1'bx, a = 'b10, und b = 'b11, so ergibt sich c = 'b1x. Im Gegensatz dazu bewertet die ifAnweisung x- oder z-Zustände als logisch falsch. Deshalb werden mit dem if-Code für foo = 1'bx, a = 'b10, und b = 'b11 c und b gleich gesetzt: c = 'b 11 .
6.
Diese Blöcke fassen mehrere Verilog-Anweisungen zusammen. Die Unterschiede von begin-end- und fork-join-Blöcken liegen darin, dass die Anweisungen in begin-endBlöcken sequentiell, in fork-join-Blöcken hingegen nebenläufig ausgeführt werden.
7.
Die Anweisungen always @ (posedge clk) begin a = 0; #5 a = 1; end erzeugen folgendes clk-Signal
clk 10
30
50
70
90
110
130
und als Ergebnis für a den Wellenzug:
a
8.
Das Modell eines 4-1-Multiplexers arbeitet nicht fehlerfrei, denn in der Sensitivitätsliste des always-Statements fehlen die Eingänge A, B, C und D. Der Multiplexer reagiert also nur auf Signalwechsel des select-Signals. Dies ist im Allgemeinen nicht beabsichtigt, denn es sollten sich auch Zustandswechsel der Dateneingänge A bis D auswirken. 9. Blockierende (blocking) Anweisungen und nicht blockierende (non blocking) Anweisungen werden unterschiedlich abgearbeitet: Bei einer blockierenden Anweisung kann erst nach deren vollständiger Ausführung und nach der Speicherung des Ergebnisses mit der nächsten Anweisungen begonnen werden. Diese Anweisungen werden also streng sequentiell bearbeitet. Nicht blockierende Anweisungen hingegen unterbrechen den Da-
152
6 Verhaltensbeschreibung
tenfluss nicht. Mit diesen nebenläufig ausgeführten Anweisungen kann man beispielsweise mehrere Register zeitgleich ansprechen. Diese Form bildet also im Gegensatz zu den blockierenden Anweisungen die Eigenschaften von Hardware-Blöcken besser nach. 10. Ein Modell eines 3-Bit-Zählers unter Verwendung einer while-Schleife kann folgendermaßen aussehen: module counter (clk,rst,enable,count); input clk, rst, enable; output [3:0] count; reg [3:0] count; always @ (posedge clk or posedge rst) begin if (rst) count