VLSI Design - Kurzanleitung

Sehr umfangreiche Integration (VLSI) ist der Prozess der Erstellung eines integrated circuit (IC) durch Kombination von Tausenden von transistorsin einen einzigen Chip. VLSI begann in den 1970er Jahren als komplexsemiconductor und communicationTechnologien wurden entwickelt. Dasmicroprocessor ist ein VLSI-Gerät.

Vor der Einführung der VLSI-Technologie verfügten die meisten ICs nur über begrenzte Funktionen. Einelectronic circuit könnte aus a bestehen CPU, ROM, RAM und andere glue logic. Mit VLSI können IC-Designer all dies in einem Chip hinzufügen.

Die Elektronikindustrie hat in den letzten Jahrzehnten ein phänomenales Wachstum erzielt, hauptsächlich aufgrund der raschen Fortschritte bei Integrationstechnologien in großem Maßstab und Systemdesignanwendungen. Mit dem Aufkommen von VLSI-Designs (Very Large Scale Integration) hat die Anzahl der Anwendungen von integrierten Schaltkreisen (ICs) in den Bereichen Hochleistungsrechnen, Steuerungen, Telekommunikation, Bild- und Videoverarbeitung sowie Unterhaltungselektronik sehr schnell zugenommen.

Die aktuellen Spitzentechnologien wie Video- und Mobilfunkkommunikation mit hoher Auflösung und niedriger Bitrate bieten den Endbenutzern eine erstaunliche Menge an Anwendungen, Rechenleistung und Portabilität. Dieser Trend wird voraussichtlich rasch zunehmen und sehr wichtige Auswirkungen auf das VLSI-Design und das Systemdesign haben.

VLSI Design Flow

Der Entwurfsablauf für VLSI-IC-Schaltungen ist in der folgenden Abbildung dargestellt. Die verschiedenen Entwurfsebenen sind nummeriert und die Blöcke zeigen Prozesse im Entwurfsablauf.

Die Spezifikationen stehen an erster Stelle. Sie beschreiben abstrakt die Funktionalität, die Schnittstelle und die Architektur der zu entwerfenden digitalen IC-Schaltung.

Anschließend wird eine Verhaltensbeschreibung erstellt, um das Design hinsichtlich Funktionalität, Leistung, Einhaltung vorgegebener Standards und anderer Spezifikationen zu analysieren.

Die RTL-Beschreibung erfolgt mit HDLs. Diese RTL-Beschreibung wird simuliert, um die Funktionalität zu testen. Ab hier brauchen wir die Hilfe von EDA-Tools.

Die RTL-Beschreibung wird dann unter Verwendung von Logiksynthesewerkzeugen in eine Netzliste auf Gate-Ebene konvertiert. Eine Gatelevel-Netzliste ist eine Beschreibung der Schaltung in Bezug auf Gates und Verbindungen zwischen ihnen, die so hergestellt sind, dass sie den Zeit-, Leistungs- und Flächenspezifikationen entsprechen.

Schließlich wird ein physisches Layout erstellt, das überprüft und dann an die Fertigung gesendet wird.

Y-Diagramm

Das Gajski-Kuhn-Y-Diagramm ist ein Modell, das die Überlegungen beim Entwurf von Halbleiterbauelementen erfasst.

Die drei Domänen des Gajski-Kuhn-Y-Diagramms liegen auf Radialachsen. Jede der Domänen kann mithilfe konzentrischer Ringe in Abstraktionsebenen unterteilt werden.

Auf der obersten Ebene (äußerer Ring) betrachten wir die Architektur des Chips; Auf den unteren Ebenen (Innenringe) verfeinern wir das Design sukzessive zu einer detaillierteren Implementierung -

Das Erstellen einer Strukturbeschreibung aus einer Verhaltensbeschreibung wird durch die Prozesse der Synthese auf hoher Ebene oder der logischen Synthese erreicht.

Das Erstellen einer physikalischen Beschreibung aus einer strukturellen wird durch Layoutsynthese erreicht.

Design Hierarchie-Struktur

Die Designhierarchie beinhaltet das Prinzip "Teilen und Erobern". Es ist nichts anderes, als die Aufgabe in kleinere Aufgaben zu unterteilen, bis sie ihre einfachste Ebene erreicht hat. Dieses Verfahren ist am besten geeignet, da die letzte Entwicklung des Designs so einfach geworden ist, dass seine Herstellung einfacher wird.

Wir können die gegebene Aufgabe in die Domäne des Entwurfsablaufprozesses (Verhalten, Struktur und Geometrie) entwerfen. Um dies zu verstehen, nehmen wir ein Beispiel für das Entwerfen eines 16-Bit-Addierers, wie in der folgenden Abbildung gezeigt.

Hier ist der gesamte Chip des 16-Bit-Addierers in vier Module von 4-Bit-Addierern unterteilt. Weiteres Teilen des 4-Bit-Addierers in 1-Bit-Addierer oder Halbaddierer. 1-Bit-Addition ist der einfachste Entwurfsprozess und seine interne Schaltung ist auch leicht auf dem Chip herzustellen. Wenn wir nun alle letzten vier Addierer verbinden, können wir einen 4-Bit-Addierer entwerfen und dann einen 16-Bit-Addierer entwerfen.

FPGA - Einführung

Die vollständige Form von FPGA ist “Field Programmable Gate Array”. Es enthält zehntausend bis mehr als eine Million Logikgatter mit programmierbarer Verbindung. Programmierbare Verbindungen stehen Benutzern oder Designern zur Verfügung, um bestimmte Funktionen einfach auszuführen. Ein typisches Modell eines FPGA-Chips ist in der angegebenen Abbildung dargestellt. Es gibt E / A-Blöcke, die entsprechend der Funktion entworfen und nummeriert sind. Für jedes Modul der Logikpegelzusammensetzung gibt esCLB’s (Configurable Logic Blocks).

CLB führt die dem Modul gegebene Logikoperation aus. Die Verbindung zwischen CLB- und E / A-Blöcken erfolgt mit Hilfe von horizontalen Routing-Kanälen, vertikalen Routing-Kanälen und PSM (Programmable Multiplexers).

Die Anzahl der darin enthaltenen CLBs entscheidet nur über die Komplexität des FPGA. Die Funktionen von CLBs und PSMs werden von VHDL oder einer anderen Hardware-Beschreibungssprache entwickelt. Nach der Programmierung werden CLB und PSM auf dem Chip platziert und über Routing-Kanäle miteinander verbunden.

Vorteile

  • Es erfordert sehr wenig Zeit; vom Entwurfsprozess bis zum funktionalen Chip.
  • Es sind keine physischen Herstellungsschritte erforderlich.
  • Der einzige Nachteil ist, dass es teurer ist als andere Stile.

Gate Array Design

Das gate array (GA)belegt nach dem FPGA den zweiten Platz in Bezug auf die Fähigkeit zum schnellen Prototyping. Während die Benutzerprogrammierung für die Designimplementierung des FPGA-Chips wichtig ist, wird für GA das Design und die Verarbeitung von Metallmasken verwendet. Die Implementierung eines Gate-Arrays erfordert einen zweistufigen Herstellungsprozess.

Die erste Phase führt zu einer Anordnung von nicht festgeschriebenen Transistoren auf jedem GA-Chip. Diese nicht festgeschriebenen Chips können zur späteren Anpassung gespeichert werden. Dies wird durch Definieren der Metallverbindungen zwischen den Transistoren des Arrays abgeschlossen. Die Strukturierung der metallischen Verbindungen erfolgt am Ende des Chipherstellungsprozesses, so dass die Durchlaufzeit noch einige Tage bis einige Wochen betragen kann. Die folgende Abbildung zeigt die grundlegenden Verarbeitungsschritte für die Implementierung des Gate-Arrays.

Typische Gate-Array-Plattformen verwenden dedizierte Bereiche, die als Kanäle bezeichnet werden, für das Routing zwischen Zellen zwischen Zeilen oder Spalten von MOS-Transistoren. Sie vereinfachen die Verbindungen. Verbindungsmuster, die grundlegende Logikgatter ausführen, werden in einer Bibliothek gespeichert, die dann verwendet werden kann, um Zeilen von nicht festgeschriebenen Transistoren gemäß der Netzliste anzupassen.

In den meisten modernen GAs werden mehrere Metallschichten für das Kanalrouting verwendet. Durch die Verwendung mehrerer miteinander verbundener Schichten kann das Routing über die aktiven Zellenbereiche erreicht werden; Damit können die Routing-Kanäle wie bei SOG-Chips (Sea-of-Gates) entfernt werden. Hier ist die gesamte Chipoberfläche mit nicht festgeschriebenen nMOS- und pMOS-Transistoren bedeckt. Die benachbarten Transistoren können unter Verwendung einer Metallmaske angepasst werden, um grundlegende Logikgatter zu bilden.

Für das Routing zwischen Zellen müssen einige der nicht festgeschriebenen Transistoren geopfert werden. Dieser Entwurfsstil führt zu mehr Flexibilität für Verbindungen und normalerweise zu einer höheren Dichte. Der GA-Chipnutzungsfaktor wird durch die verwendete Chipfläche geteilt durch die gesamte Chipfläche gemessen. Es ist höher als das des FPGA und ebenso die Chipgeschwindigkeit.

Standardzellbasiertes Design

Ein standardmäßiges zellbasiertes Design erfordert die Entwicklung eines vollständigen benutzerdefinierten Maskensatzes. Die Standardzelle ist auch als Polyzelle bekannt. Bei diesem Ansatz werden alle üblicherweise verwendeten Logikzellen entwickelt, charakterisiert und in einer Standardzellbibliothek gespeichert.

Eine Bibliothek kann einige hundert Zellen enthalten, einschließlich Inverter, NAND-Gatter, NOR-Gatter, komplexe AOI-, OAI-Gatter, D-Latches und Flip-Flops. Jeder Gate-Typ kann in mehreren Versionen implementiert werden, um eine angemessene Fahrfähigkeit für verschiedene Fan-Outs bereitzustellen. Das Inverter-Gate kann eine Standardgröße, eine doppelte Größe und eine vierfache Größe haben, so dass der Chipdesigner die richtige Größe auswählen kann, um eine hohe Schaltungsgeschwindigkeit und Layoutdichte zu erhalten.

Jede Zelle wird nach verschiedenen Charakterisierungskategorien charakterisiert, wie z.

  • Verzögerungszeit gegenüber Lastkapazität
  • Schaltungssimulationsmodell
  • Timing-Simulationsmodell
  • Fehlersimulationsmodell
  • Zellendaten für Ort und Route
  • Maskendaten

Für die automatische Platzierung der Zellen und das Routing wird jedes Zellenlayout mit einer festen Höhe entworfen, sodass mehrere Zellen nebeneinander begrenzt werden können, um Zeilen zu bilden. Die Strom- und Erdungsschienen verlaufen parallel zu den oberen und unteren Grenzen der Zelle. Damit teilen sich benachbarte Zellen einen gemeinsamen Leistungsbus und einen gemeinsamen Erdungsbus. Die folgende Abbildung ist ein Grundriss für ein auf Standardzellen basierendes Design.

Volles kundenspezifisches Design

In einem vollständig benutzerdefinierten Design wird das gesamte Maskendesign ohne Verwendung einer Bibliothek neu erstellt. Die Entwicklungskosten für diesen Designstil steigen. Daher wird das Konzept der Wiederverwendung von Konstruktionen immer bekannter, um die Konstruktionszykluszeit und die Entwicklungskosten zu reduzieren.

Das schwierigste vollständige benutzerdefinierte Design kann das Design einer Speicherzelle sein, sei es statisch oder dynamisch. Für den Entwurf eines Logikchips kann eine gute Verhandlung erzielt werden, indem eine Kombination verschiedener Entwurfsstile auf demselben Chip verwendet wird, dh Standardzellen, Datenpfadzellen undprogrammable logic arrays (PLAs).

Praktisch führt der Designer das vollständige benutzerdefinierte Layout durch, dh die Geometrie, Ausrichtung und Platzierung jedes Transistors. Die Designproduktivität ist normalerweise sehr gering; In der Regel einige zehn Transistoren pro Tag und Designer. In digitalem CMOS VLSI wird aufgrund der hohen Arbeitskosten kaum ein vollständig kundenspezifisches Design verwendet. Diese Designstile umfassen das Design von Produkten mit hohem Volumen wie Speicherchips, Hochleistungsmikroprozessoren und FPGA.

Komplementäre MOSFET (CMOS) -Technologie wird heutzutage häufig verwendet, um Schaltungen in zahlreichen und vielfältigen Anwendungen zu bilden. Heutige Computer, CPUs und Mobiltelefone nutzen CMOS aufgrund mehrerer entscheidender Vorteile. CMOS bietet in beiden Zuständen eine geringe Verlustleistung, eine relativ hohe Geschwindigkeit und hohe Rauschabstände und arbeitet über einen weiten Bereich von Quellen- und Eingangsspannungen (vorausgesetzt, die Quellenspannung ist fest).

Für die Prozesse, die wir diskutieren werden, ist der verfügbare Transistortyp der Metalloxid-Halbleiter-Feldeffekttransistor (MOSFET). Diese Transistoren sind ausgebildetas a ‘sandwich’bestehend aus einer Halbleiterschicht, üblicherweise einer Schicht oder einem Wafer, aus einem Einkristall aus Silizium; eine Schicht aus Siliziumdioxid (das Oxid) und eine Schicht aus Metall.

Struktur eines MOSFET

Wie in der Abbildung gezeigt, enthält die MOS-Struktur drei Schichten -

  • The Metal Gate Electrode

  • The Insulating Oxide Layer (SiO2)

  • P – type Semiconductor (Substrate)

Die MOS-Struktur bildet einen Kondensator, wobei Gate und Substrat als zwei Platten und Oxidschicht als dielektrisches Material vorliegen. Die Dicke des dielektrischen Materials (SiO 2 ) liegt üblicherweise zwischen 10 nm und 50 nm. Die Trägerkonzentration und -verteilung innerhalb des Substrats kann durch eine an das Gate und den Substratanschluss angelegte externe Spannung manipuliert werden. Um die Struktur von MOS zu verstehen, betrachten wir zunächst die grundlegenden elektrischen Eigenschaften des Halbleitersubstrats vom P-Typ.

Die Konzentration des Trägers im Halbleitermaterial folgt immer dem Mass Action Law. Das Massenaktionsgesetz ist gegeben durch -

$$n.p=n_{i}^{2}$$

Wo,

  • n ist die Trägerkonzentration von Elektronen

  • p ist die Trägerkonzentration von Löchern

  • ni ist die intrinsische Trägerkonzentration von Silizium

