Vorheriger AbschnittNächster AbschnittInhaltsverzeichnis

2.3.3 Die Ansteuerung des 20x2-Zeichen-Displays "display.vhd"

Die andere der beiden in eine eigene Beschreibung ausgelagerten Funktionseinheiten ist die Ansteuerung des 20x2-Zeichen-Displays in der Datei display.vhd.

Wie aus dem Blockschaltbild der Display-Steuerung (3.3.3) hervorgeht, umfaßt sie folgende Komponenten:

Nachfolgend sind obige Punkte in der Reihenfolge ihres erstmaligen Erscheinens in der VHDL-Beschreibung erläutert.

Die Pufferung der Zustände des zweiten Automaten: c_state2_buffer

Die Beschreibung findet sich in display.vhd im Prozeß ZUSTAENDE_PUFFERN.

Wie man 3.5.2 schreitet der erste Automat nur in den Folgezustand fort, wenn der zweite Automat sich in wechsel befindet. Um Fehler durch sich während der Abfrage ändernde Zustandsbits auszuschließen, werden selbige Bits nicht direkt abgefragt, sondern ein Puffer, in dem mit der Rückflanke der aktuelle Automatenzustand abgelegt wurde.

Damit kann auch hier die saubere Aufgabentrennung der Taktflanken eingehalten werden: Automaten nähren sich von der Vorderflanke, alle von ihnen abhängigen oder -gefragten speichernden Elemente (hier also a_or_d_changed_ff, user_mode_ff, user_disp_ff, c_state2_buffer, disp_d7_ff, disp_e_ff, disp_rs_ff) agieren mit der Rückflanke; die die Regel bestätigende Ausnahme ist user_char. Die Entscheidung für diese Ausnahme war aber nicht inkonsequent sondern im Gegenteil folgerichtig; siehe hierzu Kap. 2.3.5.2 Taktung der Prozesse - Fehlervermeidung.

Die Beschäftigungsanzeige: user_disp_busy

Die Beschreibung findet sich in display.vhd zwischen den Marken

"--- Beschaeftigungsanzeige Anfang ---" und "--- Beschaeftigungsanzeige Ende ---".

Das mit der Rückflanke aktualisierte Signal user_disp_busy zeigt an, ob im User Mode ein Zeichen bereits dargestellt werden konnte oder das Display noch arbeitet. Dies ist besonders deswegen für Programme auf dem Mikrorechner von Bedeutung, weil die Bearbeitung von Befehlen durch das Display mehrere hundert Takte (= ms) dauern kann und in der Länge abhängig ist von der Art (Steuer- oder ASCII-Zeichen).

Zu den Steuermöglichkeiten für das Display siehe 2.3.1.1; sobald das Top-Level-Design erkennt, daß es mit der Anzeige eines Zeichens "losgehen" soll, signalisiert es dieses dem Subdesign für das Display durch user_disp_go '1'. Auch user_disp_busy wird dann gesetzt und bleibt es so lange, bis nach der Anzeige des Zeichens der erste Automat den Zustand user_disp_clear_ff durchläuft.

Die Daten und Steuersignale für das Display: disp_d, disp_d7_out, disp_e, disp_rs, disp_rw

Die Beschreibung findet sich in display.vhd zwischen den Marken

"--- Signale fuer das Display Anfang ---" und

"--- Signale fuer das Display Ende ---".

Die intelligente Anzeige muß von der Display-Ansteuerung mit einigen Signalen versorgt werden: Daten (8 + 1 Bit), Takt und Auswahl Lesen/Schreiben (Busy Flag abfragen oder Zeichen anzeigen). Einiges hiervon ist, nicht ohne Grund, recht aufwendig; schon vorab sei auf die Kommentare in pc_if.vhd verwiesen. Zu den einzelnen Signalen:

disp_d7_out muß noch über einen Tri State-Treiber geführt werden, denn es ist mit dem selben Pin an der Anzeige verbunden, wie der Eingang disp_d7_in, der benutzt wird, wenn das Busy Flag abgefragt wird; aus Platzgründen sitzt der Tri State-Treiber außerhalb des Hilfs-FPGAs. Das ausgehende Signal disp_d7_out ist fest mit e_rs_d[7..0] verbunden, das den Tri State-Treiber steuernde disp_d7_oe ist '1', solange sich der zweite Automat in normal oder halten befindet; in diesen Zuständen liegen die Daten dann stabil an und es wird insgesamt genau eine relevante Flanke auf disp_e erzeugt, so daß das Display mit der Anzeige eines Zeichens beginnt.

Der gegebenenfalls von der Anzeige getriebene Eingang disp_d7_in, d.h. das Busy Flag, wird vom zweiten Automaten im Prozeß HALTEN_UND_WARTEN ausgewertet.

