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?
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".
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?
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...
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.
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! :-)
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...
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.