Vorheriger AbschnittNächster AbschnittInhaltsverzeichnis

2.3.4 "A guide to Carsten's VHDL"

Um das Lesen und Verstehen der vom Autor verfaßten VHDL-Quellen zu erleichtern, hat dieser versucht, den üblichen Aufbau einer VHDL-Beschreibung beizubehalten. Nach einem Kopf mit Kommentaren und Angaben zur Code-Version folgt deshalb die entity-Deklaration (Ein- und Ausgänge der beschriebenen Einheit), wiederum gefolgt vom großen Block der architecture-Definition.

Diese enthält im Top Level-Design ctrl_pur die Deklarationen der Komponenten "PC-Interface" und "Display-Ansteuerung" (Ein- und Ausgänge). Nur lokal verwendete Signale müssen anschließend deklariert werden. Für die state machines ist dabei auch die Deklaration eines Typen notwendig (Aufzählungstyp, der die Bezeichnungen der Automaten-Zustände enthält). Auf diesen folgt stets die Deklaration aller Signale dieses Typs.

Nach einem BEGIN werden gegebenenfalls Komponenten instanziiert (und angeschlossen), danach folgt bis zum Dateiende die eigentliche Verhaltensbeschreibung, gegliedert in konkurrente Prozesse und (bedingte) konkurrente Signalzuweisungen.

Die Beschreibungen von Automaten finden sich stets am Ende, und zwar in jeweils zwei Prozessen. Der erste beschreibt mit einer einzigen CASE-Anweisung eine Logik, die laufend aus dem gegenwärtigen Zustand (c_state, c_state2, c_rasta) und eventuell zusätzlichen Signalen den Folgezustand ermittelt (m_state, m_state2, m_rasta). Der zweite Prozeß, welcher stets ein "SYNCH" im Namen trägt, führt getaktet die Anweisung c_state m_state (oder entsprechend) aus. Dieser Prozeß folgt dem gleichen Aufbau, wie die Prozesse für weitere speichernde Elemente: In einer IF-Anweisung wird erst asynchron auf einen Reset und dann auf die relevante Clockflanke abgefragt, die gegebenenfalls den Wert eines Registers ändert; im einfachsten Falle müßte es für einen Automaten also heißen:

SYNCH_NUR_EIN_BEISPIEL: process(clk, reset, m_state)

begin

if (reset = '0') then

c_state initialzustand;