Nehmen wir nun an, dass das Substrat gleichmäßig mit der Akzeptor (Bor) -Konzentration N A dotiert ist . Die Elektronen- und Lochkonzentration im p-Substrat beträgt also

$$n_{po}=\frac{n_{i}^{2}}{N_{A}}$$

$$p_{po}=N_{A}$$

Hier Dopingkonzentration NAist (10 15 bis 10 16 cm –3 ) größer als die intrinsische Konzentration ni. Um die MOS-Struktur zu verstehen, betrachten Sie nun das Energieniveaudiagramm des Siliziumsubstrats vom p-Typ.

Wie in der Figur gezeigt, beträgt die Bandlücke zwischen Leitungsband und Valenzband 1,1 eV. Hier ist das Fermi-Potential Φ F die Differenz zwischen dem intrinsischen Fermi-Niveau (E i ) und dem Fermi-Niveau (E FP ).

Wo das Fermi-Niveau E F von der Dotierungskonzentration abhängt. Das Fermi-Potential Φ F ist die Differenz zwischen dem intrinsischen Fermi-Niveau (E i ) und dem Fermi-Niveau (E FP ).

Mathematisch,

$$\Phi_{Fp}=\frac{E_{F}-E_{i}}{q}$$

Die Potentialdifferenz zwischen Leitungsband und freiem Raum wird als Elektronenaffinität bezeichnet und mit qx bezeichnet.

Die Energie, die ein Elektron benötigt, um sich vom Fermi-Niveau in den freien Raum zu bewegen, wird als Austrittsarbeit (qΦ S ) bezeichnet und ist gegeben durch

$$q\Phi _{s}=(E_{c}-E_{F})+qx$$

Die folgende Abbildung zeigt das Energiebanddiagramm der Komponenten, aus denen der MOS besteht.

Wie in der obigen Abbildung gezeigt, weist die isolierende SiO 2 -Schicht eine große Energiebandlücke von 8 eV auf und die Austrittsarbeit beträgt 0,95 eV. Metalltor hat eine Austrittsarbeit von 4,1 eV. Hier sind die Arbeitsfunktionen unterschiedlich, so dass ein Spannungsabfall über dem MOS-System erzeugt wird. Die folgende Abbildung zeigt das kombinierte Energiebanddiagramm des MOS-Systems.

Wie in dieser Figur gezeigt, liegt der Fermi-Potentialpegel von Metallgatter und Halbleiter (Si) auf dem gleichen Potential. Das Fermi-Potential an der Oberfläche wird als Oberflächenpotential Φ S bezeichnet und ist in seiner Größe kleiner als das Fermi-Potential Φ F.

Arbeiten eines MOSFET

Der MOSFET besteht aus einem MOS-Kondensator mit zwei pn-Übergängen, die nahe am Kanalbereich angeordnet sind, und dieser Bereich wird durch die Gate-Spannung gesteuert. Um beide pn-Übergänge in Sperrrichtung vorzuspannen, wird das Substratpotential niedriger als das Potential der anderen drei Anschlüsse gehalten.

Wenn die Gate-Spannung über die Schwellenspannung (V GS > V TO ) hinaus erhöht wird , wird eine Inversionsschicht auf der Oberfläche aufgebaut und ein Kanal vom n-Typ wird zwischen Source und Drain gebildet. Dieser Kanal vom n-Typ führt den Drainstrom gemäß dem V DS- Wert.

Für unterschiedliche Werte von V DS kann der MOSFET in verschiedenen Regionen betrieben werden, wie nachstehend erläutert wird.

Linearer Bereich

Bei V DS = 0 besteht ein thermisches Gleichgewicht im invertierten Kanalbereich und der Drainstrom I D = 0. Wenn nun eine kleine Drainspannung V DS > 0 angelegt wird, beginnt ein Drainstrom proportional zum V DS von der Quelle zu zu fließen durch den Kanal ablassen.

Der Kanal gibt einen kontinuierlichen Pfad für den Stromfluss von der Source zur Drain. Diese Betriebsart wird aufgerufenlinear region. Die Querschnittsansicht eines im linearen Bereich arbeitenden n-Kanal-MOSFET ist in der folgenden Abbildung dargestellt.

Am Rande der Sättigungsregion

Wenn nun der V DS erhöht wird, nehmen die Ladungen im Kanal und die Kanaltiefe am Ende des Drains ab. Für V DS = V DSAT werden die Ladungen im Kanal auf Null reduziert, was aufgerufen wirdpinch – off point. Die Querschnittsansicht eines am Rand des Sättigungsbereichs arbeitenden n-Kanal-MOSFET ist in der nachstehenden Abbildung dargestellt.

Sättigungsbereich

Für V DS > V DSAT bildet sich in der Nähe des Drains eine abgereicherte Oberfläche, und durch Erhöhen der Drain-Spannung erstreckt sich dieser abgereicherte Bereich bis zur Source.

Diese Betriebsart wird aufgerufen Saturation region. Die Elektronen, die von der Quelle zum Kanalende kommen, treten in den Drain-Depletion-Bereich ein und werden in einem hohen elektrischen Feld in Richtung Drain beschleunigt.

MOSFET-Strom - Spannungseigenschaften

Um die Strom-Spannungs-Charakteristik des MOSFET zu verstehen, wird eine Annäherung für den Kanal durchgeführt. Ohne diese Annäherung wird die dreidimensionale Analyse des MOS-Systems komplex. DasGradual Channel Approximation (GCA) für Strom - Spannung Kennlinie wird das Analyseproblem reduzieren.

Allmähliche Kanalannäherung (GCA)

Betrachten Sie die Querschnittsansicht eines im linearen Modus arbeitenden n-Kanal-MOSFET. Hier sind Quelle und Substrat mit Masse verbunden. V S = V B = 0. Die Spannung von Gate zu Source (V GS ) und Drain zu Source (V DS ) sind die externen Parameter, die den Drainstrom I D steuern .

Die Spannung V GS wird auf eine Spannung eingestellt, die größer als die Schwellenspannung V TO ist, um einen Kanal zwischen Source und Drain zu erzeugen. Wie in der Abbildung gezeigt, verläuft die x-Richtung senkrecht zur Oberfläche und die y-Richtung parallel zur Oberfläche.

Hier ist y = 0 am Quellenende, wie in der Abbildung gezeigt. Die Kanalspannung in Bezug auf die Quelle wird durch dargestelltVC(Y). Es sei angenommen, dass die Schwellenspannung VTO entlang des Kanalbereichs zwischen y = 0 und y = L konstant ist. Die Randbedingungen für die Kanalspannung V C sind -

$$V_{c}\left ( y = 0 \right ) = V_{s} = 0 \,and\,V_{c}\left ( y = L \right ) = V_{DS}$$

Das können wir auch annehmen

$$V_{GS}\geq V_{TO}$$ und

$$V_{GD} = V_{GS}-V_{DS}\geq V_{TO}$$

Sei Q1 (y) die gesamte mobile Elektronenladung in der Oberflächeninversionsschicht. Diese Elektronenladung kann ausgedrückt werden als -

$$Q1(y)=-C_{ox}.[V_{GS}-V_{C(Y)}-V_{TO}]$$

Die folgende Abbildung zeigt die räumliche Geometrie der Oberflächeninversionsschicht und gibt deren Abmessungen an. Die Inversionsschicht verjüngt sich, wenn wir uns vom Drain zur Source bewegen. Wenn wir nun den kleinen Bereich dy der Kanallänge L betrachten, kann der von diesem Bereich angebotene inkrementelle Widerstand dR ausgedrückt werden als -

$$dR=-\frac{dy}{w.\mu _{n}.Q1(y)}$$

Hier ist das Minuszeichen auf die negative Polarität der Inversionsschichtladung Q1 zurückzuführen und μ n ist die Oberflächenmobilität, die konstant ist. Ersetzen Sie nun den Wert von Q1 (y) in der dR-Gleichung -

$$dR=-\frac{dy}{w.\mu _{n}.\left \{ -C_{ox}\left [ V_{GS}-V_{C\left ( Y \right )} \right ]-V_{TO} \right \}}$$

$$dR=\frac{dy}{w.\mu _{n}.C_{ox}\left [ V_{GS}-V_{C\left ( Y \right )} \right ]-V_{TO}}$$

Nun kann der Spannungsabfall im kleinen dy-Bereich durch gegeben sein

$$dV_{c}=I_{D}.dR$$

Setzen Sie den Wert von dR in die obige Gleichung

$$dV_{C}=I_{D}.\frac{dy}{w.\mu_{n}.C_{ox}\left [ V_{GS}-V_{C(Y)} \right ]-V_{TO}}$$

$$w.\mu _{n}.C_{ox}\left [ V_{GS}-V_{C(Y)}-V_{TO} \right ].dV_{C}=I_{D}.dy$$

Um die Drainstrom-ID über den gesamten Kanalbereich zu erhalten, kann die obige Gleichung entlang des Kanals von y = 0 bis y = L und die Spannungen V C (y) = 0 bis V C (y) = V DS integriert werden.

$$C_{ox}.w.\mu _{n}.\int_{V_{c}=0}^{V_{DS}} \left [ V_{GS}-V_{C\left ( Y \right )}-V_{TO} \right ].dV_{C} = \int_{Y=0}^{L}I_{D}.dy$$

$$\frac{C_{ox}.w.\mu _{n}}{2}\left ( 2\left [ V_{GS}-V_{TO} \right ] V_{DS}-V_{DS}^{2}\right ) = I_{D}\left [ L-0 \right ]$$

$$I_{D} = \frac{C_{ox}.\mu _{n}}{2}.\frac{w}{L}\left ( 2\left [ V_{GS}-V_{TO} \right ]V_{DS}-V_{DS}^{2} \right )$$

Für den linearen Bereich V DS <V GS - V TO . Für den Sättigungsbereich ist der Wert von V DS größer als (V GS - V TO ). Daher ist für den Sättigungsbereich V DS = (V GS - V TO ).

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{\left [ 2V_{DS} \right ]V_{DS}-V_{DS}^{2}}{L} \right )$$

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{2V_{DS}^{2}-V_{DS}^{2}}{L} \right )$$

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{V_{DS}^{2}}{L} \right )$$

$$I_{D} = C_{ox}.\mu _{n}.\frac{w}{2}\left ( \frac{\left [ V_{GS}-V_{TO} \right ]^{2}}{L} \right )$$

Der Wechselrichter ist wirklich der Kern aller digitalen Designs. Sobald seine Funktionsweise und Eigenschaften klar verstanden sind, wird das Entwerfen komplexerer Strukturen wie NAND-Gatter, Addierer, Multiplikatoren und Mikroprozessoren erheblich vereinfacht. Das elektrische Verhalten dieser komplexen Schaltkreise kann durch Extrapolation der für Wechselrichter erhaltenen Ergebnisse fast vollständig abgeleitet werden.

Die Analyse von Wechselrichtern kann erweitert werden, um das Verhalten komplexerer Gatter wie NAND, NOR oder XOR zu erklären, die wiederum die Bausteine ​​für Module wie Multiplikatoren und Prozessoren bilden. In diesem Kapitel konzentrieren wir uns auf eine einzelne Inkarnation des Inverter-Gates, nämlich den statischen CMOS-Inverter - oder kurz den CMOS-Inverter. Dies ist derzeit sicherlich die beliebteste und verdient daher unsere besondere Aufmerksamkeit.

Funktionsprinzip

Das Logiksymbol und die Wahrheitstabelle des idealen Wechselrichters sind in der folgenden Abbildung dargestellt. Hier ist A der Eingang und B der invertierte Ausgang, der durch ihre Knotenspannungen dargestellt wird. Unter Verwendung einer positiven Logik wird der Boolesche Wert von logisch 1 durch V dd und logisch 0 durch 0 dargestellt. V th ist die Wechselrichterschwellenspannung, die V dd / 2 ist, wobei V dd die Ausgangsspannung ist.

Der Ausgang wird von 0 auf V dd geschaltet, wenn der Eingang kleiner als V th ist . Für 0 <V in <V ist der Ausgang gleich dem logischen 0-Eingang und V th <V in <V dd ist gleich dem logischen 1-Eingang für den Wechselrichter.

Die in der Abbildung gezeigten Eigenschaften sind ideal. Die verallgemeinerte Schaltungsstruktur eines nMOS-Wechselrichters ist in der folgenden Abbildung dargestellt.

Aus der gegebenen Figur können wir sehen, dass die Eingangsspannung des Wechselrichters gleich der Gate-Source-Spannung des nMOS-Transistors und die Ausgangsspannung des Wechselrichters gleich der Drain-Source-Spannung des nMOS-Transistors ist. Die Source-to-Substrat-Spannung von nMOS wird auch als Treiber für einen geerdeten Transistor bezeichnet. also V SS = 0. Der Ausgangsknoten ist mit einer konzentrierten Kapazität verbunden, die für VTC verwendet wird.

Widerstandslastwechselrichter

Die Grundstruktur eines ohmschen Lastwechselrichters ist in der folgenden Abbildung dargestellt. Hier wirkt der Verbesserungstyp nMOS als Treibertransistor. Die Last besteht aus einem einfachen linearen Widerstand R L . Die Stromversorgung der Schaltung ist mit V DD und der Drainstrom I D ist gleich dem Laststrom I R .

Schaltungsbetrieb

Wenn der Eingang des Treibertransistors kleiner als die Schwellenspannung V TH (V in <V TH ) ist, befindet sich der Treibertransistor im Sperrbereich und leitet keinen Strom. Der Spannungsabfall über dem Lastwiderstand ist also NULL und die Ausgangsspannung ist gleich V DD . Wenn nun die Eingangsspannung weiter ansteigt, beginnt der Treibertransistor, den Strom ungleich Null zu leiten, und nMOS geht in den Sättigungsbereich.

Mathematisch,

$$I_{D} = \frac{K_{n}}{2}\left [ V_{GS}-V_{TO} \right ]^{2}$$

Wenn die Eingangsspannung weiter erhöht wird, tritt der Treibertransistor in den linearen Bereich ein und der Ausgang des Treibertransistors nimmt ab.

$$I_{D} = \frac{K_{n}}{2}2\left [ V_{GS}-V_{TO} \right ]V_{DS}-V_{DS}^{2}$$

Die unten gezeigte VTC des ohmschen Lastwechselrichters zeigt den Betriebsmodus des Treibertransistors und die Spannungspunkte an.

Wechselrichter mit N-Typ-MOSFET-Last

