Hallo zusammen Ich versuche das SDRAM auf dem DE0 Board anzusteuern. Wenn ich dies mit einzelnen Read Zugriffen mache, klappt dies auch einwandfrei. Aktuell versuche ich, den Zugriff etwas zu beschleunigen indem ich Read after Read cycles versuche. So wie im DB gezeigt (bild) Leider klappt dies auf dem Board noch nicht wirklich wie gewünscht. Die Simulation des Treibers zeigt mir das angehängte bild. Nach dem aktivieren der Bank wird ein Read durchgeführt (Read ohne Precharge) dann kommen zwei NOPs dann wieder ein Read etc. Kennt sich jemand aus und weiss, ob dies so grundsätzlich stimmen würde? Die Refreshcycles kommen natürlich auch vor. die sieht man jetzt in der Simulation aufgrund der SImulationsdauer nur nicht. CKE ist immer High und CS immer low Vielen Dank schonmal Datasheet Link: http://zentel-europe.com/datasheets/A3V64S40GTP_v1.3_Zentel.pdf
:
Bearbeitet durch User
Ich bin nun nochmals einen Schritt zurückgegangen im Vergleich zum ersten Post. Schaut euch mal bitte die beiden Timingdiagramme im Anhang an. Diese stammen von einem Logicanalyzer, welcher direkt am RAM hängt. Im Ram wurden in den ersten 256 Datenworten (16Bit) die Zahlen 0-255 hochgezählt gespeichert. Nun zu den Bildern. ...16_180deg_phase_delay.png Ich lese die Daten aus dem RAM mit einem bestimmten Delay zwischen den einzelnen Auslesevorgängen aus. Dieses Delay ist in anzahl Takten definiert. Der VHDL Code sieht so aus:
1 | test : process(clk_100m0_o) is |
2 | begin
|
3 | mem_reset <= '0'; |
4 | if rising_edge(clk_100m0_o) then |
5 | --clkenable wird über das signal clkdelay gesteuert.
|
6 | if (cmd_ready = '1' and stp_refresh = '1' and clkenable = '1' ) then |
7 | |
8 | case state is |
9 | when ST_INIT => |
10 | --.....
|
11 | when ST_WRITE => |
12 | --.....
|
13 | when ST_READ => |
14 | cmd_wr <= '0'; |
15 | cmd_address <= addr_cnt; --x"0000A0"; |
16 | cmd_byte_enable <= (others => '1'); |
17 | cmd_enable <= '1'; |
18 | |
19 | if (unsigned(addr_cnt) = 255) then |
20 | |
21 | addr_cnt <= (others => '0'); |
22 | sig_LED_state <= not sig_LED_state; |
23 | else
|
24 | addr_cnt <= addr_cnt + '1'; |
25 | end if; |
26 | |
27 | when others => null; |
28 | end case; |
29 | |
30 | else
|
31 | cmd_enable <= '0'; |
32 | end if; |
33 | end if; |
34 | end process test; |
Dieses Bild zeigt nun das Timing direkt am IC gemessen mittels Logicanalyzer. Dabei ist das Delay auf 16 Takte eingestellt. Es funktioniert alles wie es soll, da die Datenbits 0-3 hochzählen. Man sieht dies auch am MSB Bit des unteren Bytes des Datenwortes auf dem Oszilloskop: (blauer Kanal ist MSB) hantek29_9.bmp Der gelbe Kanal ist sig_LED_state Wenn ich nun das ganze delay um nur einen clock reduziere, dann sieht das ganze aus wie in Bild ...15_180deg_phase_delay.png Oder das Bit 7 wenn von 0 gezählt wird, bzw MSB des unteren Bytes auf dem oszilloskop: (blauer Kanal ist MSB) hantek30_3.bmp Es wird nun einfach irgendetwas aus dem Ram gelesen bzw. es liegt einfach irgendetwas am Datenbus des RAMs an. Dank dem Logicanalyzer sieht man jedoch, dass RAS, CAS, WE nach wie vor korrekt nacheinander anliegen. Ich suche den Fehler nun schon seit mehreren Tagen und habe keine Ahnung mehr, wonach ich suchen soll. Denn das Timing bzw. die Ansteuerung scheint ja grundsätzlich korrekt zu sein. Wenn ich das Delay auf 16 Takte oder mehr stelle, so läuft das ganze stundenlang problemlos. kaum ist das delay auf 15 oder weniger, geht nichts mehr. Ich bin über jeden Input/Anregung sehr dankbar.
:
Bearbeitet durch User
Holger K. schrieb: > Dieses Bild zeigt nun das Timing direkt am IC gemessen mittels > Logicanalyzer. Dabei ist das Delay auf 16 Takte eingestellt. Du arbeitest mit einer CAS-Latenz von 2, einer Burstlänge von 1 und einem Takt von 50MHz? Ich kann beim Draufschauen keine verbotenen Timings in deinen Logicanalyzer-Listings erkennen. Eigentlich sollte die Sequenz funktionieren. Wobei du dir ggf. durch die Benutzung des CKE noch ein Bein stellen kannst (CKE ist in dem Listing nicht gezeigt. Miss es mal mit oder setze es versuchsweise fest auf 1). Holger K. schrieb: > Man sieht dies auch am MSB Bit des unteren Bytes des Datenwortes auf dem > Oszilloskop: (blauer Kanal ist MSB) der blaue Kanal ist D3? Oder D7? Oder D15? In deinem Logic-Analyzer-Listing sind die DQ nur bis D3 gezeigt. D3 schaltet sehr viel schneller als der blaue Kanal in deiner Oszi-Aufnahme. Stimmt die Periode des blauen Signals tatsächlich mit dem überein, was du theoretisch erwartest? Holger K. schrieb: > Der gelbe Kanal ist sig_LED_state Der schaltet in der zweiten Oszi-Messung (nicht funktionierendes Read) sehr viel schneller als in der ersten. (112,7µs statt 100ms). Zu diesem Unterschied kann es nicht allein dadurch kommen, dass du 15 statt 16 Taktzyklen fürs Lesen verwendest. Da muss sich noch etwas anderes drastisch zwischen beiden Messungen unterscheiden.
Erstmal vielen Dank für deine Antwort. Achim S. schrieb: > Du arbeitest mit einer CAS-Latenz von 2, einer Burstlänge von 1 und > einem Takt von 50MHz? Absolut korrekt! Achim S. schrieb: > Ich kann beim Draufschauen keine verbotenen Timings in deinen > Logicanalyzer-Listings erkennen. Eigentlich sollte die Sequenz > funktionieren. Ok. Gut dass auch du meinst dass es funktionieren müsste. Achim S. schrieb: > Wobei du dir ggf. durch die Benutzung des CKE noch ein > Bein stellen kannst (CKE ist in dem Listing nicht gezeigt. Miss es mal > mit oder setze es versuchsweise fest auf 1). CKE ist fest auf eins. Siehe hier: Holger K. schrieb: > CKE ist immer High und CS immer low Achim S. schrieb: > der blaue Kanal ist D3? Oder D7? Oder D15? In deinem > Logic-Analyzer-Listing sind die DQ nur bis D3 gezeigt. Sorry, hätte ich genauer schreiben können. Ist D7. Holger K. schrieb: > Oder das Bit 7 Steht zwar da, aber etwas diffus. Achim S. schrieb: > D3 schaltet sehr > viel schneller als der blaue Kanal in deiner Oszi-Aufnahme. Stimmt die > Periode des blauen Signals tatsächlich mit dem überein, was du > theoretisch erwartest? Ja, die periode entspricht dem, was ich erwarte. Achim S. schrieb: > Der schaltet in der zweiten Oszi-Messung (nicht funktionierendes Read) > sehr viel schneller als in der ersten. (112,7µs statt 100ms). Zu > diesem Unterschied kann es nicht allein dadurch kommen, dass du 15 statt > 16 Taktzyklen fürs Lesen verwendest. Da muss sich noch etwas anderes > drastisch zwischen beiden Messungen unterscheiden. Das ist korrekt. Dazu muss ich sagen, dass das Bild der funktionierenden Messung beim Oszi nicht zu einem clkdelay von 16 gehört sondern zu einem von 100. Das Oszibild bei einem clkdelay von 16 sieht, bis auf die Zeiten, identisch aus. Die Logicanalyzerbilder zeigen jedoch den Unterschied zwischen 15 und 16.
Ich habe das Problem gefunden. Bei der Initialisierung der RAMs war was gewaltig falsch konfiguriert. Alt:
1 | constant MODE_REG : std_logic_vector(12 downto 0) := "000" & "0" & "00" & "010" & "0" & "000"; |
2 | |
3 | -- 23 22 | 21 20 19 18 17 16 15 14 13 12 11 10 09 | 08 07 06 05 04 03 02 01 00 |
|
4 | -- BS0 BS1 | ROW (A12-A0) 8192 rows | COL (A8-A0) 512 cols |
|
5 | addr_bank <= cmd_address(23 downto 22); |
6 | addr_row <= cmd_address(21 downto 9); |
7 | addr_col <= "0000" & cmd_address(8 downto 0); |
Neu:
1 | -- Reserved, wr bust, OpMode, CAS Latency (2), Burst Type, Burst Length (0)
|
2 | constant MODE_REG : std_logic_vector(11 downto 0) := "00" & "0" & "00" & "000" & "0" & "000"; |
3 | |
4 | -- 21 20 | 19 18 17 16 15 14 13 12 11 10 09 08 | 07 06 05 04 03 02 01 00 |
|
5 | -- BS0 BS1 | ROW (A11-A0) 4096 rows | COL (A7-A0) 256 cols |
|
6 | addr_bank <= cmd_address(21 downto 20); |
7 | addr_row <= cmd_address(19 downto 8); |
8 | addr_col <= "0000" & cmd_address(7 downto 0); |
256x 16Bit Worte bei 16.14kHz ~ 8.26 MByte/s ~ 66MBit/s Nun habe ich nur noch ein Problem beim schreiben. Wenn ich mit einem Delay ein paar clocks (10) schreibe, scheint alles zu klappen. Ohne delay (1-2 Clocks) habe ich beim auslesen ein paar merkwürdige spikes drinn. Die Spikes scheinen an fixen stellen zu sein. Somit sozusagen Bitfelher beim Speichern. Blau ist wieder D7, gelb ist wieder sig_LED_state Ähnliches Problem wie vorhin, aber wohl andere Ursache... Ihr dürft gerne mithelfen :)
Ok. Und du änderst tatsächlich nur den Delay von Precharge zu nächstem Activate um genau einen CLK-Zyklus? Und das auch nur beim Auslesen? (d.h. Schreibzugriff, Refresh, setup-hold-constraints sind ansonsten in beiden Fällen identisch?) Dann fällt mir höchstens noch ein, dass du vielleicht irgendein synchrones Timing im DRAM verletzt, obwohl du die zugehörige analoge Zeitangabe einhältst. Ich erinnere mich aus single data rate Zeiten noch an manche DRAMs mit digitalen Interlocks: ein bestimmtes Timing musste nicht nur genüngend ns lang sein, sondern es musste auch eine Mindestzahl von Taktzyklen abdecken. Das kann dazu führen, dass bei bei langsamen Takten (wie deinen 50MHz) die analogen Zeitangaben (in ns) nach oben korrigiert werden müssen. Fußnote 1 auf S. 10 deines Datenblatts könnte in diese Richtung interpretiert werden, wobei ich auch mit dieser Fußnote keinen verletzten Timing-Parameter entdecke. Vielleicht hilft ein genauerer Blick aufs Fehlerbild: Die Datenausgänge schalten im Fehlerfall ja nicht wirklich zufällig: D0-D2 sehen in deinem Logicanalyzer-Ausschnitt richtig aus, nur bei D3 sind hier Fehler sichtbar. Sind diese DQ0-2 immer richtig oder sind sie auch ab und zu vom Fehler betroffen. Wenn ein Fehler auftritt: tritt er genau reproduzierbar auf oder gibt es bei wiederholtem Zugriff unterschiedliche Ergebnisse? (kannst ja mal den Trigger der LED auf eine bestimmte Speicherzelle (RAS=CAS=BS=0) setzen und schauen, ob beim wiederholten Durchlauf immer die identischen Fehler rauskommen). Holger K. schrieb: > Ich habe das Problem gefunden. > > Bei der Initialisierung der RAMs war was gewaltig falsch konfiguriert. Der MRS-Inhalt gefiel mit in deiner alten Initialisierung besser (CL=010 für eine Latenz von 2. Jetzt setzt du CL auf 000, was ein reservierter Wert ist). Ob der Adress-Split in der neuen Version stimmt oder in der alten habe ich jetzt nicht nachgeprüft. Aber dass ein falscher Adresssplit etwas damit zu tun haben soll, ob zwischen Precharge und folgendem Activate 11 oder 12 Takte benötigt werden, erscheint mir seltsam.
Achim S. schrieb: > Ok. Und du änderst tatsächlich nur den Delay von Precharge zu nächstem > Activate um genau einen CLK-Zyklus? Und das auch nur beim Auslesen? > (d.h. Schreibzugriff, Refresh, setup-hold-constraints sind ansonsten in > beiden Fällen identisch?) Ja, dies war bisher der Fall. Achim S. schrieb: > sondern es musste auch eine > Mindestzahl von Taktzyklen abdecken. Das kann dazu führen, dass bei bei > langsamen Takten (wie deinen 50MHz) die analogen Zeitangaben (in ns) > nach oben korrigiert werden müssen. Fußnote 1 auf S. 10 deines > Datenblatts könnte in diese Richtung interpretiert werden, Interessant, daran habe ich noch nicht gedacht. Das soll bedeuten dass es im Prinzip eine mindest Zahl an Clocks gibt, da man jedoch davon ausgeht, dass das Memory z.B. mit mindestens 100MHz betrieben wird, gibt man einfach die mindest Zeit an, da damit die minimale anzahl Clocks bei z.B, 100MHz bereits abgedeckt sind. Bei jeder höheren Frequenz sind es ohnehin dann mehr. Ich habe jetzt dazu im Datenblatt auch nichts spezielles gefunden. Da der Treiber ursprünglich für 100MHz Clockfrequenz war, werden z.B. bei der Initialisierung automatisch die doppelte Zeit gewartet, da eine bestimmte Anzahl an Clocks gewartet wird. Ich hoffe dies macht keine Probleme. Achim S. schrieb: > Sind diese DQ0-2 immer richtig oder sind sie > auch ab und zu vom Fehler betroffen. Werde ich mir ansehen. Achim S. schrieb: > Der MRS-Inhalt gefiel mit in deiner alten Initialisierung besser (CL=010 > für eine Latenz von 2. Jetzt setzt du CL auf 000, was ein reservierter > Wert ist). Korrekt, habe ich korrigiert. Interessanterweise macht es überhaupt keinen Unterschied ob ich dort eine Latency von 2 oder 3 eingebe oder ob ich Burst Mode 1,2 oder 4 wähle. Dies irritiert mich ein wenig. Achim S. schrieb: > Ob der Adress-Split in der neuen Version stimmt oder in der alten habe > ich jetzt nicht nachgeprüft. Aber dass ein falscher Adresssplit etwas > damit zu tun haben soll, ob zwischen Precharge und folgendem Activate 11 > oder 12 Takte benötigt werden, erscheint mir seltsam. Du hast recht. Die Probleme sind nicht weg, nur sehen sie jetzt anders aus.
Ich werde wohl den SDRAM Treiber nochmals neu schreiben müssen. Dann werde ich diesen etappenweise testen und die Ergebnisse hier posten. Oder kennt jemand einen SDRAM Treiber in VHDL welcher in einem einzigen VHDL File Platz findet, bzw. übersichtlich ist? Danke
Holger K. schrieb: > Oder kennt jemand einen SDRAM Treiber in VHDL welcher in einem einzigen > VHDL File Platz findet, bzw. übersichtlich ist? Ich hätte auch gerne sowas, bevorzugt einen, der zwei Ports bereitstellt. Einen für normale Zugriffe, einen für lineare Lesezugriffe (Videospeicher).
Holger K. schrieb: > Oder kennt jemand einen SDRAM Treiber in VHDL welcher in einem einzigen > VHDL File Platz findet, bzw. übersichtlich ist? Hier: https://github.com/boert/Z1013-mist/blob/Z1013.64_devel/library/mist/sdram.vhd Aber schnell ist der nicht. 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.