disp_e <= '1' when ((clk = '1') AND (disp_e_ff = '1')) else '0';

Das Signal wird also aktiviert, wenn die Vorderflanke des Taktes eintrifft und das mit der Rückflanke gesetzte disp_e_ff bereits eine '1' enthält. Beachte, daß der Ausgang disp_e damit gegenüber Änderungen der Automatenzustände (und damit des internen Signals e_rs_d[9]) um einen kompletten Takt verzögert ist! Die Logik zur Erzeugung von disp_e_ff spiegelt die zwei Aufgaben von disp_e wieder:

  1. Als Standard ist disp_e_ff '0'.
  1. Zu Beginn des Durchlaufs des zweiten Automaten (in normal) soll höchstens ein Zeichen angezeigt werden, so wie im aktuellen Zustand des ersten Automaten kodiert. Also wird e_rs_d[9] zugewiesen.
  1. Anschließend muß das Busy Flag solange abgefragt werden, bis es nicht mehr '1' ist. Dazu durchläuft der zweite Automat solange wie nötig abwechselnd rw_setup und warte_busy, wobei sich folgendes Zeitverhalten ergibt: Mit der Takt-Vorderflanke wird der neue Zustand rw_setup übernommen. Dieser kann mit der Rückflanke erkannt werden, woraufhin disp_e_ff auf '1' gesetzt wird. Mit der nächsten Vorderflanke folgt warte_busy als Zustand und disp_e geht auf '1'. Da rechtzeitig mit Eintreten von rw_setup das Display in den Lese-Modus geschaltet worden ist (wo es bis zum Verlassen von rw_hold bleiben wird), liefert es rund 60 ns später ein korrektes Busy Flag. Wiederum mit der Rückflanke kann dieses dann von disp_d7_ff gepuffert werden. Die Zustandsübergangslogik hat somit noch knapp 500 ns Zeit, um bis zur nächsten Vorderflanke einen Folgezustand zu ermitteln.

Es erwies sich außerdem als notwendig, das Signal über das Flipflop disp_rs_ff zu ziehen (siehe 2.4.4), das selbstverständlich mit der Rückflanke getaktet wird.

Im Gegensatz zu disp_rs ist hier kein Flipflop gegen Hazards notwendig, weil disp_rw über 100 ns konstant bleiben muß, bevor das Display den Modus wechselt (daher die Zustände rw_setup und rw_hold).

Die Pufferung von disp_d7: disp_d7_ff

Die Beschreibung findet sich in display.vhd im Prozeß BUSYFLAG_FLIPFLOP.

Das verwendete 20x2-Zeichen-Display kann das höchstwertige Datenbit disp_d7 dazu verwenden, das Andauern einer Befehlsabarbeitung zu signalisieren (Busy Flag). Dazu muß es zunächst durch disp_rw '1' in den Lese-Modus gebracht werden. Ist die Setup-Zeit von 150 ns verstrichen, kann disp_e auf '1' gezogen werden, woraufhin das Display ca. 60 ns später das Busy Flag liefert, und zwar solange, wie disp_e aktiv bleibt.

Es ist also unmöglich, das Busy Flag mit derselben Vorderflanke, die auch disp_e aktiviert, bereits abzufragen; die folgende Vorderflanke kann aber ebenfalls nicht benutzt werden, denn bei deren Auftreten wird disp_e schon so lange inaktiv gewesen sein, daß das Busy Flag nicht mehr getrieben werden wird. Es bleiben also nur die Rückflanken, mit deren jeder disp_d7_ff das Busy Flag puffert.

Benutzt wird sein Wert vom zweiten Automat der Display-Ansteuerung (in warte_busy).

Das Einstellen des Betriebsmodus: user_mode_ff

Die Beschreibung findet sich in display.vhd im Prozeß USER_MODE_FLIPFLOP.

Der erste Automat wartet die meiste Zeit in wfc (wait for command). Wann er diesen Zustand verläßt, ist primär abhängig von user_mode_ff; ist dieses '0', so reagiert das Display auf geänderte Werte von Adreß- und/oder Datenbus mit deren Neuanzeige. Andernfalls befindet sich die Display-Ansteuerung im User Mode und beginnt mit der Anzeige eines benutzerdefinierten Zeichens, sobald user_disp_go auf '1' geht.

user_mode_ff wird einfach mit der Vorderflanke gesetzt - auf '1', falls (user_disp_set = '1'), auf '0', falls (user_disp_reset = '1'). Zur Entstehung dieser Signale und weiteren Steuermöglichkeiten für das Display siehe 2.3.1.1 .

Die Pufferung von a_or_d_changed: a_or_d_changed_ff

Die Beschreibung findet sich in display.vhd im Prozeß ADRESSE_ODER_DATEN.