Der Hauptvorteil der Verwendung eines MOSFET als Lastvorrichtung besteht darin, dass die vom Transistor eingenommene Siliziumfläche kleiner ist als die von der ohmschen Last eingenommene Fläche. Hier ist der MOSFET eine aktive Last und der Wechselrichter mit aktiver Last bietet eine bessere Leistung als der Wechselrichter mit ohmscher Last.

Erweiterungslast NMOS

In der Abbildung sind zwei Wechselrichter mit Lastvorrichtung vom Anreicherungstyp dargestellt. Der Lasttransistor kann abhängig von der an seinen Gate-Anschluss angelegten Vorspannung entweder im Sättigungsbereich oder im linearen Bereich betrieben werden. Der Wechselrichter mit gesättigter Verstärkung ist in der Abbildung dargestellt. (ein). Es erfordert eine einzige Spannungsversorgung und einen einfachen Herstellungsprozess, so dass V OH auf V DD - V T beschränkt ist .

Der Wechselrichter mit linearer Verstärkung ist in der Abbildung dargestellt. (b). Es arbeitet immer im linearen Bereich; der VOH- Pegel ist also gleich VDD .

Der Wechselrichter mit linearer Last weist im Vergleich zum Wechselrichter mit gesättigter Verstärkung einen höheren Rauschabstand auf. Der Nachteil eines Wechselrichters mit linearer Verstärkung besteht jedoch darin, dass zwei separate Stromversorgungen erforderlich sind und beide Schaltkreise unter einer hohen Verlustleistung leiden. Daher werden Verbesserungswechselrichter in keinen digitalen Großanwendungen verwendet.

Verarmungslast NMOS

Nachteile des Verbesserungslastwechselrichters können durch Verwendung eines Verarmungslastwechselrichters überwunden werden. Im Vergleich zu einem Wechselrichter mit verbesserter Last erfordert der Wechselrichter mit Verarmungslast einige weitere Herstellungsschritte für das Kanalimplantat, um die Schwellenspannung der Last anzupassen.

Die Vorteile des Verarmungslastwechselrichters sind - scharfer VTC-Übergang, bessere Rauschmarge, einzelne Stromversorgung und kleinerer Gesamtlayoutbereich.

Wie in der Figur gezeigt, sind das Gate und der Source-Anschluss der Last verbunden; Also ist V GS = 0. Somit ist die Schwellenspannung der Last negativ. Daher,

$$V_{GS,load}> V_{T,load}$$ ist befriedigt

Daher hat das Lastgerät unabhängig vom Eingangs- und Ausgangsspannungspegel immer einen Leitungskanal.

Wenn sich der Lasttransistor im Sättigungsbereich befindet, ist der Laststrom gegeben durch

$$I_{D,load} = \frac{K_{n,load}}{2}\left [ -V_{T,load}\left ( V_{out} \right ) \right ]^{2}$$

Wenn sich der Lasttransistor im linearen Bereich befindet, ist der Laststrom gegeben durch

$$I_{D,load} = \frac{K_{n,load}}{2}\left [ 2\left | V_{T,load}\left ( V_{out} \right ) \right |.\left ( V_{DD}-V_{out} \right )-\left ( V_{DD}-V_{out} \right )^{2} \right ]$$

Die Spannungsübertragungseigenschaften des Verarmungslastwechselrichters sind in der folgenden Abbildung dargestellt.

CMOS-Wechselrichter - Schaltung, Betrieb und Beschreibung

Die CMOS-Inverterschaltung ist in der Abbildung dargestellt. Hier arbeiten nMOS- und pMOS-Transistoren als Treibertransistoren; Wenn ein Transistor eingeschaltet ist, ist der andere ausgeschaltet.

Diese Konfiguration wird aufgerufen complementary MOS (CMOS). Der Eingang ist mit dem Gate-Anschluss beider Transistoren verbunden, so dass beide direkt mit Eingangsspannungen angesteuert werden können. Das Substrat des nMOS ist mit der Erde verbunden, und das Substrat des pMOS ist mit der Stromversorgung V DD verbunden .

Also ist V SB = 0 für beide Transistoren.

$$V_{GS,n}=V_{in}$$

$$V_{DS,n}=V_{out}$$

Und,

$$V_{GS,p}=V_{in}-V_{DD}$$

$$V_{DS,p}=V_{out}-V_{DD}$$

Wenn der Eingang von nMOS kleiner als die Schwellenspannung ist (V in <V TO, n ), wird der nMOS abgeschaltet und der pMOS befindet sich im linearen Bereich. Der Drainstrom beider Transistoren ist also Null.

$$I_{D,n}=I_{D,p}=0$$

Daher ist die Ausgangsspannung V OH gleich der Versorgungsspannung.

$$V_{out}=V_{OH}=V_{DD}$$

Wenn die Eingangsspannung größer als V DD + V TO, p ist , befindet sich der pMOS-Transistor im Grenzbereich und der nMOS im linearen Bereich, so dass der Drainstrom beider Transistoren Null ist.

$$I_{D,n}=I_{D,p}=0$$

Daher ist die Ausgangsspannung V OL gleich Null.

$$V_{out}=V_{OL}=0$$

Der nMOS arbeitet im Sättigungsbereich, wenn V in > V TO ist und wenn die folgenden Bedingungen erfüllt sind.

$$V_{DS,n}\geq V_{GS,n}-V_{TO,n} $$

$$V_{out}\geq V_{in}-V_{TO,n} $$

Der pMOS arbeitet im Sättigungsbereich, wenn V in <V DD + V TO, p ist und wenn die folgenden Bedingungen erfüllt sind.

$$V_{DS,p}\leq V_{GS,p}-V_{TO,p} $$

$$V_{out}\leq V_{in}-V_{TO,p} $$

Für unterschiedliche Werte der Eingangsspannungen sind die Betriebsbereiche für beide Transistoren unten aufgeführt.

Region V in V raus nMOS pMOS
EIN <V TO, n V OH Abgeschnitten Linear
B. V IL Hoch ≈ V OH Sättigung Linear
C. V th V th Sättigung Sättigung
D. V IH Niedrig ≈ V OL Linear Sättigung
E. > (V DD + V TO, p ) V OL Linear Abgeschnitten

Die VTC von CMOS ist in der folgenden Abbildung dargestellt -

Kombinierte Logikschaltungen oder Gatter, die Boolesche Operationen an mehreren Eingangsvariablen ausführen und die Ausgänge als Boolesche Funktionen der Eingänge bestimmen, sind die Grundbausteine ​​aller digitalen Systeme. Wir werden einfache Schaltungskonfigurationen wie NAND- und NOR-Gatter mit zwei Eingängen untersuchen und dann unsere Analyse auf allgemeinere Fälle von Schaltungsstrukturen mit mehreren Eingängen erweitern.

Als nächstes werden die CMOS-Logikschaltungen auf ähnliche Weise dargestellt. Wir werden die Ähnlichkeiten und Unterschiede zwischen der nMOS-Verarmungslastlogik und den CMOS-Logikschaltungen hervorheben und anhand von Beispielen auf die Vorteile von CMOS-Gattern hinweisen. In seiner allgemeinsten Form kann eine kombinatorische Logikschaltung oder ein Gatter, das eine Boolesche Funktion ausführt, als ein System mit mehreren Eingängen und einem Ausgang dargestellt werden, wie in der Figur dargestellt.

Knotenspannungen, bezogen auf das Erdpotential, repräsentieren alle Eingangsvariablen. Unter Verwendung einer positiven Logikkonvention kann der Boolesche (oder logische) Wert von "1" durch eine hohe Spannung von VDD dargestellt werden, und der boolesche (oder logische) Wert von "0" kann durch eine niedrige Spannung von 0 dargestellt werden. Der Ausgang Der Knoten ist mit einer Kapazität C L belastet , die die kombinierten Kapazitäten der parasitären Vorrichtung in der Schaltung darstellt.

CMOS-Logikschaltungen

CMOS NOR-Gatter mit zwei Eingängen

Die Schaltung besteht aus einem parallel geschalteten n-Netz und einem in Reihe geschalteten komplementären p-Netz. Die Eingangsspannungen V X und V Y werden an die Gatter eines nMOS- und eines pMOS-Transistors angelegt.

Wenn einer oder beide Eingänge hoch sind, dh wenn das n-Netz einen leitenden Pfad zwischen dem Ausgangsknoten und der Erde erzeugt, wird das p-Netz abgeschnitten. Wenn beide Eingangsspannungen niedrig sind, dh das n-Netz abgeschaltet ist, erzeugt das p-Netz einen leitenden Pfad zwischen dem Ausgangsknoten und der Versorgungsspannung.

Für jede gegebene Eingangskombination ist die komplementäre Schaltungsstruktur derart, dass der Ausgang entweder über einen niederohmigen Pfad entweder mit V DD oder mit Masse verbunden ist und für keine Eingangskombinationen ein Gleichstrompfad zwischen V DD und Masse hergestellt wird. Die Ausgangsspannung des CMOS-NOR-Gatters mit zwei Eingängen erhält eine logisch niedrige Spannung von V OL = 0 und eine logisch hohe Spannung von V OH = V DD . Die Gleichung der Schaltschwellenspannung V th ist gegeben durch

$$V_{th}\left ( NOR2 \right ) = \frac{V_{T,n}+\frac{1}{2}\sqrt{\frac{k_{p}}{k_{n}}\left ( V_{DD}-\left | V_{T,p} \right | \right )}}{1+\frac{1}{2}\sqrt{\frac{k_{p}}{k_{n}}}}$$

Layout des CMOS-NOR-Gatters mit 2 Eingängen

Die Abbildung zeigt ein Beispiellayout eines CMOS-NOR-Gatters mit zwei Eingängen unter Verwendung von einschichtigem Metall und einschichtigem Polysilicium. Die Merkmale dieses Layouts sind -

  • Einzelne vertikale Polylinien für jeden Eingang
  • Einzelne aktive Formen für N- bzw. P-Geräte
  • Metallbusse fahren horizontal

Das Stick-Diagramm für das CMOS N0R2-Gate ist in der folgenden Abbildung dargestellt. Dies entspricht direkt dem Layout, enthält jedoch keine W- und L-Informationen. Die Diffusionsbereiche sind durch Rechtecke dargestellt, die Metallverbindungen und durchgezogenen Linien bzw. Kreise repräsentieren Kontakte, und die schraffierten Streifen repräsentieren die Polysiliciumsäulen. Das Stick-Diagramm ist nützlich für die Planung einer optimalen Layout-Topologie.

CMOS NAND-Gatter mit zwei Eingängen

Das Schaltbild des CMOS-NAND-Gatters mit zwei Eingängen ist in der folgenden Abbildung dargestellt.

Das Funktionsprinzip der Schaltung ist genau das Doppelte des CMOS-NOR-Betriebs mit zwei Eingängen. Das aus zwei in Reihe geschalteten nMOS-Transistoren bestehende n-Netz erzeugt einen leitenden Pfad zwischen dem Ausgangsknoten und der Masse, wenn beide Eingangsspannungen logisch hoch sind. Beide parallel geschalteten pMOS-Transistoren in p-net sind ausgeschaltet.

Bei allen anderen Eingangskombinationen wird entweder einer oder beide der pMOS-Transistoren eingeschaltet, während p - net abgeschaltet wird, wodurch ein Strompfad zwischen dem Ausgangsknoten und der Versorgungsspannung erzeugt wird. Die Schaltschwelle für dieses Gate wird erhalten als -

$$V_{th}\left ( NAND2 \right ) = \frac{V_{T,n}+2\sqrt{\frac{k_{p}}{k_{n}}\left ( V_{DD}-\left | V_{T,p} \right | \right )}}{1+2\sqrt{\frac{k_{p}}{k_{n}}}}$$

Die Merkmale dieses Layouts sind wie folgt:

  • Einzelne Polysiliciumleitungen für Eingänge verlaufen vertikal über N und P aktive Bereiche.
  • Einzelne aktive Formen werden zum Erstellen sowohl von nMOS-Geräten als auch von beiden pMOS-Geräten verwendet.
  • Das Power-Busing verläuft horizontal über die Ober- und Unterseite des Layouts.
  • Die Ausgangsleitungen verlaufen horizontal, um den Anschluss an den benachbarten Stromkreis zu erleichtern.

Komplexe Logikschaltungen

Komplexes Logikgatter für NMOS-Verarmungslast

Um komplexe Funktionen mehrerer Eingangsvariablen zu realisieren, können die für NOR und NAND entwickelten grundlegenden Schaltungsstrukturen und Entwurfsprinzipien auf komplexe Logikgatter erweitert werden. Die Fähigkeit, komplexe Logikfunktionen unter Verwendung einer kleinen Anzahl von Transistoren zu realisieren, ist eines der attraktivsten Merkmale von nMOS- und CMOS-Logikschaltungen. Betrachten Sie die folgende Boolesche Funktion als Beispiel.

$$\overline{Z=P\left ( S+T \right )+QR}$$

Das komplexe Logikgatter mit nMOS-Verarmungslast, das zur Realisierung dieser Funktion verwendet wird, ist in der Abbildung dargestellt. In dieser Figur wird der linke nMOS-Treiberzweig von drei Treibertransistoren verwendet, um die Logikfunktion P (S + T) auszuführen, während der rechte Zweig die Funktion QR ausführt. Durch paralleles Verbinden der beiden Zweige und Platzieren des Lasttransistors zwischen dem Ausgangsknoten und der VersorgungsspannungVDD,wir erhalten die gegebene komplexe Funktion. Jede Eingangsvariable ist nur einem Treiber zugeordnet.

Die Überprüfung der Schaltungstopologie liefert einfache Entwurfsprinzipien des Pulldown-Netzwerks -

  • ODER-Operationen werden von parallel geschalteten Treibern ausgeführt.
  • UND-Operationen werden von in Reihe geschalteten Treibern ausgeführt.
  • Die Inversion wird durch die Art des MOS-Schaltungsbetriebs bereitgestellt.

Wenn alle Eingangsvariablen in der Schaltung, die die Funktion realisiert, logisch hoch sind, wird der äquivalente Treiber verwendet (W/L) Das Verhältnis des aus fünf nMOS-Transistoren bestehenden Pulldown-Netzwerks beträgt

$$\frac{W}{L}=\frac{1}{\frac{1}{\left ( W/L \right )Q}+\frac{1}{\left ( W/L \right )R}}+\frac{1}{\frac{1}{\left ( W/L \right )P}+\frac{1}{\left ( W/L \right )S+\left ( W/L \right )Q}}$$

Komplexe CMOS-Logikgatter

Die Realisierung des n-Netzes oder Pulldown-Netzwerks basiert auf denselben grundlegenden Entwurfsprinzipien, die für das komplexe Logikgatter mit nMOS-Verarmungslast untersucht wurden. Das pMOS-Pull-up-Netzwerk muss das duale Netzwerk des n-Netzes sein.

