Forum: FPGA, VHDL & Co. Speicherzugriff beim Nexys4-DDR Board


von Burkhard K. (buks)


Lesenswert?

Hat jemand hier im Forum ein Nexys4-DDR Board in Betrieb? Ich hätte ein 
paar Fragen bzw. Beobachtungen zur Nutzung des DDR2 Speichers; dabei 
handelts es sich um ein MT47H64M16 mit 64 Meg x 16 Konfiguration und 
einer eingestellten Burstlänge von 8. Ich benutze ISE 14.7.

1. Simulation:
   Der per MIG erzeugte DDR2 Core lässt sich mit ISim nicht simulieren, 
der Simulator stoppt mit einem Fehler "Signal phy_dout index is out of 
bound." Tatsächlich findet sich in der MIG-Doku der Hinweis, dass nur 
ModelSim unterstützt wird. Eine ModelSim Lizenz kommt für mein 
Hobbyprojekt nicht in Frage - kann ich evtl. einen anderen (freien) 
Simulator einsetzen?

2. Erstellen einer Netzliste:
   Es muss wohl möglich sein, aus den per MIG generierten Sourcen eine 
Netlist-Datei einmalig zu erstellen und in das Projekt einzubinden. Kann 
jemand das Vorgehen dazu kurz skizzieren?

(BTW: Die von Digilent in 
https://reference.digilentinc.com/_media/nexys4-ddr:ram2ddr_refcomp.zip 
bereitgestellte Datei hat einen Bug).

3. Timing:
   Digilent gibt die Cycle-Time 
