Forum: FPGA, VHDL & Co. Speicher auslesen (eher grundsätzlich)


von pedelec (Gast)


Angehängte Dateien:

Lesenswert?

Hallo zusammen und schon mal danke fürs lesen!

Vorweg muss/möchte ich euch dahingehend vorwarnen, dass ich mich als 
reinen Autodidakten bezeichnen muss. Die Thematik der programmierbaren 
Logik interessiert mich aber und weil es irgendwie ja auch erfüllen 
kann, Neues zu meistern habe ich mich in das Abenteuer gestürzt.
Ich muss aber feststellen, dass das fehlen eines Ansprechpartners bzw 
einer wissenden Instanz der Motivation wirklich nicht hilft, weshalb ich 
mich an Euch wende.

Ich habe mir das Nexys2 Board mit dem zugehörigen Buch "learning by 
Example" gekauft. Das hilft schon mal zusätzlich zum Forum. Da ich hier 
auch fleissig mitlese sind mir aber auch einige Dinge aufgefallen, von 
denen hier vehement abgeraten wird (beispielsweise benutzen die autoren 
keine clock enable Signale, sondern derived clocks). Da glaube ich dem 
Forum, weshalb ich natürlich auch die Beispiele nicht 1:1 übernehmen 
kann. Ich versuche aber die Blöcke beizubehalten um da einigermaßen am 
Buch zu sein und nun zu meinem Problem:

Das was alle nach blinky und Lauflicht machen steht auch bei mir an, 
nämlich ein VGA Signal. Habe ich auch hinbekommen, wenn ich nun aber 
darüber nachdenke, wie ich Daten aus einem Speicher holen könnte komme 
ich mit dem Buch nicht weiter. Da habe ich ein Verständnis Problem. 
siehe Anhang.

Es existiert ein Modul 'vga_timing' was vsync und hsync generiert sowie 
die x- und y- Position des aktuellen Pixels ausgibt.
In dem Design des Buches werden nun Sprite Daten aus einem BROM geholt. 
dazu wird aus der x/y Position eine Adresse ausgerechnen (rom_addr16) 
und dazu ein Wert M gelesen.

Was mir nun nicht klar ist: Der Takt zum hochzählen der vga Zähler und 
der Takt am BROM ist der selbe. Im Buch der derived clock clk25. In dem 
Modul vga_640x480 wird mit steigender Flanke ein Pixel weitergezählt und 
die Position als hc und vc an vga_sprite gegeben. Dort wird dann durch 
Kombinatorik die rom_addr16 angelegt und... ja mit dem Selben Takt der 
Speicher ausgelesen. Aber dieses Berechnen von rom_addr16 braucht ja 
etwas Zeit nachdem mit der Selben Flanke ja erst eine neue x/y Position 
gezählt wurde. Warum funktioniert das. Oder wo habe ich das Brett vorm 
Kopf?? Ein Takt zählt einen Zähler hoch, damit wird eine Adresse 
gebildet was ja Zeit braucht so daß die noch gar nicht am BROM anliegt 
wenn der Takt kam.... Lese ich dann nicht immer genau den vorherigen 
Pixel aus?

Da ich 50 MHz Bordtakt habe und für vga sowiso nur der halbe Takt 
gebraucht wird, könnte man da vielleicht ein halbes Pixel später lesen 
oder so, aber wenn die Auflösung höher ist kann man ja nicht immer einen 
schnelleren Systemtakt als den vga Takt haben.

Lange Rede kurzer Sinn - Erst mal hoffe ich mein Problem wurde 
verstanden. Wer kann mir Nachhilfe geben? Vielleicht auch Schnipsel ohne 
massiven overhead zeigen die so was machen?

von Schlumpf (Gast)


Lesenswert?

Ich hoffe, ich habe dein Problem richtig verstanden.

Hilft dir folgendes weiter? (mal ganz allgemein gehalten)
Wenn Werte mit einem Takt geändert werden, dann bildet die Synthese 
daraus ein Register.
Und du hast richtig erkannt, dass die Information dann eine gewisse 
Latenz hat, bis sie an anderer Stelle angekommen ist.
Wenn aber der Empfänger der Werte, also der, der sie weiter verarbeitet, 
mit dem gleichen Takt wie der Erzeuger der Daten arbeitet, dann 
übernimmt er die Daten einfach einen Takt später, als sie erzeugt 
wurden.
Das ist das Grundprinzip jedes synchronen Designs.
Die Synthese rechnet das so hin, dass sichergestellt ist, dass die 
Laufzeit immer kürzer ist, als der Abstand zwischen zwei Flanken. Damit 
wird sichergestellt, dass im gesamten Design zum Zeitpunkt der 
Steigenden Flanke alle Datenleitungen stabil sind und sich nicht ändern.

In deinem konkreten Fall heißt das:
Das Modul vga_640x480 ändert seine Ausgänge mit dem Takt "n"
Das Modul vga_bsprite verzögert diese im eine unbekannte Zeit "t".
Also kommen sie am Modul loons_240x160 verzögert an (Zeitpunkt n + t).
Da aber die Register in loons die Werte erst zum Zeitpunkt n + 1 
Taktperiode übernehmen, und die Synthese dafür sorgt, dass die Zeit t 
kleiner als eine Taktperiode ist, sind die Daten stabil, wenn sie 
übernommen werden.


Ich hoffe, ich konnte das ein bisschen verständlich ausdrücken.
Dein Stichwort, nachdem du weiter suchen kannst, ist "synchrones 
digitales Design".

von pedelec (Gast)


Lesenswert?