Dies bedeutet, dass alle parallelen Verbindungen im nMOS-Netzwerk einer Serienverbindung im pMOS-Netzwerk entsprechen und alle Serienverbindungen im nMOS-Netzwerk einer parallelen Verbindung im pMOS-Netzwerk entsprechen. Die Abbildung zeigt einen einfachen Aufbau des Dual-P-Net-Diagramms (Pull-Up) aus dem N-Net-Diagramm (Pull-Down).

Jeder Treibertransistor im Pulldown-Netzwerk ist durch ai dargestellt, und jeder Knoten ist durch einen Scheitelpunkt im Pulldown-Diagramm dargestellt. Als nächstes wird ein neuer Scheitelpunkt in jedem begrenzten Bereich im Pull-Diagramm erstellt, und benachbarte Scheitelpunkte werden durch Kanten verbunden, die jede Kante im Pulldown-Diagramm nur einmal kreuzen. Diese neue Grafik zeigt das Pull-up-Netzwerk.

Layout-Technik mit der Euler-Graph-Methode

Die Abbildung zeigt die CMOS-Implementierung einer komplexen Funktion und ihr Stickdiagramm mit beliebiger Gate-Reihenfolge, die ein sehr nicht optimales Layout für das CMOS-Gate ergibt.

In diesem Fall muss die Trennung zwischen den Polysiliciumsäulen eine Diffusion-Diffusion-Trennung dazwischen ermöglichen. Dies verbraucht sicherlich eine beträchtliche Menge an zusätzlicher Siliziumfläche.

Durch Verwendung des Euler-Pfades können wir ein optimales Layout erhalten. Der Euler-Pfad ist als ununterbrochener Pfad definiert, der jede Kante (Verzweigung) des Diagramms genau einmal durchquert. Suchen Sie den Euler-Pfad sowohl im Pulldown-Baumdiagramm als auch im Pullup-Baumdiagramm mit identischer Reihenfolge der Eingaben.

Logikschaltungen werden in zwei Kategorien unterteilt - (a) kombinatorische Schaltungen und (b) sequentielle Schaltungen.

In kombinatorischen Schaltungen hängt die Ausgabe nur vom Zustand der neuesten Eingaben ab.

In sequentiellen Schaltungen hängt der Ausgang nicht nur von den neuesten Eingängen ab, sondern auch vom Zustand früherer Eingänge. Sequenzielle Schaltungen enthalten Speicherelemente.

Es gibt drei Arten von sequentiellen Schaltungen:

Bistable- Bistabile Schaltkreise haben zwei stabile Betriebspunkte und befinden sich in einem der beiden Zustände. Beispiel - Speicherzellen, Latches, Flip-Flops und Register.

Monostable- Monostabile Schaltkreise haben nur einen stabilen Betriebspunkt, und selbst wenn sie vorübergehend in den entgegengesetzten Zustand versetzt werden, kehren sie rechtzeitig zu ihrem stabilen Betriebspunkt zurück. Beispiel: Timer, Impulsgeneratoren.

Astable- Stromkreise haben keinen stabilen Betriebspunkt und schwingen zwischen mehreren Zuständen. Beispiel - Ringoszillator.

CMOS-Logikschaltungen

SR Latch basierend auf NOR Gate

Wenn der eingestellte Eingang (S) gleich logisch ist "1" und der Rücksetzeingang ist gleich logisch "0." dann wird der Ausgang Q zur Logik gezwungen "1". Während$\overline{Q}$ ist zur Logik gezwungen "0". Dies bedeutet, dass der SR-Latch unabhängig von seinem vorherigen Zustand gesetzt wird.

In ähnlicher Weise, wenn S gleich "0" ist und R gleich ist "1" dann wird der Ausgang Q gezwungen "0" während $\overline{Q}$ ist dazu gezwungen "1". Dies bedeutet, dass der Latch unabhängig von seinem zuvor gehaltenen Zustand zurückgesetzt wird. Schließlich, wenn beide Eingänge S und R gleich Logik sind"1" dann werden beide Ausgänge zur Logik gezwungen "0" was im Widerspruch zur Komplementarität von Q und $\overline{Q}$.

Daher ist diese Eingangskombination im normalen Betrieb nicht zulässig. Die Wahrheitstabelle des NOR-basierten SR-Latch ist in der Tabelle angegeben.

S. R. Q. $\overline{Q}$ Betrieb
0 0 Q. $\overline{Q}$ Halt
1 0 1 0 einstellen
0 1 0 1 Zurücksetzen
1 1 0 0 Nicht erlaubt

Der auf dem NOR-Gatter basierende CMOS-SR-Latch ist in der folgenden Abbildung dargestellt.

Wenn S gleich V OH und R gleich V OL ist , sind beide parallel geschalteten Transistoren M1 und M2 eingeschaltet. Die Spannung am Knoten$\overline{Q}$wird einen logisch niedrigen Pegel von V OL = 0 annehmen .

Gleichzeitig werden sowohl M3 als auch M4 ausgeschaltet, was zu einer logisch hohen Spannung V OH am Knoten Q führt. Wenn R gleich V OH und S gleich V OL ist , werden M1 und M2 ausgeschaltet und M3 und M4 eingeschaltet.

SR Latch basierend auf NAND Gate

Das Blockschaltbild und das Gate-Level-Schema des NAND-basierten SR-Latch sind in der Abbildung dargestellt. Die kleinen Kreise an den Eingangsanschlüssen S und R zeigen an, dass die Schaltung auf aktive niedrige Eingangssignale reagiert. Die Wahrheitstabelle des NAND-basierten SR-Latch ist in der Tabelle angegeben

S. R. Q. Q '
0 0 NC NC Keine Änderung. Latch blieb im gegenwärtigen Zustand.
1 0 1 0 Latch SET.
0 1 0 1 Latch RESET.
1 1 0 0 Ungültiger Zustand.

Wenn S auf 0 geht (während R = 1), geht Q hoch und zieht $\overline{Q}$ niedrig und der Latch wechselt in den Set-Zustand

S = 0 dann ist Q = 1 (wenn R = 1)

Wenn R auf 0 geht (während S = 1), geht Q hoch und zieht $\overline{Q}$ niedrig und die Verriegelung ist Reset

R = 0 dann ist Q = 1 (wenn S = 1)

Der Haltezustand erfordert, dass sowohl S als auch R hoch sind. Wenn S = R = 0, ist die Ausgabe nicht zulässig, da dies zu einem unbestimmten Zustand führen würde. Der auf dem NAND-Gatter basierende CMOS-SR-Latch ist in der Abbildung dargestellt.

Der auf dem NAND-Gatter basierende nMOS SR-Latch mit Verarmungslast ist in der Abbildung dargestellt. Die Operation ähnelt der des CMOS NAND SR-Latch. Die CMOS-Schaltungsimplementierung weist eine geringe statische Verlustleistung und einen hohen Rauschabstand auf.

CMOS-Logikschaltungen

Getaktete SR-Verriegelung

Die Abbildung zeigt einen NOR-basierten SR-Latch mit einem hinzugefügten Takt. Der Latch reagiert nur dann auf die Eingänge S und R, wenn CLK hoch ist.

Wenn CLK niedrig ist, behält der Latch seinen aktuellen Zustand bei. Beachten Sie, dass Q den Zustand ändert -

  • Wenn S während des positiven CLK hoch geht.
  • An der führenden CLK-Flanke nach Änderungen in S & R während der niedrigen CLK-Zeit.
  • Ein positiver Fehler in S, während CLK hoch ist
  • Wenn R während des positiven CLK hoch geht.

Die CMOS-AOI-Implementierung eines getakteten NOR-basierten SR-Latch ist in der Abbildung dargestellt. Beachten Sie, dass nur 12 Transistoren erforderlich sind.

  • Wenn CLK niedrig ist, sind zwei Reihenanschlüsse in N Baum N offen und zwei parallele Transistoren in Baum P sind EIN, wodurch der Zustand in der Speicherzelle beibehalten wird.

  • Wenn der Takt hoch ist, wird die Schaltung einfach zu einem NOR-basierten CMOS-Latch, der auf die Eingänge S und R reagiert.

Clocked SR Latch based on NAND Gate

Die Schaltung ist mit vier NAND-Gattern implementiert. Wenn diese Schaltung mit CMOS implementiert ist, benötigt sie 16 Transistoren.

  • Der Latch reagiert nur dann auf S oder R, wenn CLK hoch ist.
  • Wenn sowohl die Eingangssignale als auch die CLK-Signale aktiv hoch sind: dh der Latch-Ausgang Q wird gesetzt, wenn CLK = "1" S = "1" und R = "0"
  • In ähnlicher Weise wird der Latch zurückgesetzt, wenn CLK = "1", S = "0" und

Wenn CLK niedrig ist, behält der Latch seinen aktuellen Zustand bei.

Getaktete JK-Verriegelung

Die obige Abbildung zeigt einen getakteten JK-Latch basierend auf NAND-Gattern. Der Nachteil eines SR-Latches besteht darin, dass sein Ausgangszustand unbestimmt wird, wenn sowohl S als auch R hoch sind. Der JK-Latch beseitigt dieses Problem, indem er eine Rückmeldung von Ausgabe zu Eingabe verwendet, so dass alle Eingangszustände der Wahrheitstabelle zulässig sind. Wenn J = K = 0 ist, behält der Latch seinen aktuellen Zustand bei.

Wenn J = 1 und K = 0 ist, wird der Latch bei der nächsten positiv verlaufenden Taktflanke gesetzt, dh Q = 1, $\overline{Q}$ = 0

Wenn J = 0 und K = 1 ist, wird der Zwischenspeicher bei der nächsten positiv verlaufenden Taktflanke zurückgesetzt, dh Q = 1 und $\overline{Q}$ = 0.

Wenn J = K = 1 ist, schaltet der Latch bei der nächsten positiv verlaufenden Taktflanke um

Die Funktionsweise des getakteten JK-Latch ist in der in der Tabelle angegebenen Wahrheitstabelle zusammengefasst.

J

K

Q

$\overline{Q}$

S

R

Q

$\overline{Q}$

Operation

0 0 0 1 1 1 0 1 Halt
1 0 1 1 1 0
0 1 0 1 1 1 0 1 Zurücksetzen
1 0 1 0 0 1
1 0 0 1 0 1 1 0 einstellen
1 0 1 1 1 0
1 1 0 1 0 1 1 0 Umschalten
1 0 1 0 0 1

CMOS D Latch-Implementierung

Der D-Latch wird normalerweise mit TG-Schaltern (Transmission Gate) implementiert, wie in der Abbildung gezeigt. Der Eingang TG wird mit CLK aktiviert, während die Latch-Rückkopplungsschleife TG mit CLK aktiviert wird. Eingang D wird akzeptiert, wenn CLK hoch ist. Wenn CLK auf Low geht, ist der Eingang offen und der Latch wird mit den vorherigen Daten D gesetzt.

VHDL steht für eine sehr schnelle Hardwarebeschreibungssprache für integrierte Schaltkreise. Es ist eine Programmiersprache, mit der ein digitales System anhand von Datenfluss, Verhalten und strukturellem Modellierungsstil modelliert wird. Diese Sprache wurde erstmals 1981 für das Verteidigungsministerium (DoD) im Rahmen des VHSIC-Programms eingeführt.

Ein Design beschreiben

In VHDL wird eine Entität verwendet, um ein Hardwaremodul zu beschreiben. Eine Entität kann beschrieben werden mit:

  • Entitätserklärung
  • Architecture
  • Configuration
  • Paketdeklaration
  • Paketkörper

Mal sehen, was das sind?

Entitätserklärung

Es definiert die Namen, Eingangs- und Ausgangssignale und Modi eines Hardwaremoduls.

Syntax - -

entity entity_name is
   Port declaration;
end entity_name;

Eine Entitätsdeklaration sollte mit 'entity' beginnen und mit 'end' Schlüsselwörtern enden. Die Richtung wird eingegeben, ausgegeben oder eingegeben.

Im Port kann gelesen werden
aus Port kann geschrieben werden
Inout Port kann gelesen und geschrieben werden
Puffer Port kann gelesen und geschrieben werden, es kann nur eine Quelle haben.

Architecture - -

Architektur kann mit Struktur, Datenfluss, Verhalten oder gemischtem Stil beschrieben werden.

Syntax - -

architecture architecture_name of entity_name 
architecture_declarative_part;

begin
   Statements;
end architecture_name;

Hier sollten wir den Entitätsnamen angeben, für den wir den Architekturkörper schreiben. Die Architekturanweisungen sollten sich innerhalb der Schlüsselwörter 'begin' und 'énd' befinden. Der deklarative Architekturteil kann Variablen, Konstanten oder Komponentendeklarationen enthalten.

Datenflussmodellierung

In diesem Modellierungsstil wird der Datenfluss durch die Entität unter Verwendung eines gleichzeitigen (parallelen) Signals ausgedrückt. Die gleichzeitigen Anweisungen in VHDL lauten WHEN und GENERATE.

Außerdem können Zuweisungen, die nur Operatoren (AND, NOT, +, *, sll usw.) verwenden, auch zum Erstellen von Code verwendet werden.

Schließlich kann auch eine spezielle Art von Zuweisung, BLOCK genannt, in dieser Art von Code verwendet werden.

Im gleichzeitigen Code kann Folgendes verwendet werden:

  • Operators
  • Die WHEN-Anweisung (WHEN / ELSE oder WITH / SELECT / WHEN);
  • Die GENERATE-Anweisung;
  • Die BLOCK-Anweisung

Verhaltensmodellierung

In diesem Modellierungsstil wird das Verhalten einer Entität als Satz von Anweisungen nacheinander in der angegebenen Reihenfolge ausgeführt. Nur Anweisungen, die in einem PROCESS, einer FUNCTION oder einem PROCEDURE platziert sind, sind sequentiell.

PROCESSES, FUNCTIONS und PROCEDURES sind die einzigen Codeabschnitte, die nacheinander ausgeführt werden.

Insgesamt stimmt jedoch jeder dieser Blöcke mit anderen außerhalb des Blocks platzierten Anweisungen überein.

Ein wichtiger Aspekt des Verhaltenscodes ist, dass er nicht auf sequentielle Logik beschränkt ist. In der Tat können wir damit sowohl sequentielle als auch kombinatorische Schaltungen bauen.

Die Verhaltensanweisungen lauten IF, WAIT, CASE und LOOP. VARIABLEN sind ebenfalls eingeschränkt und dürfen nur im sequentiellen Code verwendet werden. VARIABLE kann niemals global sein, daher kann sein Wert nicht direkt weitergegeben werden.

