FPGA VGA Puffer. Wie lese und schreibe ich?


8

Ich habe ein Altera DE2-Board und versuche, Sprites zu zeichnen. Ich habe Probleme beim Implementieren eines Bildschirmpuffers.

Ich habe eine Anzeigeeinheit, die mit einer Rate von 25 MHz Pixel für die VGA-Anzeige ausgibt.

Ich hatte gehofft, einen Puffer in SDRAM zu implementieren. Die ursprüngliche Idee war, Pixel das nächste Pixel mit einer Rate von 25 MHz aus dem SDRAM zu laden. Dies funktioniert, aber ich kann weder Pixel mit dieser Geschwindigkeit in das SDRAM schreiben noch den Bildschirm für jeden neuen Frame schnell genug löschen. Ich brauche 2 Takte, um Daten zu schreiben, und mein Board arbeitet mit 50 MHz, sodass ich gerade genug Zeit habe, um einen vollständigen Lesevorgang durchzuführen.

Ich würde annehmen, dass ich etwas schrecklich, schrecklich falsch mache. Wie wird eine solche Zeichenfläche normalerweise in VHDL implementiert?

Ich könnte am ehesten ein 2-3-3 (RGB) -Farbschema verwenden, um jedes Pixel abzurufen und während der VGA-Zeit "Veranda" (Austastung) auf den Leinwand-RAM zu schreiben. Dies bedeutet, dass ich bei jeder der 25-MHz-Uhren nur 15% des Bildschirms aktualisieren kann und meine Schaltung irgendwie wissen muss, welche 15% sie aktualisiert?

Ich kann nicht herausfinden, wie man doppelte Pufferung verwendet, weil ich nicht herausfinden kann, wie man beim Lesen Daten in den Speicher schreibt. Gibt es eine Möglichkeit, Bit-Banging des Protokolls zu vermeiden? Wie macht dieser Typ das?

Geben Sie hier die Bildbeschreibung ein



@davidcary, mit einigen Details zur Vorgehensweise beim Doppelpuffern haben Sie die Frage beantwortet. Mir ist klar, dass dies Zeit braucht und ich kann keine Steine ​​werfen, die oft einen kurzen Witz als Kommentar geben, um dem Benutzer bei seinem Problem zu helfen, bis jemand eine qualitativ hochwertige Antwort schreiben kann.
Kortuk

3
Wenn Sie sagen "Gibt es eine Möglichkeit, Bit-Banging des Protokolls zu vermeiden?", Bedeutet dies, dass Sie den SDRAM-Controller nicht selbst geschrieben haben. Ich empfehle dies, es ist eine gute Übung, und Sie werden mehr darüber verstehen, wie SDRAM funktioniert und wie man seine Timings ausnutzt.
Mng

Antworten:


3

Einige Ansätze, die für einige Anzeigestile nützlich sein können, bestehen darin, das Anzeigefeld in Kacheln und zu unterteilen

  1. Beschränken Sie jede Kachel auf die Verwendung eines kleinen Satzes von Farben, sodass weniger als 8 Bit pro Pixel verwendet werden können, oder
  2. Verwenden Sie ein oder zwei Bytes aus jeder Kachel, um einen Ort auszuwählen, an dem Bitmap-Daten gelesen werden sollen.
Der erste Ansatz könnte die Rate verringern, mit der Daten aus dem Anzeigespeicher gelesen werden mussten. Wenn man beispielsweise Kacheln mit einer Größe von 16 x 16 verwendet und jeweils vier Farben aus einem Satz von 256 auswählen kann, kann man ohne zusätzlichen RAM im FPGA die Anzahl der Speicherlesevorgänge pro 16 Pixel auf acht reduzieren (vier Farbwerte, plus vier Bytes für die Bitmap). Wenn man dem FPGA Pufferung / RAM (*) im Wert von 160 Bytes hinzufügt, könnte man die Anzahl der Speicherlesevorgänge pro 16 Pixel auf vier reduzieren, indem alle 16 Scanzeilen zusätzliche 160 Lesevorgänge verwendet werden, um den nächsten Satz von Kachelfarben zu lesen. Wenn man 16 Farben pro Kachel wollte, würde der zweite Ansatz zusätzliche 640 Bytes RAM erfordern, es sei denn, man würde die Anzahl der verschiedenen Paletten, die in einer Zeile existieren könnten, einschränken.

Der zweite Ansatz würde wahrscheinlich die Gesamtspeicherbandbreite, die zum Erzeugen einer Anzeige erforderlich ist, eher erhöhen als verringern, würde jedoch die Speichermenge verringern, die aktualisiert werden müsste, um die Anzeige zu ändern - man könnte ein oder zwei Bytes ändern, um eine 8x8 oder zu aktualisieren 16x16 Bildschirmbereich. Je nachdem, was Sie anzeigen möchten, kann es bei dieser Vorgehensweise hilfreich sein, ein Speichergerät zum Speichern der Kachelformen und ein anderes zum Speichern der Kachelauswahl zu verwenden. Man könnte zum Beispiel einen schnellen 32Kx8-RAM verwenden, um ein paar 80x60-Kachelkarten mit zwei Bytes pro Kachel zu speichern. Wenn das FPGA keine Pufferung hätte, müsste es alle vier Pixel ein Byte lesen. Selbst mit einem statischen RAM von 40 ns würde die CPU genügend Zeit haben, um die Anzeige zu aktualisieren (ein ganzer Bildschirm würde nur 9600 Byte groß sein).

