このページは、タイミングに関する連載ページの一部です。これまでのページでは、タイミング計算の背後にある理論を説明し、いくつかのタイミング制約(timing constraints)の書き方を示し、タイミングクロージャ(timing closure)の原則について述べました。前のページでは、I/O タイミング制約に関するいくつかの基本原則を説明しました。このページでは、このトピックの実践的な側面を説明します。
はじめに
I/O タイミング制約の目的は、外部とのインターフェースの信頼性を保証することです。つまり、外部から来る各信号が FPGA 上の該当するフリップフロップに確実に到達すること、そして FPGA から外部へ出る各信号が外部コンポーネント上のフリップフロップに確実に到達することを保証します。
I/O タイミング制約は、タイミング制約の中でも最も難しい種類です。タイミングパラメータの一部は、基板上の外部電子コンポーネントに依存します。正しいタイミング要件を決めるには、通常、これらの外部コンポーネントのデータシートを読む必要があります。また、正しいタイミング制約を得るためには、手計算(ペンと紙による計算)が必要になることもよくあります。
この複雑な作業を省略して、単純な代替案に飛びつきたくなるかもしれません。それは試行錯誤です。この近道は、ツールに好きなようにやらせて、うまく動くかどうかを見るというものです。入力ポートに問題があれば、入力信号を受け取るフリップフロップで反対側のクロックエッジを使います。同様に、出力がうまく動かなければ、出力フリップフロップで反対側のクロックエッジを使います。この方法で、たいてい電子回路は手早く簡単に動作するようになります。
この方法の問題は、タイミングの挙動が温度によって変化することです。また、半導体部品の製造プロセスによる不確かさもあります。これは FPGA だけでなく外部電子回路にも当てはまります。したがって、不適切なタイミング制約は「ブラックマジックモード」を引き起こす可能性があります。これはすべてのタイミング制約に言えることですが、I/O タイミング制約では特に起こりやすいです。
手計算を省略した場合の最悪の点は、基板設計が原因でタイミング要件を保証できないことがある、ということです。このような状況が基板設計の途中で発見された場合、多くの場合、簡単な解決策があります(FPGA への配線を変更する、クロック配分を考え直すなど)。しかし、この種の欠陥が PCB 製造後に発見された場合、修正する方法がないかもしれません。つまり、電子回路が確実に動作することを保証することが不可能になります。
このページの内容
このページでは、I/O ポートの基本的なタイミング制約について概説します。ここで示す構文は SDC であり、Vivado、Quartus、およびその他の FPGA ツールで使用されています。
このページは、I/O 専用のタイミング制約、つまり set_input_delay と set_output_delay から始めます。これらの制約の意味を説明します。その後に、Vivado と Quartus によるタイミングレポートの例を示す 2 つのページへの参照を示します。
また、set_max_delay と set_min_delay でタイミング制約を定義することもできます。これらのコマンドは、いくつかのシナリオでより適しています。FPGA 内部のパス(path)については既にこれらのコマンドを紹介しました。I/O タイミング制約としてのそれらの意味についても、以下で説明します。
このページでは、これらの I/O タイミング制約に関する技術的な側面のみを説明します。理論的な部分については、I/O ポートのフォールスパス(false path)の定義方法も示している前のページを参照してください。
set_input_delay と set_output_delay の意味
これら 2 つのコマンドは、外部コンポーネントとのインターフェースがシステム同期(system synchronous)である場合に適しています。簡単に言うと、次のとおりです。
- set_input_delay -clock … -max …:入力ポートに接続されている外部コンポーネントの最大クロックから出力までの遅延 + 基板配線遅延。
- set_input_delay -clock … -min …:入力ポートに接続されている外部コンポーネントの最小クロックから出力までの遅延。データシートにこの情報がない場合は、ゼロを選びます(将来の改訂版のコンポーネントが非常に速いプロセスで製造される場合に備えて)。
- set_output_delay -clock … -max …:出力信号を受け取る外部コンポーネントの tsu + 基板配線遅延。
- set_output_delay -clock … -min …:出力信号を受け取る外部コンポーネントの –thold。マイナス記号に注意してください。たとえば、ホールドタイムが 1 ns の場合は、この制約を -1 に設定します。
これらの定義が正しいのは、次の 2 つの条件が満たされた場合だけであることに注意が必要です。
- インターフェースがシステム同期であること。
- クロックを定義する create_clock コマンドが、get_ports コマンドでクロック信号を参照していること(たとえば get_pins で FPGA 内部の別の信号に依存するのではなく)。
これらの 2 つの条件は、クロック遅延が正しく計算されるために必要です。
また、-min も -max も使わない場合、そのコマンドは -min 属性を持つコマンドと -max 属性を持つコマンドの 2 つがあったかのように解釈されることにも注意してください。これはおそらく意図したものではないでしょう。
これらのコマンドの定義は少し紛らわしいです。set_input_delay は、クロックエッジの後にデータ信号の値が変化してよい時刻を定義します。一方、set_output_delay は、データ信号の値が変化した後にクロックエッジが許容される時刻を定義します。おそらく、これらの定義の背後にある論拠は、データシートの数値をそのままタイミング制約に使えるようにするためでしょう。
set_input_delay と set_output_delay のコマンドには、ここでは説明しないいくつかのオプションがあります。特に、立ち下がりクロックエッジを時刻の基準にすることもできます。詳細はツールのドキュメントを参照してください。
常に min と max の両方を使う
すべてのタイミング制約で -min と -max の両方を使うことを主張するのは、無意味に見えるかもしれません。たとえば、外部コンポーネントの tsetup が 8 ns の場合、次のどこが悪いのでしょうか。
set_output_delay -clock theclk 8 [get_ports test_out]
これはセットアップ時間を正しく定義しています。ホールド時間については、意図せず –8 ns と定義されています。これにより、出力ポートはクロックの 8 ns 前に値を変更できます。しかし、そんなことは気にしないでしょう。そんなことは起こり得ない、と思われるかもしれません。
実は、起こり得るのです。私は以前のページで、入力ピンからのクロック(つまり基板上に見えるクロック)に基づいて内部クロックを生成する PLL の使い方を説明しました。これにより、PLL は FPGA の内部クロックを入力クロックに整列させることができます。PLL は、クロック分配ネットワークの遅延を補償するために、クロックをわずかに動かす(シフトする)ことでこれを実現します。
実際、FPGA ツールはタイミング制約を達成するために、クロックを基板のクロックよりわずかに早く動かすことを自由に行う場合があります。FPGA 内部のクロックが外部クロックより前に動かされると、外部コンポーネントから見たクロックから出力までの遅延は小さくなります。これは、FPGA 内部のフリップフロップは内部クロックに同期している一方、見かけ上のタイミングは外部クロックを基準としているためです。
しかし、FPGA の内部クロックが基板上のクロックより早い場合、FPGA の出力は外部クロックのエッジより前に変化する可能性があります。これは、これらの出力を受け取るコンポーネントでホールドタイム違反につながる可能性があります。
set_output_delay コマンドがホールドタイムを –8 ns と定義しても、出力がクロックの 8 ns 前に値を変更するという意味ではありません。しかし、これはツールが thold 要件を違反するような形で内部クロックを動かすことを許してしまいます。set_output_delay で -min を正しく使えば、これを防ぐことができます。
配線遅延による補正
ツールは PCB の配線遅延を考慮しないことを覚えておくことが重要です。ツールにはその情報がありません。したがって、set_input_delay と set_output_delay のタイミング計算を行うとき、ツールはこの遅延がゼロであると仮定します。補正は、データシートのクロックから出力までの遅延と tsu の値に配線遅延を加えることです。
また、クロックスキュー(clock skew)を考慮する必要があるかもしれません。理想的な PCB では、クロックはすべてのコンポーネントに同じ遅延で到着します。実際には、FPGA と外部コンポーネントの間でクロックスキューが発生する可能性があります。このようなクロックスキューは、ツールのタイミング計算では考慮されません。
したがって、クロックが(外部コンポーネントに対して)FPGA に早く到着する場合、次の補正が必要です。
- set_input_delay -clock … -max …:コマンドの遅延値にクロックスキューを加算します(これは外部コンポーネントのクロックから出力までの遅延が大きいことに似ています)。
- set_output_delay -clock … -min …:コマンドの遅延値からクロックスキューを減算します。つまり、より負の値にします(これは外部コンポーネントの thold が大きいことに似ています)。
同様に、クロックが FPGA に遅く到着する場合、次の補正が必要です。
- set_input_delay -clock … -min …:コマンドの遅延値からクロックスキューを減算します(これは外部コンポーネントのクロックから出力までの遅延が小さいことに似ています)。外部コンポーネントのデータシートに最小クロックから出力までの遅延が記載されていない場合は、このコマンドの値としてクロックスキューの負の値を使います。
- set_output_delay -clock … -max …:コマンドの遅延値にクロックスキューを加算します(これは PCB 配線遅延が大きいことに似ています)。
ここで概説した補正に関係なく、タイミングレポートにゼロでないクロックスキューが表示されることがあることに注意してください。ただし、タイミングレポートに現れるクロックスキューは FPGA 内部のクロック遅延に関係し、PCB 上のクロックスキューには関係しません。
タイミングレポートの例
例は次の Verilog コードに基づいています。
module top(
input test_clk,
input test_in,
output reg test_out
);
reg test_samp;
always @(posedge test_clk)
begin
test_samp <= test_in;
test_out <= test_samp;
end
endmodule
@test_clk は入力クロック、@test_in は入力ピン、@test_out は出力ピンです。PLL を使って内部クロックを基板のクロックに整列させていないため、クロック遅延が大きくなることに注意してください。
タイミング制約は次のとおりです。
create_clock -name theclk -period 20 [get_ports test_clk] set_output_delay -clock theclk -max 8 [get_ports test_out] set_output_delay -clock theclk -min -3 [get_ports test_out] set_input_delay -clock theclk -max 4 [get_ports test_in] set_input_delay -clock theclk -min 2 [get_ports test_in]
タイミングレポートはかなり長いため、別々のページに示します。
set_max_delay と set_min_delay を使う場合
外部コンポーネントとのインターフェースがソース同期(source synchronous)の場合、set_input_delay と set_output_delay を使うのはあまり自然ではありません。そのような状況では、set_max_delay と set_min_delay の方が適しています。前のページでは、これら 2 つのコマンドはクロック周期制約の補足または調整(タイミング例外)としてのみ言及しました。すべてのパスは内部パスであり、順序エレメントで始まり順序エレメントで終わっていました。これらのコマンドが I/O タイミング制約として使われる場合、パスの始点または終点のどちらかが I/O ポートになります。この状況では、タイミング解析はどのように行われるのでしょうか。
実のところ、これらのコマンドのタイミング解析を詳しく調べることは、しばしば無意味です。それらの目的は通常、ツールがかろうじて満たせるようなタイミング制約を書くことで、ツールの動作を制限することにあります。したがって、これらのタイミング制約の数値は、制約をより厳しくしようとする繰り返しの試行によって見つけられます。この方法論では、タイミング解析自体は重要ではありません。
とはいえ、set_max_delay と set_min_delay の背後にある計算を理解しておくことは良い考えです。
以前に説明したとおり、タイミング解析には 2 つの部分があります。最初の部分はソースパスです。クロックエッジ(外部クロックピン)から、2 番目のフリップフロップのデータ入力に更新された有効な値が現れるまでの時間を計算します。この部分は、次の 3 つの要素の合計です。
- クロックエッジが最初のフリップフロップに到達するのにかかる時間(クロックパス)
- このフリップフロップが値を更新するのにかかる時間
- この新しい値が 2 番目のフリップフロップに到達するのにかかる時間
2 番目の部分は宛先パスであり、クロックエッジが 2 番目のフリップフロップに到達するのにかかる時間だけからなります。このフリップフロップの入力がいつ更新されるかは(ソースパスから)既にわかっているので、その時間差を必要な tsu または thold と比較できます。
しかし、それは 2 つの順序エレメントがある場合に当てはまります。一方の側が I/O ポートの場合はどうなるのでしょうか。タイミング解析のためには、ポートがあたかも仮想的なフリップフロップであるかのように扱われます。このフリップフロップへのクロックパス遅延はゼロです。
クロックが get_ports に依存する create_clock コマンドで定義されている通常の状況(私のほとんどすべての例で示したとおり)を考えてみましょう。クロックパス遅延がゼロであるということは、この仮想的なフリップフロップのクロック入力がクロックピンに直接接続されていることを意味します。したがって、クロックピンとこの仮想的なフリップフロップの間には遅延がありません。
このフリップフロップのすべてのタイミングパラメータはゼロです。tsu、thold、クロックから出力までの遅延のすべてがゼロです。これは現実の電子部品を反映したものではありませんが、set_max_delay と set_min_delay を出力ポートと一緒に使ったときに意味を与えます。つまり、ポートのクロックから出力までの遅延です。たとえば、次のとおりです。
set_max_delay -to [get_ports test_out] 7 set_min_delay -to [get_ports test_out] 0
これら 2 つのタイミング制約は、@test_out のクロックから出力までの遅延が 0 ns から 7 ns の間であることを要求します。
その理由を説明しましょう。思い出してください。通常、set_max_delay コマンドは、特定のフリップフロップ間のパスに対する周期制約のようなものです。では、宛先クロックパス(Destination Clock Path)では何が起こるのでしょうか。計算は 2 番目のクロックエッジの時刻、つまり 7 ns から始まります。しかし、2 番目のフリップフロップへのクロックパス遅延はゼロであり、このフリップフロップの tsu もゼロです。したがって、宛先クロックパスの計算結果はちょうど 7 ns になります。これは、ソースパスに許される最大値です。ソースパスは通常どおり計算されます。つまり、ソースクロックパスとデータパスの合計です。要約すると、データ出力は最初のクロックエッジから 7 ns 後までに有効でなければならないという要件になります。これは、出力ポートのクロックから出力までの遅延の定義とまったく同じです。関連するクロックの create_clock コマンドが get_ports に基づいていれば、このクロックから出力までの遅延は PCB 上のクロックを基準にしたものになります。
Vivado によるタイミングレポートの例を参照してください。
set_output_delay が外部コンポーネントの tsu または thold に関するものであるのに対し、set_max_delay は FPGA の出力ポートのクロックから出力までの遅延を定義します。つまり、これら 2 つの選択肢の主な違いは、どこに重点を置くかです。
入力ポートに関しては、set_max_delay と set_min_delay が何を意味するのかを直感的に説明することはできません。ソースパスは、入力ピンと入力信号を受け取るフリップフロップのデータ入力との間の遅延からなります。宛先クロックパスは、タイミング制約コマンドで指定された時刻から始まります。この時刻にクロックパス遅延が加算されます。これらは無意味な計算です(タイミングレポートを参照)。入力には、外部コンポーネントのクロックから出力までの遅延に関する set_input_delay を使う方が自然です。
set_max_delay と set_min_delay のために行われるタイミング解析は、クロック周期に依存しないことに注意してください。したがって、クロックの周波数が変更されても、ツールがこれらの制約を適用するときに同じ数値が使われます。対照的に、set_input_delay と set_output_delay の計算はクロック周波数に依存します。
I/O タイミング制約がクロック周波数に依存することは、状況によっては利点にも欠点にもなり得ます。タイミング制約が外部コンポーネントのタイミングパラメータに基づいて書かれている場合(そしてインターフェースがシステム同期の場合)、set_input_delay と set_output_delay に頼る方がおそらく良いでしょう。これらの制約は、クロック周波数が変わっても正しく保たれます。しかし、タイミング制約の意図が、ツールに特定の選択を強制すること(たとえばIOB レジスタを使わせること)である場合、set_max_delay と set_min_delay の方が適している可能性が高いです。
-datapath_only を使う場合
タイミング制約の動機の 1 つとして、I/O ポートとの間の遅延を可能な限り小さくするために、FPGA ツールに何でもさせることを保証したい、というものがあります。これは通常、IOB レジスタを使うことを意味します。また、入力ポートとフリップフロップの間に余分な遅延を挿入しないことも意味します(ツールは thold 要件をより良いマージンで満たすために、そのような遅延を挿入することがあります)。
この目的でタイミング制約を使う場合、目標となる特定の遅延はありません。アイデアは、ツールが達成可能な最良の結果以外のことをしないように防ぐことです。FPGA ツールが -datapath_only をサポートしているなら、set_max_delay をこのオプションと一緒に使う方が良いです。これにより、計算からクロック遅延パスが完全に取り除かれ、I/O ポートとフリップフロップの間の遅延だけが考慮されます。このようにして、タイミング制約の要件はその目的、つまりフリップフロップと I/O ピンの間の遅延を制御することと正確に対応します。
これは Vivado での簡単な例です。
set_max_delay -datapath_only -from [get_ports test_in] 2 set_max_delay -datapath_only -from [all_registers] \ -to [get_ports test_out] 3
しかし、「-from [all_registers]」という部分の目的は何でしょうか。なぜ「-from」が必要なのでしょうか。簡単に答えると、Vivado が「-from」なしのこのコマンドを受け付けなかったからです。入力ポートに関するコマンドには同様の要件はありませんでした。
datapath_only を使ったタイミングレポートは、例のページの一番下にあります。
まとめ
set_input_delay と set_output_delay は、I/O タイミング制約のための推奨コマンドと見なされることがよくあります。実際、インターフェースがシステム同期である場合は、これが通常は正しい選択です。他のシナリオでは、set_max_delay と set_min_delay を代わりに使うことを検討する価値があるかもしれません。その方が、I/O ポートのタイミングに必要な制限をより適切に反映できる可能性があるからです。
このページで、このタイミングに関する連載ページは終わりです。ただし、既存の設計を検査するのに便利な形で多くのトピックをまとめた最後のページがもう 1 つあります。