Forum: FPGA, VHDL & Co. SDRAM Timing. Geht das so? READ NOP NOP READ?


von Holger K. (holgerkraehe)


Angehängte Dateien:

Lesenswert?

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
von Holger K. (holgerkraehe)



Lesenswert?

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
von Achim S. (Gast)


Lesenswert?

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.

von Holger K. (holgerkraehe)


Lesenswert?

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.

von Holger K. (holgerkraehe)


Angehängte Dateien:

Lesenswert?

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

von Achim S. (Gast)


Lesenswert?

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.

von Holger K. (holgerkraehe)


Lesenswert?

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.

von Holger K. (holgerkraehe)


Lesenswert?

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

von S. R. (svenska)


Lesenswert?

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).

von Duke Scarring (Gast)


Lesenswert?

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
Noch kein Account? Hier anmelden.