Danke, d.h. dass der loons-Speicher immer einen Takt versetzt die Daten 
ausspuckt? Ich hatte nämlich das Buch so verstanden, dass die Daten von 
Takt n auch mit demselben Takt ausgelesen werden.

Konkretes Problem - ich habe einen Speicher für eine ganze Grafikseite. 
Wenn ich den Pixel (0,0) aus dem Speicherlesen und einfärben will muss 
ich die Adresse schon anlegen wenn ich noch der Pixelzähler noch auf dem 
linken untersten (799,520) Pixel steht und aus den Zählständen die 
Adresse für (0,0) bauen?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

pedelec schrieb:
> Aber dieses Berechnen von rom_addr16 braucht ja etwas Zeit nachdem mit
> der Selben Flanke ja erst eine neue x/y Position gezählt wurde. Warum
> funktioniert das.
Das ist das Grundprinzip jedes synchronen Designs: nach einer Taktflanke 
herrscht im FPGA große Unruhe. Neue Zählerstände werden berechnet, Logik 
ermittelt aktuelle Werte und die Folgezustände von FSM werden berechnet 
(auch bei der 1-Prozess-FSM ist das so!). Und rechtzeitig vor der 
nächsten Taktflanke müssen die Werte wieder stabil sein. Denn dann kommt 
wieder der Takt und das Spiel geht von vorne los.

Und deshalb sollte es nur 1 Takt im Sytem geben, und immer auf die selbe 
Flanke dieses Taktes reagiert werden.

> aber wenn die Auflösung höher ist kann man ja nicht immer einen
> schnelleren Systemtakt als den vga Takt haben.
1 Taktzyklus reicht für ein internes BRAM auch aus:
Jetzt wird die Adresse angelegt und mit der nächsten Taktflanke werden 
die zugehörigen Daten ausgegeben. Du bekommst die Daten also immer mit 1 
Takt Latency (=Verspätung, Verzögerung), weil immer vor der 
Taktflanke die Adresse angelegt wird, und die Daten nach der 
Taktflanke herauspurzeln. Weil das aber endlos so weitergeht, sieht dein 
Timing so aus:
1
 clk  ___----____----____----____----____---
2
3
      ___ _______ _______ _______ _______ ___     
4
addr  ___X_n_____X_n+1___X_n+2___X_n+3___X__
5
6
      ___ _______ _______ _______ _______ ___     
7
data  ___X_??____X_n_____X_n+1___X_n+2___X___

Man kann ein ROM auch asynchron beschreiben, dann hast du diese Latency 
nicht, aber blöderweise kann dann der Synthesizer auch keines der 
internen RAMs verwenden, weil die alle diese Latency eingebaut haben...

von pedelec (Gast)


Lesenswert?

Danke vielmals. Ich würde mich dann noch freuen, auf das vga-Beispiel 
bezogen konkret zu verstehen, wie man jetzt vorgeht, um Daten "passend" 
zu lesen.
Man muss ja dann einen Takt bevor das Pixel geschrieben wird schon die 
Adresse zum lesen haben. Das hatte ich in meinem letzten Post versucht 
zu beschreiben.
Der Zähler für x zählt ja von 0 bis 799 total und der für y von 0 bis 
520 total.
Wenn die Zähler rechts unten auf dem Monitor im nicht sichtbaren Bereich 
stehen, muss ich einen Vergleicher einbauen der aus 799/520 die Adresse 
0/0 erzeugt? Wie kann ich es konkret realisieren.

Die Latenz beim lesen aus dem Speicher habe ich begriffen. Befürchtete 
ich ja schon selber wodurch der Knoten in meinem Kopf erst entstand.

von pedelec (Gast)


Lesenswert?

Oder ist es ein akzeptables Vorgehen beim verschwinden von viden schon 
die Adresse auf 0/0 zu stellen und in der Austastlücke den Wert 
wiederholt zu lesen. Angezeigt wird ja nichts und sobalt viden wieder 
'1' wird den Adresszähler weiter zu setzen?

Die Problematik wird mich ganz sicher noch verfolgen wenn gar externer 
Speicher im Spiel ist.

Aber vielen Dank ans Forum - gezwungen zu sein ein Problem für andere zu 
formulieren ist schon mal gut und eure Antworten erst recht! :-)

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

pedelec schrieb:
> Oder ist es ein akzeptables Vorgehen beim verschwinden von viden schon
> die Adresse auf 0/0 zu stellen und in der Austastlücke den Wert
> wiederholt zu lesen. Angezeigt wird ja nichts und sobalt viden wieder
> '1' wird den Adresszähler weiter zu setzen?
Ja. Auch ich würde mit dem letzten Pixel der Zeile schon mal anfangen, 
dauernd den ersten Pixel der nächsten Zeile zu lesen. Also immmer 1 
Pixel "voraus" denken, dann ist das richtig. Denn das RAM hat ja genau 
diesen 1 Takt Latency...

von pedelec (Gast)


Lesenswert?

Vielen Dank.

von Duke Scarring (Gast)


Lesenswert?

pedelec schrieb:
> Die Problematik wird mich ganz sicher noch verfolgen wenn gar externer
> Speicher im Spiel ist.
Oder wenn die Daten über einen Systembus rangeschafft werden müssen.
Dann hilft ein FIFO weiter, mit einer Steuerung, welche schon mal die 
ersten Pixel aus dem Speicher holt. Sobald wieder etwas Platz im FIFO 
ist, wird mit den nächsten Pixeln aufgefüllt. Die Videoausgabe hat dann 
passend zu ihren Zählern die Pixeldaten vorliegen.

Duke

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.