Nachdem ich im Internet und in einigen Schulungen mehrere, manchmal widersprüchliche oder unvollständige Informationen darüber gefunden habe, wie man Timing-Constraints im SDC-Format korrekt erstellt, möchte ich die EE-Community um Hilfe bei einigen allgemeinen Takterzeugungsstrukturen bitten, auf die ich gestoßen bin.
Ich weiß, dass es Unterschiede gibt, wie man eine bestimmte Funktionalität auf einem ASIC oder FPGA implementiert (ich habe mit beiden gearbeitet), aber ich denke, es sollte einen allgemeinen, korrekten Weg geben, das Timing einer bestimmten Struktur unabhängig davon einzuschränken zugrunde liegende Technologie - lassen Sie es mich bitte wissen, wenn ich da falsch liege.
Es gibt auch einige Unterschiede zwischen verschiedenen Tools zur Implementierung und Zeitanalyse verschiedener Anbieter (obwohl Synopsys einen SDC-Parser-Quellcode anbietet), aber ich hoffe, dass es sich hauptsächlich um ein Syntaxproblem handelt, das in der Dokumentation nachgeschlagen werden kann.
Bitte beachten Sie auch die verwandte Frage ASIC-Timing-Einschränkungen über SDC: Wie wird ein Multiplex-Takt korrekt angegeben?
Hier geht es um den folgenden Ripple-Clock-Teiler, der Teil des clkgen -Moduls ist, das Teil eines größeren Designs ist, das die Erzeugungsuhren verwendet:
Die Generierung von clk0
scheint relativ einfach zu sein:
create_clock [get_pins clkgen/clk0] -name baseclk -period 500
Obwohl ich mir bei den SDC-Befehlen für die generierten, geteilten Uhren clk2
, clk4
und nicht so sicher bin clk8
: Wie sollten die Quell- und Zieloptionen angegeben werden? Mein anfänglicher Gedanke war, dass das Ziel der Ausgangspin der takterzeugenden Zelle ist, die Quelle so nah wie möglich am Ziel ist:
create_generated_clock -name div2clk -source [get_pins clkgen/divA/clk] -divide_by 2 [get_pins clkgen/divA/q]
Die Quelle könnte auch der Takteingangspin des Moduls sein:
create_generated_clock -name div2clk -source [get_pins clkgen/clk0] -divide_by 2 [get_pins clkgen/divA/q]
Oder die zuvor definierte Quelluhr , wie hier vorgeschlagen :
create_generated_clock -name div2clk -source [get_clocks baseclk] -divide_by 2 [get_pins clkgen/divA/q]
...was auch die Frage aufwirft, ob die Quell- oder Zieloptionen etwas anderes als sein müssen get_pins
, wie zum Beispiel get_nets
, get_registers
oder get_ports
.
Um das Beispiel so allgemein wie möglich zu halten, nehmen wir an, dass die generierten Takte clk2
, clk4
und clk8
andere, potenziell interagierende (Clock Domain Crossing) Register ansteuern könnten (nicht im Schema gezeigt).
Ich denke, die Einschränkungen für clk4
und clk8
sollten offensichtlich sein, sobald wir wissen, wie die clk2
Einschränkung geschrieben ist.
Die X1 -Instanz (ein einfacher Puffer) im Schaltplan ist nur ein Platzhalter, um hervorzuheben, wo im Clock-Propagation-Netzwerk die Source- Option des create_generated_clock
gesetzt werden sollte, da automatische Place&Route-Tools normalerweise frei sind, Puffer überall zu platzieren (z wie zwischen den divA1/q
und divB1/clk
Pins).
Ich würde sagen, die Faustregel lautet: Stellen Sie entweder den Eingangsport des oberen Moduls oder den Q-Pin eines internen Flip-Flops als Quelle des generierten Takts ein.
Beispiel Verilog-Code:
module top (
input clk,
input rst,
...
);
...
always @(posedge clk or negedge rst)
begin
if (rst == 1'b0)
div_2_clk = 1'b0;
else
div_2_clk = ~div_2_clk;
end
...
endmodule
Beispiel SDC-Code:
create_clock -name clk -period 5 [get_port clk]
...
create_generated_clock -name slow_clk -source [get_port clk] -divide_by 2 [get_pins div_2_clk_reg/Q]
Ich habe die obige Syntax nicht getestet. Beachten Sie auch die Erweiterung _reg
, die dem RTL-Namen des Signals hinzugefügt wurde - dies ist die Erweiterung, die vom Synthesetool hinzugefügt wird, wenn es erkennt, dass das Signal durch ein Flip-Flop dargestellt werden muss. Diese Erweiterung kann zwischen den Tools variieren (ich weiß es nicht genau).
Wenn Sie einen RTL-Wrapper um Flip-Flops verwenden, stellen Sie die Quelle der generierten Takte auf den internen Q-Pin des Flip-Flops ein, nicht auf den Ausgangs-Pin des Wrappers.
Wenn Sie diese einfachen Regeln befolgen, müssen Sie sich keine Gedanken über Puffer machen, die von den Synthese- oder P&R-Tools hinzugefügt werden.
FriendFX
create_clock [get_ports clk0]
stattdessen sein (vorausgesetzt,clk0
es handelt sich um den Top-Level-Port)? Wenn Sie das in Ihre Antwort aufnehmen und auch mindestens ein vollständiges Beispiel dercreate_generated_clock
Aussage hinzufügen könnten, würde ich es gerne akzeptieren!Wassilij
FriendFX
create_*clock
Befehle, dass der Timing-Analysator die Verzögerungen des Pfads (und des potenziell eingefügten Puffers) zur Latenz der (erzeugten) Takte hinzufügt?Wassilij
FriendFX
source
zumtarget
in einer generierten Uhr alle Puffer enthält, die das P&R-Tool zwischen diesen Knoten einfügen könnte?Wassilij
FriendFX
-source
Option auf den nächstgelegenen Clock-Pin des angegebenen Ziels verweisen sollte “ . In diesem Fall kann die-master_clock
Option trotzdem verwendet werden. Ich möchte nur sicherstellen, dass ich den Timing-Analysator nicht daran hindere, alle Verzögerungen richtig zu berücksichtigen.FriendFX
clk0
undclk4
vorhanden sind, müssen Verzögerungen im Taktnetzwerk zwischenclk0
undclk4
durch das Timing berücksichtigt werden Analysator für diese Pfade, habe ich recht?Wassilij
clk0
und habenclk4
, definieren Sie ihn entweder als falschen Pfad (wenn sich die Uhren gegenseitig ausschließen, wenn Sie Synchronisierer verwenden, ...) oder als Multi-Cycle-Pfad. Im ersten Fall sollte das Tool keine Timing-Analyse durchführen und es liegt an Ihnen, sicherzustellen, dass kein logischer Fehler auftreten kann. Im letzteren Fall wurden alle relevanten Verzögerungen von anderen Tools berücksichtigt, die ich gesehen habe.FriendFX
Wassilij
FriendFX
create_generated_clock
SDC-Befehl. Ich habe deine Antwort akzeptiert. Vielleicht starte ich-source
irgendwann eine separate Frage zu den Details der Option. Danke für Ihr Bemühen!