Strukturmodellierung

In dieser Modellierung wird eine Entität als eine Reihe miteinander verbundener Komponenten beschrieben. Eine Komponenteninstanziierungsanweisung ist eine gleichzeitige Anweisung. Daher ist die Reihenfolge dieser Aussagen nicht wichtig. Der strukturelle Modellierungsstil beschreibt nur eine Verbindung von Komponenten (als Black Box angesehen), ohne dass dies ein Verhalten der Komponenten selbst oder der Entität impliziert, die sie gemeinsam darstellen.

In der Strukturmodellierung besteht der Architekturkörper aus zwei Teilen - dem deklarativen Teil (vor dem Beginn des Schlüsselworts) und dem Anweisungsteil (nach dem Beginn des Schlüsselworts).

Logikbetrieb - UND TOR

X. Y. Z.
0 0 0
0 1 0
1 0 0
1 1 1

VHDL Code:
Library ieee;
use ieee.std_logic_1164.all;

entity and1 is
   port(x,y:in bit ; z:out bit);
end and1;

architecture virat of and1 is
begin
   z<=x and y; 
end virat;

Wellenformen

Logikbetrieb - ODER-Gatter

X. Y. Z.
0 0 0
0 1 1
1 0 1
1 1 1

VHDL Code: 
Library ieee; 
use ieee.std_logic_1164.all;  

entity or1 is
   port(x,y:in bit ; z:out bit); 
end or1; 
 
architecture virat of or1 is
begin
   z<=x or y; 
end virat;

Wellenformen

Logikbetrieb - NICHT Tor

X. Y.
0 1
1 0

VHDL Code:
  
Library ieee; 
use ieee.std_logic_1164.all; 
 
entity not1 is
   port(x:in bit ; y:out bit); 
end not1; 
 
architecture virat of not1 is
begin
   y<=not x;
end virat;

Wellenformen

Logikbetrieb - NAND-Gatter

X. Y. z
0 0 1
0 1 1
1 0 1
1 1 0

VHDL Code:
  
Library ieee; 
use ieee.std_logic_1164.all; 

entity nand1 is
   port(a,b:in bit ; c:out bit); 
end nand1; 
 
architecture virat of nand1 is
begin
   c<=a nand b; 
end virat;

Wellenformen

Logikbetrieb - NOR-Gatter

X. Y. z
0 0 1
0 1 0
1 0 0
1 1 0

VHDL Code: 
 
Library ieee; 
use ieee.std_logic_1164.all; 
 
entity nor1 is
   port(a,b:in bit ; c:out bit); 
end nor1; 
 
architecture virat of nor1 is
begin
   c<=a nor b;
end virat;

Wellenformen

Logikbetrieb - XOR-Gatter

X. Y. Z.
0 0 1
0 1 1
1 0 1
1 1 0

VHDL Code: 
 
Library ieee; 
use ieee.std_logic_1164.all;
  
entity xor1 is
   port(a,b:in bit ; c:out bit); 
end xor1;
  
architecture virat of xor1 is
begin
   c<=a xor b; 
end virat;

Wellenformen

Logikbetrieb - X-NOR-Gatter

X. Y. Z.
0 0 1
0 1 1
1 0 1
1 1 0

VHDL Code: 
 
Library ieee; 
use ieee.std_logic_1164.all; 

entity xnor1 is
   port(a,b:in bit ; c:out bit); 
end xnor1; 
 
architecture virat of xnor1 is
begin
   c<=not(a xor b); 
end virat;

Wellenformen

In diesem Kapitel wird die VHDL-Programmierung für kombinatorische Schaltungen erläutert.

VHDL-Code für einen Halbaddierer

VHDL Code:
  
Library ieee; 
use ieee.std_logic_1164.all;
  
entity half_adder is
   port(a,b:in bit; sum,carry:out bit); 
end half_adder; 
 
architecture data of half_adder is
begin
   sum<= a xor b;  
   carry <= a and b;  
end data;

Wellenformen

VHDL-Code für einen Volladdierer

Library ieee; 
use ieee.std_logic_1164.all;
 
entity full_adder is port(a,b,c:in bit; sum,carry:out bit); 
end full_adder;
  
architecture data of full_adder is
begin
   sum<= a xor b xor c; 
   carry <= ((a and b) or (b and c) or (a and c)); 
end data;

Wellenformen

VHDL-Code für einen Halb-Subtrahierer

Library ieee;
use ieee.std_logic_1164.all;
  
entity half_sub is
   port(a,c:in bit; d,b:out bit);
end half_sub;  

architecture data of half_sub is
begin
   d<= a xor c;
   b<= (a and (not c));
end data;

Wellenformen

VHDL-Code für einen vollständigen Subtrahierer

Library ieee; 
use ieee.std_logic_1164.all;
  
entity full_sub is
   port(a,b,c:in bit; sub,borrow:out bit); 
end full_sub; 
 
architecture data of full_sub is
begin
   sub<= a xor b xor c; 
   borrow <= ((b xor c) and (not a)) or (b and c); 
end data;

Wellenformen

VHDL-Code für einen Multiplexer

Library ieee; 
use ieee.std_logic_1164.all;
  
entity mux is
   port(S1,S0,D0,D1,D2,D3:in bit; Y:out bit);
end mux;
  
architecture data of mux is
begin 
   Y<= (not S0 and not S1 and D0) or 
      (S0 and not S1 and D1) or 
      (not S0 and S1 and D2) or
      (S0 and S1 and D3); 
end data;

Wellenformen

VHDL-Code für einen Demultiplexer

Library ieee; 
use ieee.std_logic_1164.all;
  
entity demux is
   port(S1,S0,D:in bit; Y0,Y1,Y2,Y3:out bit); 
end demux;
  
architecture data of demux is
begin 
   Y0<=  ((Not S0) and (Not S1) and D); 
   Y1<=  ((Not S0) and S1 and D); 
   Y2<=  (S0 and (Not S1) and D); 
   Y3<=  (S0 and S1 and D); 
end data;

Wellenformen

VHDL-Code für einen 8 x 3-Encoder

library ieee; 
use ieee.std_logic_1164.all; 
 
entity enc is
   port(i0,i1,i2,i3,i4,i5,i6,i7:in bit; o0,o1,o2: out bit); 
end enc; 
 
architecture vcgandhi of enc is
begin 
   o0<=i4 or i5 or i6 or i7; 
   o1<=i2 or i3 or i6 or i7; 
   o2<=i1 or i3 or i5 or i7; 
end vcgandhi;

Wellenformen

VHDL-Code für einen 3 x 8-Decoder

library ieee; 
use ieee.std_logic_1164.all;

entity dec is
   port(i0,i1,i2:in bit; o0,o1,o2,o3,o4,o5,o6,o7: out bit); 
end dec; 
 
architecture vcgandhi of dec is
begin 
   o0<=(not i0) and (not i1) and (not i2); 
   o1<=(not i0) and (not i1) and i2; 
   o2<=(not i0) and i1 and (not i2); 
   o3<=(not i0) and i1 and i2; 
   o4<=i0 and (not i1) and (not i2); 
   o5<=i0 and (not i1) and i2; 
   o6<=i0 and i1 and (not i2); 
   o7<=i0 and i1 and i2; 
end vcgandhi;

Wellenformen

VHDL-Code - 4-Bit-Paralleladdierer

library IEEE; 
use IEEE.STD_LOGIC_1164.all;
  
entity pa is
   port(a : in STD_LOGIC_VECTOR(3 downto 0);
      b : in STD_LOGIC_VECTOR(3 downto 0);
      ca : out STD_LOGIC;
      sum : out STD_LOGIC_VECTOR(3 downto 0) 
   ); 
end pa; 
 
architecture vcgandhi of pa is
   Component fa is
      port (a : in STD_LOGIC; 
         b : in STD_LOGIC; 
         c : in STD_LOGIC; 
         sum : out STD_LOGIC; 
         ca : out STD_LOGIC
      ); 
   end component;         
   signal s : std_logic_vector (2 downto 0); 
   signal temp: std_logic;
begin 
   temp<='0'; 
   u0 : fa port map (a(0),b(0),temp,sum(0),s(0)); 
   u1 : fa port map (a(1),b(1),s(0),sum(1),s(1)); 
   u2 : fa port map (a(2),b(2),s(1),sum(2),s(2));
   ue : fa port map (a(3),b(3),s(2),sum(3),ca);  
end vcgandhi;

Wellenformen

VHDL-Code - 4-Bit-Paritätsprüfung

library ieee; 
use ieee.std_logic_1164.all; 
 
entity parity_checker is 
   port (a0,a1,a2,a3 : in std_logic; 
      p : out std_logic); 
end parity_checker;  

architecture vcgandhi of parity_checker is 
begin    
   p <= (((a0 xor a1) xor a2) xor a3); 
end vcgandhi;

Wellenformen

VHDL-Code - 4-Bit-Paritätsgenerator

library ieee;
use ieee.std_logic_1164.all;

entity paritygen is
   port (a0, a1, a2, a3: in std_logic; p_odd, p_even: out std_logic);
end paritygen;  

architecture vcgandhi of paritygen is
begin
   process (a0, a1, a2, a3)
   
	if (a0 ='0' and a1 ='0' and a2 ='0' and a3 =’0’)
      then odd_out <= "0";
      even_out <= "0";
   else
      p_odd <= (((a0 xor a1) xor a2) xor a3);
      p_even <= not(((a0 xor a1) xor a2) xor a3);  
end vcgandhi

Wellenformen

In diesem Kapitel wird die VHDL-Programmierung für sequentielle Schaltungen erläutert.

VHDL-Code für einen SR-Latch

library ieee; 
use ieee.std_logic_1164.all;
  
entity srl is 
   port(r,s:in bit; q,qbar:buffer bit); 
end srl;  

architecture virat of srl is 
   signal s1,r1:bit; 
begin 
   q<= s nand qbar; 
   qbar<= r nand q; 
end virat;

Wellenformen

VHDL-Code für einen D-Latch

library ieee; 
use ieee.std_logic_1164.all;

entity Dl is 
   port(d:in bit; q,qbar:buffer bit); 
end Dl; 
 
architecture virat of Dl is 
   signal s1,r1:bit; 
begin 
   q<= d nand qbar; 
   qbar<= d nand q; 
end virat;

Wellenformen

VHDL-Code für ein SR Flip Flop

library ieee; 
use ieee.std_logic_1164.all;
  
entity srflip is 
   port(r,s,clk:in bit; q,qbar:buffer bit); 
end srflip;
  
architecture virat of srflip is 
   signal s1,r1:bit; 
begin 
   s1<=s nand clk; 
   r1<=r nand clk;
   q<= s1 nand qbar;
   qbar<= r1 nand q;
end virat;

Wellenformen

VHDL-Code für ein JK Flip Flop

library IEEE; 
use IEEE.STD_LOGIC_1164.all;  

entity jk is 
   port(
      j : in STD_LOGIC; 
      k : in STD_LOGIC; 
      clk : in STD_LOGIC; 
      reset : in STD_LOGIC; 
      q : out STD_LOGIC; 
      qb : out STD_LOGIC 
   ); 
end jk;
  
architecture virat of jk is 
begin 
   jkff : process (j,k,clk,reset) is 
   variable m : std_logic := '0'; 
   
   begin 
      if (reset = '1') then 
         m : = '0'; 
      elsif (rising_edge (clk)) then 
         if (j/ = k) then
            m : = j; 
         elsif (j = '1' and k = '1') then 
            m : = not m; 
         end if; 
      end if; 
      
      q <= m; 
      qb <= not m; 
   end process jkff; 
end virat;

Wellenformen

VHDL-Code für ein D-Flip-Flop

Library ieee; 
use ieee.std_logic_1164.all;  

entity dflip is 
   port(d,clk:in bit; q,qbar:buffer bit); 
end dflip; 
 
architecture virat of dflip is 
   signal d1,d2:bit; 
begin 
   d1<=d nand clk; 
   d2<=(not d) nand clk; 
   q<= d1 nand qbar; 
   qbar<= d2 nand q; 
end virat;

Wellenformen

VHDL-Code für ein T-Flip-Flop

library IEEE; 
use IEEE.STD_LOGIC_1164.all;  

entity Toggle_flip_flop is 
   port( 
      t : in STD_LOGIC; 
      clk : in STD_LOGIC; 
      reset : in STD_LOGIC; 
      dout : out STD_LOGIC
   ); 
end Toggle_flip_flop;  

architecture virat of Toggle_flip_flop is 
begin 
   tff : process (t,clk,reset) is 
   variable m : std_logic : = '0'; 
   
   begin 
      if (reset = '1') then 
         m : = '0'; 
      elsif (rising_edge (clk)) then 
         if (t = '1') then 
            m : = not m;        
         end if; 
      end if; 
      dout < = m; 
   end process tff; 
end virat;

Wellenformen

VHDL-Code für einen 4-Bit-Aufwärtszähler

library IEEE; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all;
  
entity counter is 
   port(Clock, CLR : in std_logic; 
      Q : out std_logic_vector(3 downto 0)
   ); 
end counter;  

architecture virat of counter is 
   signal tmp: std_logic_vector(3 downto 0); 
