Forum: FPGA, VHDL & Co. Daten zwischen zwei Clockdomains austauschen


von Martin W. (mawahh)


Lesenswert?

Ich habe hier ein Design mit zwei Clockdomains (jeweils 25MHz) und will 
Daten hin und her schicken. Dazwischen hängt ein CPLD (XC9536XL).

In einem FPGA würde ich ja einfach einen asynchronen FIFO benutzen, das 
geht hier leider nicht. Und einfach die Daten auf der neuen Clock 
einsynchronisieren, bring es auch nicht, da halt manchmal ein Bit fehlt 
oder doppelt ist.

Was kann man da tun? Zwischen den Datenpaketen können die "doppelten" 
oder "fehlenden" Bits ruhig auftreten. Doch wie bekomme ich das hin? Ein 
RX_EN Signal hätte ich, um zu erkennen, ob die Datenbits gültig sind.

Gibt es einen asynchronen FIFO als VHDL, der sich auch einem CPLD 
einsetzen lässt?

Grüße, Martin

von Valerij M. (fpga-dev)


Lesenswert?

Hallo!
Ich kenne zwar die Anwendung nicht, aber vielleicht ist es möglich aus 
zwei Clock Domains eine mit 25 MHz erzeugen? Einfach einen gemeinsamen 
Taktgeber benutzen?

Gruß,
fpga-dev

von Falk B. (falk)


Lesenswert?

@ Martin W. (mawahh)

>Ich habe hier ein Design mit zwei Clockdomains (jeweils 25MHz) und will

>Was kann man da tun? Zwischen den Datenpaketen können die "doppelten"
>oder "fehlenden" Bits ruhig auftreten. Doch wie bekomme ich das hin?

Im Prinzip über ein Zwischenspeicher, der langsamer getaktet ist, und 
damit sicher doppelt getaktet werden kann. Also ein Art Schieberegister.

>Gibt es einen asynchronen FIFO als VHDL, der sich auch einem CPLD
>einsetzen lässt?

Jain.

