Hallo, sorry für den wenig aussagekräftigen Thread-Titel aber ich tue mir schwer, das Problem kurz zu beschreiben. Ich habe in meinem Virtex 5 Design Probleme, die sehr nach Timing-Problemen aussehen: Dinge, die in der Simulation funktionieren verhalten sich in der HW anders, bei manchen Syntheseergebnissen kommt es sogar zu einem vollkommen falschen Verhalten einer bestimmten State Machine, das ich mir nur mit einem Timing-Problem erklären kann, das dazu führt, dass die einen FFs in den Folgezustand gehen und die anderen nicht. Das ganze tritt am Übergang zwischen zwei Clock-Domänen auf, allerdings sind diese nicht komplett asynchron sondern beide haben 125 MHz Taktfrequenz nur ist die eine mittels PLL aus der anderen abgeleitet. Diese zwei Taktdomänen existieren schon lange problemfrei im Design und bisher hatte ich keine Probleme, von der einen zu anderen ohne Synchronisation Daten zu schieben. Insbesondere dachte ich, dass das Synthesetool das durchaus berücksichtigt und eben den notwendigen margin für zusätzlichen Jitter durch die PLL sowie anderes Taktnetzwerk usw einrechnet. Der Timing-Report sagt jedenfalls, dass alle Constraints erfüllt sind. Habe ich da was falsch verstanden bzgl Taktdomänen und via PLL abgeleiteten Taktdomänen. Ich hab da nämlich noch einige andere langsamere Taktdomänen (62.5 MHz), die aus derselben PLL kommen und die ich bisher auch als synchron zur 125 MHz Taktdomäne gesehen habe. Es wäre schlecht für mich, wenn die auch ein Problem haben. Danke fürs Lesen und lG Matthias
In deinem Fall sollten alle Uebergaenge zwischen clock domains von den Tools beruecksichtigt werden. Durch die Benutzung der PLLs sind die Beziehungen zwischen den Clock Domains ja fest vorgegeben. Wenn ein Design in der Simulation funktioniert, aber nicht in der Wirklichkeit, dann wuerde ich zu allererst ueberpruefen, ob auch wirklich ueberall alle sensitivity lists komplett und korrekt sind. Aus welchem Grund benutzt du so viele verschiedene Takte? Gibt es nicht vielleicht doch eine Moeglichkeit, einen gemeinsamen Takt zu verwenden?
Um die vielen Takte komme ich wahrscheinlich nicht herum, ich habe eine PCIe Anbindung über den Endpoint Block Plus und brauche für die Ansteuerung diverser externer Koponenten Takte mit 62.5 MHz, teilweise auch mit 180 Grad Phasenversatz. Bisher hatte ich damit keine Probleme. Jetzt soll auch noch der DDR2 auf dem Board an das ganze ran und der braucht neben den 125 MHz und den 62.5 MHz die ich habe auch noch einen 125 MHz + 90 Grad Phase und einen 200 MHz Takt. Das ganze kann ich noch mit einer PLL erzeugen. Und jetzt geschieht es eben, dass das ganze solange ordentlich läuft, wie ich nichts aus dem DDR2 auslesen, wenn von dem aber das rd_data_valid Signal kommt (das gültige Lesedaten anzeigt) dann gibt es Probleme, im nicht so dramatischen Fall kommt das erste der beiden gelesenen Wörter nicht im entsprechenden Register an aber die FSM macht, was sie soll, im dramatischen läuft die FSM "Amok" und das gesamte System hängt. Soweit zumindest der Befund nachdem ich mir die Signale auf den Logikanalysator hinausgeführt habe. Irgendwie kann es, soweit ich es derzeit sehe, nur ein Timing-Problem von diesem rd_data_valid Signal sein. Das ganze passiert überall in getakteten Prozessen, darum glaube ich nicht, dass es an vergessenen Signalen in der Sensitivity List liegt, aber ich werde es natürlich checken. Lg Matthias
Um es noch ein wenig klarer zu machen: Die FSM die Amok läuft hängt am PCIe und benutzt den von dort ausgegebenen 125 MHz Takt, das DDR2 Interface benutzt einen 125 MHz Takt der in der PLL mit aus dem Takt vom PCIe Endpoint erzeugt wird. Das sind die beiden Taktdomänen, zwischen denen das Problem auftritt. Lg Matthias
Das eine ist ein Takt, der ueber das Interface rein kommt, der andere kommt (ueber eine PLL) aus einem lokalen Oszillator? Das heisst dann also, dass die Phasenbeziehung und die Unterschiede in der Frequenz vollkommen unbekannt sind? In diesem Fall kommst du um eine aufwendige Synchronisierung mittels eines dual-port-dual-clock-FIFO wahrscheinlich nicht herum. Ausserdem solltest du darauf achten, dass alle Eingaenge in den FPGA auch mit INPUT bzw. OUTPUT - constraints belegt sind, sowie die IO-Fliflops direkt an den Eingaengen auch wirklich benutzt werden.
@ Matthias (Gast) >Um es noch ein wenig klarer zu machen: Die FSM die Amok läuft hängt am >PCIe und benutzt den von dort ausgegebenen 125 MHz Takt, das DDR2 >Interface benutzt einen 125 MHz Takt der in der PLL mit aus dem Takt vom >PCIe Endpoint erzeugt wird. Das sind die beiden Taktdomänen, zwischen >denen das Problem auftritt. Tja, und wenn der PCIe Takt jittert, dann ist die Phasenlage alles andere als konstant. Und er TUT jittern, vor allem weil er mittels Spread Spectrum erzeugt wird. -> Ergo Die beiden Taktdomänen müssen als asynchron betrachtet werden. -> Asynchrones FIFO. MFG Falk
Danke für die Antworten. Ich habe inzwischen folgendes gemacht: Ich habe einen Satz FFs, die ich schon vorher zur Behebung von Timing-Problemen am Lese-Interface dazwischen (sozusagen pipelined) reingehängt habe, von der steigenden Taktflanke (auf der der Rest läuft) auf die fallende Taktflanke umgehängt, das Ergebnis war sehr schön, alles hat perfekt funktioniert (min. 4 mio mal Schreiben/Auslesen ohne einen einzigen Fehler). Die Ursache des Problems dürfte also klarer werden. Jetzt muss ich mir noch klar werden, wie ich damit umgehe, immerhin gibts da ja noch diverse andere Taktdomänen, die zwar in allen Syntheseläufen bisher problemlos funktioniert haben aber die dasselbe Problem haben -> jitternde Clock am PCIe Interface trifft auf PLL gefilterter Clock im innerern des FPGA. LG Matthias
Auch ein Grund auf mehrere Taktdomänen zu verzichten: Das läßt sich nicht gescheit simulieren. Duke
@ Duke Scarring (Gast)
>Auch ein Grund auf mehrere Taktdomänen zu verzichten:
Geht manchmal nicht. ABER!
Man sollte die Anzahl der Schnittstellen zwischen den Domänen möglichst
gering halten. Und an den wenigen Stellen SEHR koneservativ arbeiten.
MFG
Falk
Was mich gewundert hat ist dass die Synthese das nicht erkennt und das beim PAR entsprechend berücksichtigt. Ich habe jetzt bei den Constraints beim PERIOD Constraint das INPUT_JITTER Keyword entdeckt, damit sollte ich eigentlich die notwendige Information geben können. Aber wie kann ich der Spread-Spectrum PCIe Clock einen Jitterwert zuweisen? Ich habe noch nicht mal eine Angabe über das Spektrum der Clock gefunden. LG Matthias
Nachdem ich mich gestern mit meinem Chef dazu eingehend besprochen habe hat er mir geraten, es mal mit einem DLL statt einer PLL zu versuchen, weil diese den Jitter nicht rausfiltert. Siehe da, jetzt funktioniert alles auch ohne Tricks wie die FFs auf der negativen Taktflanke dazwischen zu schalten. Ich muss das ganze erst noch weiter erproben, immerhin hatte ich je nach Syntheselauf unterschiedliche Ergebnisse. Aber immerhin, das ist das erste Design das vollständig funktioniert, inzwischen schon für einige 100 mio Schreib/Lesezugriffe auf den DDR2 fehlerfrei, also ganz so schlecht kann es ja nicht sein. LG Matthias
Ich mache es immer folgendermaßen: Ich habe eine Takt z.B. deine 125MHz. Den Takt gibst Du auf ein Register das eine 1 enthält. Mit der steigenden Clockflanke schiebe ich die 1 um eine stelle nach links weiter. Mit der fallenden Clockflanke frage ich ab ob das Bit an der gewünschnten Stelle angekommen ist. Wenn das der Fall ist führe eine gewisse funktion aus. Wenn Du nur ein Takt durch 2 teilen willst ist das Register halt nur zwei stellen lang. Zudem hälst Du damit immer die Setuptime ein. --********************************************************** -- Ansteuerung des AD-Wandlers über die CS-Leitung * --********************************************************** process (CLK) begin if(CLK'event and CLK = '1') then if(GATE = '0' or CLR = '1')then CS_ADC <= '1'; else CS_ADC <= S_REGA(0); end if; end if; end process; --********************************************************** -- Irgendetwas ausführen * --********************************************************** process (CLK) begin if(CLK'event and CLK = '1') then if(GATE = '0' or CLR = '1')then Test <= '1'; else if(S_REGA(3) = '1')then; Test <= '0'; // Hier kann irgendeine Funktion ausgeführt werden end if; end if; end if; end process; --********************************************************** -- Schieberegister für AD-Wandleransteuerung * --********************************************************** process (CLK) begin if(CLK'event and CLK = '0') then if(CLR = '1' or GATE = '0') then S_REGA <= "00000000000001"; else S_REGA <= S_REGA(12 downto 0) & S_REGA(13); -- schieben end if; end if; end process; end structure;
> if(CLK'event and CLK = '0') then ... > if(CLK'event and CLK = '1') then ... > Zudem hälst Du damit immer die Setuptime ein. Klar, denn das ist trotzdem nur 1 Taktdomäne, beschrieben mit Clock-Enables. Interessant wird es allerdings, wenn die Clock-Enables über größere Flächen (an viele FFs) geroutet werden müssen... Da kann es schnell mal vorkommen, dass ein globales Taktnetz besser wäre.
@Johann Es gibt keinen Grund dies mit unterschiedlichen Flanken zu tun, ganz im Gegenteil, bei es kommt möglicherweise zu einen Halbierung der möglichen Taktrate, weil Du nur mehr die halbe Taktperiode als Setup-Zeit hast.
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.