begin 
   process (Clock, CLR) 
   
   begin 
      if (CLR = '1') then 
         tmp < = "0000"; 
      elsif (Clock'event and Clock = '1') then 
         mp <= tmp + 1; 
      end if; 
   end process; 
   Q <= tmp; 
end virat;

Wellenformen

VHDL-Code für einen 4-Bit-Abwärtszähler

library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all;
  
entity dcounter is 
   port(Clock, CLR : in std_logic; 
      Q : out std_logic_vector(3 downto 0)); 
end dcounter; 
 
architecture virat of dcounter is 
   signal tmp: std_logic_vector(3 downto 0); 

begin 
   process (Clock, CLR) 
   begin 
      if (CLR = '1') then 
         tmp <= "1111"; 
      elsif (Clock'event and Clock = '1') then 
         tmp <= tmp - 1; 
      end if; 
   end process; 
   Q <= tmp; 
end virat;

Wellenformen

Verilog ist eine HARDWARE-BESCHREIBUNGSSPRACHE (HDL). Diese Sprache beschreibt ein digitales System wie einen Netzwerk-Switch oder einen Mikroprozessor oder einen Speicher oder ein Flip-Flop. Mit einem HDL können wir jede digitale Hardware auf jeder Ebene beschreiben. Entwürfe, die in HDL beschrieben werden, sind unabhängig von der Technologie, sehr einfach zu entwerfen und zu debuggen und normalerweise nützlicher als Schaltpläne, insbesondere für große Schaltungen.

Verilog unterstützt ein Design auf vielen Abstraktionsebenen. Die drei wichtigsten sind -

  • Verhaltensstufe
  • Register-Transfer-Level
  • Torebene

Verhaltensstufe

Diese Ebene beschreibt ein System durch gleichzeitige Algorithmen (Behavioral). Jeder Algorithmus ist sequentiell, dh er besteht aus einer Reihe von Anweisungen, die einzeln ausgeführt werden. Funktionen, Aufgaben und Blöcke sind die Hauptelemente. Die strukturelle Realisierung des Entwurfs wird nicht berücksichtigt.

Register - Transfer Level

Entwürfe, die den Registerübertragungspegel verwenden, spezifizieren die Eigenschaften einer Schaltung unter Verwendung von Operationen und der Übertragung von Daten zwischen den Registern. Die moderne Definition eines RTL-Codes lautet "Jeder synthetisierbare Code wird als RTL-Code bezeichnet".

Gate Level

Innerhalb der logischen Ebene werden die Eigenschaften eines Systems durch logische Verknüpfungen und ihre Timing-Eigenschaften beschrieben. Alle Signale sind diskrete Signale. Sie können nur bestimmte logische Werte haben ("0", "1", "X", "Z"). Die verwendbaren Operationen sind vordefinierte Logikprimitive (Basisgatter). Die Modellierung auf Gate-Ebene ist möglicherweise keine richtige Idee für das Logikdesign. Gate-Level-Code wird mit Tools wie Synthesewerkzeugen generiert und seine Netzliste wird für die Gate-Level-Simulation und für das Backend verwendet.

Lexikalische Token

Verilog-Sprachquelltextdateien sind ein Strom von lexikalischen Token. Ein Token besteht aus einem oder mehreren Zeichen, und jedes einzelne Zeichen befindet sich in genau einem Token.

Die von Verilog HDL verwendeten lexikalischen Grundtoken ähneln denen in der Programmiersprache C. Verilog unterscheidet zwischen Groß- und Kleinschreibung. Alle Schlüsselwörter sind in Kleinbuchstaben.

Leerraum

Leerzeichen können Zeichen für Leerzeichen, Tabulatoren, neue Zeilen und Formular-Feeds enthalten. Diese Zeichen werden ignoriert, es sei denn, sie dienen zur Trennung von Token.

Leerzeichen sind Leerzeichen, Tabulatoren, Zeilenumbrüche, Neue Zeilen und Formular-Feeds.

Bemerkungen

Es gibt zwei Formen, um die Kommentare darzustellen

  • 1) Einzeilige Kommentare beginnen mit dem Token // und enden mit dem Wagenrücklauf.

Bsp.: // Dies ist eine einzeilige Syntax

  • 2) Mehrzeilige Kommentare beginnen mit dem Token / * und enden mit dem Token * /

Bsp.: / * Dies ist eine mehrzeilige Syntax * /

Zahlen

Sie können eine Zahl im Binär-, Oktal-, Dezimal- oder Hexadezimalformat angeben. Negative Zahlen werden in den Komplimentzahlen von 2 dargestellt. Verilog erlaubt Ganzzahlen, reelle Zahlen und vorzeichenbehaftete und vorzeichenlose Zahlen.

Die Syntax wird durch - <Größe> <Radix> <Wert> angegeben

Größe oder nicht dimensionierte Zahl können in <Größe> definiert werden, und <Radix> definiert, ob es sich um eine Binär-, Oktal-, Hexadezimal- oder Dezimalzahl handelt.

Kennungen

Bezeichner ist der Name, mit dem das Objekt definiert wird, z. B. eine Funktion, ein Modul oder ein Register. Bezeichner sollten mit alphabetischen Zeichen oder Unterstrichen beginnen. Ex. A_Z, a_z, _

Bezeichner sind eine Kombination aus alphabetischen, numerischen, Unterstrichen und $ -Zeichen. Sie können bis zu 1024 Zeichen lang sein.

Betreiber

Operatoren sind Sonderzeichen, die zum Setzen von Bedingungen oder zum Bedienen der Variablen verwendet werden. Es gibt ein, zwei und manchmal drei Zeichen, mit denen Operationen an Variablen ausgeführt werden.

Ex. >, +, ~, &! =.

Verilog-Schlüsselwörter

Wörter, die in Verilog eine besondere Bedeutung haben, werden als Verilog-Schlüsselwörter bezeichnet. Weisen Sie beispielsweise case, while, wire, reg und / oder nand und module zu. Sie sollten nicht als Bezeichner verwendet werden. Zu den Verilog-Schlüsselwörtern gehören auch Compiler-Direktiven sowie Systemaufgaben und -funktionen.

Gate Level Modellierung

Verilog verfügt über integrierte Grundelemente wie Logikgatter, Übertragungsgatter und Schalter. Diese werden selten für Entwurfsarbeiten verwendet, aber sie werden in der Welt nach der Synthese zur Modellierung von ASIC / FPGA-Zellen verwendet.

Die Modellierung auf Gate-Ebene weist zwei Eigenschaften auf:

Drive strength- Die Stärke der Ausgangsgatter wird durch die Antriebsstärke definiert. Die Ausgabe ist am stärksten, wenn eine direkte Verbindung zur Quelle besteht. Die Stärke nimmt ab, wenn die Verbindung über einen leitenden Transistor erfolgt, und am wenigsten, wenn die Verbindung über einen Pull-Up / Down-Widerstand erfolgt. Die Antriebsstärke wird normalerweise nicht angegeben. In diesem Fall sind die Stärken standardmäßig strong1 und strong0.

Delays- Wenn keine Verzögerungen angegeben sind, haben die Gates keine Ausbreitungsverzögerungen. Wenn zwei Verzögerungen angegeben sind, repräsentiert die erste die Anstiegsverzögerung und die zweite die Abfallverzögerung. Wenn nur eine Verzögerung angegeben ist, sind sowohl Anstieg als auch Abfall gleich. Verzögerungen können bei der Synthese ignoriert werden.

Torprimitive

Die grundlegenden Logikgatter mit einem Ausgang und vielen Eingängen werden in Verilog verwendet. GATE verwendet eines der Schlüsselwörter - und nand oder nor oder xor xnor zur Verwendung in Verilog für N Anzahl von Eingaben und 1 Ausgabe.

Example:  
   Module gate() 
   Wire ot0; 
   Wire ot1; 
   Wire ot2; 
   
   Reg in0,in1,in2,in3; 
   Not U1(ot0,in0); 
   Xor U2(ot1,in1,in2,in3); 
   And U3(ot2, in2,in3,in0)

Transmission Gate Primitive

Übertragungsgatterprimitive umfassen sowohl Puffer als auch Inverter. Sie haben einen einzelnen Eingang und einen oder mehrere Ausgänge. In der unten gezeigten Gate-Instanziierungssyntax steht GATE entweder für das Schlüsselwort buf oder NOT gate.

Beispiel: Nicht, buf, bufif0, bufif1, notif0, notif1

Kein Wechselrichter

Pufferausgabepuffer

Bufifo - Tristate Buffer, Active Low Enable

Bufif1 - Tristate-Puffer, aktive Hochfreigabe

Notifo - Tristate - Wechselrichter, aktive Low - Freigabe

Notif1 - Tristate-Wechselrichter, aktive Hochfreigabe

Example:  
   Module gate() 
   Wire out0; 
   Wire out1; 
   
   Reg in0,in1;
   Not U1(out0,in0); 
   Buf U2(out0,in0);

Datentypen

Wert gesetzt

Verilog besteht hauptsächlich aus vier Grundwerten. Alle Verilog-Datentypen, die in Verilog verwendet werden, speichern diese Werte -

0 (logische Null oder falsche Bedingung)

1 (logische Eins oder wahre Bedingung)

x (unbekannter logischer Wert)

z (hochohmiger Zustand)

Die Verwendung von x und z ist für die Synthese sehr begrenzt.

Draht

Ein Draht wird verwendet, um einen physischen Draht in einer Schaltung darzustellen, und er wird zum Verbinden von Gates oder Modulen verwendet. Der Wert eines Drahtes kann nur gelesen und nicht in einer Funktion oder einem Block zugewiesen werden. Ein Draht kann keinen Wert speichern, wird jedoch immer durch eine fortlaufende Zuweisungsanweisung oder durch Verbinden des Drahtes mit dem Ausgang eines Gatters / Moduls gesteuert. Andere spezifische Arten von Drähten sind -

Wand (wired-AND) - Hier hängt der Wert von Wand vom logischen UND aller daran angeschlossenen Gerätetreiber ab.

Wor (wired-OR) - Hier hängt der Wert eines Wor vom logischen ODER aller damit verbundenen Gerätetreiber ab.

Tri (three-state) - hier müssen alle mit einem Tri verbundenen Treiber z sein, außer nur einem (der den Wert von Tri bestimmt).

Example: 
   Wire [msb:lsb] wire_variable_list; 
   Wirec // simple wire 
   Wand d; 
   
   Assign d = a; // value of d is the logical AND of 
   Assign d = b; // a and b 
   Wire [9:0] A; // a cable (vector) of 10 wires. 
   
   Wand [msb:lsb] wand_variable_list; 
   Wor [msb:lsb] wor_variable_list; 
   Tri [msb:lsb] tri_variable_list;

Registrieren

Ein reg (register) ist ein Datenobjekt, das den Wert von einer prozeduralen Zuordnung zur nächsten enthält und nur in verschiedenen Funktionen und prozeduralen Blöcken verwendet wird. Eine Registrierung ist ein einfaches Verilog-Register vom Variablentyp und kann kein physikalisches Register implizieren. In Mehrbitregistern werden die Daten in Form von vorzeichenlosen Zahlen gespeichert und die Vorzeichenerweiterung wird nicht verwendet.

Beispiel -

reg c; // einzelne 1-Bit-Registervariable

reg [5: 0] gem; // ein 6-Bit-Vektor;

reg [6: 0] d, e; // zwei 7-Bit-Variablen

Eingabe, Ausgabe, Inout

Diese Schlüsselwörter werden verwendet, um Eingabe-, Ausgabe- und bidirektionale Ports einer Aufgabe oder eines Moduls zu deklarieren. Hier sind die Eingangs- und Ausgangsanschlüsse, die vom Drahttyp und vom Ausgangsanschluss sind, so konfiguriert, dass sie vom Draht-, Reg-, Stab-, Wor- oder Tri-Typ sind. Standard ist immer der Drahttyp.

Example

Module sample(a, c, b, d);  
Input c;   // An input where wire is used. 

Output a, b;  // Two outputs where wire is used. 
Output [2:0] d;  /* A three-bit output. One must declare type in a separate statement. */ 
reg [1:0] a;  // The above ‘a’ port is for declaration in reg.

Ganze Zahl

Ganzzahlen werden in Allzweckvariablen verwendet. Sie werden hauptsächlich in Schleifenangaben, Konstanten und Parametern verwendet. Sie sind vom Datentyp 'reg'. Sie speichern Daten als vorzeichenbehaftete Zahlen, während explizit deklarierte Reg-Typen sie als vorzeichenlose Daten speichern. Wenn die Ganzzahl zum Zeitpunkt des Kompilierens nicht definiert ist, beträgt die Standardgröße 32 Bit.

Wenn eine Ganzzahl eine Konstante hält, passt der Synthesizer sie auf die zum Zeitpunkt der Kompilierung erforderliche Mindestbreite an.

Example

Integer c;   // single 32-bit integer 
Assign a = 63;  // 63 defaults to a 7-bit variable.

Supply0, Supply1

Versorgung0 definiert Drähte, die an logisch 0 (Masse) gebunden sind, und Versorgung1 definiert Drähte, die an logisch 1 (Stromversorgung) gebunden sind.

Example

supply0 logic_0_wires; 
supply0 gnd1;  // equivalent to a wire assigned as 0 

supply1 logic_1_wires; 
supply1 c, s;

Zeit

Zeit ist eine 64-Bit-Größe, die in Verbindung mit der $ time-Systemaufgabe verwendet werden kann, um die Simulationszeit zu speichern. Die Zeit wird für die Synthese nicht unterstützt und daher nur für Simulationszwecke verwendet.

Example

time time_variable_list; 
time c; 
c = $time;   //c = current simulation time

Parameter

Ein Parameter definiert eine Konstante, die festgelegt werden kann, wenn Sie ein Modul verwenden, wodurch das Modul während des Instanziierungsprozesses angepasst werden kann.

Example 
Parameter add = 3’b010, sub = 2’b11; 
Parameter n = 3; 
Parameter [2:0] param2 = 3’b110; 