Übrigens, wenn man keinen 32Kx8-RAM hinzufügen wollte, aber 320 Bytes Pufferung / RAM (**) zum FPGA hinzufügen konnte, könnte man einen Tile-Map-Ansatz verwenden, aber die CPU oder den DMA 160 Bytes in den FPGA einspeisen lassen Alle 8 Scanzeilen anzeigen. Dies würde den Controller etwas belasten, selbst wenn sich nichts auf dem Display ändert, könnte aber die Schaltung vereinfachen.

(*) Der Puffer könnte als RAM oder als Folge von 32 40 Bit langen Schieberegistern plus einer kleinen Steuerlogik implementiert werden.

(**) Der Puffer könnte als zwei 160-Byte-RAMs oder als zwei Gruppen von 16 80-Bit-Schieberegistern implementiert werden.


5

Sprites werden normalerweise nicht mit einem Frame Buffer erstellt (wie ich das Wort verstehe). Stattdessen vergleichen Sie die x- und y-Koordinate mit xmin, ymin und xmax, ymax des Sprites. Wenn die aktuelle Scanposition innerhalb des Sprites liegt, geben Sie die entsprechende Farbe aus dem Sprite-Speicher aus.

Wenn Sie versuchen, einen Bildspeicher anzuzeigen, nehmen Sie sich Mut. Dies war mein erstes großes FPGA-Projekt. SDRAM sollte bei 100 MHz kein Problem sein (ich habe dies vor ungefähr einem Jahrzehnt zum ersten Mal getan, und Silizium ist jetzt schneller), also multiplizieren Sie Ihren 50-MHz-Takt. Das Schreiben eines eigenen Controllers ist lehrreich :)

Das gibt Ihnen viel Bandbreite zum Spielen, Sie können dann problemlos puffern. 60 Hz VGA benötigt durchschnittlich 18 Mpixel / Sek. Wenn Sie ein 16 Bit breites Gerät haben, haben Sie eine maximale Bandbreite von 200 MByte / s. Selbst wenn Sie nur 50% effizient sind (was machbar sein sollte), sind das 100 Mpixel / s bei 16 Bit pro Pixel oder 50 Mpixel / s bei 32 Bit pro Pixel.

Zum Beispiel kann es sein, dass Ihr RAM 60 ns benötigt, um einen Lesevorgang einzurichten, aber danach 8 Wörter in 80 ns platzen kann - das sind 8 Bytes in ~ 140 ns. Wenn Sie Ihren RAM dazu bringen können, längere Bursts auszuführen, würden sich die Kosten für die Einrichtung des Lesevorgangs amortisieren.

Basierend auf Ihrem Kommentar, dass es sich um einen byte-seitigen RAM handelt, sind das etwas mehr als 50 MByte / s, nur 16 MBit / s bei 24 Bit pro Pixel :( Sie haben einfach nicht genug Bandbreite, um eine echte Farbanzeige zu erstellen, selbst bei VGA könnte ziemlich leicht 8 Bit pro Pixel machen, aber das sind nur 2 oder 3 Bit pro Farbe - was für Ihre Anwendung in Ordnung sein kann, weiß ich nicht. Oder Sie könnten eine Nachschlagetabelle mit 256 Farben wie früher machen - danach Wenn Sie aus dem Bildspeicher lesen, verwenden Sie den Wert, um in einem internen RAM-Takt nachzuschlagen und die 24-Bit-Farbe (oder 18 Bit, die gut in ein BRAM passen würden) für die Ausgabe auf dem Monitor zu erhalten.

Die doppelte Pufferung funktioniert immer noch:

Zeigen Sie einen Frame von Adresse 0 an (lesen Sie einfach alle Pixel nacheinander aus und unterbrechen Sie die Lesevorgänge während der Austastintervalle).

Schreiben Sie Ihren nächsten Frame an einen anderen Ort. Für diese doppelte Pufferung muss Ihr DRAM-Controller zwischen den konkurrierenden Anforderungen der Lese- und Schreibkanäle priorisieren. Tipp, priorisieren Sie die Lesevorgänge, da sie zeitkritisch sind :)


Ist es im Allgemeinen besser, Lesevorgänge zu priorisieren, oder ist es besser, Daten in ein FIFO einzulesen, Schreibprioritäten zu geben, wenn sich eine bestimmte Datenmenge im FIFO befindet, und Leseprioritäten zu geben, wenn der FIFO-Pegel zu niedrig wird? Ich habe festgestellt, dass es zumindest beim Fahren von LCD-Bildschirmen mit Taktsignal nützlich ist, das Lese-Timing ziemlich "locker" zu lassen, vorausgesetzt, alle Daten werden pünktlich verschoben.
Supercat

Vielen Dank für Ihren Beitrag, ich könnte einen Blick auf die Pufferung werfen. Aber ich denke, ich brauche 2 Takte (1/50 MHz), um Daten zu lesen, und ich habe auch ein 8-Bit-Gerät.
Mikhail

@supercat: Ja, das ist eine fortschrittlichere Lösung, die möglicherweise erforderlich ist, wenn die Bandbreite erhöht wird.
Martin Thompson

1
@ Mischa: Es dauert eine Weile, bis ein Datenlesevorgang eingerichtet ist, aber Sie können große Mengen gleichzeitig platzen lassen.
Martin Thompson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.