Hallo, leider habe ich ein Problem damit, den SDRAM auf meinem (custom) Board zum laufen zu bringen. Was ich bereits erfolgreich gemacht habe ist ein NIOS Core mit OnChip Memory ausgestattet und das "Hello-World" Programm gestartet. Das läuft soweit. Der nächste Schritt ware dann im NIOS Core unter QSYS ein SDRAM Controller hinzuzufügen und anzuschließen. Ebenfalls habe ich über eine PLL eine weitere Clock für den SDRAM erstellt. Im QSYS habe ich dann die Reset und Exception Vektoren von dem on-chip Memory auf den SDRAM gelegt. Leider funktioniert das Design so nicht. Ich finde zwar den NIOS unter "Run Configurations" mit richtiger System ID und entsprechendem Timestamp, jedoch kann ich ihn nicht beschreiben. Es kommt in der Konsole immer eine Fehlermeldung (Verify failed) wie im Anhang und anschließend die Meldung Downloading ELF Process failed. Ich habe ebenfalls mal meine Konfiguration des Cores mit angehängt, vielleicht gibt es ja hier auch noch Fehler. Als Referenzboard für die Platine habe ich übrigens das DE0 verwendet - mit dem gleichen SDRAM (aber anderer FPGA). Auf diesem Development Board habe ich das SDRAM auch schon zum laufen gebracht. Hat vielleicht jemand eine Idee, wie ich dem Problem auf die Sprünge kommen könnte? Oder benötigt ihr dazu noch weitere Informationen über meinen Aufbau? Viele Grüße, Thomas
Die Frage taucht immer wieder auf. Ich kann es nur jedes Mal das Gleiche sagen: mache nicht so große Schritte. Wenn Du NIOS aus dem ONCHIP Ram zum laufen gebracht hast, dann kannst Du im nächsten Schritt einfach mal aus dem NIOS heraus SDRAM beschreiben und die Daten auszulesen (NIOS läuft immer noch aus dem ONCHIP). Wenn das schon mal funktioniert, machst Du halt weiter. Aber es kann sein, dass der NIOS sich gleich beim ersten Zugriff aufhängt, dann geht die Suche los (Clock kontrollieren, Pinbelegung, Frequenz messen, Phase stimmt, Datenleitungen kontrollieren, Reset check). Kest
Hey, vielen Dank für den Hinweis, genau so habe ich es gemacht. Was mir aufgefallen ist, dass viele Werte beim Lesen nicht den beschriebenen Werten entsprechen. Wenn ich die Phase des Clock-Signals verändere, verbessert bzw. verschlechtert sich das Verhalten. Es scheint also an der Phase des Clock-Signals zu liegen. Ich muss gestehen das ich mich auch nicht großartig um das Timing gekümmert habe, da es im Beispiel-Projekt des DE0-Boards auch nicht gemacht wurde. Da komme ich jetzt wohl nicht mehr so einfach rum. Jetzt ist natürlich die Frage, wie man auf die exakte Phasenverschiebung kommt? Vllt. finde ich etwas dazu im Internet. Grüße, Thomas
Das Problem hatte ich vor kurzem auch gehabt. Schaue mal hier:) Beitrag "NIOSII mit SDRAM startet nicht."
Hey, ich bin leider immer noch nicht viel weiter gekommen :/ Wie bereits kurz erwähnt, beschreibe ich nun in meinem Test-Programm den SDRAM und lese die einzelnen Adressen dann aus. Bei bestimmten Phasenlagen (z.B. -4ns Phasenversatz) bekomme ich teilweise beim Auslesen der Adressen auch die richtigen Daten, immer in kleinen Paketen (ca. 10 Datenzellen sind richtig). Weißt das auf ein Timing-Problem hin? Das wäre meine Vermutung. Ebenfalls habe ich die Geschwindigkeit des NIOS Cores sowie des SDRAMs auf 20MHz verringert. Mit einem Scope kann ich mir nun auch die Signale ansehen. Nur bin ich mir nun gar nicht mehr so sicher, was ich eigentlich sehen will/müsste. Und zwar sehe ich mir immer das Clock-Signal am SDRAM an sowie z.B. die Datenpins (oder Command-Pins). Eigentlich dachte ich, es müssten zuerst die Pins gesetzt werden, und dann die Clock-Flanke kommen. Wenn ich dies mit der Clock-Phase einstelle, bekomme ich allerdings gar keine richtigen Werte mehr aus meinem Testprogramm. Wann sollte denn die Clock am SDRAM bestenfalls mit den anderen Signalen auftreten? Oder kann man das nicht pauschal sagen? Viele Grüße, Thomas
20 MHz ist etwas wenig, mach ruhig 100 MHz. Wie sieht Dein Top-Level aus? Ich meine, hast Du eine PLL? Kest
In meinem Top-Level Design habe ich auch eine PLL (siehe die Bilder im 1. Post). Ich habe jetzt herausgefunden, dass es scheinbar mit dem Schreib-Vorgang Probleme gibt. Mein Test-Code sieht etwa so aus:
1 | for (i=0; i<WRITE_CYCLES;i++) |
2 | IOWR(SDRAM_BASE,i, WRITE_DATA ); |
3 | |
4 | nError = 0; |
5 | for (i=0; i<WRITE_CYCLES;i++) |
6 | { |
7 | if (IORD(SDRAM_BASE,i ) != WRITE_DATA) |
8 | { |
9 | nError++; |
10 | printf("[ERROR] Address %lu: %lu\n", i,IORD(SDRAM_BASE,i )); |
11 | } |
12 | } |
13 | |
14 | printf("\n\n[FINISH] %d Addresses tested, %d errors.", |
15 | |
16 | |
17 | //Dauer schreiben |
18 | |
19 | while(1) |
20 | { |
21 | for (i=0; i<WRITE_CYCLES;i++) |
22 | IOWR(SDRAM_BASE,i, WRITE_DATA); |
23 | } |
Kurz der Ablauf: 1) Ich schreibe N Adressen mit dem Wert X 2) Ich lese N Adressen aus und gebe das Ergebnis aus 3) Ich schreibe Dauerhaft (um mir auf dem Scope etwas ansehen zu können) Wenn ich das Programm nun direkt hintereinander ausführe, lese ich beim 2. mal immer mehr Speicherzellen richtig aus. Ich denke es liegt daran, dass ich am Ende des Programms in der Endlosschleife dauerhaft den richtigen Wert in die Speicherzellen schreibe. Wodurch könnte sich ein solches Timing Problem ergeben? Ich habe jetzt auch 50MHz und 100MHz NIOS + SDRAM Frequenzen ausprobiert, alle mit ähnlichem Verhaltem. Viele Grüße, Thomas
Mach Dir bitte klar, wie SDRAM organisiert ist und mit wievielen Bits Avalon angebunden ist. Was passiert, wenn Du das machst? for (i=0; i<WRITE_CYCLES;i++) IOWR(SDRAM_BASE,i, WRITE_DATA ); Musst Du nicht stattessen for (i=0; i<WRITE_CYCLES;i++) IOWR(SDRAM_BASE,i*4, WRITE_DATA ); machen? Oder verwende gleich: for (i=0; i<WRITE_CYCLES;i++) IOWR_32DIRECT(SDRAM_BASE,i*4, WRITE_DATA ); Ansonsten könnte es ein Verdrahtungproblem sein (Bank/Adress Leitungen nicht richtig angebunden). Meines wissens, kalibriert sich SDRAM Controller selber, aber vielleicht geht da was schief. Wenn Du nur ein Paar Mal hintereinander z.B. 16-32 Bytes ausliest, sind die Werte immer gleich? Grüße Kest
Ich habe das mit der Adressierung mal abgeändert, das war mir in der Tat nicht klar. Ich lese immer exakt gleiche Werte aus, wenn ich mehrfach hintereinander Lese. Der Lesevorgang ist also recht stabil und scheint zu funktionieren. Getestet habe ich das so: Programmstart mit while-Schleife:
1 | while(1) |
2 | { |
3 | |
4 | for (i=0; i<WRITE_CYCLES;i++) |
5 | IOWR(SDRAM_BASE,i*4, WRITE_DATA); |
6 | } |
Dies habe ich ausgeführt (mit WRITE_DATA = 456). Anschließend die While schleife entfernt, so das mein Programm nichts mehr in den SRAM schreibt. In dem Testcode
1 | for (i=0; i<WRITE_CYCLES;i++) |
2 | { |
3 | nData = IORD(SDRAM_BASE,i*4 ); |
4 | if (nData != WRITE_DATA) |
5 | { |
6 | nError++; |
7 | printf("[ERROR] Address %lu: %lu\n", i, nData); |
8 | } |
9 | } |
10 | |
11 | printf("\n\n[FINISH] %d Addresses tested, %d errors.", WRITE_CYCLES, nError); |
stimmen nun alle Speicherzellen überein. Es gibt keine Fehler - alle Speicherzellen enthalten den Wert 456. Schreibe ich allerdings nur 1x die Werte in den SRAM (und nicht in einer endlosschleife), befindet sich in nur ca. 300 Speicherzellen der richtige Wert. Irgendwie blicke ich noch nicht dahinter, wodurch sich dieses Verhalten ergibt. Für weitere Anregungen bin ich dankbar :) Viele Grüße, Thomas
Ich würde Dir raten die Werte, die Du ausliest auch in HEX anzuschauen, die Adressen aber zugehörig auch! Es kann nämlich sein, dass gerade, wenn eine Bank gewechselt wird, was schief läuft (z.B. ein BA[1] Pin nicht richtig dran, Adresspin stimmt nicht oder es gibt Übersprechen). Wenn SDRAM Controller angelaufen ist, dann hat er geschaff sich zu kalibrieren (allerdings weiß ich nicht, ob das vielleicht nicht nur bei einem DDR/DDR2/DDR3 so ist (bei Altera)). Aus Erfahrung weiß ich, dass man da schon sehr viel Zeit versenken kann, eh es funktioniert. Der Fehler ist meistens so trivial, dass man sich gar nicht traut, zuzugeben, dass man so doof war ;-) Das "komplizierteste" war bei mir mal, dass DDR2 Speicherkontroller nur jeweils in 128 ms falsche Werte geliefert hat. So etwas rauszufinden ist sehr schwierig, weil es eben "eigentlich" läuft, aber ab und zu kippt ein Bit/Byte. Bei Altera gibt es für NIOS ein Memory-Test programm (template bei Eclipse). Dabei werden verschiedene Muster geschrieben/gelesen und man bekommt schnell heraus, was nun nicht stimmt, vielleicht könntest Du damit probieren. Ich wünsche Dir viel Erfolg und ganz wichtig: nicht aufgeben! :-) Grüße Kest
Ich spiele im Moment auch mit NIOSII und SDRAM auf DE1 Board Gibt es eigentlich ein Unterschied zwischen IOWR und IOWR_16DIRECT ? Ich habe bemerkt, dass der SDRAM Chip zwar in 4194804 Adressen je 16 bit geteilt ist(so steht auch in Qsys), aber für NIOSII wird er in 8 bit Partitionen dargestellt. Deswegen beläuft die Adresse von 0x800000 bis 0xFFFFFF (das doppelte von 4194804). Schreibe ich jetzt ein 16 bit langer Wert an die Adresse 0 mit IOWR_16DIRECT Befehl rein, so gehen die ersten 8 bit des Werts in die Adresse 0, und die zweite Hälfte in Adresse 1. Somit kann ich komischerweise nicht direkt in die Adresse 1 Schreiben, nur lesen. Erst in die Adresse 2 kann ein neuer Wert gespeichert werden. Nehme ich IOWR_8DIRECT, so kann ich separat jede Adresse beschreiben. Recht komischer Verhalten.... Vllt. liegt die Lösung zu deinem Problem in meiner Frage;)?
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.