reg [n-1:0] jam; /* A 3-bit register with length of n or above. */ 
always @(z) 
y = {{(add - sub){z}};  

if (z)
begin 
   state = param2[1];
else
   state = param2[2]; 
end

Betreiber

Rechenzeichen

Diese Operatoren führen arithmetische Operationen aus. Die + und - werden entweder als unäre (x) oder binäre (z - y) Operatoren verwendet.

Die Operatoren, die in der arithmetischen Operation enthalten sind, sind -

+ (Addition), - (Subtraktion), * (Multiplikation), / (Division),% (Modul)

Example - -

parameter v = 5;
reg[3:0] b, d, h, i, count; 
h = b + d; 
i = d - v; 
cnt = (cnt +1)%16; //Can count 0 thru 15.

Vergleichsoperatoren

Diese Operatoren vergleichen zwei Operanden und geben das Ergebnis in einem einzelnen Bit 1 oder 0 zurück.

Wire- und Reg-Variablen sind positiv. Somit ist (–3'd001) = = 3'd111 und (–3b001)> 3b110.

Die Operatoren, die in der relationalen Operation enthalten sind, sind -

  • == (gleich)
  • ! = (ungleich)
  • > (größer als)
  • > = (größer oder gleich)
  • <(weniger als)
  • <= (kleiner oder gleich)

Example

if (z = = y) c = 1; 
   else c = 0; // Compare in 2’s compliment; d>b 
reg [3:0] d,b; 

if (d[3]= = b[3]) d[2:0] > b[2:0]; 
   else b[3]; 
Equivalent Statement 
e = (z == y);

Bitweise Operatoren

Bitweise Operatoren, die einen bitweisen Vergleich zwischen zwei Operanden durchführen.

Die Operatoren, die in der bitweisen Operation enthalten sind, sind -

  • & (bitweises UND)
  • | (bitweise ODER)
  • ~ (bitweise NICHT)
  • ^ (bitweises XOR)
  • ~ ^ oder ^ ~ (bitweises XNOR)

Example

module and2 (d, b, c); 
input [1:0] d, b; 
output [1:0] c; 
assign c = d & b; 
end module

Logische Operatoren

Logische Operatoren sind bitweise Operatoren und werden nur für Einzelbitoperanden verwendet. Sie geben einen einzelnen Bitwert 0 oder 1 zurück. Sie können Ganzzahlen oder Gruppen von Bits und Ausdrücken bearbeiten und alle Werte ungleich Null als 1 behandeln. Logische Operatoren werden im Allgemeinen in bedingten Anweisungen verwendet, da sie mit Ausdrücken arbeiten.

Die Operatoren, die in der logischen Operation enthalten sind, sind -

  • ! (logisch NICHT)
  • && (logisches UND)
  • || (logisches ODER)

Example

wire[7:0] a, b, c; // a, b and c are multibit variables. 
reg x; 

if ((a == b) && (c)) x = 1; //x = 1 if a equals b, and c is nonzero. 
   else x = !a; // x =0 if a is anything but zero.

Reduktionsoperatoren

Reduktionsoperatoren sind die unäre Form der bitweisen Operatoren und arbeiten mit allen Bits eines Operandenvektors. Diese geben auch einen Einzelbitwert zurück.

Die Operatoren, die in der Reduktionsoperation enthalten sind, sind -

  • & (Reduktion UND)
  • | (Reduktion ODER)
  • ~ & (Reduktion NAND)
  • ~ | (Reduktion NOR)
  • ^ (Reduktion XOR)
  • ~ ^ oder ^ ~ (Reduktion XNOR)

Example

Module chk_zero (x, z); 

Input [2:0] x; 
Output z; 
Assign z = & x; // Reduction AND 
End module

Schichtarbeiter

Verschiebungsoperatoren, die den ersten Operanden um die Anzahl der durch den zweiten Operanden in der Syntax angegebenen Bits verschieben. Freie Positionen werden für beide Richtungen, Links- und Rechtsverschiebung, mit Nullen gefüllt (es gibt keine Verwendungszeichenerweiterung).

Die Operatoren, die im Schichtbetrieb enthalten sind, sind -

  • << (nach links verschieben)
  • >> (nach rechts verschieben)

Example

Assign z = c << 3; /* z = c shifted left 3 bits;

Freie Stellen werden mit Nullen * / besetzt

Verkettungsoperator

Der Verkettungsoperator kombiniert zwei oder mehr Operanden, um einen größeren Vektor zu bilden.

Der in der Verkettungsoperation enthaltene Operator ist - {} (Verkettung)

Example

wire [1:0] a, h; wire [2:0] x; wire [3;0] y, Z; 
assign x = {1’b0, a}; // x[2] = 0, x[1] = a[1], x[0] = a[0] 
assign b = {a, h}; /* b[3] = a[1], b[2] = a[0], b[1] = h[1], 
b[0] = h[0] */ 
assign {cout, b} = x + Z; // Concatenation of a result

Replikationsoperator

Der Replikationsoperator erstellt mehrere Kopien eines Elements.

Der im Replikationsvorgang verwendete Operator ist - {n {item}} (n-fache Replikation eines Elements)

Example

Wire [1:0] a, f; wire [4:0] x; 
Assign x = {2{1’f0}, a}; // Equivalent to x = {0,0,a } 
Assign y = {2{a}, 3{f}}; //Equivalent to y = {a,a,f,f} 
For synthesis, Synopsis did not like a zero replication.

For example:- 
Parameter l = 5, k = 5; 
Assign x = {(l-k){a}}

Bedingter Operator

Der bedingte Operator synthetisiert zu einem Multiplexer. Es ist die gleiche Art wie in C / C ++ und wertet einen der beiden Ausdrücke basierend auf der Bedingung aus.

Der im bedingten Betrieb verwendete Operator ist -

(Bedingung) ? (Ergebnis, wenn die Bedingung erfüllt ist) -

(Ergebnis wenn Bedingung falsch)

Example

Assign x = (g) ? a : b; 
Assign x = (inc = = 2) ? x+1 : x-1; 
/* if (inc), x = x+1, else x = x-1 */

Operanden

Literale

Literale sind Operanden mit konstantem Wert, die in Verilog-Ausdrücken verwendet werden. Die beiden häufig verwendeten Verilog-Literale sind -

  • String - Ein String-Literal-Operand ist ein eindimensionales Array von Zeichen, die in doppelte Anführungszeichen ("") eingeschlossen sind.

  • Numeric - Ein Operand mit konstanter Zahl wird in Binär-, Oktal-, Dezimal- oder Hexadezimalzahl angegeben.

Example

n - Ganzzahl, die die Anzahl der Bits darstellt

F - eines von vier möglichen Basisformaten -

b für binär, o für oktal, d für dezimal, h für hexadezimal.

“time is”  // string literal 
267        // 32-bit decimal number 
2’b01      // 2-bit binary 
20’hB36F   // 20-bit hexadecimal number 
‘062       // 32-bit octal number

Drähte, Regs und Parameter

Drähte, Register und Parameter sind die Datentypen, die als Operanden in Verilog-Ausdrücken verwendet werden.

Bitauswahl “x [2]” und Teileauswahl “x [4: 2]”

Bitauswahl und Teilauswahl werden verwendet, um ein Bit bzw. mehrere Bits aus einem Draht-, Register- oder Parametervektor unter Verwendung der eckigen Klammern „[]“ auszuwählen. Bitauswahl und Teilauswahl werden ebenso wie ihre Hauptdatenobjekte als Operanden in Ausdrücken verwendet.

Example

reg [7:0] x, y; 
reg [3:0] z; 
reg a; 
a = x[7] & y[7];      // bit-selects 
z = x[7:4] + y[3:0];  // part-selects

Funktionsaufrufe

In den Funktionsaufrufen wird der Rückgabewert einer Funktion direkt in einem Ausdruck verwendet, ohne dass er zuerst einem Register oder einer Leitung zugewiesen werden muss. Es wird lediglich der Funktionsaufruf als einer der Operandentypen platziert. Es ist erforderlich, um sicherzustellen, dass Sie die Bitbreite des Rückgabewerts des Funktionsaufrufs kennen.

Example  
Assign x = y & z & chk_yz(z, y); // chk_yz is a function 

. . ./* Definition of the function */ 
Function chk_yz; // function definition 
Input z,y; 
chk_yz = y^z; 
End function

Module

Moduldeklaration

In Verilog ist ein Modul die Hauptentwurfseinheit. Dies gibt den Namen und die Portliste (Argumente) an. Die nächsten Zeilen geben den Eingabe- / Ausgabetyp (Eingabe, Ausgabe oder Eingang) und die Breite jedes Ports an. Die Standardportbreite beträgt nur 1 Bit. Die Portvariablen müssen per Draht, Stab, deklariert werden. . ., reg. Die Standardportvariable ist wire. Normalerweise sind die Eingänge drahtgebunden, da ihre Daten außerhalb des Moduls zwischengespeichert werden. Die Ausgänge sind vom Reg-Typ, wenn ihre Signale darin gespeichert sind.

Example

module sub_add(add, in1, in2, out); 
input add; // defaults to wire 
input [7:0] in1, in2; wire in1, in2; 

output [7:0] out; reg out; 
... statements ... 
End module

Kontinuierliche Zuordnung

Die fortlaufende Zuweisung in einem Modul wird zum Zuweisen eines Werts zu einem Draht verwendet. Dies ist die normale Zuordnung, die außerhalb von Always- oder Anfangsblöcken verwendet wird. Diese Zuweisung erfolgt mit einer expliziten Zuweisungsanweisung oder um einem Draht während seiner Deklaration einen Wert zuzuweisen. Kontinuierliche Zuordnung wird zum Zeitpunkt der Simulation kontinuierlich ausgeführt. Die Reihenfolge der Zuweisungsanweisungen hat keinen Einfluss darauf. Wenn Sie das Eingangssignal auf der rechten Seite ändern, ändert sich das Ausgangssignal auf der linken Seite.

Example

Wire [1:0] x = 2’y01;   // assigned on declaration 
Assign y = c | d;       // using assign statement 
Assign d = a & b; 
/* the order of the assign statements does not matter. */

Modulinstanziierungen

Moduldeklarationen sind Vorlagen zum Erstellen tatsächlicher Objekte. Module werden in anderen Modulen instanziiert, und bei jeder Instanziierung wird aus dieser Vorlage ein einzelnes Objekt erstellt. Die Ausnahme ist das Modul der obersten Ebene, das eine eigene Instanziierung darstellt. Die Ports des Moduls müssen mit denen übereinstimmen, die in der Vorlage definiert sind. Es ist angegeben -

  • By nameVerwenden Sie dazu den Punkt ".template port name (Name des an den Port angeschlossenen Kabels)". Oder

  • By positionPlatzieren Sie die Ports an derselben Stelle in den Portlisten sowohl der Vorlage als auch der Instanz.

Example

MODULE DEFINITION 
Module and4 (x, y, z); 
Input [3:0] x, y; 
Output [3:0] z; 
Assign z = x | y; 
End module

Verhaltensmodelle in Verilog enthalten prozedurale Anweisungen, die die Simulation steuern und Variablen der Datentypen manipulieren. Diese alle Aussagen sind in den Verfahren enthalten. Jeder Prozedur ist ein Aktivitätsfluss zugeordnet.

Während der Simulation des Verhaltensmodells beginnen alle durch die Anweisungen 'always' und 'initial' definierten Flüsse zum Simulationszeitpunkt 'zero' zusammen. Die anfänglichen Anweisungen werden einmal ausgeführt, und die Always-Anweisungen werden wiederholt ausgeführt. In diesem Modell werden die Registervariablen a und b zum Simulationszeitpunkt 'Null' auf binär 1 bzw. 0 initialisiert. Die erste Anweisung ist dann abgeschlossen und wird während dieses Simulationslaufs nicht erneut ausgeführt. Diese anfängliche Anweisung enthält einen Anfang-Ende-Block (auch als sequentieller Block bezeichnet) von Anweisungen. In diesem Anfangstyp-Block wird a zuerst initialisiert, gefolgt von b.

Beispiel für Verhaltensmodellierung

module behave; 
reg [1:0]a,b; 

initial 
begin 
   a = ’b1; 
   b = ’b0; 
end 

always 
begin 
   #50 a = ~a; 
end 

always 
begin 
   #100 b = ~b; 
end 
End module

Verfahrensaufgaben

Prozedurale Zuweisungen dienen zum Aktualisieren von Reg-, Integer-, Zeit- und Speichervariablen. Es gibt einen signifikanten Unterschied zwischen prozeduraler Zuweisung und kontinuierlicher Zuweisung, wie unten beschrieben -

Kontinuierliche Zuweisungen steuern Netzvariablen und werden ausgewertet und aktualisiert, wenn ein Eingabeoperand den Wert ändert.

Prozedurale Zuweisungen aktualisieren den Wert von Registervariablen unter der Kontrolle der sie umgebenden prozeduralen Flusskonstrukte.

Die rechte Seite einer prozeduralen Zuweisung kann ein beliebiger Ausdruck sein, der einen Wert ergibt. Teileauswahlen auf der rechten Seite müssen jedoch konstante Indizes haben. Die linke Seite gibt die Variable an, die die Zuweisung von der rechten Seite erhält. Die linke Seite einer prozeduralen Aufgabe kann eine der folgenden Formen annehmen:

  • Register-, Ganzzahl-, Real- oder Zeitvariable - Eine Zuordnung zur Namensreferenz eines dieser Datentypen.

  • Bitauswahl eines Registers, einer Ganzzahl, einer Real- oder Zeitvariablen - Eine Zuordnung zu einem einzelnen Bit, bei der die anderen Bits unberührt bleiben.

  • Teilauswahl eines Registers, einer Ganzzahl, einer Real- oder Zeitvariablen - Eine Teilauswahl von zwei oder mehr zusammenhängenden Bits, die den Rest der Bits unberührt lässt. Für das Teileauswahlformular sind nur konstante Ausdrücke zulässig.

  • Speicherelement - Ein einzelnes Wort eines Speichers. Beachten Sie, dass Bitauswahl und Teilauswahl bei Speicherelementreferenzen unzulässig sind.

  • Verkettung einer der oben genannten Formen - Es kann eine Verkettung einer der vorherigen vier Formen angegeben werden, die das Ergebnis des Ausdrucks auf der rechten Seite effektiv partitioniert und die Partitionsteile der Reihe nach den verschiedenen Teilen der Verkettung zuordnet.

Zuordnungsverzögerung (nicht zur Synthese)

Bei einer verzögerten Zuweisung vergehen Δt Zeiteinheiten, bevor die Anweisung ausgeführt und die Zuweisung für die linke Hand vorgenommen wird. Bei einer Verzögerung innerhalb der Zuweisung wird die rechte Seite sofort ausgewertet, es gibt jedoch eine Verzögerung von Δt, bevor das Ergebnis in die Zuweisung für die linke Hand eingefügt wird. Wenn eine andere Prozedur während Δt ein Signal auf der rechten Seite ändert, wirkt sich dies nicht auf die Ausgabe aus. Verzögerungen werden von Synthesewerkzeugen nicht unterstützt.

Syntax

  • Procedural AssignmentVariable = Ausdruck

  • Delayed assignment# Δt Variable = Ausdruck;

  • Intra-assignment delayVariable = # Δt Ausdruck;

Beispiel

reg [6:0] sum; reg h, ziltch; 
sum[7] = b[7] ^ c[7]; // execute now. 
ziltch = #15 ckz&h; /* ckz&a evaluated now; ziltch changed 
after 15 time units. */ 

#10 hat = b&c; /* 10 units after ziltch changes, b&c is
evaluated and hat changes. */

Zuweisungen blockieren

Eine blockierende prozedurale Zuweisungsanweisung muss vor der Ausführung der darauf folgenden Anweisungen in einem sequentiellen Block ausgeführt werden. Eine blockierende prozedurale Zuweisungsanweisung verhindert nicht die Ausführung von Anweisungen, die ihr in einem parallelen Block folgen.

Syntax

Die Syntax für eine blockierende prozedurale Zuweisung lautet wie folgt:

<lvalue> = <timing_control> <expression>

Wobei lvalue ein Datentyp ist, der für eine prozedurale Zuweisungsanweisung gültig ist, = der Zuweisungsoperator ist und die Zeitsteuerung die optionale Verzögerung innerhalb der Zuweisung ist. Die Zeitsteuerungsverzögerung kann entweder eine Verzögerungssteuerung (zum Beispiel # 6) oder eine Ereignissteuerung (zum Beispiel @ (posedge clk)) sein. Der Ausdruck ist der Wert auf der rechten Seite, den der Simulator der linken Seite zuweist. Der Zuweisungsoperator =, der zum Blockieren von prozeduralen Zuweisungen verwendet wird, wird auch von prozeduralen fortlaufenden Zuweisungen und fortlaufenden Zuweisungen verwendet.

Beispiel

rega = 0; 
rega[3] = 1;            // a bit-select 
rega[3:5] = 7;          // a part-select 
mema[address] = 8’hff;  // assignment to a memory element 
{carry, acc} = rega + regb;  // a concatenation

Nicht blockierende (RTL) Zuweisungen

Mit der nicht blockierenden prozeduralen Zuweisung können Sie Zuweisungen planen, ohne den prozeduralen Ablauf zu blockieren. Sie können die nicht blockierende prozedurale Anweisung verwenden, wenn Sie mehrere Registerzuweisungen innerhalb desselben Zeitschritts vornehmen möchten, ohne Rücksicht auf Reihenfolge oder Abhängigkeit voneinander.

Syntax

Die Syntax für eine nicht blockierende prozedurale Zuweisung lautet wie folgt:

<lvalue> <= <timing_control> <expression>

Wenn lvalue ein Datentyp ist, der für eine prozedurale Zuweisungsanweisung gültig ist, ist <= der nicht blockierende Zuweisungsoperator und die Zeitsteuerung die optionale Zeitsteuerung innerhalb der Zuweisung. Die Zeitsteuerungsverzögerung kann entweder eine Verzögerungssteuerung oder eine Ereignissteuerung sein (zum Beispiel @ (posedge clk)). Der Ausdruck ist der Wert auf der rechten Seite, den der Simulator der linken Seite zuweist. Der nicht blockierende Zuweisungsoperator ist derselbe Operator, den der Simulator für den weniger als ungleichen relationalen Operator verwendet. Der Simulator interpretiert den Operator <= als relationalen Operator, wenn Sie ihn in einem Ausdruck verwenden, und den Operator <= als Zuweisungsoperator, wenn Sie ihn in einem nicht blockierenden prozeduralen Zuweisungskonstrukt verwenden.

Wie der Simulator nicht blockierende prozedurale Zuweisungen bewertet Wenn der Simulator auf eine nicht blockierende prozedurale Zuweisung stößt, bewertet der Simulator die nicht blockierende prozedurale Zuweisung und führt sie in zwei Schritten aus:

  • Der Simulator wertet die rechte Seite aus und plant die Zuweisung des neuen Werts zu einem Zeitpunkt, der durch eine prozedurale Zeitsteuerung festgelegt wird. Der Simulator wertet die rechte Seite aus und plant die Zuweisung des neuen Werts zu einem Zeitpunkt, der durch eine prozedurale Zeitsteuerung festgelegt wird.

  • Am Ende des Zeitschritts, in dem die angegebene Verzögerung abgelaufen ist oder das entsprechende Ereignis stattgefunden hat, führt der Simulator die Zuweisung aus, indem er den Wert der linken Seite zuweist.

Beispiel

module evaluates2(out); 
output out; 
reg a, b, c; 
initial 

begin 
   a = 0; 
   b = 1; 
   c = 0; 
end 
always c = #5 ~c; 
always @(posedge c) 

begin 
   a <= b; 
   b <= a; 
end 
endmodule

Bedingungen

Die bedingte Anweisung (oder if-else-Anweisung) wird verwendet, um eine Entscheidung darüber zu treffen, ob eine Anweisung ausgeführt wird oder nicht.

Formal lautet die Syntax wie folgt:

<statement> 
::= if ( <expression> ) <statement_or_null> 
||= if ( <expression> ) <statement_or_null> 
   else <statement_or_null> 
<statement_or_null> 

::= <statement> 
||= ;

Der <Ausdruck> wird ausgewertet. Wenn es wahr ist (dh einen bekannten Wert ungleich Null hat), wird die erste Anweisung ausgeführt. Wenn es falsch ist (einen Nullwert hat oder der Wert x oder z ist), wird die erste Anweisung nicht ausgeführt. Wenn eine else-Anweisung vorhanden ist und <expression> false ist, wird die else-Anweisung ausgeführt. Da der numerische Wert des if-Ausdrucks auf Null getestet wird, sind bestimmte Verknüpfungen möglich.

Zum Beispiel drücken die folgenden zwei Anweisungen dieselbe Logik aus:

if (expression) 
if (expression != 0)

Da der else-Teil eines if-else optional ist, kann es zu Verwirrung kommen, wenn ein else in einer verschachtelten if-Sequenz weggelassen wird. Dies wird behoben, indem das else immer mit dem nächstgelegenen vorherigen verknüpft wird, wenn das else fehlt.

Beispiel

if (index > 0) 
if (rega > regb) 
   result = rega; 
   else // else applies to preceding if 
   result = regb; 

If that association is not what you want, use a begin-end block statement 
to force the proper association 

if (index > 0) 
begin 

if (rega > regb) 
result = rega; 
end 
   else 
   result = regb;

Konstruktion von: if- else- if

Die folgende Konstruktion kommt so oft vor, dass es sich lohnt, eine kurze separate Diskussion zu führen.

Example

if (<expression>) 
   <statement> 
   else if (<expression>) 
   <statement> 
   else if (<expression>) 
   <statement> 
   else  
   <statement>

Diese Folge von ifs (bekannt als if-else-if-Konstrukt) ist die allgemeinste Art, eine Mehrwegentscheidung zu schreiben. Die Ausdrücke werden der Reihe nach ausgewertet. Wenn ein Ausdruck wahr ist, wird die ihm zugeordnete Anweisung ausgeführt, wodurch die gesamte Kette beendet wird. Jede Anweisung ist entweder eine einzelne Anweisung oder ein Anweisungsblock.

Der letzte else-Teil des if-else-if-Konstrukts behandelt den Fall 'keine der oben genannten' oder den Standardfall, in dem keine der anderen Bedingungen erfüllt war. Manchmal gibt es keine explizite Aktion für die Standardeinstellung. In diesem Fall kann das nachfolgende else weggelassen oder zur Fehlerprüfung verwendet werden, um einen unmöglichen Zustand zu erfassen.

Fallbeschreibung

Die case-Anweisung ist eine spezielle Mehrwegentscheidungsanweisung, die prüft, ob ein Ausdruck mit einer Reihe anderer Ausdrücke übereinstimmt, und entsprechend verzweigt. Die case-Anweisung ist nützlich, um beispielsweise die Decodierung eines Mikroprozessorbefehls zu beschreiben. Die case-Anweisung hat die folgende Syntax:

Example

<statement> 
::= case ( <expression> ) <case_item>+ endcase 
||= casez ( <expression> ) <case_item>+ endcase 
||= casex ( <expression> ) <case_item>+ endcase 
<case_item> 
::= <expression> <,<expression>>* : <statement_or_null> 
||= default : <statement_or_null> 
||= default <statement_or_null>

Die Fallausdrücke werden in der genauen Reihenfolge ausgewertet und verglichen, in der sie angegeben sind. Wenn während der linearen Suche einer der Ausdrücke für Fallelemente mit dem Ausdruck in Klammern übereinstimmt, wird die diesem Fallelement zugeordnete Anweisung ausgeführt. Wenn alle Vergleiche fehlschlagen und das Standardelement angegeben ist, wird die Standardelementanweisung ausgeführt. Wenn die Standardanweisung nicht angegeben wird und alle Vergleiche fehlschlagen, wird keine der Anweisungen für Fallelemente ausgeführt.

Abgesehen von der Syntax unterscheidet sich die case-Anweisung in zwei wichtigen Punkten vom Mehrweg-if-else-if-Konstrukt:

  • Die bedingten Ausdrücke im if-else-if-Konstrukt sind allgemeiner als der Vergleich eines Ausdrucks mit mehreren anderen, wie in der case-Anweisung.

  • Die case-Anweisung liefert ein endgültiges Ergebnis, wenn ein Ausdruck x- und z-Werte enthält.

Schleifenanweisungen

Es gibt vier Arten von Schleifenanweisungen. Sie bieten eine Möglichkeit, die Ausführung einer Anweisung null, einmal oder mehrmals zu steuern.

  • führt für immer kontinuierlich eine Anweisung aus.

  • repeat führt eine Anweisung eine feste Anzahl von Malen aus.

  • while führt eine Anweisung aus, bis ein Ausdruck falsch wird. Wenn der Ausdruck mit false beginnt, wird die Anweisung überhaupt nicht ausgeführt.

  • zur Steuerung der Ausführung der zugehörigen Anweisung (en) durch einen dreistufigen Prozess wie folgt:

    • Führt eine Zuweisung aus, die normalerweise zum Initialisieren einer Variablen verwendet wird, die die Anzahl der ausgeführten Schleifen steuert

    • Wertet einen Ausdruck aus. Wenn das Ergebnis Null ist, wird die for-Schleife beendet. Wenn es nicht Null ist, führt die for-Schleife die zugehörigen Anweisungen aus und führt dann Schritt 3 aus

    • Führt eine Zuweisung aus, die normalerweise zum Ändern des Werts der Schleifensteuerungsvariablen verwendet wird, und wiederholt dann Schritt 2

Im Folgenden sind die Syntaxregeln für die Schleifenanweisungen aufgeführt:

Example

<statement> 
::= forever <statement> 
||=forever 
begin 
   <statement>+ 
end  

<Statement> 
::= repeat ( <expression> ) <statement> 
||=repeat ( <expression> ) 
begin
   <statement>+ 
end  

<statement> 
::= while ( <expression> ) <statement> 
||=while ( <expression> ) 
begin 
   <statement>+ 
end  
<statement> 
::= for ( <assignment> ; <expression> ; <assignment> ) 
<statement> 
||=for ( <assignment> ; <expression> ; <assignment> ) 
begin 
   <statement>+ 
end

Verzögerungssteuerung

Verzögerungssteuerung

Die Ausführung einer prozeduralen Anweisung kann mithilfe der folgenden Syntax verzögert gesteuert werden:

<statement> 
::= <delay_control> <statement_or_null> 
<delay_control> 
::= # <NUMBER> 
||= # <identifier> 
||= # ( <mintypmax_expression> )

Das folgende Beispiel verzögert die Ausführung der Zuordnung um 10 Zeiteinheiten -

# 10 rega = regb;

Die nächsten drei Beispiele enthalten einen Ausdruck nach dem Nummernzeichen (#). Die Ausführung der Zuweisung verzögert sich um die Simulationszeit, die durch den Wert des Ausdrucks angegeben wird.

Ereignissteuerung

Die Ausführung einer prozeduralen Anweisung kann mit einer Wertänderung in einem Netz oder Register oder dem Auftreten eines deklarierten Ereignisses mithilfe der folgenden Ereignissteuerungssyntax synchronisiert werden:

Example

<statement> 
::= <event_control> <statement_or_null> 

<event_control> 
::= @ <identifier> 
||= @ ( <event_expression> ) 

<event_expression> 
::= <expression> 
||= posedge <SCALAR_EVENT_EXPRESSION> 
||= negedge <SCALAR_EVENT_EXPRESSION> 
||= <event_expression> <or <event_expression>>

* <SCALAR_EVENT_EXPRESSION> ist ein Ausdruck, der in einen Ein-Bit-Wert aufgelöst wird.

Wertänderungen an Netzen und Registern können als Ereignisse verwendet werden, um die Ausführung einer Anweisung auszulösen. Dies wird als Erkennen eines impliziten Ereignisses bezeichnet. Mit der Verilog-Syntax können Sie Änderungen auch anhand der Richtung der Änderung erkennen, dh in Richtung des Werts 1 (Posedge) oder des Werts 0 (Negedge). Das Verhalten von posedge und negedge für unbekannte Ausdruckswerte ist wie folgt:

  • Beim Übergang von 1 nach unbekannt und von unbekannt nach 0 wird ein Negedge erkannt
  • Beim Übergang von 0 nach unbekannt und von unbekannt nach 1 wird ein Posedge erkannt

Prozeduren: Immer und Anfangsblöcke

Alle Prozeduren in Verilog werden in einem der folgenden vier Blöcke angegeben. 1) Anfangsblöcke 2) Immer Blöcke 3) Aufgabe 4) Funktion

