Moderne digitale Logikbausteine werden normalerweise (*) mit "synchroner Entwurfspraxis" entworfen: einem global synchronen flankengetriggerten Registertransfer-Entwurfsstil (RTL): Alle sequentiellen Schaltungen werden in flankengetriggerte Register aufgeteilt, die mit dem globalen Taktsignal CLK verbunden sind und reine kombinatorische Logik.
Dieser Designstil ermöglicht es Menschen, digitale Logiksysteme ohne Rücksicht auf das Timing schnell zu entwerfen. Ihr System funktioniert "nur", solange von einer Taktflanke zur nächsten genügend Zeit vorhanden ist, damit sich der interne Zustand einpendelt.
Bei diesem Designstil sind Taktversatz und andere zeitliche Probleme irrelevant, außer um herauszufinden, "Was ist die maximale Taktrate für dieses System?".
Was genau ist ein Zeitversatz?
Beispielsweise:
...
R1 - register 1 R3
+-+
->| |------>( combinational ) +-+
...->| |------>( logic )->| |--...
->|^|------>( )->|^|
+-+ ( ) +-+
| +--->( ) |
CLK | +->( ) CLK
| |
R2: | |
+-+ | |
...->| |->+ |
->|^|->--+
+-+
|
CLK
In realer Hardware, das „CLK“ Signal schaltet nie wirklich genau gleichzeitig an jedem Register. Der Taktversatz Tskew ist die Verzögerung des stromabwärtigen Takts relativ zum stromaufwärtigen Takt ( a ):
Tskew (Quelle, Ziel) = Zielzeit - Quellzeit
Dabei ist source_time die Zeit einer aktiven Taktflanke am Upstream-Quellregister (in diesem Fall R1 oder R2) und destination_time die Zeit "derselben" aktiven Taktflanke an einem Downstream-Zielregister (in diesem Fall R3). .
- negativer Taktversatz: Der CLK bei R3 schaltet vor dem Takt bei R1.
- positiver Taktversatz: Der CLK bei R3 schaltet nach dem Takt bei R1.
Was bewirkt der Zeitversatz?
(Vielleicht würde ein Zeitdiagramm hier dies klarer machen)
Damit die Dinge auch im schlimmsten Fall ordnungsgemäß funktionieren, dürfen sich die Eingänge von R3 während der Rüst- oder Haltezeit von R3 nicht ändern. Schlimmer noch, damit die Dinge richtig funktionieren, müssen wir die Dinge so gestalten, dass:
Tskew (R1, R3) <Tco - Th.
Tclk_min = Tco + Tcalc + Tsu - Tskew (R1, R3).
wo:
- Tcalc ist die maximale Einschwingzeit im ungünstigsten Fall eines Blocks kombinatorischer Logik an einer beliebigen Stelle im System. (Manchmal können wir den Block der kombinatorischen Logik, der sich auf dem kritischen Pfad befindet, neu entwerfen, Teile stromaufwärts oder stromabwärts schieben oder eine andere Stufe des Pipelining einfügen, sodass das neue Design einen kleineren Tcalc aufweist, wodurch wir die Taktrate erhöhen können.) .
- Tclk_min ist die minimale Zeitspanne von einer aktiven Taktflanke zur nächsten aktiven Taktflanke. Wir berechnen es aus der obigen Gleichung.
- Tsu ist die Registereinrichtungszeit. Der Registerhersteller erwartet, dass wir eine Uhr verwenden, die langsam genug ist, um diese Anforderung immer zu erfüllen.
- Dies ist die Haltezeit des Registers. Der Registerhersteller erwartet von uns, dass wir den Taktversatz so steuern, dass diese Anforderung immer erfüllt wird.
- Tco ist die Verzögerung von Takt zu Ausgang (Laufzeit). Nach jeder aktiven Taktflanke treiben R1 und R2 die alten Werte für kurze Zeit Tco weiter zur Kombinationslogik, bevor sie zu den neuen Werten wechseln. Dies wird von der Hardware festgelegt und vom Hersteller garantiert, jedoch nur solange wir die Tsu und Th und andere Anforderungen erfüllen, die der Hersteller für den normalen Betrieb spezifiziert.
Zu viel positiver Versatz ist eine absolute Katastrophe. Zu viel positiver Versatz kann (bei einigen Datenkombinationen) zu "Schleichpfaden" führen, so dass anstelle von R3 die "korrekten Daten" beim Takt N + 1 zwischengespeichert werden (eine deterministische Funktion der Daten, die zuvor beim Takt N in R1 und R2 zwischengespeichert wurden). können die neuen Daten, die beim Takt N + 1 in R1 und R2 zwischengespeichert werden, durchlaufen, die Kombinationslogik stören und dazu führen, dass falsche Daten bei "derselben" Taktflanke N + 1 in R3 zwischengespeichert werden.
Ein beliebiger negativer Versatz kann durch Verlangsamen der Taktrate "behoben" werden. Es ist nur "schlecht" in dem Sinne, dass es uns zwingt, das System mit einer langsameren Taktrate zu betreiben, um den Eingängen von R3 Zeit zu geben, sich einzurichten, nachdem R1 und R2 neue Daten an der Taktflanke N und später R3 zwischengespeichert haben speichert das Ergebnis bei "der nächsten" Taktflanke N + 1.
Viele Systeme verwenden ein Taktverteilungsnetzwerk, das versucht, den Versatz auf Null zu reduzieren. Gegenintuitiv ist es durch sorgfältiges Hinzufügen von Verzögerungen entlang des Taktpfads - dem Pfad vom Taktgenerator zum CLK-Eingang jedes Registers - möglich, die scheinbare Geschwindigkeit zu erhöhen, mit der sich die Wellenflanke der Taktflanke physikalisch vom CLK-Eingang eines Registers zum CLK-Eingang bewegt Der CLK-Eingang des nächsten Registers ist schneller als die Lichtgeschwindigkeit.
In der Altera-Dokumentation wird erwähnt
"Vermeiden Sie die Verwendung kombinatorischer Logik in Taktpfaden, da dies zum Taktversatz beiträgt."
Dies bezieht sich auf die Tatsache, dass viele Leute HDL schreiben, das auf ein FPGA so kompiliert wird, dass etwas anderes als das globale CLK-Signal den lokalen CLK-Eingang einiger Register steuert. (Dies kann eine "Clock Gating" -Logik sein, bei der neue Werte nur dann in ein Register geladen werden, wenn bestimmte Bedingungen erfüllt sind, oder eine "Clock Divider" -Logik, die nur 1 von N Takten durchlässt, oder so weiter). Dieser lokale CLK wird normalerweise irgendwie vom globalen CLK abgeleitet - der globale CLK tickt, und dann ändert sich entweder der lokale CLK nicht oder (eine kurze Verzögerung nach dem globalen CLK, damit sich das Signal durch dieses "etwas anderes" ausbreitet) Der lokale CLK ändert sich einmal.
Wenn dieses "etwas anderes" den CLK des nachgeschalteten Registers (R3) antreibt, macht es den Versatz positiver. Wenn dieses "etwas anderes" den CLK des Upstream-Registers (R1 oder R2) antreibt, wird der Versatz negativer. Gelegentlich hat alles, was den CLK des Upstream-Registers antreibt, und was auch immer den CLK des Downstream-Registers antreibt, praktisch die gleiche Verzögerung, so dass der Versatz zwischen ihnen praktisch Null ist.
Das Taktverteilungsnetzwerk in einigen ASICs ist absichtlich mit kleinen Mengen an positivem Taktversatz in einigen Registern ausgelegt, wodurch die kombinierte Logik stromaufwärts etwas mehr Zeit zum Abwickeln hat und das gesamte System mit einer schnelleren Taktrate betrieben werden kann. Dies wird als "Taktversatzoptimierung" oder "Zeitversatzplanung" bezeichnet und steht im Zusammenhang mit " Retiming ".
Der set_clock_uncertainty
Befehl verwirrt mich immer noch - warum sollte ich jemals den Versatz "manuell angeben" wollen?
(*) Eine Ausnahme:
asynchrone Systeme .