Forum: FPGA, VHDL & Co. VHDL Dual FIFO Clock Domain Crossing


von Tim Z. (Gast)


Lesenswert?

Kennt sich jemand eventuell mit dual clock FIFOs gut aus und kann mir 
sagen, was ich für unterschiedliche Taktfrequenzen auf read und write 
Seite haben kann? Ich arbeite mit einem Xilinx Spartan 6. Ich habe den 
Core Generator FIFO und auf der Read Seite 100MHz und auf der Write 
Seite nur 2 MHz. Das funktioniert völlig unzuverlässig. auf beiden 
Seiten 2 MHz funktioniert. Ich habe es immer so verstanden, dass bei 
solchen FIFOs mit 2 Clocks die Synchronisierung für mich erledigt wird 
und ich mich nicht darum kümmern muss oder sind solche starken 
Unterschiede ein Problem? Ich habe auch mal mit dem VHDL-extras FIFO 
herumprobiert aber da ist es das gleiche und der scheint wohl auch ein 
Problem mit dem Handshake zu haben.

von Axel F. (Gast)


Lesenswert?

Sollte eigentlich keine Probleme geben, wenn Graycounter und korrekt 
konfiguriertes RAM im Spiel sind. Welche Version nutzt du?

von Tim Z. (Gast)


Lesenswert?

Axel F. schrieb:
> Sollte eigentlich keine Probleme geben, wenn Graycounter und
> korrekt
> konfiguriertes RAM im Spiel sind. Welche Version nutzt du?

Ich nutze die letzte ISE Version. Beim VHDL extras wird kein gray 
counter eingesetzt. Da fällt mir gerade noch auf, dass ich vermutlich 
nicht beachte, dass die Empty flag um einen clock cycle verspätet kommt 
und sich mein read enable und empty überlappen. Das heißt ja, dass ich 
immer einen cycle warten muss um empty nach einem read zu prüfen. Das 
heißt nur halbe bandbreite beim lesen, oder?

von Axel F. (Gast)


Lesenswert?

Tim Z. schrieb:
> Das heißt ja, dass ich immer einen cycle warten muss um empty nach einem
> read zu prüfen. Das heißt nur halbe bandbreite beim lesen, oder?

Du brauchst ja nur genug puffern (bis zu einer gewissen Wassermarke) und 
mit 100 mhz in Bursts auszulesen .

von J. S. (engineer) Benutzerseite


Lesenswert?

Tim Z. schrieb:
> Ich arbeite mit einem Xilinx Spartan 6.
Der hatte einige RAM-issues. Allerdings bezogen die sich auf bestimmte 
Adress-Konstellationen und sollten bei den FIFOs keine Rolle spielen.

> Ich nutze die letzte ISE Version.
Die 14.7

> Beim VHDL extras wird kein gray counter eingesetzt.
Der gc wird automatisch im FIFO instanziiert.

> dass die Empty flag um einen clock cycle verspätet kommt
> und sich mein read enable und empty überlappen.
Das gibt es nicht, wenn du synchron ausliest.

Schau dir mal die FIFOs genau an, mit welchem Takt die Statussignale 
rauskommen. Einige liegen auf der Read-Seite, andere auf der Write 
Seite. Je nachdem was du machen und synchen willst, musst du die 
rübersynchronisieren.

Sieh auch zu, dass der initiale Reset aus dem langsameren der beiden 
Takte kommt und lange genug dauert.

> heißt nur halbe bandbreite beim lesen, oder?
Nein. Du kannst z.B. das "not empty" direkt auf das read drahten, um 
einen permanenten Ausgang zu haben. Wie man das FIFO nutzt, hängt 
allerdings von der Anwendung ab. Ich benutze oft die 
Transportbandfunktion.

von dfIas (Gast)


Lesenswert?

