Hallo,
irgendwie komme ich nicht weiter. Der Cyclone II besitzt ja internen
Speicher namens M4K. Diesen habe ich in ein Testprojekt von mir über den
Wizard von Quartus als 1-Port-RAM eingebunden.
Wenn ich die Doku richtig verstanden habe, wird bei der steigenden
Flanke des an den RAM angelegten Takts der Speicher an der zu diesem
Zeitpunkt angelegten Adresse ausgelesen.
Dummerweise kann ich (zumindest in der Simulation) Adresse und Takt
nicht gleichzeitig setzen. Den dann kommt der Speicherinhalt der zuvor
angelegten Adresse.
Erst wenn ich die Adresse einen Takt vorher ausgebe, bekomme ich das
gewünschte Datum. Dazu brauche ich aber zwei Takte für einen
Lesezugriff.
Hat jemand eine Idee - oder habe ich vielleicht etwas übersehen?
Schon mal vielen Dank
MuePlus
MuePlus schrieb:> irgendwie komme ich nicht weiter. Der Cyclone II besitzt ja internen> Speicher namens M4K. Diesen habe ich in ein Testprojekt von mir über den> Wizard von Quartus als 1-Port-RAM eingebunden.>> Wenn ich die Doku richtig verstanden habe, wird bei der steigenden> Flanke des an den RAM angelegten Takts der Speicher an der zu diesem> Zeitpunkt angelegten Adresse ausgelesen.
Lt http://www.altera.com/literature/hb/cyc2/cyc2_cii51008.pdf S.9
unterstützt M4k keinen asynchronen Memory (unregistered Input), die
adresse wird also immer eingetaktet.
MfG,
@Datenblattversteher
Kannst du mal bitte auf die folgenden Zeilen schauen. Dann muss der
Fehler in meiner Implementierung bzw. der Simulation stecken.
In meiner Verhaltensbeschreibung des RAMs habe ich für das Lesen
folgendes zu stehen:
-- Lesen vom RAM
data <= q WHEN (wr = '0' AND rd = '1' AND cs = '1')
ELSE (others => 'Z');
Wie beschrieben brauche ich bei meiner Simulation das zweite WAIT, um an
das richtige Datum zu kommen:
WAIT UNTIL rising_edge(clk_stim);
address <= x"003";
WAIT UNTIL rising_edge(clk_stim);
cs <= '1';
rden <= '1';
Ist da ein Denkfehler?
Grüße
MuePlus
> Wenn ich die Doku richtig verstanden habe, wird bei der steigenden> Flanke des an den RAM angelegten Takts der Speicher an der zu diesem> Zeitpunkt angelegten Adresse ausgelesen.
Dann lege doch die Adresse an der Fallenden Flanke davor an.
Das geht leider nicht. Ich brauche pro Takt einen Zugriff. Auch kann ich
nicht den Takt invertieren, da das Schreibsignal genau anders herum,
also zur fallenden Flanke übernimmt. Dann hätte ich das Problem
lediglich dorthin verschoben.
Gruß
MuePlus
Du schreibst wenig über deinen Testbench und über das M4K-RAM:
Kannst du die Addresse z.B. 0.5-1.0 ns vor der Clock-Flanke anlegen
(um mögliche Hold-Time-Violations zu vermeiden)?
Wie sieht in deinem M4k-RAM der Parameter "outdata_reg_a" aus?
"UNREGISTERED","CLOCK0" bzw "CLOCK1"? "UNREGISTERED" liest
das RAM sofort aus, "CLOCK*" ein Takt später.
Schon einmal vielen Dank für Eure Hilfe.
Bei "outdata_reg_a" steht "UNREGISTERED". Daher ging ich (vor meinem
Test) davon aus, das ich im selben Takt auch das Datum bekomme.
Um mein Problem besser darzustellen, habe ich einmal ein Screenshot der
Simulation angehängt. Dort ist gut zu erkennen, das das Setzen der
Adresse bei steigender Flanke eigentlich schon zu spät ist. Das Datum
wird immer erst im Folgetakt ausgegeben.
Ich habe ebenfalls das Projekt mit angehangen. Vielleich hat ja jemand
eine Idee.
Viele Grüße
MuePlus
Ich kenne zwar nicht alle deine Einstellungen, würde aber
mal sagen, dass das das ist was ich als Ausgabe erwartet
habe. Du setzt z.B. zur 2. steigenden Flanke addresse=03,
worauf dann in der 3. st. Flanke 03 im internen Addr.Reg
steht und "kurz" darauf 03030303 als Wert ausgegeben
wird. (Bem: zur 3. Flanke kannst du natürlich die nächste
Addresse anlegen etc..)
Du erwartest wohl, dass 03030303 in der 2. Taktperiode
(d.h. kurz nach der 2. st.Flanke) ausgegeben wird. Dafür
müsstest du aber das interne Addr-Register der M4K
ausschalten können (ist aber nicht möglich).
Mögliche Lösung: Falls dein Design nicht gerade gross
über 100MHz läuft, dann kannst du ja per PLL eine 2X-Clk
generieren und damit das M4K antreiben. Dein Wert wird
dann mitten in der Taktperiode geliefert.
MuePlus schrieb:> Bei "outdata_reg_a" steht "UNREGISTERED". Daher ging ich (vor meinem> Test) davon aus, das ich im selben Takt auch das Datum bekomme.
Du hast die Register am Eingang übersehen. Im Datenblatt steht dazu:
"All M4K memory blocks are fully synchronous, meaning
that you must send all inputs through a register, but you can either
send
outputs through a register (pipelined) or bypass the register
(flow-through)".
Leider kann man bei cyclone nicht statt aus M4K-Blöcken deinen
RAM-Speicher aus den LUT's im Speichermode (ähnlich distributed ram bei
spartan) bauen.
MuePlus schrieb:> Um mein Problem besser darzustellen, habe ich einmal ein Screenshot der> Simulation angehängt. Dort ist gut zu erkennen, das das Setzen der> Adresse bei steigender Flanke eigentlich schon zu spät ist. Das Datum> wird immer erst im Folgetakt ausgegeb
Entschuldige, aber das ist doch bei jedem Standard FF so.
Es wird immer der Zustand von VOR der Taktflanke übernommen. Wenn eine
synchrone Schaltung die Ausgänge schaltet, dann liegen diese nach der
Durchlaufzeit an den Eingängen wieder an und bestimmen das
Schaltverhalten für die NÄCHSTE Flanke.
Zugriffszeit 1 Takt heißt trotzdem weiterhin, dass die Adressen vor der
Taktflanke anliegen müssen.
Hallo MuePlus,
habe in meinem momentanen Projekt einen DCFIFO mit unterschiedlicher
Eingangs und Ausgangsbreite und dort ist es so, dass ich die Daten zu
Negativer Flanke anlege und auf Positive Flanke übernimmt sie der
DCFIFO... Aber denke mal das es dann allgemein bei Altera so ist das die
Daten auf steigende Flanke in den FIFO's/Buffer übernommen werden.
Allerdings hab ich das Problem im moment das ich kein richtiges rdused
Signal (Füllstandssignal des DCFIFO) bekomme...
Was bitte versprichst Du Dir von der RAM-Lesefunktion, wenn Du den Bus
auf "Z" setzt???
Es gibt im FPGA intern kein "hochohmig" - die Zeiten bidirektionaler
Busse in solchen Logikbausteinen sind längst vorbei. Du hast immer einen
Schreib- UND einen Leseanschluss.
Woher kommt diese Beschreibung?
---
Bei den Altera-RAMs kann man i.d.R. auch unregistriert zugreifen,
allerdings geht das nur unterhalb einer meist unakzeptablen Frequenz. In
der Regel wird man aber immer registriert einschreiben, weil Daten und
Adressen ja irgendwo her kommen und das WE synchron gesetzt wird. Im
nächsten Takt wird eingeschrieben und beim Lesen auf derselben Adresse
auch transparent ausgegeben (wenn man das zulässt und nutzt).
Am Besten nutzt Du das vom Megawizzard generierte RAM-Modell. Da ist die
parametrierte Taktverzögerung wie sie eingestellt ist, auch simulierbar.