HES Praktikum, Aufgabe 3a
Character-Display I (Timing, Character-Generator)

Aufgabenstellung

Bauen Sie ein Schwarz/Weiss-Text-Display mit 30 Zeilen zu je 80 Zeichen. Die "Zelle", die ein Zeichen auf dem Bildschirm belegt, ist 8 Pixel breit und 16 Pixel hoch. Die Zellen werden ohne Zwischenraeume auf dem Monitor dargestellt. Es sollen die 256 verschiedenen Zeichen des PC-Zeichensatzes verfuegbar sein. Der Zeichensatz ist fest (Character-Generator im "ROM"), der Bildschirminhalt ist variabel (Display-Memory im "RAM"). ROM und RAM stehen hier in Anfuehrungszeichen, da sie beide durch sogenannte "Embedded Memory Blocks" innerhalb des FPGAs realisiert werden (siehe unten).

Hier eine kurze Erlaeuterung, wie's funktioniert: Ein Timing-Modul erzeugt fortlaufend Adressen, die zum Auslesen des Display-Memories dienen (Textzeile fuer Textzeile, von links nach rechts und von oben nach unten). Das ausgelesene Zeichen (Kodierung wie im PC-Zeichensatz, 8 Bit breit) waehlt aus dem Character-Generator das zugehoerige Pixelmuster aus. Dieses wird, vom Timing-Modul gesteuert, Pixel fuer Pixel ueber den VGA-DAC an den Monitor gesendet. Ausserdem muss das Timing-Modul wie in der vorhergehenden Aufgabe die Synchronsignale fuer den Monitor erzeugen.

Hinweise

In diesem ersten Aufgabenteil soll das Timing-Modul und der Character-Generator gebaut werden. Zuerst sollten Sie sich den zeitlichen Zusammenhang zwischen den Synchronsignalen und den Speicheradressen sowohl des Display-Memories als auch des Character-Generators klarmachen. Runden Sie 30x80 auf 32x128 auf! Dann wird die Adressierung der Speicher einfacher: die Adressen sind gewisse Bits der Synchronsignal-Zaehler. Der Entwurf des Timing-Moduls sollte danach nicht mehr schwer sein.

Benutzen Sie fuer den Character-Generator (und spaeter fuer das Display-Memory) das sogenannte "Block-Memory" unseres FPGAs. Im Datenblatt des FPGAs finden Sie genaue Hinweise dazu. Die Vorbelegung, die ja zumindest fuer den Character-Generator absolut notwendig ist, erledigen Sie am besten mit einer "$readmemb()"-Anweisung in Verilog, die eine Datei in einen Speicher einliest. Das ist offensichtlich nicht synthetisierbar - warum genau? Wenn Sie aber diese Anweisung innerhalb einer "initial"-Anweisung platzieren, erkennt die Synthesesoftware das als eine Vorbelegung des Block-Memories (und die wird beim Laden des Bitstrings in den FPGA mit uebertragen). Ein Zeichensatz, der aus dem BIOS eines PCs ausgelesen wurde, befindet sich in der Datei font-8x16 . Schreiben Sie am besten ein kleines Programm, das diese Spezifikation in die entsprechende Datei zur Initialisierung umwandelt (ohne Rechnerunterstuetzung ist das doch ganz schoen muehsam). Vielleicht haben Sie Verwendung fuer dieses Programm, mit dem ich die genannte Umsetzung erledigt habe.

Zum Testen ihrer Schaltung steuern Sie den Character-Generator statt mit dem Display-Memory (das es ja noch nicht gibt) mit ausgewaehlten Signalen aus dem Timing-Modul an, um die Funktion Ihrer Schaltung zu pruefen (Vorschlag: ASCII-Code = Textzeile * 8 + Textspalte). Beachten Sie dabei unbedingt, dass das Block-RAM getaktet ist: Wenn Sie ein Signal erzeugen, das gleichzeitig mit der Adresse des RAMs wechselt, dann kommt das zugehoerige Datum erst zum naechsten Takt aus dem RAM heraus. Soll also das erzeugte Signal gleichzeitig mit den Daten des RAMs wechseln, benoetigen Sie eine Verzoegerung von einem Takt (also ein D-Flip-Flop) in der Signalleitung.

Das geschilderte Prinzip nennt man "Pipelining". Meine Realisierung des Displays benutzt vierstufiges Pipelining: die erste Stufe ist das Timing-Modul, die zweite ist das Display-Memory, die dritte ist der Character-Generator, und die vierte ist die "Pixelstufe", die die RGB-Signale und die Synchronsignale noch einmal mit dem Takt synchronisiert. ACHTUNG: Bei unserem Board sind die Flip-Flops der Pixelstufe fuer die RGB-Signale bereits im VGA-DAC vorhanden, die fuer die Synchronsignale aber nicht!

HES Praktikum, Aufgabe 3b
Character-Display II (Display-Memory, Test)

Aufgabenstellung

Ergaenzen Sie Ihre Loesung der Aufgabenstellung 3a durch den Bildschirmspeicher, den Sie ebenfalls mittels Block-Memory realisieren.

Hinweise

Verwenden Sie dazu einen Speicher mit zwei Zugaengen ("dual-ported memory")! Dann wird es moeglich, von aussen frei waehlbare Zeichen in das Display-Memory zu schreiben, ohne dass der Auslesebetrieb gestoert wird. Ohne Aufwand kann man das Interface so gestalten, dass nicht nur in den Bildschirmspeicher hineingeschrieben werden kann, sondern auch das Auslesen moeglich ist. Warum ist das insbesondere fuer das "Scrollen" des Bildschirminhalts durch Software wichtig?

Zum Testen Ihrer Loesung kann dieser Controller dienen. Er schreibt definiert Zeichen (welche?) an bestimmte Stellen des Display-Memories (wohin?). Sie koennen ausserdem den Speicher statisch vorbelegen, so wie Sie das mit dem Character-Generator auch schon tun. Dann kann man den Schreibvorgang besser beobachten. Hier ist meine Vorbelegung zusammen mit dem kleinen Programm zur Umwandlung in eine Datei passend fuer eine "$readmemh()"-Anweisung zur Initialisierung des Display-Memories.

ACHTUNG, WICHTIG!

Sie MUESSEN sich IMMER erst ENTLADEN, bevor Sie irgendeinen Teil des FPGA-Bords beruehren! Nichtbeachtung kann zur Zerstoerung der Bauteile durch statische Aufladung fuehren!