Jürgen S. schrieb:
>> dass die Empty flag um einen clock cycle verspätet kommt
>> und sich mein read enable und empty überlappen.
> Das gibt es nicht, wenn du synchron ausliest.
Doch, es gibt bei den Flags ein anderes Timing. Entweder mit halber 
Frequenz lesen/schreiben oder - deutlich eleganter - mit einem almost 
empty/full ausbremsen. Die Almost-Flags können jeweils auf einen Versatz 
von Eins eingestellt werden. Während eines Bursts also auf das jeweilige 
Almost-Flag schauen, außerhalb des Bursts (ohne gleichzeitigen Zugriff) 
auf empty bzw. full achten. Das geht tatsächlich nicht anders.

von dfIas (Gast)


Lesenswert?

Erwähnenswert bei diesen FIFOs auch noch die Möglichkeit, auf beiden 
Seiten verschiedene Wortbreiten zu verwenden (2^n, also z. B. 8 auf 16 
oder 9 auf 36). Man muss dann auf die Endianity achten (Symbolfolge auf 
der breiteren Seite).

von Tim Z. (Gast)


Lesenswert?

Jürgen S. schrieb:
> Der gc wird automatisch im FIFO instanziiert.

Beim FIFO aus der vhdl-extras library ist kein gray counter 
implementiert, sondern ein handshake.

von Martin S. (strubi)


Lesenswert?

Die Coregen-FIFOs habe ich in aelteren ISE wegen irgendwas nicht 
brauchen koennen, kann schon sein, dass da ein Szenario nicht abgedeckt 
ist, dazu muesste man die Testbench/Simulation sehen.
Ein FIFO fuer den Spezialfall 'Paket-Streaming' musste schlussendlich 
von Hand geschrieben werden, dabei sind Gray-Counter ein Muss. Da ging 
auch erst was schief, eine Implementation die auf Xilinx 24/7 lief, 
schmiss auf einer anderen Architektur sporadisch Fehler, warum das so 
ist, ist Xilinx' kleines Geheimnis zu seiner RAM-Architektur. Auf jeden 
Fall muss man akribisch drauf achten, dass die Almost-Full bzw. 
Wassermarken-Flags aus den Gray-Countern hergeleitet werden, dann ist es 
voll portabel und verifizierbar. Keine Ahnung, ob VHDL-extras das 
richtig macht.

Der Spartan6 RAM-Bock mit der Initialisierung hat definitiv keine 
Auswirkung auf FIFO-Verhalten.

von VHDL hotline (Gast)


Lesenswert?

Tim Z. schrieb:
> dass die Empty flag um einen clock cycle verspätet kommt
> und sich mein read enable und empty überlappen. Das heißt ja, dass ich
> immer einen cycle warten muss um empty nach einem read zu prüfen. Das
> heißt nur halbe bandbreite beim lesen, oder?

Falls es das bei bei deiner library gibt (bei Xilinx-FifoGen lässt es 
sich definitiv konfigurieren), nutze einen First-Word-Fall-Through 
(FWFT)-FIFO. Da ist das Verhalten von empty m.M. nach angenehmer. (Man 
kann das negierte empty z.B. direkt auf das valid-Signal eines 
AXI-Stream-Interface o.ä. verdrahten.)

von J. S. (engineer) Benutzerseite


Lesenswert?

Tim Z. schrieb:
> Jürgen S. schrieb:
>> Der gc wird automatisch im FIFO instanziiert.
>
> Beim FIFO aus der vhdl-extras library ist kein gray counter
> implementiert, sondern ein handshake.

Aha!

dfIas schrieb:
> Jürgen S. schrieb:
>>> dass die Empty flag um einen clock cycle verspätet kommt
>>> und sich mein read enable und empty überlappen.
>> Das gibt es nicht, wenn du synchron ausliest.
> Doch, es gibt bei den Flags ein anderes Timing. Entweder mit halber
> Frequenz lesen/schreiben oder - deutlich eleganter - mit einem almost
> empty/full ausbremsen.
Ich blicke das Problem nicht. Wenn das empty zeitrichtig (gfs 
kombinatorisch) ausgewertet wird, bekomme ich durch die Ausleseseite 
keine Lücke. Nur, wenn nichts drinsteht, lese ich leer.

