このページは、タイミングに関する連載ページの一部です。これまでのページでは、タイミング計算の背後にある理論やクロック周期タイミング制約など、いくつかの基本トピックを説明しました。また、いくつかのタイミングレポートを示して解説しました。今回はいよいよ、この知識の重要な用途の 1 つである「タイミング問題の解決」について説明します。
はじめに
FPGA ツールにとって最大の難関は、タイミング制約(timing constraints)の要件を達成することです。それは、うまくいけば成功ですし、場合によっては失敗します。そして失敗したとき、その原因を突き止め、修正する義務を負うのは、私たち人間です。この作業には名前があります。私たちはそれをタイミングクロージャ(timing closure)と呼びます。そして、それは決して簡単な作業ではありません。
なぜタイミングクロージャは難しいのでしょうか。実は、ツールは FPGA のリソースを最適な方法で使おうとする配置配線(place and route)アルゴリズムを備えています。通常、このアルゴリズムは、FPGA 上に論理エレメントをそれほど努力せずに配置することから始まります。その後、反復プロセスが始まります。ツールはすべてのパス(path)を調べ、タイミング制約を満たしていないパスを見つけます。これらの未達を解消するために、該当パスに対して是正措置が取られます。最も顕著なのは、論理エレメントを FPGA 上の別の位置に移動したり、配線を調整したりすることです。より高度な是正措置については、FPGA ツールごとに独自の方法があります。
すべてのパスがタイミング制約を満たせば、インプリメンテーションは完了したと見なされます。しかし、インプリメンテーションが終了するのは、ツールがこの目標に到達できず、その結果として試行を断念した場合もあります。この状況では、努力が止まった時点でツールが達成したものが得られます。この結果は必ずしも最適ではありません。インプリメンテーションには改善できたはずのパスがあったかもしれませんが、ツールは別の何かの修正に忙しかったのです。そしてその修正に失敗すると、ツールは他のことを試さずに断念しました。あたかもツールがこう言っているかのようです。「どうせ失敗するなら、インプリメンテーションを修正する時間を無駄にする価値はない」と。
FPGA 設計者である私たちの仕事は、この最適とは言えない結果を見て、タイミング制約の目標が達成されなかった理由を見つけることです。
アルゴリズムは時代とともに改良されていきます。タイミング制約の未達に共通する原因がある場合、次バージョンのソフトウェアはその状況に対する特別な解決策を備えています。つまり、ツールが失敗するとき、そこには通常、十分な理由があるのです。
そこで私たちはツールが達成した結果を見つめ、こう自問します。なぜツールは失敗したのか。不可能なことを要求したのだろうか。さらに重要なのは、不必要なことを要求したのだろうか。ツールを失敗させた障害は、そもそも必要のないものかもしれません。あるいは、最適化アルゴリズムがうまく機能しなかったのでしょうか。時には単に運が悪かっただけ、ということもあります。論理エレメントの初期配置があまりにも悪く、その後の性能改善の試みが決定的に失敗する運命にあることもあります。
問題が何であれ、失敗の理由を見つける作業は、犯罪現場を調べる探偵の仕事に似ています。事実は目の前にありますが、理由はしばしば隠されています。そうした事実のほとんどはタイミングレポートの中に見つかりますが、手がかりは簡単には姿を現しません。常に問いかけるべきことは、タイミングレポートの中で何が間違っているのか、何が普通ではないのか、何が異常なのか、ということです。犯人を見つけようとする探偵と同じように、問題にたどり着く手がかりを見つけることが目標です。
しかし、異常を見つけるためには、何が正常かを知っておく必要があります。例えば、特定のファンアウト(fan-out)を持つネットの遅延として正常な値はどれくらいか。特定の論理関数を実装するのに、ロジックレベルがいくつなら正常なのか。この種の質問への答えは FPGA ごとに異なります。したがって、すべてがうまくいっているときでも、タイミングレポートを読み理解することで経験を積むことが必要なのです。タイミングレポートがどこに問題を示しているのかを見つけるには、すべてが問題ないときのタイミングレポートがどのようなものかを知っていなければなりません。前のページであえて細部まで踏み込んだ理由をお尋ねなら、これもその理由の 1 つです。
クリティカルパス
ツールがタイミング制約を達成できない場合、少なくとも 1 つのパスに負のスラック(slack)があることを意味します。最も負のスラックが大きいパスをクリティカルパス(critical path)と呼びます。この名前は、タイミングクロージャの一般的な戦略を反映しています。クリティカルパスに注目することが、タイミング問題の解決策になることが多いのです。しかし、この戦略が時間の無駄になることもあるということを、以下でお見せしましょう。
タイミング制約が達成されている場合、クリティカルパスはスラックが最小のパスです。このパスは、多くの場合あまり重要ではありません。ツールは正のスラックを持つパスを改善しようとしないからです。つまり、最悪のパスが正のスラックを持つ場合、そのパスが最悪になったのは偶然であることがあります。
しかし、スラックが正でほぼゼロの場合(たとえば 0.2 ns 未満)、このパスでタイミング制約を達成するのが難しかったことを示している可能性があります。この種のクリティカルパスは、将来これらのパスが問題を引き起こすかもしれないという警告と見なせます(特に FPGA がより多くのロジックで満たされ、ツールの努力が他のパスに向けられるとき)。
タイミングレポートには、通常、各クロックについて限られた数のクリティカルパスが含まれます。ほとんどの FPGA ツールのデフォルトでは、スラックが正(つまりタイミング制約が達成されている)場合でも、いくつかのクリティカルパスを表示します。これは推奨される設定です。
クリティカルパスの例
まず、クリティカルパスの解析の例から始めます。この例の Verilog コードは次のとおりです。
reg [24:0] calc, result;
reg [11:0] x, y, z;
always @(posedge clk)
begin
calc <= x * y + z;
result <= calc;
end
この例では、@clk の周波数は 250 MHz で、このクロックを生成するために PLL は使われていません。また、@x、@y、@z は @clk に同期するレジスタであると仮定します。これらのレジスタに値を代入する Verilog コードは、関連しないため示していません。
このコードを Vivado でインプリメントしたところ、タイミング制約は達成できませんでした。タイミングレポートで、これがクリティカルパスでした。
Slack (VIOLATED) : -0.239ns (required time - arrival time) Source: x_reg[1]__0_replica_2/C (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Destination: calc_reg[23]/D (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Path Group: clk Path Type: Setup (Max at Slow Process Corner) Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns) Data Path Delay: 4.180ns (logic 1.642ns (39.282%) route 2.538ns (60.718%)) Logic Levels: 7 (CARRY8=4 LUT3=1 LUT4=1 LUT6=1) Clock Path Skew: -0.087ns (DCD - SCD + CPR) Destination Clock Delay (DCD): 3.176ns = ( 7.176 - 4.000 ) Source Clock Delay (SCD): 3.864ns Clock Pessimism Removal (CPR): 0.601ns Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE Total System Jitter (TSJ): 0.071ns Total Input Jitter (TIJ): 0.000ns Discrete Jitter (DJ): 0.000ns Phase Error (PE): 0.000ns Clock Net Delay (Source): 2.032ns (routing 0.396ns, distribution 1.636ns) Clock Net Delay (Destination): 1.748ns (routing 0.365ns, distribution 1.383ns) Location Delay type Incr(ns) Path(ns) Netlist Resource(s) ------------------------------------------------------------------- ------------------- (clock clk rise edge) 0.000 0.000 r AG12 0.000 0.000 r clk (IN) net (fo=0) 0.000 0.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.738 0.738 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.105 0.843 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.049 0.892 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.839 1.731 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.101 1.832 r clk_IBUF_BUFG_inst/O X2Y0 (CLOCK_ROOT) net (fo=106, routed) 2.032 3.864 clk_IBUF_BUFG SLICE_X54Y54 FDRE r x_reg[1]__0_replica_2/C ------------------------------------------------------------------- ------------------- SLICE_X54Y54 FDRE (Prop_HFF2_SLICEL_C_Q) 0.137 4.001 r x_reg[1]__0_replica_2/Q net (fo=21, routed) 0.371 4.372 x[1]_repN_2 SLICE_X56Y53 LUT6 (Prop_E6LUT_SLICEL_I1_O) 0.219 4.591 r calc[23]_i_101/O net (fo=2, routed) 0.550 5.141 calc[23]_i_101_n_0 SLICE_X54Y57 CARRY8 (Prop_CARRY8_SLICEL_DI[5]_CO[7]) 0.228 5.369 r calc_reg[23]_i_30/CO[7] net (fo=1, routed) 0.030 5.399 calc_reg[23]_i_30_n_0 SLICE_X54Y58 CARRY8 (Prop_CARRY8_SLICEL_CI_O[1]) 0.163 5.562 r calc_reg[23]_i_22/O[1] net (fo=3, routed) 0.351 5.913 calc_reg[23]_i_22_n_14 SLICE_X56Y57 LUT3 (Prop_C6LUT_SLICEL_I1_O) 0.146 6.059 r calc[23]_i_26/O net (fo=3, routed) 0.240 6.299 calc[23]_i_26_n_0 SLICE_X55Y58 LUT4 (Prop_A6LUT_SLICEM_I0_O) 0.089 6.388 r calc[23]_i_7/O net (fo=1, routed) 0.407 6.795 calc[23]_i_7_n_0 SLICE_X53Y57 CARRY8 (Prop_CARRY8_SLICEM_DI[2]_O[4]) 0.308 7.103 r calc_reg[23]_i_2/O[4] net (fo=1, routed) 0.538 7.641 P[20] SLICE_X54Y56 CARRY8 (Prop_CARRY8_SLICEL_S[4]_O[7]) 0.352 7.993 r calc_reg[23]_i_1/O[7] net (fo=1, routed) 0.051 8.044 P0_out[23] SLICE_X54Y56 FDRE r calc_reg[23]/D ------------------------------------------------------------------- ------------------- (clock clk rise edge) 4.000 4.000 r AG12 0.000 4.000 r clk (IN) net (fo=0) 0.000 4.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.515 4.515 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.066 4.581 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.034 4.615 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.722 5.337 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.091 5.428 r clk_IBUF_BUFG_inst/O X2Y0 (CLOCK_ROOT) net (fo=106, routed) 1.748 7.176 clk_IBUF_BUFG SLICE_X54Y56 FDRE r calc_reg[23]/C clock pessimism 0.601 7.777 clock uncertainty -0.035 7.741 SLICE_X54Y56 FDRE (Setup_HFF_SLICEL_C_D) 0.063 7.804 calc_reg[23] ------------------------------------------------------------------- required time 7.804 arrival time -8.044 ------------------------------------------------------------------- slack -0.239
このパスのスラックは –0.239 ns なので、タイミング制約をわずかに満たせていません。最初に調べるべきは、このパスの始点と終点です。レポートのヘッダーにある 「Source」 と 「Destination」 を見ると、x_reg と calc_reg があることがわかります。つまり、問題の原因は明らかにこの部分です。
calc <= x * y + z;
これは驚くことではありません。Verilog コードの中で意味のある演算がこれだけだからです。実際のシナリオでは、ロジックのどの部分が問題を引き起こしたかは、それほど明らかではありません。
また、タイミングレポートから、ロジックレベル数が 7 と多いことも明らかです。組み合わせパス(combinatorial path)が長すぎるのです。言い換えれば、@clk の 2 つのクロックエッジの間に行うべき処理が多すぎます。
しかし、失敗の実際の理由は何でしょうか。遅延の 61% を配線が占めていることが理由なのでしょうか。配線遅延は通常、合計遅延の約 40% になるという経験則を思い出してください。それなら FPGA ツールがもっとうまく動くように試してみるのはどうでしょう。しかし、それは成功する見込みが薄い解決策です。ツールは通常、パスのタイミング制約を達成しようと懸命に努力してから断念するからです。
@x と @calc の間の論理関数を変えようとするのも、同様に無意味です。乗算は必須なので、代わりに何か簡単なものを置くわけにはいきません。
この種の問題を解決するための他の可能な方法については、次のページで紹介します。しかし、このケースでは、テクニックのリストを眺めても役に立ちません。この単純な例は、時には探偵のように考える必要があることを示しています。
結局は自分の頭で考えるしかない
タイミングレポートを読むときに最初に問うべきことは、そのどこが異常なのかということです。この例では、組み合わせパスがスライス(slice)だけで構成されていることです。ほとんどすべての FPGA には、乗算が要求されたときに使われる専用の演算ユニット(DSP、ALU など、名前はさまざま)があります。実際、乗算と加算は、そうした専用ロジックで最もよく使われる機能です。したがって、ほとんどの場合の最も簡単な解決策は、ツールに専用の演算ユニットを使わせることです。その解決策でのタイミングレポートは、このページの最後に示します。
しかし、本当に問うべきなのは、専用の演算ユニットの代わりにスライスが使われたのはなぜかということです。最も一般的な理由は、FPGA が持つ利用可能な演算ユニットのすべてが、設計の別の部分ですでに使われていることです。この場合、必要な変更はクリティカルパスとはまったく無関係かもしれません。設計からいくつかのロジックを取り除いて、演算ユニットをいくつか空ける必要があるかもしれません。あるいは、ツールに指示して、設計の各部分の間で演算ユニットの割り当てを変えることも考えられます。
この例でスライスが演算ユニットの代わりに使われたのは、私がそうしたかったからです。つまり、意図的に演算ユニットの使用を無効にしました(Vivado の合成ツール(synthesizer)のパラメータの 1 つで、max_dsp をゼロに設定しました)。しかし、このことがこの例を人為的にしているわけではありません。FPGA ツールに誤ったパラメータを指定すると、まさにこの種の状況が起こることがあります。実際、設計の別の場所で演算ユニットがもっと必要になるため、意図的に演算ユニットを使わないことが正しい場合もあります。
つまり、簡単な解決策は専用の演算ユニットを使うことでした。しかし、スライスを使わなければならない場合はどうでしょうか。この場合も、解決策は間接的です。問題のある部分は次のとおりでしたね。
calc <= x * y + z;
しかし、この直後にあるものに注目してください。
result <= calc;
@calc がこの行でしか使われず、他のどこにも使われていないなら、計算を 2 段階に分割することができます。この技法は、しばしばパイプライン(pipeline)処理と呼ばれます。すると Verilog コードは次のように変わります。
reg [24:0] calc, result;
reg [11:0] x, y, z, z_d;
always @(posedge clk)
begin
z_d <= z;
calc <= x * y;
result <= calc + z_d;
end
この解決策では、@calc には乗算の結果だけが与えられます。@z の値が @calc に加算されるのは、次のステージになってからです。より正確には、加算は @calc と @z_d の間で行われます。この演算は 1 クロックサイクル後に行われるからです。したがって、@result の値は以前とまったく同じになります。
この方法で問題を簡単に解決できたのは、元の Verilog コードでは @result が @calc を単に遅延させたコピーだったからです。実際の設計では、それほど運が良くないのが普通です。
クリティカルパスには @calc と @x しか関与していないことに注意してください。@z はパスの中にまったく現れていません。つまり、この操作の目的は、算術演算の負担を減らすことです。より正確には、ロジックレベル数を減らすことです。
クリティカルパスは、最適化アルゴリズムを実行した後の最悪のパスであることを思い出してください。このアルゴリズムは、問題の理由を問いません。むしろ、負のスラックを持つパスを改善しようとします。つまり、問題の解決に @z の操作が必要だったにもかかわらず、@z に関連するパスはクリティカルパスではありませんでした。これは偶然にすぎませんが、よくあることです。
この解決策におけるクリティカルパスのタイミングレポートも、このページの最後に示します。ロジックレベル数が 7 から 6 に減っていることがわかります。その結果、データパス遅延は 0.715 ns 短縮され、タイミング制約を満たすには十分すぎるほどでした。
この例から学べる教訓は、クリティカルパスが必ずしも問題の直接の原因ではないということです。なぜこのパスが失敗したのかを問うことは正しいですが、解決策は別の場所にあるかもしれません。各 FPGA ツールには、問題の根本原因を見つけるのに役立つ情報を提供する独自のユーティリティがあります。これらのユーティリティを調べ、ドキュメントを読む価値はあります。
後で解決するより、早い段階で問題を避ける
論理設計を最初から正しく行えば、タイミングクロージャの作業の多くは避けられます。そのためには、論理設計はソフトウェアではないという事実を常に意識する必要があります。Verilog コードの目的は、シミュレーション中に正しい結果を生成することではありません。本当に重要なのは、Verilog コードから合成ツール(synthesizer)が生成する出力です。
良い論理設計は、ロジックがその目的を最もよく達成するにはどうすればよいかを考え抜くことから始まります。これには、タイミングに関連する潜在的な障害を特定することも含まれます。
経験の浅い FPGA 設計者は、試行錯誤で Verilog コードを書くことがよくあります。ロジックが期待どおりに動作するかを確認するためにシミュレーションを使い、シミュレーション出力が正しくなるまで少しずつ修正します。その結果、ハードウェアでは使えないロジックができあがることがあります。タイミング制約を達成するには Verilog コードを完全に書き直す必要があるのです。
Verilog コードが生成する組み合わせパスについて前もって考えることが重要です。具体的には、各レジスタを見て、組み合わせパスをその終点まで追いかけるのです。組み合わせパスは常にレジスタで始まりレジスタで終わることを思い出してください。
次の例を見てみましょう。
reg [15:0] a, b;
wire [16:0] x, y;
reg [33:0] z;
assign x = a + 2;
assign y = b + 3;
always @(posedge clk)
z <= x * y;
@a について考えます。このレジスタが変化すると、組み合わせパスは最初のステージとして @x に到達します。しかし @x はレジスタではありません。@x は連続代入によって更新されます。したがって、パスは @z まで続きます。つまり、このロジックは、組み合わせパスの中で加算と乗算という 2 つの重要な演算を実行していることになります。これはやりすぎでしょうか。これをパイプライン処理によって 2 つのクロックサイクルに分割する必要があるでしょうか。それは、クロック周波数と使用する FPGA 次第です。
もう 1 つの重要な要素は、組み合わせパスを短くすることがどれほど難しいかです。長い組み合わせパスが避けられないこともあります。しかし、パスのタイミングを簡単に改善できるのであれば、設計内にはるかに悪いパスがある場合でも、その改善を行いましょう。設計内の問題のあるパスがいくつかある場合、ツールはそれらのパスに努力を集中させることで、タイミング制約を達成できることがよくあります。他のパスのタイミング要件を満たすのが簡単であれば、非常に役立ちます。
したがって、タイミング制約を満たす設計を得るために「何が許されて、何が許されないか」という規則はありません。この分野で正しい判断をするには FPGA 設計の経験が必要です。特定の FPGA ツールに慣れていることも重要です。常に正しい唯一の規則はこれです。Verilog コードの簡単な変更でタイミングを改善できるなら、その変更を行いなさい。怠けずに、最初からその変更を加えなさい。常にタイミングを意識すること。
高速なロジックを書く
先にも述べたとおり、目標はレジスタ間の組み合わせパスを短くすることです。レジスタの次の値を計算する論理関数は単純であるべきです。言い換えれば、これらの論理関数を実装するのに必要なロジックレベル数は少ないほうがよいのです。
FPGA 設計者である私たちの仕事は、Verilog コードを見て、論理関数がどれほど複雑になるかを評価することです。そのためには、合成ツール(synthesizer)が Verilog をどのように論理エレメント(LUT やその他のロジックプリミティブ(primitive))に変換するかについての知識が必要です。この知識は経験を通じて得られ、その一部はタイミングレポートの解析によって培われます。さらに難しいことに、この変換は FPGA ごとに異なります。したがって、高速なロジックを生む Verilog コードを書くことは、決して簡単な作業ではありません。
FPGA 初心者の方は、学習のために、インプリメンテーションの結果を眺める時間を取ることをお勧めします。タイミングレポートには、論理設計が単純な論理エレメントに分解される様子の例が示されています。FPGA ツールには、低レベルの論理エレメントを表示するための他のユーティリティもあります。
さらに、役立つ簡単な規則がいくつかあります。
- パイプライン(pipeline)処理:レジスタは惜しみなく使いましょう。可能であれば、ロジックのタスクを小さな部分に分割し、各ステップの後にレジスタを挿入します。FPGA にはフリップフロップがたくさんあります(多くの場合、各 LUT の隣に 1 つフリップフロップがあります)。したがって、レジスタを挿入しても FPGA の使用率は上がりません。パイプライン処理を避ける唯一の理由は、設計が複雑になりすぎる場合です。
- if-then-else を使う場合、多くの 「else」 句を連ねるのは避けましょう。代わりに 「case」 文を使えるなら、通常そちらが良いです。「else」 句は、その前にあるすべての条件が偽であることを保証する論理関数を必要とすることがよくあります。したがって、複数の 「else」 句は複数のロジックレベルを必要とする可能性があります。
- 不要なリセットは避けましょう。特に、同期リセット(synchronous reset)は、論理関数にわずかな複雑さを追加します。また、同期/非同期のどちらのリセット(asynchronous reset)も配線を難しくします。これらの信号は多くの論理エレメントに到達する必要があるからです。このトピックについては別の連載ページがあります。
- 巨大なステートマシン(state machine)を作らないでください。状態数がいくつまでなら良いかという明確な制限はありません。しかし、状態数が 20 を超えるなら、設計の再構成を検討すべきです。また、大きなステートマシンには、合成ツールがワンホットエンコーディングを使うようにしましょう(ほとんどの合成ツールはデフォルトでそうします)。これにより、高速なロジックを生成しやすくなります。
- RAM の後にレジスタを 1 つ追加するのが、通常は良い結果をもたらします。暗黙的に作成される RAM の次の例を見てみましょう。
reg [7:0] array[0:127]; reg [7:0] val; reg [6:0] addr; always @(posedge clk) val <= array[addr];この Verilog コードは正しいですが、@val は RAM の同期出力であることに注意してください。つまり、立ち上がりクロックエッジがあると RAM の動作が始まり、配列から値が得られて初めて @val が更新されます。したがって、@val は(フリップフロップと比較して)比較的大きなクロックから出力までの遅延を持ちます。そのため、@val から始まるパスには本質的に不利があります。これは、レジスタを 1 つ追加することで修正できます。
reg [7:0] array[0:127]; reg [7:0] val_d, mem_out; reg [6:0] addr; always @(posedge clk) begin mem_out <= array[addr]; val_d <= mem_out; endここで注意:これは機能的に等価ではありません。ここでは @mem_out が RAM の出力です。この出力が @val_d にコピーされるのは 1 クロック後なので、@val の完全な置き換えにはなりません。しかし @val_d は本物のレジスタであり、クロックから出力までの遅延が小さくなります。多くの FPGA では、この追加レジスタはブロック RAM の一部であるため、フリップフロップの無駄にはなりません。フリップフロップの無駄を気にする必要はないと、以前言ったことを覚えていますか?
残念ながら、このようなレジスタを追加すると、設計がかなり複雑になることがよくあります。その場合は、この追加レジスタを入れないほうが良く、むしろ @val からの組み合わせパスを短く保つように努めるのが良いでしょう。
追加のタイミングレポート 2 件
先ほどの「結局は自分の頭で考えるしかない」という節で、2 つのタイミングレポートを約束しました。それらは長く、内容的にも部分的にしか関係しないため、言及した場所ではなく、ここに置きました。
これら 2 つのタイミングレポートは、それぞれのシナリオでのクリティカルパスであることに注意してください。したがって、上に示したパスと同じレジスタで始まり、終わるわけではありません。
最初のタイミングレポートは、最初の Verilog コード例に関するものです。上記のタイミングレポートとは異なり、ツールは専用の演算ユニットを使うことを許可されています。その結果、タイミング制約は簡単に達成できました。
このタイミングレポートは Kintex UltraScale FPGA 向けに生成されたものです。この FPGA ファミリでは、専用の演算ユニットは DSP48E2 と呼ばれます。このパスは同じ DSP48E2 ユニット上で始まり終わっていることに注意してください。したがって、ロジック遅延は 100% です。
Slack (MET) : 1.406ns (required time - arrival time) Source: calc_reg/DSP_A_B_DATA_INST/CLK (rising edge-triggered cell DSP_A_B_DATA clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Destination: calc_reg/DSP_OUTPUT_INST/ALU_OUT[10] (rising edge-triggered cell DSP_OUTPUT clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Path Group: clk Path Type: Setup (Max at Slow Process Corner) Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns) Data Path Delay: 2.445ns (logic 2.445ns (100.000%) route 0.000ns (0.000%)) Logic Levels: 4 (DSP_ALU=1 DSP_M_DATA=1 DSP_MULTIPLIER=1 DSP_PREADD_DATA=1) Clock Path Skew: -0.010ns (DCD - SCD + CPR) Destination Clock Delay (DCD): 3.392ns = ( 7.392 - 4.000 ) Source Clock Delay (SCD): 4.096ns Clock Pessimism Removal (CPR): 0.694ns Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE Total System Jitter (TSJ): 0.071ns Total Input Jitter (TIJ): 0.000ns Discrete Jitter (DJ): 0.000ns Phase Error (PE): 0.000ns Clock Net Delay (Source): 2.264ns (routing 0.756ns, distribution 1.508ns) Clock Net Delay (Destination): 1.964ns (routing 0.696ns, distribution 1.268ns) Location Delay type Incr(ns) Path(ns) Netlist Resource(s) ------------------------------------------------------------------- ------------------- (clock clk rise edge) 0.000 0.000 r AG12 0.000 0.000 r clk (IN) net (fo=0) 0.000 0.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.738 0.738 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.105 0.843 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.049 0.892 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.839 1.731 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.101 1.832 r clk_IBUF_BUFG_inst/O X2Y1 (CLOCK_ROOT) net (fo=80, routed) 2.264 4.096 calc_reg/CLK DSP48E2_X11Y34 DSP_A_B_DATA r calc_reg/DSP_A_B_DATA_INST/CLK ------------------------------------------------------------------- ------------------- DSP48E2_X11Y34 DSP_A_B_DATA (Prop_DSP_A_B_DATA_DSP48E2_CLK_A2_DATA[9]) 0.302 4.398 r calc_reg/DSP_A_B_DATA_INST/A2_DATA[9] net (fo=1, routed) 0.000 4.398 calc_reg/DSP_A_B_DATA.A2_DATA<9> DSP48E2_X11Y34 DSP_PREADD_DATA (Prop_DSP_PREADD_DATA_DSP48E2_A2_DATA[9]_A2A1[9]) 0.182 4.580 r calc_reg/DSP_PREADD_DATA_INST/A2A1[9] net (fo=1, routed) 0.000 4.580 calc_reg/DSP_PREADD_DATA.A2A1<9> DSP48E2_X11Y34 DSP_MULTIPLIER (Prop_DSP_MULTIPLIER_DSP48E2_A2A1[9]_U[10]) 0.994 5.574 f calc_reg/DSP_MULTIPLIER_INST/U[10] net (fo=1, routed) 0.000 5.574 calc_reg/DSP_MULTIPLIER.U<10> DSP48E2_X11Y34 DSP_M_DATA (Prop_DSP_M_DATA_DSP48E2_U[10]_U_DATA[10]) 0.164 5.738 r calc_reg/DSP_M_DATA_INST/U_DATA[10] net (fo=1, routed) 0.000 5.738 calc_reg/DSP_M_DATA.U_DATA<10> DSP48E2_X11Y34 DSP_ALU (Prop_DSP_ALU_DSP48E2_U_DATA[10]_ALU_OUT[10]) 0.803 6.541 r calc_reg/DSP_ALU_INST/ALU_OUT[10] net (fo=1, routed) 0.000 6.541 calc_reg/DSP_ALU.ALU_OUT<10> DSP48E2_X11Y34 DSP_OUTPUT r calc_reg/DSP_OUTPUT_INST/ALU_OUT[10] ------------------------------------------------------------------- ------------------- (clock clk rise edge) 4.000 4.000 r AG12 0.000 4.000 r clk (IN) net (fo=0) 0.000 4.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.515 4.515 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.066 4.581 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.034 4.615 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.722 5.337 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.091 5.428 r clk_IBUF_BUFG_inst/O X2Y1 (CLOCK_ROOT) net (fo=80, routed) 1.964 7.392 calc_reg/CLK DSP48E2_X11Y34 DSP_OUTPUT r calc_reg/DSP_OUTPUT_INST/CLK clock pessimism 0.694 8.086 clock uncertainty -0.035 8.050 DSP48E2_X11Y34 DSP_OUTPUT (Setup_DSP_OUTPUT_DSP48E2_CLK_ALU_OUT[10]) -0.104 7.946 calc_reg/DSP_OUTPUT_INST ------------------------------------------------------------------- required time 7.946 arrival time -6.541 ------------------------------------------------------------------- slack 1.406
2 つ目のタイミングレポートは、2 つ目の Verilog コード例に関するものです。この例では、パイプライン処理によって状況が改善されました。
Slack (MET) : 0.433ns (required time - arrival time) Source: y_reg[1]__0/C (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Destination: calc_reg[23]/D (rising edge-triggered cell FDRE clocked by clk {rise@0.000ns fall@2.000ns period=4.000ns}) Path Group: clk Path Type: Setup (Max at Slow Process Corner) Requirement: 4.000ns (clk rise@4.000ns - clk rise@0.000ns) Data Path Delay: 3.465ns (logic 1.653ns (47.706%) route 1.812ns (52.294%)) Logic Levels: 6 (CARRY8=4 LUT4=2) Clock Path Skew: -0.129ns (DCD - SCD + CPR) Destination Clock Delay (DCD): 3.373ns = ( 7.373 - 4.000 ) Source Clock Delay (SCD): 4.040ns Clock Pessimism Removal (CPR): 0.538ns Clock Uncertainty: 0.035ns ((TSJ^2 + TIJ^2)^1/2 + DJ) / 2 + PE Total System Jitter (TSJ): 0.071ns Total Input Jitter (TIJ): 0.000ns Discrete Jitter (DJ): 0.000ns Phase Error (PE): 0.000ns Clock Net Delay (Source): 2.208ns (routing 0.756ns, distribution 1.452ns) Clock Net Delay (Destination): 1.945ns (routing 0.696ns, distribution 1.249ns) Location Delay type Incr(ns) Path(ns) Netlist Resource(s) ------------------------------------------------------------------- ------------------- (clock clk rise edge) 0.000 0.000 r AG12 0.000 0.000 r clk (IN) net (fo=0) 0.000 0.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.738 0.738 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.105 0.843 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.049 0.892 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.839 1.731 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.101 1.832 r clk_IBUF_BUFG_inst/O X2Y1 (CLOCK_ROOT) net (fo=121, routed) 2.208 4.040 clk_IBUF_BUFG SLICE_X54Y88 FDRE r y_reg[1]__0/C ------------------------------------------------------------------- ------------------- SLICE_X54Y88 FDRE (Prop_EFF2_SLICEL_C_Q) 0.138 4.178 r y_reg[1]__0/Q net (fo=25, routed) 0.505 4.683 y[1] SLICE_X53Y91 LUT4 (Prop_B6LUT_SLICEM_I0_O) 0.150 4.833 r calc[7]_i_28/O net (fo=1, routed) 0.344 5.177 calc[7]_i_28_n_0 SLICE_X53Y89 CARRY8 (Prop_CARRY8_SLICEM_DI[2]_CO[7]) 0.424 5.601 r calc_reg[7]_i_9/CO[7] net (fo=1, routed) 0.043 5.644 calc_reg[7]_i_9_n_0 SLICE_X53Y90 CARRY8 (Prop_CARRY8_SLICEM_CI_O[0]) 0.122 5.766 r calc_reg[23]_i_30/O[0] net (fo=3, routed) 0.402 6.168 calc_reg[23]_i_30_n_15 SLICE_X51Y88 LUT4 (Prop_C5LUT_SLICEL_I0_O) 0.169 6.337 r calc[15]_i_8/O net (fo=1, routed) 0.437 6.774 calc[15]_i_8_n_0 SLICE_X51Y92 CARRY8 (Prop_CARRY8_SLICEL_DI[1]_CO[7]) 0.422 7.196 r calc_reg[15]_i_1/CO[7] net (fo=1, routed) 0.030 7.226 calc_reg[15]_i_1_n_0 SLICE_X51Y93 CARRY8 (Prop_CARRY8_SLICEL_CI_O[7]) 0.228 7.454 r calc_reg[23]_i_1/O[7] net (fo=1, routed) 0.051 7.505 calc_reg[23]_i_1_n_8 SLICE_X51Y93 FDRE r calc_reg[23]/D ------------------------------------------------------------------- ------------------- (clock clk rise edge) 4.000 4.000 r AG12 0.000 4.000 r clk (IN) net (fo=0) 0.000 4.000 clk_IBUF_inst/I AG12 INBUF (Prop_INBUF_HRIO_PAD_O) 0.515 4.515 r clk_IBUF_inst/INBUF_INST/O net (fo=1, routed) 0.066 4.581 clk_IBUF_inst/OUT AG12 IBUFCTRL (Prop_IBUFCTRL_HRIO_I_O) 0.034 4.615 r clk_IBUF_inst/IBUFCTRL_INST/O net (fo=1, routed) 0.722 5.337 clk_IBUF BUFGCE_X1Y0 BUFGCE (Prop_BUFCE_BUFGCE_I_O) 0.091 5.428 r clk_IBUF_BUFG_inst/O X2Y1 (CLOCK_ROOT) net (fo=121, routed) 1.945 7.373 clk_IBUF_BUFG SLICE_X51Y93 FDRE r calc_reg[23]/C clock pessimism 0.538 7.910 clock uncertainty -0.035 7.875 SLICE_X51Y93 FDRE (Setup_HFF_SLICEL_C_D) 0.063 7.938 calc_reg[23] ------------------------------------------------------------------- required time 7.938 arrival time -7.505 ------------------------------------------------------------------- slack 0.433
専用の演算ユニットを使った場合ほどの劇的な違いはありません。しかし、それでもタイミング制約を達成するには十分です。
これで、タイミングクロージャに関する一般的な議論は終わりです。次のページでは、このテーマに関するいくつかの実践的な戦略を紹介します。