Hallo Leute!
Es ist bekanntlich nötig, externe asynchrone Signale erstmal über 2 FFs
im FPGA einzusynchronisieren. Dieses Einsynchronisieren führt allerdings
dazu, dass man dann eine Verzögerung von 2 Takten hat. Nehmen wir nun
an, dass ein internes Modul, welches ein externes Triggersignal
empfängt, mit einem Clock von nur 8 MHz getaktet wird. Das würde
bedeuten, dass das Signal erst nach 2 * 125 ns synchronisiert dort
ankommen würde.
Nun frage ich mich, ob es nicht sinnvoll ist, dass man das
Einsynchronisieren mit Hilfe von 2 FFs durchführt, die allerdings mit
einer höheren Frequenz arbeiten. Das hätte auch den Vorteil, dass man
kürzere externe Triggerpulse erkennen kann. Da ich im FPGA über DCMs an
anderer Stelle mit 100 MHz arbeite, könnte ich dann diese 100 MHz dazu
nutzen, um mein Signal in nur 2 * 10 ns einzusynchronisieren.
Dieses auf den 100 MHz Clock einsynchronisierte Signal muss dann zwar
"langgezogen" werden, um in die 8 MHz Domäne ordnungsgemäß transferiert
zu werden, aber das würde IMHO höchstens zu einen weiteren
Taktverzögerung von bis zu 125 ns führen. Das Domain-Crossing an sich
von 100 MHz nach 8 MHz sollten Tools wie Xilinx ISE eigentlich
automatisch machen, da das ganze ja intern über DCMs geht, deren
Clock-Beziehungen die Tools kennen. Und falls dort das Timing nicht
hinkommen sollte, wird ja eh gesagt, dass Metastabilität sowieso nur bei
höheren Frequenzen auftreten kann.
Ist sowas sinnvoll, oder mache ich da einen Denkfehler?
Grüße,
Anguel
Anguel S. schrieb:> Das Domain-Crossing an sich von 100 MHz nach 8 MHz sollten Tools wie> Xilinx ISE eigentlich automatisch machen,
Ja, das machen sie. Allerdings wirst du beim Umweg über die 100
MHz-Domäne dann auf ein mal mit einer virtuellen Taktfrequenz von 200
MHz (und damit einer Zeit von 5ns) am Übergang zwischen den 100 MHz und
den 8 MHz konfrontiert werden. Denn 100/8 = 12,5. Und diese 0,5
halbieren dir die Setupzeit für den Übergang des Triggersignals. Denn es
könnte ja ein 100MHz-Takt genau zum Zeitpunkt t=120ns und der nächste
zum Zeitpunkt t=130ns kommen. Der 8 MHz-Takt kommt aber zum Zeitpunkt
t=125ns... :-o
> Es ist bekanntlich nötig, externe asynchrone Signale erstmal über 2 FFs> im FPGA einzusynchronisieren.
Mit diesen Faustformeln ist das so eine Sache...
Man sollte wissen, warum diese 2 FFs da sind. Wenn dieses externe
Signal in einen Zähler oder eine FSM geht (was ja meist der Fall sein
dürfte), dann muß das entsprechende signal rechtzeitig vor der nächsten
steigenden Taktflanke stabil am FF-eingang anliegen. Die 2 FFs
wurden/werden verwendet, wenn sich möglicherweise der metastabile
Zustand des 1. FFs solange halten kann, dass bei der nächsten Taktflanke
noch kein stabiler Zustand an den beteiligten FFs angekommen wäre. Dann
sorgt das 2. FF für klare Verhältnisse.
Allerdings sind solche Betrachtungen zur Metastabilität bei aktuellen
FPGAs eigentlich erst bei Taktfrequenzen >200MHz nötig. Deren FFs sind
so schnell, dass sich bei kleineren Taktfrequenzen ein metastabiler
Zustand gar nicht so lange halten kann, dass bei einer Taktfrequenz von
8MHz beim nächsten Takt nicht schon alles klar wäre.
Fazit: bei dieser Taktfrequenz wird dir zum Einsynchronisieren 1 FF
ausreichen.
> Ist sowas sinnvoll, oder mache ich da einen Denkfehler?
Dieser Umweg über die 100MHz Taktdomäne ist unnötig. Aber er könnte dir
(wenn du die Sache mit den 5 ns in den Griff bekommst) die Latenz zum
Erkennen des Triggersignals reduzieren. Denn wenn ein Triggersignal zum
Zeitpunkt t=10ns kommt, dann bekommst du es auch mit nur 1 Sync-FF erst
zum Zeitpunkt t=250ns in deiner FSM mit (also fast 2 Takte später). Wenn
du es in der 100MHz-Domäne eintaktest und den 5 ns Pfad nach dem Sync-FF
im Griff hast, dann könntest du schon bei t=125 darauf reagieren.
Vielen Dank an Lothar für die sehr ausführliche Antwort!
Lothar Miller schrieb:> Allerdings wirst du beim Umweg über die 100> MHz-Domäne dann auf ein mal mit einer virtuellen Taktfrequenz von 200> MHz (und damit einer Zeit von 5ns) am Übergang zwischen den 100 MHz und> den 8 MHz konfrontiert werden.
Ja, das ist mir bekannt. Falls ich übrigens mit dem Timing an der Grenze
zw. 100 MHz und 8 MHz nicht hinkommen sollte, würde (wenn ich das
richtig verstehe) schlimmstenfalls folgendes passieren: Das
einsynchronisierte Signal aus der 100 MHz Domäne wechselt von '0' auf
'1' so, dass die Setup-Zeit des 8 MHz FFs missachtet wird. Somit wird
dieses 8 MHz FF kurz metastabil, was aber keine schlimmen Konsequenzen
für den Rest der Schaltung hätte da < 200 MHz. Schlimmstenfalls würde
ich dann "nur" das Triggersignal zu diesem Zeitpunkt verpassen, da sich
das FF aufgrund der Metastabilität auf '0' statt auf '1' einpendelt. In
diesem Fall würde ich das Triggersignal aber beim nächsten 8 MHz clk
rising edge mitbekommen, ich würde es also nicht ganz verpassen, da ich
das Signal in der 100 MHz Domäne sowieso auf 13 * 10 ns = 130 ns
stretche. Richtig?
> Fazit: bei dieser Taktfrequenz wird dir zum Einsynchronisieren 1 FF> ausreichen.
2 FFs werden also nur empfohlen, falls man 100% sicher sein möchte, dass
auch bei hohen Frequenzen nix schief geht.
> Dieser Umweg über die 100MHz Taktdomäne ist unnötig. Aber er könnte dir> (wenn du die Sache mit den 5 ns in den Griff bekommst) die Latenz zum> Erkennen des Triggersignals reduzieren.
Genau diese Latenz möchte ich reduzieren. Außerdem möchte ich in der
Lage sein, Triggersignale, die kürzer als 125 ns sind, zu erkennen.
Deshalb wollte ich über 100 MHz eintakten.
Anguel S. schrieb:> Ja, das ist mir bekannt. Falls ich übrigens mit dem Timing an der Grenze> zw. 100 MHz und 8 MHz nicht hinkommen sollte, würde (wenn ich das> richtig verstehe) schlimmstenfalls folgendes passieren: ... Richtig?
Insgesamt richtig, aber weil du damit ja auch 1 FF zusätzlich hast, ist
nichts gewonnen. Das könntest du mit 8 MHz Takt direkt auf dem
Eingangssignal auch machen...
> Deshalb wollte ich über 100 MHz eintakten.
Du gewinnst wie gesagt nur was, wenn du dann das 100 MHz FF direkt
weiterverwenden kannst, ohne nochmal auf 8 MHz "umzusynchronisieren"...
> 2 FFs werden also nur empfohlen, falls man 100% sicher sein möchte, dass> auch bei hohen Frequenzen nix schief geht.
Es ist eine Frage von Wahrscheinlichkeiten. Dazu gibt es entsprechende
Whitepaper und Dokumentationen von den FPGA-Herstellern...
Siehe auch im Beitrag "Re: Signal per Taktflanken setten/resetten"
Lothar Miller schrieb:> Insgesamt richtig, aber weil du damit ja auch 1 FF zusätzlich hast, ist> nichts gewonnen. Das könntest du mit 8 MHz Takt direkt auf dem> Eingangssignal auch machen...
Jetzt bin ich wieder etwas verwirrt und poste deshalb mal, was ich jetzt
habe (clk_slow = 8 MHz, clk_fast = 100 MHz):
Ich denke so müsste ich nun innerhalb von ca. 125 ns (etwas mehr wenn
das Triggersignal ungünstig ankommt) immer in der clk_slow (8 MHz)
Domäne angekommen sein, oder?
Zwischen irgendeinem Zeitpunkt, zu dem hw_trig_in_stretched gesetzt wird
und einem anderen Zeitpunkt, zu dem es abgefragt wird, vergehen u.U. nur
5ns. Das ist das Problem, das auf diese Art nicht lösen kannst...
Jetzt habe ich folgendes gefunden:
http://www.lothar-miller.de/s9y/categories/19-SpikePuls
Das würde wahrscheinlich mein Problem am besten lösen. Ich würde dann
aber nur 1 Synchro-FF (statt 2 FFs) verwenden und den synchronen Teil
mit den 8 MHz betreiben. Das einzige wo ich mir nicht ganz sicher bin,
wie ich das abändere, damit nicht nur ein einzelnes Spikeout Signal
ausgegeben wird, sondern dass Spikeout oben bleibt, während Spikein oben
bleibt.
Anguel S. schrieb:> Jetzt habe ich folgendes gefunden:
Das war auch nicht sonderlich gut versteckt... ;-)
> Das würde wahrscheinlich mein Problem am besten lösen.
Das glaube ich nicht, denn deine Aufgabe ist ein andere...
Es ist auch nicht schneller als das einfache Einsynchronisieren über 1
FF. Denn wenn du das wegdiskutierst, bekommst du wieder ein asynchrones
Signal mit den hinlänglich bekannten Effekten...
> ich würde dann aber nur 1 Synchro-FF (statt 2 FFs) verwenden und den> synchronen Teil mit den 8 MHz betreiben.
Dann bist du wieder beim einfachen FF zum Eintakten. Fertig.
Das letzte FF ist nur dafür da, das erste zurückzusetzen...
Also jetzt bin ich komplett verwirrt :-)
Meine Idee ist, dass ich möglichst kurze Signale erkennen kann und diese
so schnell wie möglich in die 8 MHz Domäne einsynchronisiere.
Durch
ext. Signal --> Marker-FF --> Einzelnes Synchro-FF @ 8 MHz
hätte ich das doch erreicht, wenn ich nicht etwas komplett falsche
verstehe.
Da ich vorher nicht wusste, dass man solche asynchronen Marker-FFs
verwenden kann, wollte ich das ext. Signal ursprünglich mit einer
höheren Taktrate (100 MHz) abtasten. Außerdem bin ich ganz am Anfang
davon ausgegangen, dass ich 2 Synchro-FFs @ 8 MHz zum einsynchronisieren
bräuchte, was sich nachher als überflüssig herausstellte, da nur 1
Synchro-FF bei dieser Frequenz reicht.
Anguel S. schrieb:> Meine Idee ist, dass ich möglichst kurze Signale erkennen kann und diese> so schnell wie möglich in die 8 MHz Domäne einsynchronisiere.
Ah, ok.
Wenn ein externes signal kürzer sein kann als das Abtastintervall, dann
ist der Spike-Detektor das richtige...
Nur darfst du dann das Zurücksetzen eben nicht direkt vom externen
Signal abhängig machen. Es könnten ja auch 2 (oder mehr) externe Impulse
gekommen sein...
BTW:
Der Spike-Detector ist übrigens während des Rücksetzens für 1 Takt
"blind"!
Chris schrieb:> Geht das überhaupt intern, mit nur 8 MHz?
Was geht?
Immerhin lief der erste IBM-PC auf X86 Basis mit 4,77MHz, und auch das
hat die Entwicklung der Menschheit nicht aufgehalten... ;-)
Ich habe den "Spike zu Puls" Code von Lothar Miller
(http://www.lothar-miller.de/s9y/categories/19-SpikePuls) nun etwas
umgewandelt. Wie bei Lothar werden auch hier sehr kurze Spikes mit Hilfe
eines asynchr. FFs, das auf deren rising_edge() reagiert, erkannt.
Erkannte Spikes erscheinen dann beim nächsten rising_edge(clk) am
synchronen Ausgang des Moduls. Ich nutze zum einsynchronisieren ein
einziges synchr. FF, da ich davon ausgehe, dass mein Takt weit unter 200
MHz liegt. Bei mir bleibt dann der synchrone Ausgang solange auf '1',
bis an einem darauf folgenen rising_edge(clk) eine '0' als ext. Signal
anliegt. Angehängt habe ich die Simulation und die RTL-Ansicht.
Das UND-Gatter sieht irgendwie zwielichtig aus... :-/
1. Das verletzt mein Postulat zum nicht-kombinatorischen Reset.
2. Ich bin mir nicht sicher, was passiert, wenn hw_trig_in_synch_int='1'
ist und eine steigende Flanke am hw_trig_in_asynch kommt. Ich würde fast
behaupten, dass der Reset langsamer weggeht, als der Takt ans FF kommt.
Damit wäre die Taktflanke verpasst...
Überzeugt :) Dann muss wohl eine HW-Lösung zum Abfangen kurzer Pulse
her. Und einsynchronisiert wird dann über ein einziges synchrones FF.
Ich hoffe trotzdem, dass diese Gedankenspielerei auch anderen hilft.
Nochmals vielen Dank an Lothar!