Forum: FPGA, VHDL & Co. sauberes clock domain crossing für unidirektionales IF


von Andreas B. (loopy83)


Lesenswert?

Hallo zusammen,

ich bin auf der Suche nach einer eleganten Lösung für ein CDC eines 
unidirektionalen Interfaces.
1
  signal data_rdy : std_logic;
2
  signal addr     : std_logic_vector(11 DOWNTO 0);

Beide Clock-Domains sind nicht phasengleich und können im der Frequenz 
variieren. Die Quell-Domain kann also größer der Ziel-Domain sein, oder 
auch kleiner, maximal jedoch Faktor 2 kleiner/größer.

Ein Handshake kann ich leider nicht einsetzen, ich habe also nur diese 
beiden Eingänge zur Verfügung. Der Vorteil ist, dass ich eine definierte 
Startadresse habe und die Adressen auch in definierter Reihenfolge 
eintrudeln.

Meine Idee:
Ich verwende in der Quell-Domain einen Counter, der die data_rdy Pulse 
zählt, damit diese dann in korrekter Anzahl auf der Ziel-Domain 
ausgegeben werden können. Den Counter muss ich ausreichend groß 
dimensionieren, so dass er auch bei "2*Ziel = Quell" nicht überläuft. 
Also z.B. 9 Bit.
Nun hatte ich die Idee, dass der Counter in der Zieldomain entsprechend 
heruntergezählt wird, bis er wieder auf 0 ist und solange synchron zum 
Zieltakt Pulse ausgegeben werden.

An welcher Stelle aber muss ich den Counter dann sauber synchronisieren?
Und wie kann ich ihn dann gleichzeitig auf der einen Seite hochzählen, 
aber auf der anderen Seite quasi asynchron herunterzählen?

Vielen Dank!
Andi :)

von Marius W. (mw1987)


Lesenswert?

Schon einmal über einen Dual-Clock-FIFO nachgedacht?

Gruß
Marius

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Andreas B. schrieb:
> Ein Handshake kann ich leider nicht einsetzen, ich habe also nur diese
> beiden Eingänge zur Verfügung.
Und dann willst du irgendwie noch einen Zähler über die Grenze 
schmuggeln?

> Meine Idee:
> Ich verwende in der Quell-Domain einen Counter, der die data_rdy Pulse
> zählt, damit diese dann in korrekter Anzahl auf der Ziel-Domain
> ausgegeben werden können. Den Counter muss ich ausreichend groß
> dimensionieren, so dass er auch bei "2*Ziel = Quell" nicht überläuft.
> Also z.B. 9 Bit.
> Nun hatte ich die Idee, dass der Counter in der Zieldomain entsprechend
> heruntergezählt wird, bis er wieder auf 0 ist und solange synchron zum
> Zieltakt Pulse ausgegeben werden.
Welchen Takt sollte denn dieser Zähler haben? Du kannst ihn ja nicht 
einmal mit dem Takt der Domain A und dann mit dem anderen Takt der 
Domain B zählen lassen.

> Die Quell-Domain kann also größer der Ziel-Domain sein, oder auch
> kleiner, maximal jedoch Faktor 2 kleiner/größer.
Und wie lange sind die Daten stabil? Wieviele Takte darf eine 
Übertragung dauern? Wie ist die Datenrate (bzw. deren Verhältnis zur 
Taktfrequenz)?

Dein ganzes Problem ruft irgendwie laut "Dual Clock Fifo"...
EDIT: nur Zweiter... ;-)

: Bearbeitet durch Moderator
von Andreas B. (loopy83)


Lesenswert?

Hallo,

Marius Wensing schrieb:
> Schon einmal über einen Dual-Clock-FIFO nachgedacht?

Ja habe ich, aber irgendwie hatte ich gehofft, dass ich mir nur wegen 
dieses dummen Interfaces nicht so ein Monster einbauen muss. Denn eine 
Logik, die den FIFO in der Ziel-Domain wieder auslesen muss, gehört dann 
auch noch dazu.