Befindet sich die Display-Ansteuerung nicht im User Mode, so soll die Anzeige neu aufgebaut werden, wenn sich die Werte von Adreß- und/oder Datenbus ändern. Ob dieses der Fall ist, wird in ctrl_pur durch ein Schaltnetz detektiert und mit a_or_d_changed weitergemeldet. Damit keine solche Meldung verloren geht, wenn der erste Automat sich gerade nicht im Wartezustand wfc befindet, und weil außerdem der erste Automat erst dann fortschreiten kann, wenn der zweite einen kompletten Durchlauf hinter sich hat, wird statt dessen a_or_d_changed_ff abgefragt. Dieses Flipflop wird mit jeder Vorderflanke gesetzt, falls a_or_d_changed '1' ist, aber erst wieder gelöscht, sobald der erste Automat mit der Anzeige beginnt (also cls erreicht).

Die darzustellenden Daten: Multiplexer und Wandlung nach ASCII

Die Beschreibung findet sich in display.vhd im Prozeß HEX_NACH_ASCII.

Im "Normalbetrieb" soll in der ersten Zeile des Displays eine Adresse als fünfstellige Hexadezimal-Zahl erscheinen, in der zweiten Zeile ein Datum als vierstellige Hexadezimal-Zahl. Es besteht also die Notwendigkeit der Wandlung von jeweils vier Bits des Adreß- bzw. Datenbusses in die ASCII-Kodes für '0' bis '9' und 'A' bis 'F'.

Dazu wählt die obere Logik im Prozeß HEX_NACH_ASCII ständig das zu wandelnde, weil darzustellende Nibble aus den neun möglichen aus (5.4 Bit Adressen, 4.4 Bit Daten); die untere Logik kodiert die sechzehn möglichen Bitkombinationen laufend in die korrespondierenden ASCII-Werte um.

Die zwei Automaten

Die Beschreibung findet sich in display.vhd in den am Dateiende gelegenen Prozessen KONTROLLE, HALTEN_UND_WARTEN, SYNCH_HALTEN_UND_WARTEN und SYNCH.

Die zwei endlichen Automaten der Display-Ansteuerung dienen dazu, ASCII-Zeichen auf der Anzeige auszugeben und zugleich das aufwendige Timing dieser Ausgabe abzuwickeln. Um ihre Funktionsweise grundlegend zu verstehen, muß man die wichtigsten Fakten kennen:

Soll kein Zeichen ausgegeben werden, so ist e_rs_d[9], welches letztenendes auf den Takt für das Display geführt wird, '0'. Dieses ist z.B. beim Warten (Zustand wfc - wait for command) oder nach einem Reset (Zustand wfr - wait for reset) der Fall.

Soll kein ASCII-Zeichen ausgegeben werden, so ist e_rs_d[8] '0'. In den Zuständen init1 bis init4 z.B. wird das Display so konfiguriert und gelöscht.

Das eigentliche anzuzeigende Steuer- oder ASCII-Zeichen ist folglich in e_rs_d[7..0] enthalten.

Daraufhin wird die Anzeige gelöscht (der Cursor automatisch auf die erste Position der ersten Zeile gesetzt), in der ersten Zeile die fünf Hexadezimalstellen der Adresse ausgegeben, ein Zeilenvorschub gesendet (Cursor auf Anfang zweite Zeile) und die vier Stellen des Datums ausgegeben (Zustände cls, a_disp, a_disp2, a_disp3, a_disp4, a_disp5, cr, d_disp, d_disp2, d_disp3, d_disp4 und zurück zu wfc).

Im User Mode wird der Wartezustand wfc verlassen, sobald in ctrl_pur das Signal user_disp_go "ausgeschlagen" hat (weil eine bestimmte Adresse beschrieben wurde, siehe Kap. 2.3.1.1 Das Protokoll für den User Mode des Displays), woraufhin sein Wert in user_disp_ff gespeichert wurde. Es werden nur zwei Zustände durchlaufen: user_disp zeigt das (vorher in den Speicher geschriebene und gepufferte) Zeichen an, user_disp_ff_clear löscht user_disp_ff (und zeigt nichts an); anschließend Rückkehr nach wfc.

Beide Automaten werden mit der Vorderflanke getaktet, die Startzustände lauten wfr und normal. Die Abfrage des Zustands des zweiten Automaten durch den ersten (im Prozeß SYNCH) erfolgt gepuffert durch c_state2_buffer (Aktualisierung mit Rückflanke).

Die Abläufe in den Automaten und ihre Abhängigkeit voneinander finden sich visualisiert in 3.5.2 Automaten zur Ansteuerung von Display und Speicher. Zur weiteren Erklärung der Details sei auf den ausführlich dokumentierten Code verwiesen.


Vorheriger AbschnittNächster AbschnittInhaltsverzeichnis