Es gab mla ne schöne Seite von Xilinx zum Thema, ich kann sie aber 
leider nicht mehr finden :-(

MFg
Falk

von Martin W. (mawahh)


Lesenswert?

Falk Brunner wrote:
> Im Prinzip über ein Zwischenspeicher, der langsamer getaktet ist, und
> damit sicher doppelt getaktet werden kann. Also ein Art Schieberegister.

Kannst du das genauer erklären? Meinst du zwei Register, die immer 
abwechselnd mit den Eingangsdaten beschrieben werden, so dass man auf 
der Ausgangsseite in einem großen Bereich mit der Ausgangsclock abtasten 
kann, ohne setup- und holdtimeviolations zu bekommen? Gibt es VHDL 
davon?

von Falk B. (falk)


Lesenswert?

@ Martin W. (mawahh)

>Kannst du das genauer erklären? Meinst du zwei Register, die immer
>abwechselnd mit den Eingangsdaten beschrieben werden, so dass man auf
>der Ausgangsseite in einem großen Bereich mit der Ausgangsclock abtasten
>kann, ohne setup- und holdtimeviolations zu bekommen? Gibt es VHDL
>davon?

So in der Art. Per Schieberegister wird der Datenstrom verlangsamt, 
meinetwegen auf 1/4 der ursprünglichen Taktfrequenz. Mit jedem 4. Takt, 
an dem neue Daten parallel in einem Zwischenregister zur Verfügung 
stehen, wird ein Steuersignal invertiert. Die Empfangsseite tastet das 
ab und erkennt einen Wechsel, woraufhin die Daten gefahrlos übernommen 
werden können.

MfG
Falk

von Martin W. (mawahh)


Lesenswert?

Ok, ich habe das mal simuliert. Leider verursacht das Steuersignal auf 
der Empfängerseite jede Menge Setup-Time violations, wenn es zum 
falschen Zeitpunkt kommt, je nachdem wie die beiden Clocks halt grade 
zueinander laufen.

Was kann ich denn dagegen tun? Die Daten scheinen korrekt übergeben zu 
werden. Oder kann ich das ignorieren und hoffen, dass es in der Realität 
läuft? Wenn das Steuersignal einen Takt später auf der Empfängerseite 
gesehen wird, geht es ja auch...

von Falk B. (falk)


Lesenswert?

@ Martin W. (mawahh)

>Ok, ich habe das mal simuliert. Leider verursacht das Steuersignal auf
>der Empfängerseite jede Menge Setup-Time violations, wenn es zum
>falschen Zeitpunkt kommt, je nachdem wie die beiden Clocks halt grade
>zueinander laufen.

Logisch,ist ja asynchron. Sowas ist schwer simulierbar.

>Was kann ich denn dagegen tun? Die Daten scheinen korrekt übergeben zu
>werden. Oder kann ich das ignorieren und hoffen, dass es in der Realität
>läuft?

Jain. Wie sieht deine Schaltung denn aus? Postem mal VHDL oder 
Schaltplan.

> Wenn das Steuersignal einen Takt später auf der Empfängerseite
>gesehen wird, geht es ja auch...

Eben.

MfG
Falk

von Gast (Gast)


Lesenswert?

Die oben gepostete lösung ist aber auch nichts anderes, als ein 
asynchroner Fifo, nur eben per Hand. Das kann man schon sn machen, nur 
muss man die Steuersignale auch synchronisieren. Zum Abtasten würde ich 
mal lieber die 3fache Frequenz nehmen, das ist leichter überschaubar, 
beim simulieren, da es nur den Fall von 1+1 und 2+1 Latenzcklocks gibt, 
was bei Faktor 3 wieder nur einem Zieltakt entspricht.

von Martin W. (mawahh)


Lesenswert?

Ich hab jetzt das hier gebaut. Es scheint zu funktionieren...


   -- select input flip flop
   select_i0 : PROCESS (RESET_N, RXCLK0)
   BEGIN
      IF (RESET_N = '0') THEN
       select_input0 <= '0';
     ELSIF (RXCLK0'event AND RXCLK0 = '1') THEN
       IF (RXDV0 = '0') THEN
         select_input0 <= '0';
      ELSIF (select_input0 = '0') THEN
         select_input0 <= '1';
      ELSE
         select_input0 <= '0';
       END IF;
     END IF;
   END PROCESS;

   -- ff1 0->1
   ff0_1: PROCESS (RESET_N, RXCLK0)
   BEGIN
      IF (RESET_N = '0') THEN
         q0_0 <= '0';
        q0_1 <= '0';
        q0_2 <= '0';
        q0_3 <= '0';
       ELSIF (RXCLK0'event AND RXCLK0 = '1') THEN
       IF (select_input0 = '0') THEN
        q0_0 <= RXD0_0;
        q0_1 <= RXD0_1;
        q0_2 <= RXD0_2;
        q0_3 <= RXD0_3;
         END IF;
       END IF;
   END PROCESS;

   -- ff2 0->1
   ff0_2: PROCESS (RESET_N, RXCLK0)
   BEGIN
      IF (RESET_N = '0') THEN
         q1_0 <= '0';
        q1_1 <= '0';
        q1_2 <= '0';
        q1_3 <= '0';
       ELSIF (RXCLK0'event AND RXCLK0 = '1') THEN
       IF (select_input0 = '1') THEN
        q1_0 <= RXD0_0;
        q1_1 <= RXD0_1;
        q1_2 <= RXD0_2;
        q1_3 <= RXD0_3;
         END IF;
       END IF;
   END PROCESS;

   -- latch RXDV0
  latch_rxdv0_0 : PROCESS (RESET_N, RXCLK0)
   BEGIN
      IF (RESET_N = '0') THEN
      q0_rxdv <= '0';
      ELSIF (RXCLK0'event AND RXCLK0 = '1') THEN
        q0_rxdv <= RXDV0;
    END IF;
  END PROCESS;

   latch_rxdv0_1 : PROCESS (RESET_N, TXCLK1)
   BEGIN
      IF (RESET_N = '0') THEN
      q1_rxdv <= '0';
      ELSIF (TXCLK1'event AND TXCLK1 = '1') THEN
      q1_rxdv <= q0_rxdv; -- possible setup-time violation here!
    END IF;
  END PROCESS;

   -- select output flip flop
   select_o1 : PROCESS (RESET_N, TXCLK1)
   BEGIN
      IF (RESET_N = '0') THEN
       select_output1 <= '0';
     ELSIF (TXCLK1'event AND TXCLK1 = '1') THEN
       IF (q1_rxdv = '0') THEN
         select_output1 <= '0';
      ELSIF (select_output1 = '0') THEN
         select_output1 <= '1';
      ELSE
         select_output1 <= '0';
       END IF;
     END IF;
   END PROCESS;

   -- ff3 0->1
   ff0_3: PROCESS (RESET_N, TXCLK1)
   BEGIN
       IF (RESET_N = '0') THEN
        TXD1_0 <= '0';
        TXD1_1 <= '0';
        TXD1_2 <= '0';
        TXD1_3 <= '0';
        TXEN1 <= '0';
       ELSIF (TXCLK1'event AND TXCLK1 = '1') THEN
         IF (select_output1 = '0' AND q1_rxdv = '1') THEN
           TXD1_0 <= q0_0;
           TXD1_1 <= q0_1;
           TXD1_2 <= q0_2;
           TXD1_3 <= q0_3;
            ELSIF (select_output1 = '1' AND q1_rxdv = '1') THEN
           TXD1_0 <= q1_0;
           TXD1_1 <= q1_1;
           TXD1_2 <= q1_2;
           TXD1_3 <= q1_3;
        ELSE
           TXD1_0 <= '0';
           TXD1_1 <= '0';
           TXD1_2 <= '0';
           TXD1_3 <= '0';
        END IF;
        TXEN1 <= q1_rxdv;
       END IF;
   END PROCESS;

von Falk B. (falk)


Lesenswert?

Bitte vollständigen Code posten.

MFG
Falk

von FPGA-Heinz (Gast)


Lesenswert?

Ich lese hier angestrengt mit, verstehe aber immer noch nicht das 
grundsätzliche Problem. Wir haben doch einfach einen Datenbus mit einer 
Art von data valid? Das wäre doch zu hehandlen, wie ein ganz "schnödes" 
asynchrones Bus-Interface, oder kapiere ich da was nicht ?

von Stefan Hanke (Gast)


Lesenswert?

Für den genannten CPLD hat mawahh keine FIFO-Implementierung gefunden, 
die asynchrone Schreib- und Lesetakte erlaubt...

@falk: Das hier?
XAPP051 - Synchronous and Asynchronous FIFO Designs (PDF)
http://www.xilinx.com/support/documentation/application_notes/xapp051.pdf
Device (XC4000) passt zwar net, aber immerhin gehts hier um CPLDs.
Intern wird leider dual-ported RAM benutzt, was der XC9536XL nicht 
besitzt.

von Gast (Gast)


Lesenswert?

Das FIFO kann man sich in der üblichen Weise selber bauen, es muss nur 
sichergestellt werden, daß beide Seiten die für sie gültigen Signale der 
anderen Seite einsynchronsieren. Das kann man sogar beliebig dämlich und 
redundant formulieren - solange man eine RTL-optimierung drüberlaufen 
lässt, kommmt immer dasselbe bei raus, habe ich gemerkt :-)

von Stefan M. (Gast)


Lesenswert?

Flancter ist ein Stichwort. Das Problem: Wie setze ich ein Flag in einer 
Clock-Domain und lösche es in der anderen?

mfg, Stefan.

von Axel II (Gast)


Lesenswert?

Statisch : Ein asynchrones Schaltwerk, das beide Takte im Auge hat und 
per Vorrang entscheidet, ob gelöscht wird, oder nicht. Beide Löschpegel 
müssen mindestens 2 Takte bezogen auf den gegenüber anliegen. 
Massgeblich für das Flipflop ist das so ermittelte set/reset, sowie das 
Ergebnis einer Vorrangschaltung, die den durchschaltet, der zuletzt 
getaktet hat. Im Kollisionsfall setzt sich so der druch der zuletzt noch 
setrzen/resetten wollte. Kann man aber auch anders einstellen.

Dynamisch : Indem Du die Löschinfo als einen Impuls überträgst, der lang 
genug ist, um von der Zieldomain, die das Flag verwaltet, erkannt zu 
werden. Die Zieldomain nimmt dann den Resetwunsch entgegen und taktet 
das Ergebnis synchronisiert wieder raus. Macht, wenn man es korrekt 
programmiert genau 3 Takte Delay, bis der Generationsprozess das 
fallende Flag sieht. Wenn der Verwaltungsprozess auch resetten (und 
nicht nur setten) kann, muss dessen Reset auch verzögert werden und gfs 
ein Semaphor entscheiden, wer auf dem Flag arbeiten darf.

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.