Zumal der FIFO ja nur ein Bit breit sein muss. Ich will ja nicht die 
Adressen zwischenspeichern, die kenne ich ja, sondern nur das data_rdy. 
Zumindest sollte das mit den Adressen so passen... hoffe ich...

Lothar Miller schrieb:
> Welchen Takt sollte denn dieser Zähler haben? Du kannst ihn ja nicht
> einmal mit dem Takt der Domain A und dann mit dem anderen Takt der
> Domain B zählen lassen.

Der Zähler soll in der Quell-Domain hochgezählt werden.
Aber genau an diesem Punkt wird es dann eben unlösbar, wenn der Zähler 
in der Ziel-Domain wieder heruntergezählt werden soll :D

Genau diesen Knoten in meinem Kopf gilt es zu lösen...

Vielen Dank!
Andi :)

Ich habe gerade noch eine neue Info bekommen, die alles über den Haufen 
wirft. Muss ich nochmal neu anfangen zu denken... Mist... gut, dass ich 
noch nicht allzu weit war.

von berndl (Gast)


Lesenswert?

Fuer ein unidirektionales IF? Der Klassiker: 
http://www.fpga4fun.com/CrossClockDomain.html

In der Quelle setzt du deine 12-bit Adresse auf, einen Takt (der Quelle) 
spaeter geht DATA_RDY von 0 auf 1.
Im Ziel taktest du mit dessen Takt DATA_RDY ein, beim Uebergang von 0->1 
uebernimmst du die Adresse, die natuerlich solange stabil sein muss.
Abhaengig von den Quell- und Zieltakten nimmst du dann dein DATA_RDY 
wieder auf 0 zurueck (evtl. Counter in der Quelle, mit derem Takt falls 
Ziel langsamer laeuft als Quelle)

Du kannst auch Adresse und DATA_RDY gleichzeitig setzen in der Quelle, 
dann musst du aber im Ziel nochmal eine Verzoegerung (n Takte) einbauen.

von J. S. (engineer) Benutzerseite


Lesenswert?

Andreas B. schrieb:
> Der Zähler soll in der Quell-Domain hochgezählt werden.
> Aber genau an diesem Punkt wird es dann eben unlösbar, wenn der Zähler
> in der Ziel-Domain wieder heruntergezählt werden soll :D

Sowas macht man dadurch, dass in der Zieldomain, ein Differenzzähler 
gebildet wird und die Differenz dynmamisch gebildet wird. Damit kann die 
Zieldomain auch schneller abziehen, als die Quelldomain reinschreibt. 
Das ist aber ein Konstrukt, den ich selber nur einmal benötigt habe und 
ich bezweifle stark, dass Deine Applikation sowas braucht.

Ein Asynchroner Fifo (wie schon angeraten) mitsamt overflow und 
underflow-Behandlung zur abstrakten Weiterschaltung der Information 
"FF-State" löst das Problem einfacher und übersichtlicher.

von Schlumpf (Gast)


Lesenswert?

Andreas B. schrieb:
> signal data_rdy : std_logic;
>   signal addr     : std_logic_vector(11 DOWNTO 0);

Ich verstehe nur Bahnhof..

Die Quelldomain soll also Adressen und data_rdy an die Zieldomain 
übertragen?
Aber die Adressen sind vorhersehbar?
Und was ist mit den Daten?

Auf welche der Timings hast du einen Einfluss?
Quelle, Ziel, beide?

Am Besten, du zeichnest uns mal ein Timing hin, wie die Signal aus der 
Quelle kommen und wie das Ziel sie erwartet. Und welche Paramteter im 
Timing du beeinflussen kannst.

von Duke Scarring (Gast)


Lesenswert?

berndl schrieb:
> Fuer ein unidirektionales IF? Der Klassiker:
> http://www.fpga4fun.com/CrossClockDomain.html
Leider nur in Verilog :-(
Das wäre doch noch ein schöner Artikel für Lothars Homepage.

Duke

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Duke Scarring schrieb:
> Das wäre doch noch ein schöner Artikel für Lothars Homepage.
Ich hätte auch sonst noch ein paar Ideen, aber irgendwie gerade keine 
Zeit... ;-)

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.