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
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
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:
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
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;)?