このページは、 timingに関する一連のページに属しています。前のページでは、 timing 計算の背後にある理論を説明し、いくつかの timing constraints を記述する方法を示し、 timing closureの原理について説明しました。このページでは、 clock domainsに関連する timing constraints を定義する方法について説明します。
序章
特定の logic elements を見つける方法と pathsを定義する方法に関する知識を備えたので、この知識を利用する timing constraints を見ていきます。
最初に見ていくのは、 timing constraints と clock domainsの関係です。これら 2 つのトピックは密接に関連しており、一方を含めずに一方を議論することは不可能です。したがって、このトピックが初めての場合は、 clock domainsに関するこの一連のページを読むことをお勧めします。特に、これは以下で使用する用語を理解するために必要です。
logic は、 clocks間の関係を定義します。
この Verilog コードの例を見てみましょう。
module top(
input clk,
input foo,
output reg bar_reg,
output reg baz
);
reg foo_reg;
reg bar;
reg baz_metaguard;
wire pll_clk_8, pll_clk_6;
clk_wiz_1 pll_i
(.clk_in1(clk),
.clk_out1(pll_clk_8),
.clk_out2(pll_clk_6));
always @(posedge pll_clk_8)
foo_reg <= foo;
always @(posedge pll_clk_6)
begin
bar <= !foo_reg;
bar_reg <= bar;
end
always @(posedge clk)
begin
baz_metaguard <= bar;
baz <= baz_metaguard;
end
これは、先ほど見た PLLの例とほぼ同じです。違いは、新しい clock domain crossingがあることです。 @bar の値は、 metastability guardを介して @baz にコピーされます。
したがって、この例には 2 種類の clock domain crossings があります。
- @foo_reg から @barまで、2 つの related clocks の間 ( metastability guardはありません)。
- @bar から @bazまで、2 つの unrelated clocks の間 (@baz_metaguard は metastability guardです)。
clock domain crossingのタイプを決定する基準は 1 つだけです。 metastability guardの有無。 logic が unrelated clocksを想定している場合、必要な安全メカニズムを使用します。したがって、他に問題はありません。 これらの clocksの間に paths 上の timing requirements を確保することが可能であったとしても、これを行う理由はありません。
およびその逆: logic が related clocksを想定している場合、 timing violationsに対する保護はありません。したがって、これらの clocks間のすべての paths で timing の要件を満たす必要があります。
結論として、 logic は常に、どの clocks が related clocks で、どの clocks がそうでないかという仮定を立てます。これらの仮定は、保護メカニズムの有無に反映されます。しかし、これらの仮定が現実のものとなるようにするのは FPGA tools です。特に、ツールは、 related clocks間の paths で timing の要件が満たされることを保証します。
そのため、ツールが clocksに関する logicの前提を認識していることを確認する必要があります。
上記の例では、ツールは @pll_clk_6 と @clkに関する logicの期待を知る方法がないことに注意してください。 logic は、これらが related clocks であると想定し、その逆を想定する場合があります。実際、 related clocks間の path をデモンストレーションするために、以前に同様の例(「アイデア #9」を参照) を使用しました。上記の例では、これら 2 つの clocks が unrelated clocksとして扱われます。
おそらく、ツールは @baz_metaguardの名前からインテリジェントな推測を行うことができます。 metastability guard の典型的な構造がヒントになるかもしれません。しかし、そのような重要な問題について決定を下すには、それだけでは十分ではありません。
clocksについてツールに伝える
これまでの例では、 timing constraintは 1 つだけでした。
create_clock -period 4.000 -name clk [get_ports clk]
頭に浮かぶ最初の質問は、ツールがデフォルトで @pll_clk_6 から @clk への clock domain crossing をどのように扱うかということです。これが唯一の timing constraintである場合、ツールは @bar と @baz_metaguardの間で path に何かを適用しますか?
答えは、どの FPGA tool が使用されているかによって異なります。事実上すべての FPGA tools は @pll_clk_6 と @pll_clk_8 を related clocksとして扱いますが、他の clocksの組み合わせではどうなるかは明らかではありません。ツールは通常、すべての clocks をデフォルトで related clocks として扱いますが、それに頼るのは安全ではありません。
多くの FPGA tools は set_clock_groups commandをサポートしています。これは、 clocks間の関係を定義するための最適なオプションです。この commandは重要であるため、 designで使用する前にツールのドキュメントを参照することをお勧めします。
上記の例では、この command は Vivado で次のように使用できます (または他のツールでも同様です)。
set_clock_groups -asynchronous \ -group [list \ [get_clocks -of_objects [get_pins pll_i/clk_out1] ] \ [get_clocks -of_objects [get_pins pll_i/clk_out2] ] ] \ -group [get_clocks -of_objects [ get_pins pll_i/clk_in1] ]
get_clocks と get_pins のこの使用法は前に説明されました: 各 get_clock command は、 clk_wiz_1 の関連する port の名前に従って clock object を見つけます ( clk_wiz_1の instantiation の名前は pll_iであることに注意してください)。たとえば、最後の get_clock command は、 @clkの clock object を取得します。
この例は、 set_clock_groups が clocksのグループを定義する方法を示しています。この場合、1 つのグループは @pll_clk_6 と @pll_clk_8で構成され、2 つ目のグループは @clk のみで構成されます。この constraint は、同じグループに属するすべての clocks が related clocksであることをツールに伝えます。同様に、2 つの clocks が異なるグループに属している場合、ツールはそれらを unrelated clocksと見なします。
つまり、ツールは、 path の両側の clocks が同じグループに属している場合に限り、 path に timing constraints を適用します。
designの timing constraintsには複数の set_clock_groups commands を使用できます。ただし、すべての clocks をグループに分割するには、1 つの set_clock_groups command を使用するのが最適です。これにより矛盾が回避され、混乱を防ぐこともできます。 この command の主な利点は、 clocks間の関係を簡潔に説明していることです。短く、簡潔で、数学的です。それが私たちの求めているものです。
言及されている clocks objects はすでに存在しているはずなので、 set_clock_groups はすべての create_clock commandsの後に使用する必要があることに注意してください。
clocks間の一貫性のない関係
clocks が designの一部で related clocks 、別の場所で unrelated clocks と見なされる場合、 set_clock_groupsを使用することはできません。
たとえば、 @clk と @pll_clk_6 は、上記の Verilog コードでは unrelated clocks として扱われます。しかし、理論的には、それらを related clocksとして扱う追加の logic が存在する可能性があります。良い考えではありませんが、この追加の logicに対して @pll_clk_6 と @clk の間に timing constraints を強制することは可能です。
このような理由で set_clock_groups が使用できない場合は、まず logicを変更して set_clock_groups を使用できないかどうか自問してください。これは、この command が非常に優れているからというだけではありません。 どの clocks が related clocks でどれがそうでないかを示す単純なルールがないと、 clock domain crossingsで間違いを犯しやすくなります。それでも logicでそのような変更を行いたくない場合、解決策は false pathsを定義することです。
set_false_path commandについて簡単に
false pathsを宣言するための主な commands は 2 つあります。 set_clock_groups とset_false_paths 。
set_clock_groups command は上記で紹介されました: 異なるグループに属する 2 つの clocks の間にある path はすべて false pathと見なされます。ただし、 set_clock_groups は、 false pathとして宣言する必要があるすべての paths に使用できるとは限りません。場合によっては、 paths の選択は、 clocksのグループを定義するよりも具体的にする必要があります。 set_false_path command は、 pathsの特定の選択を許可することでこの問題を解決します。
たとえば、上記の set_clock_groups command を set_false_path commandに置き換えてみましょう。修正が必要なのは、 @bar から @baz_metaguardへの path だけです。他のすべての paths の timing 要件は、そのまま正しく適用されます。したがって、これはこの pathの set_false_path command を記述する 1 つの方法です。ただし、この例から学ぶ必要はありません。
set_false_path -from [get_cells bar_reg__0] -to [get_cells baz_metaguard_reg]
この command は、 get_cells を使用して pathの始まりと pathの終わりを選択します。これには、両側の cell objects の名前を知る必要があります。この場合、「bar_reg__0」という名前があり、名前に依存することの問題点を示しています。 この名前は「bar_reg」のはずでしたが、すでに説明したように、偶然にも「bar_reg__0」になりました。
したがって、この例は set_false_pathの問題の 1 つを示しています。 design で logic elements を詳細に選択するには、 objectの名前に頼らざるを得ないことがよくあります。この問題と考えられる解決策については、以前に説明しました。
この command は簡略化できます: @baz_metaguard は metastability guardであるため、 paths からこの register がどこから来たのかは関係ありません。では、この registerまでのすべての paths を無視してみませんか?
set_false_path -to [get_cells baz_metaguard_reg]
この command の効果も全く同じです。
set_clock_groupsの代わりにset_false_path
もう 1 つの可能性は、 clocksに従って paths を定義することです。実際、上記の set_clock_groups command は次の constraintsに置き換えることができます。
set_false_path -from [get_clocks -of_objects [get_pins pll_i/clk_out1]] \ -to [get_clocks -of_objects [ get_pins pll_i/clk_in1] ] set_false_path -from [get_clocks -of_objects [get_pins pll_i/clk_out2] ] \ -to [get_clocks -of_objects [ get_pins pll_i/clk_in1] ] set_false_path -from [get_clocks -of_objects [ get_pins pll_i/clk_in1] ] \ -to [get_clocks -of_objects [get_pins pll_i/clk_out1] ] set_false_path -from [get_clocks -of_objects [ get_pins pll_i/clk_in1] ] \ -to [get_clocks -of_objects [get_pins pll_i/clk_out2] ]
これは、同じ false pathsを作成するための長くて詳細な方法です。 clocks をグループに分割する代わりに、 unrelated clocksのペアごとに 2 つの set_false_path commands があります。 各方向に 1 つの command があります。 constraintsが多数あると、間違いが起こりやすいことは明らかです。これは、3 つの clocksを使用した単純な例です。
それにもかかわらず、 set_clock_groupsの代わりに set_false_path がこのように使用されることがよくあります。これはおそらく誰かがどこかから timing constraints をコピーしたためです。
間違いが起こりうる例
考えられる間違いの簡単な例を見てみましょう。 上記の説明から、 false pathとして宣言する必要がある path は 1 つだけであることは明らかです。 @bar から @baz_metaguardへ。したがって、最後の例の 4 つの set_false_path commands のうち、意味があるのはこの 1 つだけです。
set_false_path -from [get_clocks -of_objects [get_pins pll_i/clk_out2] ] \ -to [get_clocks -of_objects [ get_pins pll_i/clk_in1] ]
他の 3 つの set_false_path commands は、 pathsをカバーしません。しかし、待ってください。 constraint をさらに簡略化したらどうでしょうか。 @clk で終わるすべての paths は false pathsになるべきでしょうか。これはどうでしょうか。
set_false_path -to [get_clocks -of_objects [ get_pins pll_i/clk_in1] ]
実際、「clk」を定義する create_clock command は set_false_path commandのすぐ上にあるため、代わりに次のように記述できます。
set_false_path -to [get_clocks clk]
この constraint は短くてエレガントです。残念ながら、それはひどく間違っています: 私は、 @clk で終わるすべての paths は false pathであるべきだと提案しました。しかし、 @baz_metaguard から @bazまでの path はどうでしょうか。これは、 @clk から @clkまでの path です。もちろん、この path は false pathであってはなりません。しかし、最後の 2 つの set_false_path commands には、 path が @clkで始まっていても、 @clkで終わるすべての paths が含まれます。
特に、 false path 用の constraints が数学的な考え方の精度なしで書かれている場合、この種の間違いを犯しやすいです。どの paths が false paths でどの false paths でないかを明らかにできる特別な timing reportsを作成すると役立つ場合があります。
これで、 FPGAの内部にある paths に対する timing constraints に関する実際的な議論を終了します。次のページでは、このトピックに属する multi-cycle pathsについて説明します。ただし、通常、 multi-cycle path constraints は推奨されません。したがって、代わりに I/O constraintsの紹介にスキップしても問題ありません。