VGA im FPGA – Der VGA-Controller

Zynq FPGA

Nachdem wir nun einige Grundlagen über das Processing System und eigene IP-Cores gelernt haben, widmen wir uns wieder dem FPGA des Zynq. In diesem Artikel stelle ich euch eine Möglichkeit vor, wie ihr einen alten VGA Monitor an das FPGA anbinden und ansteuern könnt. Da diese Aufgabe etwas länger wird unterteile ich den Artikel in zwei Sektionen:

  1. Die Erstellung eines eigenen VGA-Controllers zur Generierung aller Signale
  2. Der VGA-Controller wird zur Ausgabe eines Bildes genutzt

In diesem Artikel zeige ich euch wie ein VGA-Signal aufgebaut ist und wie ihr einen einfachen VGA-Controller in das FPGA bauen könnt.

-> Ein paar Grundlagen zum VGA:

Bevor ich damit beginne einen VGA-Controller zu entwerfen, müssen ein paar Grundlagen zum VGA bekannt sein.
Beim VGA handelt es sich um einen analog/digitalen Übertragungsstandard für Bildsignale. Das Bild wird Zeilenweise übertragen und dabei hat jedes Pixel eine fest definierte Dauer.
Die Farbinformationen eines Pixels liegen als analoge Spannungen an und werden bei jedem Pixel neu eingelesen.
Sobald eine Zeile zu Ende ist, wird ein Horizontal-Synchronisationssignal ausgelöst, wodurch der Monitor die Zeile wechselt und wieder an den Anfang einer Zeile springt.
Wenn alle Zeilen durchlaufen sind, löst der VGA-Controller ein Horizontal-Synchronisationssignal aus, wodurch der Monitor wieder an die Anfangsposition springt.
Neben dem sichtbaren Teil besitzt jedes Bild noch eine rechte und eine linke, sowie eine obere und untere Schwarzschuler.
Diese Schwarzschultern dienen dazu die Zeit zu überbrücken bis der Elektronenstrahl an den Anfang der nächsten Zeile, bzw. an den Bildanfang gesprungen ist.
Ein komplettes Bild sieht also so aus:

VGA(1)
Der VGA-Standard kommt aus der Zeit der Röhrenmonitore und da benötigten die Elektronenstrahlen eine gewisse Zeit um an eine Position zu springen. Hätte man die Schwarzschultern nicht eingeführt, würde bei jedem Zeilenwechsel ein Teil des Bildes fehlen und es wäre zudem noch verschoben, da sich der Elektronenstrahl noch nicht an der Startposition befunden hätte.
Durch dieses Bild wird der Vorgang des Zeilenwechsels etwas verdeutlicht:

VGA Pixel
Quelle: www.google.de

Ein VGA-Stecker hat folgende Pinbelegung:

VGA(2)
Quelle: www.wikipedia.com

Für unsere Zwecke werden folgende Pins benötigt:

  • 1 – 3 für die Farben
  • 5-8, 10 als Masse
  • 13 Horizontales Synchronisationssignal (Low Aktiv)
  • 14 Vertikales Synchronisationssignal (Low Aktiv)

Mit diesem Wissen kann man nun mit dem Entwurf des VGA-Controllers beginnen.

-> Entwurf des VGA-Controllers:

Da die Farben des Bildes durch analoge Spannungen generiert werden, ein FPGA aber in der Regel nur über digitale Ausgänge verfügt, muss man an den Ausgängen Spannungsteiler platzieren um die Spannungen zu erzeugen, wie es beim Zybo der Fall ist:

VGA(3)
Quelle: Schaltplan Zybo

Die genauen Timings für das VGA-Signal kann man dieser Seite entnehmen.
Für den Anfang soll der Controller für ein 640×480 Pixel Display ausgelegt sein. Daraus ergeben sich nun folgende Daten, die für das Projekt wichtig sind:

  • Pixeltakt 25,175MHz

Für eine einzelne Zeile:

  • Sichtbarer Bereich 25,422µs oder 640 Pixel
  • Linke Schwarzschulter (Back porch) 1,9µs oder 48 Pixel
  • Rechte Schwarzschulter (Front porch) 0,635µs oder 16 Pixel
  • Sync Puls 3,81µs oder 96 Pixel
  • Gesamte Zeile 31,777µs oder 800 Pixel

Für ein komplettes Bild

  • Sichtbarer Bereich 15,253ms oder 480 Reihen
  • Linke Schwarzschulter (Back porch) 1,04ms oder 33 Reihen
  • Rechte Schwarzschulter (Front porch) 0,3177ms oder 10 Reihen
  • Sync Puls 0,063ms oder 2 Reihen
  • Gesamtes Bild 16,683ms oder 480 Reihen

Der VGA-Controller muss also alle 31,77µs den Horizontalsync für 3,81µs und alle 16,68ms den Vertikalsync für 0,063ms auf Low ziehen, eben immer genau dann, wenn eine Zeile bzw. ein komplettes Bild abgeschlossen wurde.
Da das Zybo nur einen 125MHz Takt besitzt, ich aber 25,175MHz brauche, kann kein einfacher Taktteiler verwendet werden (theoretisch würde es gehen, aber dann müssten alle Pixelwerte neu berechnet werden).
Daher verwende ich ein Clocking Wizard Modul um den Takt zu erzeugen. Dieses Modul ist in Vivado als IP-Core hinterlegt. Es muss also erst ein Blockschaltbild erzeugt werden, wo dann der IP-Core eingefügt wird:

VGA(4)
Der IP-Core muss anschließend noch konfiguriert werden:

VGA(5)
Praktischer weise können die IP-Cores aus dem Blockschaltbild im eigenen VHDL-Code instanziiert werden. Vivado stellt dafür sogar ein Beispiel bereit:

VGA(6)
Mit diesem Beispiel kann der Clocking Wizard direkt im eigenen Code eingefügt werden:

Im Moment befindet sich der Clocking Wizard noch direkt im Code für den VGA-Controller. Später wird er aber daraus entfernt, da dem VGA-Controller dann der richtige Takt einfach nur zur Verfügung gestellt wird und die Takterzeugung nichts mit dem Controller an sich zu tun hat.
Wie ihr seht, habe ich dem VGA-Controller zusätzlich noch einige Anschlüsse verpasst:

  • HSync – Der Ausgang für den Horizontal Sync
  • VSync – Der Ausgang für den Vertikal Sync
  • Clock_VGA – Der Eingang für den 25,175MHz Takt
  • Reset – Zum Deaktivieren des Controllers
  • x_out – Die aktuelle x-Koordinate des Bildes vom Controller
  • y_out – Die aktuelle y-Koordinate des Bildes vom Controller

Der eigentliche VGA-Controller besteht aus drei Prozessen, die bei jedem Taktimpuls ausgelöst werden.
Der erste Prozess zählt die Pixel einer Zeile der Reihe nach durch und erhöht einen weiteren Zähler für die Reihen sobald 800 Pixel gezählt wurden.
Zudem steuert dieser Prozess auch die Erzeugung der H-Synch und V-Synch Signale:

Sobald der Pixelcounter den 703 erreicht hat wird der Pin für den H-Sync auf Low gezogen und bleibt so lange Low bis der Counter den Wert 800 erreicht hat.

Das selbe Verfahren verwende ich für den V-Sync. Es müssen nur die Werte angepasst werden.

Damit wären die Hardwaresignale generiert. Theoretisch kann jetzt schon ein Bild ausgegeben werden.
Für die spätere Bildausgabe ist es aber ganz praktisch, wenn man bereits fertige x und y Koordinaten des „Elektronenstahls“ hat. Diese generiere ich mit diesem Teil des Codes:

Sobald der „Elektronenstrahl“ den nicht sichtbaren Bereich verlassen hat werden die Pixel gezählt, aber nur solange wie der Wert kleiner als 640 ist.
Dieser Wert entspricht auf dem Monitor später den Pixeln 0 – 639. Das Pixel 640 verwende ich als „Reset“-Wert den der Zähler annimmt zum pausieren.
Sobald der Wert größer ist, ist der „Elektronenstrahl“ im nicht sichtbaren Bereich und diese Pixel brauche ich nicht zählen.
Für die y-Koordinate übernehme ich das Prinzip, nur das ich nebenbei noch warten muss bis der Pixelcounter den Wert 799 erreicht hat (erst dann ist eine Zeile zu Ende).

Damit wäre der VGA-Controller einsatzbereit. Im nächsten Schritt zeige ich euch dann wie ihr ein Bild generieren könnt.

 

Dokumentation:

 

-> Zurück zum FPGA + VHDL Tutorial

3 thoughts on “VGA im FPGA – Der VGA-Controller
  1. Hallo,

    ich hätte eine kleine Anmerkung bzw. Frage zu der VHDL-Beschreibung zur Erzeugung von H-Sync und V-Sync.

    if(Pixel_Counter = 800) then
    HSync <= '1';
    end if;

    Dieser Bereich kann meiner Meinung nach gar nicht erreicht werden, da vorher der Pixelcounter schon wieder bei 799 zurück gesetzt wird:

    if(Pixel_Counter = 799) then
    Pixel_Counter <= 0;
    Line_Counter <= Line_Counter + 1;
    end if;

    Oder habe ich hier einen Denkfehler.
    Danke und Gruß

    • Hallo paul,

      du hast Recht. In dem Artikel stehen noch alte Codeschnipsel drin. Ich habe in letzter Zeit etwas an dem Core weiter gearbeitet und bissl debugt. Allerdings habe ich vergessen den Artikel zu aktualisieren.
      Die Zeile muss lauten:

      if(Pixel_Counter = 799) then
      HSync <= '1'; end if; Ich korrigiere das heute Abend mal. Mit was machst du den VGA? Auch mit einem Zybo? Weil dann würde ich dich quasi als "Testperson" missbrauchen wollen um meinen IP-Core zu testen :) Gruß Daniel

  2. Ich mache gerade die ersten Versuche mit dem Zybo und bin auf der Suche nach Einstieg und Projekten auf deine Seite aufmerksam geworden. Ein VGA-Projekt kommt eventuell in Frage.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

Time limit is exhausted. Please reload CAPTCHA.