Hi,
ich habe das Problem, dass ich vom BRAM die Daten gerne schon bei der
nächsten steigenden Taktflanke hätte, wenn ich die Adresse anlege. Aber
mein FPGA (MAX 10) hat nur synchrone BRAM-Blöcke.
Kann ich über eine PLL die Eingangsfrequenz des BRAMs verdoppeln und
einfach über eine Schaltung mit der einfachen Frequenz (auch Ausgabe der
PLL) steuern und auswerten? Grundsätzlich sind es ja zwei Taktdomänen
und müssen daher synchronisiert werden, aber wie gestaltet sich das mit
n-fachen Frequenzen ? Bin kein Elektrotechniker. Habe im Netz auch
nichts dazu gefunden, es sieht also schlecht aus...
True Dual Port RAM schrieb:> ich habe das Problem, dass ich vom BRAM die Daten gerne schon bei der> nächsten steigenden Taktflanke hätte, wenn ich die Adresse anlege. Aber> mein FPGA (MAX 10) hat nur synchrone BRAM-Blöcke.
Herzlichen Glückwunsch, du hast die "Latency" entdeckt. Warum kannst du
nicht einfach die Adresse einen Takt früher anlegen?
> Kann ich über eine PLL die Eingangsfrequenz des BRAMs verdoppeln
Warum taktest du dein gesamtes Desgin insgesamt nicht einfach doppelt so
schnell?
> Kann ich über eine PLL die Eingangsfrequenz des BRAMs verdoppeln
Warum taktest du dein BRAM nicht einfach mit der fallenden Flanke? Auch
das wäre eine Verdopplung der Taktfrequenz...
> Kann ich über eine PLL die Eingangsfrequenz des BRAMs verdoppeln und> einfach über eine Schaltung mit der einfachen Frequenz (auch Ausgabe der> PLL) steuern und auswerten? Grundsätzlich sind es ja zwei Taktdomänen> und müssen daher synchronisiert werden
Das Synchronisieren übernimmt die PLL für dich: die sorgt dafür, dass
die zeitliche Verzögerung konstant ist und die Toolchain kann
überprüfen, ob die zeitlichen Zusammenhänge passen.
Ich vermute dass das eher ein Konfigurationsproblem oder
Verständnisproblem ist.
Normalerweise funktioniert der M9k so:
1: du legst die Adresse an die Adresspins an
2: die Clock steigt
3: der BRAM gibt etwas später (< 1-2 Nanosekunden) die Daten an den
Datenpins aus
4: bis zur nächsten Clockflanke sind die Daten auf jeden Fall stabil und
du kannst sie in nachfolgender Logik verwenden.
Eventuell hast du Die Registeroption für "'address' input port"
aktiviert gelassen (ist per default so), oder hast Register am Ausgang.
Das ist zwar besser fürs Timing und so, gibt aber halt ein bis zwei
Schritte Latenz.
Google mal nach UG-M10MEMORY und schau das Timingdiagramm auf Seite 8
an, rechte Hälfte (wren = 0). Da wird bei address z.B. a1 angelegt, dann
steigt die Clock und fast sofort später erscheint "FFCD" am Ausgang.
True Dual Port RAM schrieb:> die Daten gerne schon bei der> nächsten steigenden Taktflanke hätte, wenn ich die Adresse anlege
Verstehe ich das so richtig:
1: du legst irgendwann deine Adresse an
2: die Clock steigt
2: gleichzeitig sind die Daten schon da
Weil das macht designtechnisch keinen Sinn. Entweder sind die Daten
deutlich vor der Clockflanke da, damit du Zeit hast die Daten zu
verarbeiten, oder sie kommen erst nach der Flanke und werden einen Takt
später verarbeitet.
Oder meinst du:
1: steigende Clockflanke
2: eine Logik berechnet deine Adresse
3: jetzt ist deine Adresse valid
4: die Daten kommen aus dem BRAM
5: die Daten werden verarbeitet
6: steigende Clockflanke
Das geht dann eben nicht, weil der BRAM eben nur synchron läuft.
Es gibt aber ein paar dreckige Tricks mit denen das trotzdem ginge:
- negative/invertierte Clock verwenden, dann hast du die Daten schon
nach einer halben Taktperiode gültig, aber das Timing wird enger.
- mit XOR und Invertern händisch eine Flankenerkennung bauen, die dir
kombinatorisch zwei positive Clockpulse erzeugt wann immer die Clock
sich ändert. Garstig und nicht zu empfehlen, außer man hat genug
Erfahrung mit manueller LUT-Platzierung und den Gatterlaufzeiten über
alle design corners.
Lothar M. schrieb:> True Dual Port RAM schrieb:>> ich habe das Problem, dass ich vom BRAM die Daten gerne schon bei der>> nächsten steigenden Taktflanke hätte, wenn ich die Adresse anlege. Aber>> mein FPGA (MAX 10) hat nur synchrone BRAM-Blöcke.> Herzlichen Glückwunsch, du hast die "Latency" entdeckt. Warum kannst du> nicht einfach die Adresse einfach einen Takt früher anlegen?
Das wäre schön, aber das klappt wahrscheinlich nicht. Bin noch in der
Planungsphase, deshalb ist das ganze noch etwas unkonkret. Der Fall hat
mich aber jetzt schon beschäftigt und wollte dem nachgehen.
Lothar M. schrieb:>> Kann ich über eine PLL die Eingangsfrequenz des BRAMs verdoppeln> Warum taktest du dein gesamtes Desgin insgesamt nicht einfach doppelt so> schnell?
Ich vermute, dass das Design das nicht mitmachen wird.
Lothar M. schrieb:>> Kann ich über eine PLL die Eingangsfrequenz des BRAMs verdoppeln> Warum taktest du dein BRAM nicht einfach mit der fallenden Flanke? Auch> das wäre eine Verdopplung der Taktfrequenz...
Stimmt, daran habe ich gar nicht gedacht. Das werde ich dann
ausprobieren.
Lothar M. schrieb:>> Kann ich über eine PLL die Eingangsfrequenz des BRAMs verdoppeln und>> einfach über eine Schaltung mit der einfachen Frequenz (auch Ausgabe der>> PLL) steuern und auswerten? Grundsätzlich sind es ja zwei Taktdomänen>> und müssen daher synchronisiert werden> Das Synchronisieren übernimmt die PLL für dich: die sorgt dafür, dass> die zeitliche Verzögerung konstant ist und die Toolchain kann> überprüfen, ob die zeitlichen Zusammenhänge passen.
Ah sehr schön. Da war ich mir nicht sicher.
@bla
Der Vorgang sieht so aus:
1. steigende Clockflanke
2. Adresse wird berechnet
3. Adresse ist gültig und liegt am RAM an
4. ...
5. steigende Clockflanke
6. jetzt hätte ich gerne die Daten zum Verarbeiten
bla schrieb:> Google mal nach UG-M10MEMORY und schau das Timingdiagramm auf Seite 8> an, rechte Hälfte (wren = 0). Da wird bei address z.B. a1 angelegt, dann> steigt die Clock und fast sofort später erscheint "FFCD" am Ausgang.
Ja genau das habe ich mir zuvor angeschaut und muss zugeben, dass mich
das Diagramm verwirrt hat. Warum ist der Ausgang plötzlich nicht mehr
getaktet q (asynch)? Auf der nächsten Seite gibts hingegen wieder den
Ausgang q (synch), also synchron mit der Latenz. Ich hab dann ins
Quartus Handbuch geschaut, um zu sehen wie man den BRAM in HDL
beschreibt. Und da war der Lesevorgang im getakteten Prozess. Testweise
habe auch den Code mal mit asynchronem Lesen durch den Synthesizer
gejagt. Da kam dann wie erwartet auch die Warnung: "RAM logic
"Ram:ram0|mem" is uninferred due to asynchronous read logic". Also
bedeutete das für mich, dass ich die Latenz anders weg kriegen muss.
True Dual Port RAM schrieb:> Das wäre schön, aber das klappt wahrscheinlich nicht. Bin noch in der> Planungsphase, deshalb ist das ganze noch etwas unkonkret. Der Fall hat> mich aber jetzt schon beschäftigt und wollte dem nachgehen.
Das klappt schon, nur eben nur bei "geringen" Taktgeschwindigkeiten.
Beim Artix z.B. bis 80MHz. Allerdings kann man den mit dem doppelten
Takten und ist letztlich mit einem FF genau so weit. Man kann ihn auch
mit dem Dreifachen Takten und braucht dann gfs noch ein weiteres FF.
Man kommt eben um die Physik nicht drum herum. Die BRAMs sitzen in
Blöcken an bestimmten Stellen im FPGA und da muss man hin. Laufzeiten
kosten. Das ist mit externen SRAMs auch nicht anders. Die reagieren auch
nicht binnen 5ns.
True Dual Port RAM schrieb:> Der Vorgang sieht so aus:> 1. steigende Clockflanke> 2. Adresse wird berechnet> 3. Adresse ist gültig und liegt am RAM an> 4. ...> 5. steigende Clockflanke> 6. jetzt hätte ich gerne die Daten zum Verarbeiten
Vorsicht! In so ziemlich jedem Syntheseratgeber steht, dass die Adressen
gefaelligst aus FFs zu kommen haben.
Und das hat einen guten Grund...
Nach deinem Punkt 1. passiert folgendes: Deine Adressbits flippen fuer
eine ganze Weile munter hin und her. Und das bzgl. Laufzeit sogar
Daten-/Zustandsabhaengig...
Dein READ_ENABLE am SRAM ist schon aktiv (aktiviert zum Zeitpunkt 1.)...
Dein SRAM besteht aus vielen Bits, gebaut im Prinzip aus 6T-Zellen...
Deine wackelnde Adresse stimuliert jetzt munter die Word- und Bit-Lines
(siehe hier
https://de.wikipedia.org/wiki/Static_random-access_memory#Eigenschaften_und_Aufbau
als Beispiel). Und damit kannst du dir deine gespeicherten Bits
ueberschreiben!
Nicht aus Haeme oder Theorie, sondern vor ca. 20 Jahren leidvoll selber
erfahren... Wir hatten ein SRAM, das hing ueber Chip-I/Os an einem
anderen Chip. Und wir hatten an unserem Chip-Eingang Pulldowns. Und in
ganz bestimmten Faellen, relativ selten, hat das andere Chip den
Adressbus (der an unser SRAM angeschlossen war) auf high-Z geschaltet.
Und dann sind die '1'er Bits langsam nach '0' gedriftet... Und das hat
die Daten im SRAM zerstoert/umgeschrieben...
Also Vorsicht mit sowas. Lothar hat dir ja den praktischen Weg
beschrieben: SRAM mit fallender Flanke takten. Dann aber auch den
READ_ENABLE sowie die Adressen mit der fallenden Flanke ans RAM
verdrahten. Dann funktioniert das zuverlaessig, wenn's halt mit dem
Timing reicht...
True Dual Port RAM schrieb:> Der Vorgang sieht so aus:> 1. steigende Clockflanke> 2. Adresse wird berechnet> 3. Adresse ist gültig und liegt am RAM an> 4. ...> 5. steigende Clockflanke> 6. jetzt hätte ich gerne die Daten zum Verarbeiten
Bis auf die erwähnte Tatsache, dass man die Adressse gerne aus FFs
hätte, ist daran nicht auszusetzen und würde bei heutigen BRAMs
funktionieren. Die FFs sind jedoch "nur" eine Recommendation, kein must.
Ohne FFs hat man u.a. natürlich ein schlechteres Timing. Ob man es sich
leisten kann, hängt vom Takt ab und sagt dir die "Static Timing
Analysis". Weiterer Nachteil ist, dass der Energiebedarf (minimal) höher
sein wird, da die Adresse nicht gleich stabil ist und somit der BRAM
versucht, den Adressen zu folgen und ggf. auf mehrere Zellen
nacheinander zugreift. Solange die STA aber keinen Fehler wirft, werden
die richtigen Daten nach der Taktflanke am Ausgang anliegen. Auch beim
Schreiben würde es zu keinem Fehler kommen, da der BRAM erst bei der
Flanke aktiv wird.
PS: Je nach Datenmenge kann man auch distributed RAM verwenden.
Ausreichend Timingreserven vorausgesetzt, liefern die die Daten noch vor
der Taktflanke.