VHDL hotline schrieb im Beitrag #7097950:
> nutze einen First-Word-Fall-Through
> (FWFT)-FIFO. Da ist das Verhalten von empty m.M. nach angenehmer. (Man
> kann das negierte empty z.B. direkt auf das valid-Signal eines
> AXI-Stream-Interface o.ä. verdrahten.)
oder so!

von dfIas (Gast)


Lesenswert?

Jürgen S. schrieb:
> dfIas schrieb:
>> Jürgen S. schrieb:
>>>> dass die Empty flag um einen clock cycle verspätet kommt
>>>> und sich mein read enable und empty überlappen.
>>> Das gibt es nicht, wenn du synchron ausliest.
>> Doch, es gibt bei den Flags ein anderes Timing. Entweder mit halber
>> Frequenz lesen/schreiben oder - deutlich eleganter - mit einem almost
>> empty/full ausbremsen.
> Ich blicke das Problem nicht. Wenn das empty zeitrichtig (gfs
> kombinatorisch) ausgewertet wird, bekomme ich durch die Ausleseseite
> keine Lücke. Nur, wenn nichts drinsteht, lese ich leer.
Das Empty kann meist nicht "zeitrichtig" ausgewertet werden, es kommt 
einen Clock zu spät. Somit "unterliest" du das FIFO, wenn der 
vorangegangene und der aktuelle Clock das Read aktiv halten (Burst).
Die Flaglogik muss während des Lesens auf Füllstand > 1 schauen (not 
almost empty), außerhalb des Lesens auf Füllstand > 0 (not empty).
Analog dazu gilt beim Schreiben der Vergleich gegen Füllstand < Full - 1 
(not almost full) oder Füllstand < Full (not full).
Mit halber Clockfrequenz schaffen es Empty/Full bis zum nächsten aktiven 
Read/Write - das wäre die einfachere Implementation, wenn die Bandbreite 
ausreicht. Andererseits ist es nicht sehr schwierig, die Almost-Flags 
passend zu konfigurieren und auszuwerten.

von dfIas (Gast)


Lesenswert?

Beispiel Read-Signal ausgeben:
1
   if ((Read = '0' and Empty   = '0')  or
2
       (Read = '1' and Empty_1 = '0')) then
3
     Read <= '1';
4
   end if;
Das Empty_1 ist aktiv bei Füllstand 0 und 1, Empty nur bei Füllstand 0.
Das Read muss als Signal definiert werden, damit man es auch lesen kann. 
Bei vorangegangenem Read muss man quasi "einen im Sinn" haben.

von VHDL hotline (Gast)


Lesenswert?

Zumindest bei den Xilinx-FIFOs ist ein underrun (lesen bei empty=1) kein 
Problem, sondern wird einfach ignoriert. D.h. man muss das Read nicht 
zwingend von Empty abhängig machen, sondern nur auf die Validität der 
ausgelesen Daten achten.

von J. S. (engineer) Benutzerseite


Lesenswert?

dfIas schrieb:
> Das Empty kann meist nicht "zeitrichtig" ausgewertet werden, es kommt
> einen Clock zu spät.

Ist aber kombinatorisch und kann direkt verwendet werden. Dass man mit 
dem Takten seiner FSM nicht hinkommt, kann natürlich sein. Das liegt 
aber darin, dass die Erzeugung des Empty einen Vergleich erfordert, der 
bei breiten Countern sehr aufwändig ist und die Zeit hochtreibt. Die 
Auswertung kann damit nur im nächsten Tag erfolgen, wenn die FPGA - 
Frequenz zu hoch wird.

Nutzung des AlmostEmpty klappt dann auch nicht, wenn man den Takt 
gewinnen will, weil man nicht weis, ob was eingeschrieben wird und er 
wirklich empty wird.

Ich mache das daher so, dass ich die FIFOs im Zweifel unterlese und ein 
Valid IM Fifo-Vektor mitschleppe.

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.