はじめに
FPGA では、すべての I/O ポートに対して、ロジックファブリック上に小さな領域が割り当てられています。この領域は IOB(Input / Output Block)と呼ばれ、I/O ポートの機能を支えるために必要なもの、すなわち I/O ピンに正しい電圧と電流を供給するためのアナログ回路や、いくつかの特別な論理要素を含んでいます。
ここで指摘しておくと、「IOB」という用語は AMD(旧 Xilinx)が使っている用語です。FPGA ベンダーによって、呼び方はそれぞれ異なります。
IOB の中には、ほとんどの場合 IOB レジスタがあります。これらのレジスタは、I/O ポートのピンに直接接続されたフリップフロップです。
一部のフリップフロップは、ピンが入力ポートの場合に使うためのものです。これらのフリップフロップの D 入力は I/O ポートのピンに接続されています。したがって、この種のフリップフロップは、外部から届く信号のサンプリング (sampling) を行います。
別のフリップフロップは、ピンを出力ポートとして使うときに備えたものです。これらのフリップフロップの Q 出力はピンに接続されています。
IOB の構造は FPGA によって異なります。複雑で多機能な IOB もあれば、より単純な構造の IOB もあります。多くの場合、IOB レジスタは SERDES のようなより大きな論理要素の一部になっています。したがって、IOB を説明するドキュメントの図にフリップフロップが明示的に描かれていなくても、その FPGA の I/O ピンに IOB レジスタがある可能性は十分にあります。
なぜ IOB レジスタを使うのか
IOB レジスタを使う主な動機はタイミングです。これらのレジスタが I/O ポートのピンのすぐ近くにあるため、この方法で得られる clock-to-output は他に類を見ません。入力ポートについても、IOB レジスタは要求されるタイミングを実現できる可能性が最も高くなります。
しかし、タイミング要件を満たすのが簡単な場合でも、IOB レジスタを使うべき立派な理由があります。それは再現性です。IOB レジスタを使わない場合、I/O ポートのピンとフリップフロップの間の遅延は、FPGA プロジェクトを実装するたびに変わります。これは、ツールがフリップフロップを毎回別の場所に配置することを許されているからです。ツールは、タイミング制約 (timing constraints) を満たす限り、配線遅延も変更できます。PCB 設計が正しく、外部部品とのインターフェースが適切に計画されていれば、これは問題になりません。しかし、そうした問題が実際にある場合、実装ごとの遅延の違いは混乱を招きかねません。すなわち、何かが動作せず、設計のどこかを修正したところ問題が解決したように見える。ところが実際に差をもたらしたのは、どこかの I/O タイミングが少し変わっただけだった、ということがあり得ます。
IOB レジスタを使用することにより、FPGA のロジックを開発している最中に、外部部品との電気的インターフェースが意図せず変化しないことが保証されます。これにより、問題が発生した場合に、その原因を切り分けやすくなります。
IOB レジスタの使用を指定する
FPGA ツールに対して、IOB レジスタを使うよう明示的に指示しなければならない場合があります。通常、シンセサイザ (synthesizer) がこの処理を担当するので、Vivado では次のような合成属性を使うことができます。
(* IOB = "TRUE" *) input the_input,
同じことは XDC ファイルでも可能です。
set_property IOB true [get_ports the_input]
もう 1 つの方法は、入力に接続されているレジスタに合成属性を追加することです。
(* IOB = "TRUE" *) reg the_input_samp;
XDC ファイル内の属性だけでは不十分な場合があることに注意してください。IOB にフリップフロップを配置するためには、シンセサイザがレジスタを複製しなければならないことがよくあります。これは、そのフリップフロップの出力が FPGA 内の通常のロジックでも使われる場合に当てはまります。IOB 内にあるフリップフロップの出力は、そのポート専用にしか使えないからです。したがって、ロジックファブリック内でも使える同じ出力を作るために、もう 1 つのフリップフロップが必要になります。このような状況では、しばしば合成属性(前述のもの)が必要になります。
Quartus では、次のようなコマンドを QSF ファイルに追加できます。
set_instance_assignment -name FAST_INPUT_REGISTER ON -to the_input set_instance_assignment -name FAST_OUTPUT_REGISTER ON -to the_output
各ツールには、これを実現する方法に多少の違いがあります。
タイミング制約
IOB レジスタを使うポートに対して、タイミング制約 (timing constraints)を書く理由はあるのでしょうか。何しろ、IOB レジスタの位置は 1 つしかあり得ません。タイミング制約があってもなくても、タイミングは常に同じになると結論しても安全ではないでしょうか?
IOB レジスタを使っている場合でもタイミング制約を書くのには、主に 2 つの良い理由があります。
1 つ目の理由は、IOB レジスタが確実に使われるようにすることです。ロジック設計の変更によって、すべてのポートまたは一部のポートで IOB が使えなくなってしまうことが、意図せず起こり得ます。このような場合、ツールが警告を出すことはほとんどありません。むしろ、IOB の外にあるフリップフロップが黙って使われてしまいます。タイミング制約はこの状況を防ぐことができます。関連するすべてのフリップフロップが IOB の中にある場合にのみタイミング制約を達成できるようにしておけば、フリップフロップが IOB から追い出されても黙っては済みません。結果としてタイミング制約が失敗するからです。
2 つ目の理由は、ツールが I/O ポートのピンと IOB レジスタの間に意図的な遅延を挿入することがあるためです(もっとも、この機能をサポートしていない FPGA もあります)。この遅延は、thold に関するタイミングを改善するためのものです(Quartus での例を参照)。この望ましくない処置は、この余分な遅延なしでのみ達成できるタイミング制約によって防ぐことができます。
IOB レジスタが一貫して使われることを保証するには、通常 set_max_delay が適切なタイミング制約です。FPGA ツールがこのコマンドの "datapath_only" オプション(または類似の機能)をサポートしていれば、なおさら便利です。
まとめ
IOB レジスタは、可能な限り使うべきです。FPGA ツールが自発的にそうしてくれるとは限らないため、この目標を達成するには多少の努力が必要かもしれません。その努力の見返りは、最適なタイミングだけではなく、I/O ポートの動作が再現性を持つことでもあります。