elsif (clk'event and clk='1') then -- Vorderflanke

c_state m_state; -- Zustandswechsel

end if;

end process;

Wenn in einer konkurrenten Zuweisung der Form

signal signal_ff when <Bedingung> else <Wert>;

ein Signal aus einem Puffer abgeleitet wird, folgt direkt darauf der Prozeß, der den Wert dieses Puffers bestimmt.

2.3.5 Besondere Designentscheidungen im Detail

Warum statische RAM-Bausteine (SRAMs)?

Als Technik für den Speicher mit wahlfreiem Zugriff (random access memory, RAM) wurde die der statischen Informationsspeicherung gewählt (SRAM), im Gegensatz zu der im Massenmarkt dominierenden dynamischen Technik (DRAM). Warum dieses, obwohl SRAM-Bausteine deutlich teurer sind und ihr Geschwindigkeitsvorteil für das vorliegende Design von Anfang an keine Rolle spielte (ein Takt im einstelligen MHz-Bereich ist von beiden Techniken problemlos ohne Wartezyklen zu bewältigen)?

Der Grund ist die wesentlich einfachere Ansteuerung von SRAMs; diese besitzen keine nach außen hin sichtbare Zeilenstruktur und müssen, anders als DRAMs, auch nicht regelmäßig aufgefrischt werden, um ihren Inhalt nicht zu verlieren. Mit SRAMs konnte also das Ziel, überhaupt funktionsfähigen Speicher zu bauen, schneller erreicht werden; man bedenke hierbei, daß die an dem Projekt teilnehmenden Studenten größtenteils keinerlei Vorkenntnisse im Hardware-Entwurf besaßen noch eine Vielzahl anderer Aufgaben zu lösen hatten.

Kein Nachteil ist die geringere Kapazität des installierten SRAMs - 131072 Worte reichen für Assemblerprogramme vollkommen aus.

Taktung der Prozesse - Fehlervermeidung

Erst getaktete Schaltwerke sind mit vernünftigem Aufwand zu handhaben und erfüllen, falls eine Übertaktung ausgeschlossen wurde und, im Falle von Taktpegelsteuerung, eine Zweiflankensteuerung vorgesehen wurde, meist schnell ihre Spezifikation. Sobald ein Entwurf jedoch über einen endlichen Automaten mit Logik, die dessen Zustände abfragt, hinausgeht, kommt ein neues Feld von Fehlern hinzu.

Betrachten wir hierzu zunächst den einfachsten möglichen Fall: Ein triviales Schaltwerk invertiert mit jedem Takt sein einziges Zustandsflipflop A. Ein Flipflop B soll den Zustand des Schaltwerkes speichern. In diesem Fall ist es noch sicher, beide Flipflops auf dieselbe Taktflanke reagieren zu lassen. Günstigenfalls erreicht die Flanke beide Zeitglieder praktisch gleichzeitig, woraufhin A seinen neuen Wert annimmt und B den alten Wert speichert; B enthält also den im vorherigen Takt aktuellen Wert von A. Daß B sicher den alten und nicht den neuen Wert, oder gar den Übergang zwischen beiden, sieht, liegt am sogenannten propagation delay, also der Zeit, die zwischen Eintreffen der Taktflanke am Takteingang und Erscheinen des neuen Wertes am Ausgang eines Flipflops vergeht; dieses muß größer sein, als der Versatz der Clockflanken an A und B zuzüglich der Haltezeit von B.

Sei nun das Schaltwerk weniger trivial, A und B mithin Bit-Vektoren. Dadurch steigt die Wahrscheinlichkeit, daß die Taktflanke ein Flipflop aus B erst erreicht, wenn schon eines aus A den neuen Wert am Ausgang zeigt; B würde dann einen beliebig falschen Wert enthalten (Zustandscodes, die nur um ein Bit differieren, müssen nicht "verwandte" Zustände bezeichnen). Die Wahrscheinlichkeit wird nochmals erhöht, wenn die Clock sich auf den gleichen Bahnen auf dem FPGA fortpflanzt, wie andere logische Signale auch und eventuell noch aus Logik entsteht (Ableiten der inversen Clock aus der normalen) - die geringe maximale Taktfrequenz (siehe 2.3.5.3) deutet auf relativ große Verzögerungszeiten hin. Weil die Verhaltensbeschreibung in VHDL die Zuordnung der Logik zu den Logikzellen des FPGAs offenläßt, was aus Gründen der Übersichtlichkeit und Handhabbarkeit auch erwünscht ist, können Fehler durch Taktimpulsverschiebungen mit jeder Version eines Designs in der Stärke variieren.

Auf dem Hilfs-FPGA werden Fehler durch kritische Taktimpulsverschiebungen auf zweierlei Arten ausgeschlossen:

  1. Benutzung der globalen Clocknetze der FLEX-Bausteine
    Die Altera FLEX8000-Bausteine stellen zwei Eingänge zur Verfügung, auf denen Signale eingespeist werden können, die mit sehr geringer Verzögerung auf dem gesamten FPGA zur Verfügung stehen. Diese werden für clk und clk_invers benutzt, wobei clk_invers also extern aus clk erzeugt werden muß.
  1. Benutzung unabhängiger Taktflanken
    Der Autor hat sich bemüht, konsequent ein gewisses Schema der Taktung zu befolgen; scheinbare Ausnahmen sind entweder wohl begründet oder prinzipiell in der Sicherheit nicht zu verbessern (weil z.B. nicht bekannt sein kann, welche Taktflanke der Mikroprozessor für die Erzeugung eines bestimmten Signals verwendet). Das Schema lautet:

Man beachte, daß 1. die Problematik der gegeneinander verschobenen Taktflanken bereits entschärft, es aber trotzdem gute Gründe für die gleichzeitige Einhaltung von 2. gibt. Hierzu gehören die Klarheit des Timings, die Irrtümer des Entwerfers seltener macht (Vor- und Nachzeitigkeit sind nach Ansicht des Autors klarer zu erkennen) ebenso wie die Notwendigkeit, gewisse Wartezeiten einzuhalten (beim RAM-Zugriff etc.). Durch die Benutzung beider Taktflanken kann in einem Automaten immer, z.B. mit der Vorderflanke, ein Signal angefordert werden, welches rechtzeitig vor der Rückflanke anliegt und gespeichert wird. Der nächste Automatenzustand kann dann bereits eine andere Aufgabe erfüllen und muß kein Wartezustand sein, was die Automatengröße reduziert.

Ein Beispiel für eine "wohl begründete" Ausnahme wäre: In ctrl_pur.vhd ändert das Register user_char seinen Inhalt mit der Vorderflanke, obwohl es in display.vhd vom ersten, ebenfalls mit der Vorderflanke betriebenen, Automaten benutzt wird.

Dies ist ungefährlich, denn die Gefahr unerwünschten Verhaltens bestünde nur dann, wenn jemand user_char in dem Takt überschriebe, in dem sein Inhalt (im Zustand user_disp) angezeigt wird. Es wäre aber unklug, ein neues Zeichen in user_char abzulegen, ohne sich vergewissert zu haben, daß das alte schon angezeigt wurde, der erste Automat user_disp mithin schon hinter sich hat.

Dies ist sogar wünschenswert, denn user_char puffert den Datenbus, der sich - vom Mikroprozessor getrieben - mit unbekannter Taktflanke oder - vom Hilfs-FPGA getrieben - mit der Rückflanke ändert, weshalb eine Taktung mit der Vorderflanke also erstrebenswerter ist.

Momentane und maximale Taktfrequenz

Das Hilfs-FPGA wird momentan mit 1 MHz getaktet (aus dem Quarzoszillator IC18). Der kritische Pfad, also die zeitintensivste Aneinanderreihung von Gattern und Flipflops, die innerhalb eines Taktes ein Ergebnis liefern muß, hat eine Länge, die eine maximale Taktfrequenz von ca. 6 MHz bei Einflankenbetrieb erlaubt, d.h. 3 MHz bei Nutzung beider Taktflanken.

Die Design-Annahme eines Taktes von (höchstens) 1 MHz wurde an einigen Stellen ausgenutzt, die bei Erhöhung des Taktes zu ändern wären:

2.4 Sonstiges

Anmerkung zur Notation

In Anlehnung an eine früher am Arbeitsbereich TECH in Standardzellen-Technik gefertigte Familie von Prozessoren (Democom 1, 2 und 3) und eine vom Autor im Vorfeld des Hilfs-FPGA-Entwurfs verfaßte VHDL-Beschreibung eines Prozessors für das 81500er-FPGA (Democom '95), ist in den VHDL-Sourcen nahezu ausschließlich von einem "Democom" die Rede. Diese aus Platzgründen gewählte Bezeichnung meint den Mikroprozessor.

In dieser Dokumentation erlaubte sich der Autor bei der Nennung von Arrays ebenfalls aus Platzgründen statt der korrekten VHDL-Syntax

status_reg(1 downto 0)

häufig das aus PASCAL, aber auch AHDL, bekannte

status_reg[1..0].

Altera FLEX8000-Bausteinfamilie

Die FLEX8000-Bausteine von Altera gehören als Teil der FPGA-Familie zu den programmable logic devices, also zu ICs, die nicht in einer fernen Chip-Fabrik mit den Logikfunktionen ausgestattet werden, die sie ausführen sollen, sondern die vor Ort, in diesem Falle also direkt am Arbeitsbereich TECH, programmiert werden können. Damit eignen sie sich hervorragend für Versuchsaufbauten und Prototypen, deren Spezifikation noch im Fluß ist. Auch Fehler können ohne lange Umlaufzeiten schnell beseitigt werden und es ist durchaus ein Vorgehen nach "trial and error" möglich - keine elegante Methode, aber eine, die, im Einzelfall kritisch abgewogen, viel Zeit sparen kann.

Mit den "klassischen" FPGAs von Altera haben die FLEX-Bausteine folgendes gemein:

Die FLEX8000-Familie insbesondere hat folgende Eigenschaften:

Für weitere Informationen und Details sei auf das Datenbuch der Altera-FPGAs verwiesen, sowie auf die Zusammenfassung "ALTERAs Feldprogrammierbare Logik-ICs. Kurzbeschreibung für das FPGA-Praktikum" von André Klindworth.

Die Problematik VHDL <-> AHDL

Altera propagiert für das Abfassen einer Verhaltens- und/oder Strukturbeschreibung von Hardware die Verwendung ihrer firmeneigenen Sprache AHDL (Altera Hardware Description Language), für die ihr Werkzeug Max+plus II ursprünglich ausschließlich ausgelegt war. Aufgrund des proprietären Charakters von AHDL bevorzugte der Autor jedoch den Quasi-Industriestandard VHDL (Very high speed integrated circuit Hardware Description Language). Diese sehr mächtige Sprache verfügt über den Vorzug einer verbindlichen Normung und erfreut sich großer, noch wachsender Akzeptanz und Verbreitung. Wegen der darin begründeten Marktbedeutung bekam auch Max+plus II eine VHDL-Schnittstelle eingebaut, die sich, wie viele Konvertierer, als steter Quell von Ungemach entpuppte.

Positiv ist noch zu beurteilen, daß Max+plus II bei der Detektion von fehlerhaftem bzw. verbesserungswürdigem Code sehr gründlich zu Werke geht und so ein "vhdlan -spc_elab" des Synopsys-VSS Simulators noch an "Ausbeute" übertrifft.

Negativ ist, daß Max+plus II (noch) nicht den vollen Sprachumfang von VHDL unterstützt. So ist es u.a. nicht möglich, mit dem Attribut vektor'range den Wertebereich eines Vektors zu ermitteln. Vektoren werden obendrein nur dann unterstützt, wenn ihre Elemente nicht mit mehr als nur einem Bit zu kodieren sind (was Vektoren von Elementen des Typs std_logic glücklicherweise noch nicht ausschließt, sehr wohl aber nicht-triviale Records, wie z.B. Mikrocodezeilen).

Wer über Fehlermeldungen des Typs "attribute not supported" bzw. "non locally static attribute not supported" rätselt, der hat vermutlich ein speicherndes Element von clk abhängig beschrieben, aber in der sensitivity list des Prozesses versehentlich clk_invers aufgeführt (oder natürlich umgekehrt).

Lediglich unschön ist es, daß explizit als Don't Care definierte Signale (mittels '-', z.B. e_rs_d  "00­­­­­­­­";) immer als '0' angenommen werden; dies beschert dem Entwerfer eine Flut an Warnings und eventuell ein zu früh gefülltes FPGA. Desweiteren fehlt eine elegante Möglichkeit, auf die Zustandskodierung von endlichen Automaten Einfluß zu nehmen - nur die Auskodierung durch Verwendung von ebenso vielen Konstanten wie Automatenzuständen ist möglich.

Beliebte Fehler - Hinweise für zukünftige Entwürfe

Unerfüllte Wünsche


Vorheriger AbschnittNächster AbschnittInhaltsverzeichnis