Die anfänglichen und immer-Anweisungen werden zu Beginn der Simulation aktiviert. Die Anfangsblöcke werden nur einmal ausgeführt und ihre Aktivität stirbt, wenn die Anweisung beendet ist. Im Gegensatz dazu werden die Always-Blöcke wiederholt ausgeführt. Seine Aktivität stirbt nur, wenn die Simulation beendet wird. Die Anzahl der Anfangs- und immer Blöcke, die in einem Modul definiert werden können, ist unbegrenzt. Aufgaben und Funktionen sind Prozeduren, die an einer oder mehreren Stellen in anderen Prozeduren aktiviert werden.

Anfangsblöcke

Die Syntax für die ursprüngliche Anweisung lautet wie folgt:

<initial_statement> 
::= initial <statement>

Das folgende Beispiel zeigt die Verwendung der Anfangsanweisung zur Initialisierung von Variablen zu Beginn der Simulation.

Initial 
Begin 
   Areg = 0; // initialize a register 
   For (index = 0; index < size; index = index + 1) 
   Memory [index] = 0; //initialize a memory 
   Word 
End

Eine andere typische Verwendung der anfänglichen Blöcke ist die Spezifikation von Wellenformbeschreibungen, die einmal ausgeführt werden, um den Hauptteil der zu simulierenden Schaltung zu stimulieren.

Initial 
Begin 
   Inputs = ’b000000; 
   // initialize at time zero 
   #10 inputs = ’b011001; // first pattern 
   #10 inputs = ’b011011; // second pattern 
   #10 inputs = ’b011000; // third pattern 
   #10 inputs = ’b001000; // last pattern 
End

Blockiert immer

Die Anweisung 'always' wird während des gesamten Simulationslaufs kontinuierlich wiederholt. Die Syntax für die always-Anweisung ist unten angegeben

<always_statement> 
::= always <statement>

Die 'always'-Anweisung ist aufgrund ihrer Schleifenfunktion nur dann nützlich, wenn sie in Verbindung mit einer Form der Zeitsteuerung verwendet wird. Wenn eine 'always'-Anweisung keine Zeit zum Vorrücken bietet, erstellt die' always'-Anweisung eine Simulations-Deadlock-Bedingung. Der folgende Code erstellt beispielsweise eine Endlosschleife mit null Verzögerung -

Always areg = ~areg;

Durch die Bereitstellung einer Zeitsteuerung für den obigen Code wird eine potenziell nützliche Beschreibung erstellt - wie im folgenden Beispiel -

Always #half_period areg = ~areg;