(https://reference.digilentinc.com/nexys4-ddr:sram) mit 210 (tRC) bzw. 
260 (tWR) ns an. Tatsächlich gemessen habe ich für den Lesezyklus ca. 
350 ns, mit gelegentlichen Ausreissern (> 400 ns) nach oben (vom Anlegen 
des CEN Signals bis zur Assertion von RD_DATA_VALID des MIG UIs - bei 
Verwendung des RAM2DDRxadc Moduls von Digilent). Die Zeit für einen 
Schreibzyklus kann ich mit meinem Mitteln leider nicht messen; sie 
scheint aber unter der fürs Lesen zu liegen.

   Hat evtl. jemand die Zeit für einen Schreibzyklus gemessen oder per 
Simulation ermittelt?

   Meine Anwendung erzeugt 2x16 bit (Audio-)Daten mit 1 MSps/s die per 
FFT analysiert und später auf 200 kSps/s reduziert ausgegeben werden. 
Bei den oben dargestellten Zugriffszeiten muss ich die aus dem RAM 
gelesenen Daten (Burstlänge 8) in einem FiFo zwischenspeichern. 
Hinsichtlich des Timings ist der Ersatz von SRAM durch DDR2 ein eher 
enttäuschender Rückschritt.

   Nur so nebenbei: Digilent umgeht in seinem Referenzdesign für das 
Board mögliche Timingprobleme durch eine fest eingestellte Wartezeit von 
1200 ns (sic!) vor Ausgabe des ACK-Signals.

Gruß,
Burkhard

von Duke Scarring (Gast)


Lesenswert?

Ich habe auch ein Nexys4, aber die Variante mit dem PSRAM.
Bis zum externen Speicher bin ich aber noch nicht vorgedrungen...

Burkhard K. schrieb:
> 1. Simulation:
>    Der per MIG erzeugte DDR2 Core lässt sich mit ISim nicht simulieren,
> der Simulator stoppt mit einem Fehler "Signal phy_dout index is out of
> bound."
Erzeugt der MIG 'normale' Netzlisten zum Simulieren oder irgendwas 
verschüsseltes/proprietäres?

> Tatsächlich findet sich in der MIG-Doku der Hinweis, dass nur
> ModelSim unterstützt wird. Eine ModelSim Lizenz kommt für mein
> Hobbyprojekt nicht in Frage - kann ich evtl. einen anderen (freien)
> Simulator einsetzen?
Du kannst GHDL probieren. Ich weiß nicht, ob es bei Altera noch 
ModelSim-AE gibt. Aber der Fehler sieht nach einem kaputten Design bzw. 
kaputtem Modell aus. Da sollte ein anderer Simulator die gleiche 
Fehlermeldung bringen.

Duke

von Burkhard K. (buks)


Lesenswert?

Duke Scarring schrieb:

> Erzeugt der MIG 'normale' Netzlisten zum Simulieren oder irgendwas
> verschüsseltes/proprietäres?
Eine *.ngc Datei kann ich nicht finden, dafür aber ein Verzeichns 
"user_design" mit Verilog Sourcen, die bei der Synthese gelesen werden. 
Siehe auch meine zweite Frage zur Erzeugung einer Netlist-Datei.

>
Aber der Fehler sieht nach einem kaputten Design bzw.
> kaputtem Modell aus. Da sollte ein anderer Simulator die gleiche
> Fehlermeldung bringen.
Zu dieser Vermutung würden die ca. 2300 Warnungen passen, mit denen mich 
Synthese und Implementation überschütten.

Burkhard

von Matze (Gast)


Lesenswert?

Hallo Burkhard,

Habe auch ein Nexys4 Board und möchte den DDR2-Ram ansteuern.
Wenn ich es richtig lese hast du es geschafft den Ram anzusteuern, 
zumindest als SRAM.
Dabei soll Vivado 15.4 genutzt werden.

Wie hast du dass geschafft?

Ich habe nun verschiedene Varianten versucht:

1. Mit MIG7 das DDR-Interface so wie hier:
https://reference.digilentinc.com/nexys4-ddr:sram
vorgesehen einzustellen und den Ram als DDR-Ram zu nutzen.

2. Ein Demoprojekt welches DDR-Ram nutzt als Basys für mein eigenes 
Projekt zu nutzen.

3. Die auf der Seite vorgesehene refferenz Komponente nutzen, sie 
richtig verbinden:
z.b. mit PLL für clk_200MHz_i und einem Ablauf bei dem ich versuche den 
RAM so wie es mit sinvoll erscheint anzusprechen:
1
    RD_DATA: process(CLK100MHZ)
2
    variable counter : integer;
3
    variable counter_langsam : integer;
4
    begin
5
        if rising_edge(CLK100MHZ) then
6
            counter := counter + 1;
7
            if counter = 200000000 then
8
                counter :=0;
9
                counter_langsam := counter_langsam + 1;
10
                if counter_langsam = 11 then
11
                    counter_langsam :=0;
12
                end if;
13
            end if;
14
            if counter_langsam = 0 then
15
                LED <= "0000000000000001";
16
                schreibdaten <= x"0FA5";
17
                cen <='0';
18
                read_en <= '0';
19
                write_en <= '0';
20
                ub <= '0';
21
                lb <= '0';
22
            elsif counter_langsam = 1 then
23
                LED <= "0000000000000010";
24
                schreibdaten <= x"0FA5";
25
                cen <='0';
26
                read_en <= '0';
27
                write_en <= '1';
28
                ub <= '1';
29
                lb <= '1';
30
            elsif counter_langsam = 2 then
31
                LED <= "0000000000000100";
32
                schreibdaten <= x"0FA5";
33
                cen <='1';
34
                read_en <= '0';
35
                write_en <= '1';
36
                ub <= '1';
37
                lb <= '1';
38
            elsif counter_langsam = 3 then
39
                LED <= "0000000000001000";
40
                schreibdaten <= x"0000";
41
                cen <='0';
42
                read_en <= '0';
43
                write_en <= '1';
44
                ub <= '1';
45
                lb <= '1';
46
            elsif counter_langsam = 4 then
47
                LED <= "0000000000010000";
48
                schreibdaten <= x"0000";
49
                cen <='0';
50
                read_en <= '0';
51
                write_en <= '0';
52
                ub <= '0';
53
                lb <= '0';
54
            elsif counter_langsam = 5 then
55
                LED <= "0000000000100000";
56
                schreibdaten <= x"0000";
57
                cen <='0';
58
                read_en <= '1';
59
                write_en <= '0';
60
                ub <= '1';
61
                lb <= '1';
62
            elsif counter_langsam = 6 then
63
                LED <= "0000000001000000";
64
                schreibdaten <= x"0000";
65
                cen <='1';
66
                read_en <= '1';
67
                write_en <= '0';
68
                ub <= '1';
69
                lb <= '1';
70
            elsif counter_langsam = 7 then
71
                LED <= "0000000010000000";
72
                schreibdaten <= x"0000";
73
                cen <='1';
74
                read_en <= '1';
75
                write_en <= '0';
76
                ub <= '1';
77
                lb <= '1';
78
                LED <= lesedaten;
79
            elsif counter_langsam = 8 then   
80
                LED <= "0000000100000000";
81
                schreibdaten <= x"0000";
82
                cen <='0';
83
                read_en <= '1';
84
                write_en <= '0';
85
                ub <= '1';
86
                lb <= '1';
87
            elsif counter_langsam > 9 then   
88
                LED <= "0000001000000000";
89
                schreibdaten <= x"0000";
90
                cen <='0';
91
                read_en <= '0';
92
                write_en <= '0';
93
                ub <= '0';
94
                lb <= '0';
95
            else 
96
                LED <= x"0000";
97
                cen <='0';
98
                read_en <= '0';
99
                write_en <= '0';
100
                ub <= '0';
101
                lb <= '0';
102
            end if;
103
        end if;
104
    end process;

Doch im grunde spielt es keine Rolle welchen weg ich wähle, es treten 
immer an die 1000 Info's, von denen nicht wenige auf Fehler innerhalb 
des MIG-Erzeugten Verilogs hindeuten.

Dies führt zu etwa 500 Warnungen, verschiedenster Art, die aber 
sicherlich aufzeigen, dass es so nicht gehen kann.

Es entstehen zwischen 100 und 200 Warnungen, z.b. der Form:
1
[Netlist 29-160] Cannot set property 'IN_TERM', because the property does not exist for objects of type 'pin'. ["d:...ram2ddr/ram2ddr.srcs/sources_1/ip/ddr/ddr/user_design/constraints/ddr.xdc":34]
Sowas sollte doch nicht vorkommen, wozu bekommt man vordefinierte 
UCF-Files für das Pining?

Letztendlich gibt es beim Bitstream generieren Fehler, diese sind von je 
mach Fall verscienener Art, besonders was den Clk_eingang der 200MHz 
angeht.

von J. S. (engineer) Benutzerseite


Lesenswert?

Burkhard K. schrieb:
> Hat jemand hier im Forum ein Nexys4-DDR Board in Betrieb?
Auf dem Atlys

>    Der per MIG erzeugte DDR2 Core lässt sich mit ISim nicht simulieren,
das ist keine so wirklich neue Information
ISIM wird von Xilinx aus irgendeinem mir nicht verständlichen Grund 
nicht vollständig gepflegt. Im Bereich SERDES und GBT habe ich weitere 
Beispiele, wo man mit ISIM nicht weiterkommt und nur ModelSIM das kann.


>    Es muss wohl möglich sein, aus den per MIG generierten Sourcen eine
> Netlist-Datei einmalig zu erstellen und in das Projekt einzubinden. Kann
> jemand das Vorgehen dazu kurz skizzieren?
Du musst das user design entsprechend anpassen. Meistens muss man einen 
internen Takt benutzen, der aus einer eigenen PLL kommt, oder sich an 
die des DDR-CTRL dranhängen.


> Meine Anwendung erzeugt 2x16 bit (Audio-)Daten mit 1 MSps/s die per
> FFT analysiert und später auf 200 kSps/s reduziert ausgegeben werden.
Warum wird die so hoch gesampelt? Wenn man eine Steigerung der Auflösung 
möchte, muss man in der Regel auch die Bitbreite anpassen. 24 Bit wären 
bei Audio ohnehin Pflicht.

> Bei den oben dargestellten Zugriffszeiten muss ich die aus dem RAM
> gelesenen Daten (Burstlänge 8) in einem FiFo zwischenspeichern.
> Hinsichtlich des Timings ist der Ersatz von SRAM durch DDR2 ein eher
> enttäuschender Rückschritt.

Eigentlich würde man bei FFTs eher die Blockrams nehmen. Wenn Du später 
runtersampelst, müssen bei 200kHz x Stereoaudio aber ein SRAM 100mal 
reichen (?)

Ungeachtet dessen, willst Du sicher den DDR-CRTRL ins Laufen bekommen.
Hast Du die Möglichkeit, einen physischen Test zu machen? Einfach mal 
statisch reinschreiben und rausschreiben, ohne großartige 
Zugriffskontrolle?

von Josef G. (bome) Benutzerseite


Lesenswert?

Ich habe zwar kein Nexys4, aber vielleicht ist
in diesem Zusammenhang folgendes interessant:

Bei der Realisierung meines 8bit-Computers auf dem Spartan-3A-Starterkit
hatte ich das Problem, das DDR2-RAM (MT47H32M16) als Ersatz für ein SRAM
verwenden zu müssen. Der Zeitablauf besteht aus einer Folge von Halb-
zyklen tA und tB, welche jeweils 320 ns dauern. Der Speicherzugriff
durch die CPU erfolgt während tA, der Refresh während tB.

Ich habe das Problem ohne Verwendung des MIG so gelöst: Bei
der Initialisierung des RAMs habe ich eingestellt Burstlänge 4. Bei
den Speicherzugriffen verwende ich Auto-Precharge. Die 4 Datenworte
eines Bursts werden als ein einziges Datenwort behandelt: Beim
Schreiben erhalten alle 4 Worte denselben Wert. Das Lesen erfolgt
irgendwo im Inneren des Bursts. Man braucht keine DDR-Flipflops,
und das Timing beim Lesen vereinfacht sich drastisch. Ich habe
nicht einmal Timing-Constraints gebraucht. Ein theoretisch
denkbares Glitch-Problem beim Lesen ist nie aufgetreten.

Siehe Datei ps3a.vhd auf der Seite Downloads meiner Website:
http://www.bomerenzprojekt.de

von Burkhard K. (buks)


Lesenswert?

Hallo Matze,

den DDR2 habe ich inzwischen eigenem Controller in Benutzung (mit 
ISE14.7). Die Anzahl der Warnungen ist Legion (> 1700). Simulieren ist 
nicht (s.oben). PAR schmeisst zwei Timing-Violations aus den Tiefen des 
PHY-Layers, die ich aber als unkritisch einstufe (Temperatur-Kontrolle).

Mein Controller-Design habe ich aus Digilentics Referenzkomponente 
https://reference.digilentinc.com/_media/nexys4-ddr:ram2ddr_refcomp.zip 
(ram2ddrxadc.vhd) abgeleitet. Die Referenz-Komponente basiert auf dem 
MIG-UserInterface.

Gestört hat mich an Digilents ram2ddrxadc.vhd insbeondere das sehr 
langsame Timing und die fest eingestellte Wartezeit (1200 ns bis zum 
RAM-ACK). Um ein für meine Anwendung brauchbares Timing zu realisieren, 
habe ich einge Anpassungen vorgenommen:

  * den vorgeschalteten SRAM Controller eingedampft
  * die Steuer-Eingänge (ram_cen, ram_rnw) nach ram2ddrxadc.vhd 
übernommen und dort registriert
  * die Steuersignale "rd_data_valid" bzw. "mem_rdy" für die Erzeugung 
der ACK-Signale ausgewertet
  * eine fixe Datenbreite von 32 Bit eingestellt, wodurch sich das 
Setzen der WDF-Maske erheblich vereinfacht
  * und schliesslich das MIG Interface auf 2:1 Mode umgestellt so dass 
sich die Zugriffszeiten für einzelne Schreib- ( < 100 ns) Lesezugriffe 
(ca. 200 ns) erheblich verkürzen
  * einen Arbiter mit fixer Priorität (Schreiben) integriert

Das MIG-UserInterface läuft mit 75 MHz (4:1 Mode) bzw. 150 MHz (2:1) bei 
eingestellter 3333 ps DDR2-Clock. Daher müssen die Kontroll-Signale im 
User-Design einsynchronisiert werden - bei 150 MHz zusätzlich noch 
gestreckt werden.

Da ich nicht simulieren kann (s.o.) musste ich die relevanten 
Steuersignale auf einen Pmod-Port legen und per USB-Logicanalyzer 
anschauen (Mein Hobby-Bastel Analog-Discovery kann 10 ns Auflösung 
gerade noch so). Zum Testen und Verifizieren habe ich die Daten über die 
16 Schiebeschalter eingegeben, die Address-Eingabe per an einen Pmod 
angeschlossen Drehgeber realisiert, die 27bit Adresse auf der 
7-Segmentanzeige ausgegeben.

@Jürgen - ich analysiere Ultraschalldaten bis ca. 200 kHz - 5faches 
Oversampling scheint mir dafür angemessen. Für die (hörbare) Ausgabe der 
heruntergemischten bzw. Frequenz-transponierten Signale verwende ich 
"normale" Audio-Samplingraten. HiFi spielt in diesem Zusammenhang keine 
Rolle, 16bit Datenbreite reicht aus.

Gruß,
Burkhard

: Bearbeitet durch User
von Matze (Gast)


Lesenswert?

Burkhard K. schrieb:
> Hi Matze, das mem_rdy Signal des UserInterfaces ist tatsichlich 99% der
> Zeit auf '1', bewegt sich aber doch auf '0' - nämlich bei zwei
> Gelegenheiten:
>
>   * sobald das Write Kommando akzeptiert wurde, also als Reaktion auf
> das Setzen von "mem_wdf_wren" UND "mem_wdf_end"

Stimmt, das konnte ich nun auch nachvollziehen.

Burkhard K. schrieb:
> Wenn Dein "debug"-Signal in einer anderen
> Clk-Domäne weiterverarbeitet wird, muss es noch einsynchronisiert
> werden, die mem_ui_clk läuft mit einem Viertel  bzw. der Hälfte (2:1
> Mode) der DDR2 Clk.

Würde es von einem anderen CLK getaktet müsste es einsyncronisiert 
werden.
Werde von daher erstmal den ui_clk als Systemtackt nutzen.
Der ui_clk läuft etwa mit 150MHZ.

Burkhard K. schrieb:
> Tatsächlich gibt es gleich mehrere mögliche Reihenfolgen, in denen
> Daten, WDF Maske und Schreibkommando präsentiert werden können, bitte am
> besten selbst im MIG User Guide, Abschnitt "User Interface" nachlesen -
> und zwar in der neuesten Version (Zynq-7000 AP SoC and 7 Series Devices
> Memory Interface Solutions v2.4)! In älteren Versionen des Dokuments ist
> die Abfolge unvollständig dargestellt, was mich einige Zeit gekostet
> hat.

Danke, dies ist der entscheidende Tipp, ich hatte ein unvollständiges 
Datenblatt und wusste so nicht genau in welcher Reihenfolge die Signale 
gesetzt werden müssen.

Habe schreiben/lesen nun deutlich verkürzen können.

Hiermit kann man den RAM lesen + schreiben
1
        if (rising_edge(ui_clk)) then
2
            if state = 0 then           --Idle
3
                addr <= address;
4
                cmd <= CMD_WRITE;
5
                en <= '0';
6
                wdf_mask <= "00000000";
7
                wdf_wren <= '0';
8
                wdf_data <= data_in;
9
                wdf_end <= '0';
10
                debug <=x"0"; 
11
                write_ok <= '0';
12
                read_ok <= '0';
13
                if wdf_rdy = '1' and rdy = '1' then -- MIG bereit
14
                    DDR2_rdy <= '1';--Controller bereit
15
                    if write_en = '1' and read_en = '0' then
16
                        state := 1; 
17
                    elsif write_en = '0' and read_en = '1' then
18
                        state := 2;
19
                    else 
20
                        state := 0;
21
                    end if;
22
               else
23
                    DDR2_rdy <= '0';                     --Controller ! bereit
24
               end if;
25
            elsif state = 1 then        --Schreiben
26
                addr <= address;
27
                cmd <= CMD_WRITE;
28
                en <= '1';
29
                wdf_mask <= "00000000";
30
                wdf_wren <= '1';
31
                wdf_data <= data_in;
32
                wdf_end <= '1';
33
                debug <=x"1"; 
34
                write_ok <= '1';
35
                read_ok <= '0';
36
                DDR2_rdy <= '0'; 
37
                state := 0;
38
            elsif state = 2 then        --Lesen
39
                addr <= address;
40
                cmd <= CMD_READ;
41
                en <= '1';
42
                wdf_mask <= "11111111";
43
                wdf_wren <= '0';
44
                wdf_data <= data_in;
45
                wdf_end <= '0';
46
                debug <=x"2"; 
47
                write_ok <= '0';
48
                DDR2_rdy <= '0'; 
49
                if rd_data_valid = '1' then
50
                    data_out <= rd_data;
51
                    read_ok <= '1';
52
                    state := 0;
53
                else 
54
                    read_ok <= '0';
55
                end if;
56
                
57
            else
58
                state := 0;
59
            end if;
60
        end if;
61
    end process;

Angesteuert wird das ganze Testhalber so:
1
            if state = "0000" then
2
                data_in <= address(26 downto 0) & x"000000000" & '0';
3
                if DDR2_rdy = '1' then
4
                    write_en <= '1';
5
                    read_en <= '0';
6
                    state <= "0001";
7
                end if;
8
                JC(1 downto 0) <= "01";-- Gelb, Blau, Lila
9
                JC(2)           <= '0';
10
            elsif state = "0001" then
11
                if write_ok = '1' then
12
                    write_en <= '0';
13
                    read_en <= '0';
14
                    state <= "0010";
15
                end if;   
16
                JC(1 downto 0) <= "10";
17
                JC(2)           <= '0';
18
            elsif state = "0010" then
19
                if DDR2_rdy = '1' then
20
                    data_in <= address(26 downto 0) & x"000000000" & '0';
21
                    write_en <= '0';
22
                    read_en <= '1';
23
                    state <= "0011";
24
                end if;
25
                JC(1 downto 0) <= "11";
26
                JC(2)           <= '0';
27
            elsif state = "0011" then
28
                 if read_ok = '1' then
29
                    write_en <= '0';
30
                    read_en <= '0';
31
                    LED(15 downto 0) <= data_out(63 downto 48);
32
                    disp_data(15 downto 0) <= data_out(47 downto 32);
33
                    address <= address + '1';
34
                    data_in <= address(26 downto 0) & x"000000000" & '0';
35
                    state <= "0000";
36
                end if;
37
                JC(1 downto 0) <= "00";
38
                JC(2)           <= '1';
39
            end if;

Problem ist der Lesezyklus, wie du es schreibst dauert er bei mir gut 
400ns, da die Gültigkeit der daten ewig auf sich warten lässt.

Jedenfalls liegen die Signale
1
 JC(1 downto 0) <= "00";
2
 JC(2)           <= '1';
des so lange an.

Somit müsste es hierran liegen:
1
if rd_data_valid = '1' then


Aber es kann doch nicht sein, dass der DDR-Controller so extrem langsam 
liest. Was bringen 128MByte DDR2 wenn man nur mit Einstelliger MB/s- 
Datenrate davon lesen kann?

Schreiben scheint um ein vielfaches schneller zu gehen.

Somit hast du völlig Recht:
Burkhard K. schrieb:
> 3. Timing:
>    Digilent gibt die Cycle-Time
> (https://reference.digilentinc.com/nexys4-ddr:sram) mit 210 (tRC) bzw.
> 260 (tWR) ns an. Tatsächlich gemessen habe ich für den Lesezyklus ca.
> 350 ns, mit gelegentlichen Ausreissern (> 400 ns) nach oben (vom Anlegen
> des CEN Signals bis zur Assertion von RD_DATA_VALID des MIG UIs - bei
> Verwendung des RAM2DDRxadc Moduls von Digilent). Die Zeit für einen
> Schreibzyklus kann ich mit meinem Mitteln leider nicht messen; sie
> scheint aber unter der fürs Lesen zu liegen.

Hast du schon versucht den DDR-Controller MIG7 IP-Block von Hand 
anzulegen.
Dass werd ich nun mal versuchen.

von Josef G. (bome) Benutzerseite


Lesenswert?

Duke Scarring schrieb:
> Ich habe auch ein Nexys4, aber die Variante mit dem PSRAM.

Ist zwar OT, aber ich häng mich mal hier mit einer Frage dran:

Mir ist aufgefallen, dass Digilent innerhalb kurzer Zeit die Boards
Nexys2/Nexys3/Nexys4 mit PSRAM vom Markt genommen hat, obwohl die
FPGAs darauf verschiedenen Generationen angehören. Offenbar lag's
nicht an veralteten FPGAs (Spartan-3E beim Nexys2), sondern an
den PSRAMs. Weiss jemand, was es damit auf sich hat? Werden
diese RAMs nicht mehr hergestellt?

von Josef G. (bome) Benutzerseite


Lesenswert?

Korrektur:

Das Nexys3 und Nexys4 mit PSRAM gibt es noch, aber "Limited Time".

von Michael W. (Gast)


Lesenswert?

Hat sich das mit dem Speicherproblem geklärt?

von Burkhard K. (buks)


Lesenswert?

M. W. schrieb:
> Hat sich das mit dem Speicherproblem geklärt?

Ich selbst habe den DDR2-Speicher im 2:1 Modus - nach einigen "Gotchas" 
(MIG-7 - die Doku ist extrem dünn und in älteren Versionen 
unvollständig) - im Einsatz; Matze soweit ich lese ebenso. Das Digilent 
"Referenz-Design" ist ein schlechter Witz. Was genau willst Du wissen?

MIG: Was immer noch nervt, ist die Nichtsimulierbarkeit mit ISIM und die 
in die Tausenden gehenden Warnungen aus diesem IP-Block. Implementieren 
mit MIG im Design dauert ewig (gefühlt +10 Minuten). Leider habe ich es 
bisher nicht hinbekommen, das MIG User Interface für den Speicher 
vorsynthesiert in eine .ngc Datei zu packen (ISE). Noch genialer wäre 
es, wenn sich der ganze MIG Kram vorimplementiert (PAR) auf den FPGA 
klatschen liesse und ich mein restliches Design anschliessend darum 
bauen könnte. Für einen Tip in diese Richtung wäre ich dankbar.

Gruß,
Burkhard

von Christian R. (supachris)


Lesenswert?

Das Nexsys 4 ist doch ein Artix Board, wieso nutzt ihr dann ISE? In 
Vivado kann man den Mig simulieren, geht zwar langsamer als Modelsim 
aber immerhin. Doku ist beschissen aber anhand des Example Designs 
kriegt man das hin. Den 2:1 Modus sollte man meiner Meinung nach nur 
nutzen, wenn man auf Schmerzen steht. Im 4:1 ist das wenigstens halbwegs 
sinnvoll, da kann man einfach beim Schreiben den Fall 1 nehmen, und 
Daten, Adresse, app_en wdf_end und wren gleichzeitig setzen.
Klar, beim Sdram hat man immer Latenz, wenn man nur einen Burst liest, 
ist das langsam, aber wenn es einmal los ging kommen die Daten 
hintereinander.

von Burkhard K. (buks)


Lesenswert?

Christian R. schrieb:
> Den 2:1 Modus sollte man meiner Meinung nach nur
> nutzen, wenn man auf Schmerzen steht.

Danke für die Blumen - Du hast im Thread meine Requirements gelesen? Was 
nützt mir der vermeintlich einfachere Transfer, wenn das Timing nicht zu 
gebrauchen ist?
2:1 Mode: Eine zusätzliche UI_Clock Periode und 4 Zeilen Code mehr - das 
piekst nur ganz sanft - sobald man mal weiss wie's geht.
1
   MEM_WR_CTL: process(cState, ram_wrm_int)
2
   begin
3
      -- first transmission - upper address part transferred during BL8
4
      -- these part must be masked completely to prevent unintended
5
      -- overwrite at app_addr(7 downto 4)
6
      if cState = stSendData then
7
         mem_wdf_wren  <= '1';
8
         mem_wdf_end   <= '0';
9
         mem_wdf_mask   <= "11111111";
10
 
11
      -- second transmission - lower address part transferred during BL8
12
      -- contains 32bit payload
13
      -- mask non-payload data at app_addr(3 downto 2)
14
      elsif cState = stSendData2 then
15
         mem_wdf_wren  <= '1';
16
         mem_wdf_end   <= '1';
17
         mem_wdf_mask   <= "1111" & "0000";
18
      else
19
         mem_wdf_wren  <= '0';
20
         mem_wdf_end    <= '0';
21
         mem_wdf_mask   <= "11111111";
22
      end if;
23
   end process MEM_WR_CTL;

Für ISE hab ich meine Gründe - z.B. hätte mein Design von dem ganzen 
AXI-Geraffel nur den Overhead - aber keinen Vorteil (ausser dass ich 
eine Handvoll IP-Blöcke grafisch in das Design klicken könnte).

Gruß, Burkhard

von Christian R. (supachris)


Lesenswert?

Man kann Vivado und dort auch den MIG komplett ohne Axi benutzen. Ivh 
mag Axi auch nicht und benutze es nicht. Aber ISE und Artix war wirklich 
nur eine Krücke. Das mit dem Timing verstehe ich nicht ganz, DDR Sdram 
braucht halt prinzipiell eine gewisse Latenz, dafürgibts Buffer. Jeder 
B8L einzeln mag dann mit 2:1 besser gehen, richtig.

von Burkhard K. (buks)


Lesenswert?

Christian R. schrieb:
> Man kann Vivado und dort auch den MIG komplett ohne Axi benutzen.

Den MIG schon - aber divsere andere IPs (FIR-Compiler, CIC-Compiler, 
CORDIC, DDS-Compiler, XADC-Wizard etc.) gibt es - anders als in ISE - in 
Vivado offensichtlich nur noch mit AXI-Interface. Sollten sich in ISE 
vorhandene, ältere Versionen dieser IPs nach Vivado importieren, wäre 
das ein Grund mir Vivado noch mal anzuschauen.

Beim Timing gibt es nicht viel zu verstehen, wenn ich in einer 
Mikrosekunde je einen Schreib- und einen (oder sogar zwei) 
Lesezugriff(e) unterbringen muss, dann ist der 4:1 Modus mit der 
schlecht definierten Lesezeit von 400 ns und darüber zu dicht am Limit.

von Christian R. (supachris)


Lesenswert?

OK, manche Cores gibts nur noch mit Axi, stimmt, aber Axi Streaming ist 
auch nur ein simples FIFO Interface. Ich hab mit ISE und dem Artix ganz 
schlechte Erfahrungen gemacht, dauert alles lange, Simulation klappt 
nicht, da bin ich dann auch auf Vivado umgestiegen. Hat auch Macken, 
aber für die 7er einfach besser als ISE.

Klar, wenn du nicht puffern kannst, ist der 2:1 besser. Ich finde den 
halt bissl seltsam, passt nicht so recht zu meinem Interface und 
außerdem braucht der bei DDR400 den 3er Speedgrade. Timing ist schon bei 
4:1 irre, aber bei 2:1 mit DDR400 aufm Artix schon echt schwierig.
Daher umgehe ich den wo es geht. ;)

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.