このページは、プロの FPGA 設計者になるための全 5 ページのシリーズの 2 ページ目です。ここでは、FPGA 設計者なら誰でも身につけるべきだと思うさまざまな理論的テーマを順に見ていき、それぞれがなぜ重要だと私が考えているのかも説明していきます。
論理理論
理論を知っていることは贅沢ではありません。それは他のすべてがその上に築かれる土台です。たとえ、言うことを聞いてくれない開発ツールと格闘しているときや、エレクトロニクスが勝手に振る舞っているように見えるときには、そうは感じられないとしても。
FPGA エンジニアは、自分が書いた Verilog がどのようにロジック要素として実装されるかを思い描ける必要があります。詳細まで完璧に、ではなくても、どの部分が設計を遅くしてクロック周波数を制限するのか、どの部分が大量のロジックリソースを食いつぶすのかが分かる程度には。これはたとえば、ある処理をレジスタを追加してパイプライン化 (pipeline) する必要があるかどうかを判断するのに決定的に重要です。パイプライン化はたいてい設計を複雑にしますが、要求される速度に到達する唯一の方法であることもよくあります。他の重要な設計判断も、この能力に依存しています。
また、論理合成ツール (synthesizer) が何をしたのか、なぜそうしたのかを追いかけるのにも欠かせません。たとえば、合成ツールが何を最適化で消し去る傾向があるかを知っていれば、読みやすくて効率的な Verilog コードを書けます。自分のコードを合成ツールがどう扱うかを知らなければ、闇雲に書いているのと同じです。
では、どんなテーマが関係してくるのでしょうか。まずこのチェックリストから始めることをおすすめします。これで全部を網羅していると言うつもりはありません。
- ゲート(AND、OR、XOR など)、フリップフロップ、ROM/RAM、LUT、マルチプレクサ。これらはすべての基本構成要素で、データシートやユーザーガイド、あるいはツールが自分のやったことを伝えてくるときにも登場します。複雑ではありませんが、これが分からないとお手上げになります。
- 組み合わせ論理 (combinatorial logic) と順序論理 (sequential logic)、そして同期設計の原理。これらはあらゆるロジック設計の中心となる概念です。
- ステートマシン (state machine)。状態遷移図がどうやって Verilog コードになるのかを理解し、ステートマシンがどう動くかをしっかり肌で感じておきましょう。入力信号に応じて順序立てた処理をする、つまりソフトウェアのように振る舞うロジックの裏には、ほとんどの場合ステートマシンがあります。
- ブール代数。x && (y || z) = x && y || x && z や、ド・モルガンの法則 !(x && y) = !x || !y などです。これらはコードを簡略化するのによく使われます。代数の基本を知っているのと同じことです。
- 固定小数点演算、2 の補数、オーバーフロー (overflow) と飽和。加算と減算がどう実装されるか。キャリーの伝搬遅延 (propagation delay) が抱える問題を理解すること。乗算器がどう実装されるかをざっと眺めておくのもおすすめです。算術演算はロジック設計のいたるところに現れます。これらの演算が正確にどう振る舞うのか、どれだけのリソースを消費するのか、そしてどれだけ設計を遅くするのかを知っておく必要があります。
ロジックのパラダイムと手法
純粋な論理理論を知っていることに加えて、確実かつ効率的に動作し、ハードウェアでもシミュレーションと同じように振る舞うコードを書くために必要なテーマがいくつかあります。ソフトウェアの世界ではほぼ当たり前のことですが、FPGA 設計者は別の領域に住んでいます。どの FPGA 設計者も、これらのテーマを常に頭に置いておかなければなりません。
中心となる考え方は RTL(Register Transfer Level)パラダイムです。ひと言でいえば、値を保持するものはすべて、クロックエッジに応じてのみその値を変えるということです。非同期リセットが、慎重に制御された唯一の例外になりえます。この考え方を身につけてしまえば、正しく設計できる可能性は高いです。
リセットはそれ自体がひとつのテーマです。同期リセット (synchronous reset) と非同期リセット (asynchronous reset) のどちらを使うか、そしてリセットの同期化は、関わるすべての設計で決着をつける必要がある問題です。これをやらないと、設計はほとんど問題なく動きますが、ときどき散発的な不具合を起こします。納品できる動くシステムはあるのに、この散発的な失敗のせいでリリースできません。プロジェクトはどんどん遅れていき、何が悪いのかまったく分からなくなります。こういう状況でリセットの不備が思い浮かぶことはありません。このテーマは本当に深く理解しておくべきです。このサイトにはこのテーマに関する短い連載ページがあります。
密接に関連するのが、クロックイネーブル (clock enable) とゲート付きクロック(gated clock、クロックのゲーティング)のどちらを使うかという問題です。これは本質的に、ロジック設計を毎クロックサイクル動かさないようにするための 2 つの異なる手法です。FPGA にはクロックゲーティング用の専用リソースがありますが、やり方を間違えると謎の問題を生み出す格好の手段になります。ロジックではクロックイネーブルを使うのが安全な習慣ですが、実効クロックレートが下がることを利用してタイミング制約 (timing constraints) を緩めたいなら、それもまた問題にぶつかることがあります。
ステートマシンの符号化にも触れておくべきでしょう。バイナリ符号化、ワンホット符号化、グレイ符号化にはそれぞれ使いどころがあり、その選択は速度とリソース使用量の両方に影響します。ツールが自動で選んでくれることもよくありますが、各選択肢が何を意味するかは知っておくべきです。とくにワンホット符号化は大規模なステートマシンに最適です。ただし、ステートマシンがきちんとリセットされていないと、この符号化によって Verilog コード上ではありえない動作をすることがあります。FPGA 内部の魔術か論理合成ツールのバグに見えますが、違います。ワンホット符号化と、おざなりなリセット処理のせいなのです。
そして最後にパイプライン化です。これは単なる手法ではなく、考え方です。レジスタを 1 つ追加するのは簡単ですが、データ処理が複数のクロックサイクルにまたがるという事実が、実にさまざまな問題を生み出します。たとえば、最初の有効なデータが届く前に、このデータを受け取る側は何をすべきでしょうか。入力データが連続して届かず、パイプラインを一時的に止める必要がある場合はどうなるでしょうか。処理チェーン内のすべてのロジック要素に広がる巨大なファンアウト (fan-out) を持つ単一のクロックイネーブルを使わずに、どうやってそれを実現するのでしょうか。
どのシナリオにも異なる種類のパイプライン設計が必要で、それぞれに独自の難しさと癖があります。
デジタル設計
先にも述べたとおり、FPGA 設計者は Verilog が最終的に FPGA 内のロジック要素になる様子を思い描ける必要があります。具体的な例を見てみましょう。
私が Verilog で単純に "assign x = a + b;" と書いたとします。この加算器はどう実装されるのでしょうか。この FPGA は加算器を実装するために特別な仕掛けを使っているのでしょうか。専用のハードブロック、たとえば DSP ブロックを使うのでしょうか。もし使うとして、加算器の結果が配線ではなくレジスタだった場合、どれだけ役に立つのでしょうか。"assign x = a + b + c;" のように 3 つの数を足したらどうなるでしょうか。FPGA に 3 つの数を足すための近道はあるのでしょうか。答えはほぼ間違いなく「ない」ですから、これは (a + b) + c のような形で実装されます。縦続接続された 2 つの論理演算は、設計をかなり遅くする可能性があります。しかし、あなたの使う特定の FPGA ではどうなのでしょうか?
自分がターゲットにしている特定の FPGA でどんなリソースが使えるかを意識しておくことは重要です。それが Verilog の書き方を形づくり、論理合成ツールが高速で効率的なロジックを作れるようにします。合成ツールは、投げつけられたどんな問題でも解決してくれる魔法使いではありません。Verilog を賢く書き、その限界を知っていれば、リソース消費が少なく、消費電力も比較的小さく、高いクロック周波数で動く設計が得られます。これは経験とともに身につくもので、デジタル設計の知識があれば、そうした知恵を獲得するスピードが上がります。
実際には、結果がなぜ遅かったのか、なぜリソースを取りすぎたのかを理解する必要があるため、タイミングクロージャ (timing closure) の問題を解決するときにだけ、FPGA 内部のロジック実装を調べざるをえないのが普通です。そこで、時間やリソースの無駄を探しながら、ロジック実装の細部を 1 つずつ追っていきます。ただ、もっと知識を深めるため、あるいはおかしなことが起きていないかを確認するために、ときどき自発的に結果を分析するのも良い考えです。これは長い目で見て報われます。
自分の FPGA を知る
Verilog がどうロジック要素になるかを思い描くという話のもう 1 つの側面は、基本的なロジックリソースに関係します。つまり、FPGA の構成要素と、それらが何に向いているかを知るということです。
まず FPGA 自体の構造です。基本要素、CLB、そして使う FPGA のスライス (slice) です。Verilog コードを書くとき、必要なロジックを実装するためにこれらの要素がどう使われるかを思い描ければ、大きな強みになります。そうすれば、今書いているものが設計のタイミングクロージャのボトルネックになるかどうか、あるいはこのコード片が二度と悩ませることはないかどうかが分かります。
ほとんどの FPGA は多かれ少なかれ同じような構造をしています。どの FPGA にも、算術加算器、マルチプレクサ、デマルチプレクサなどを効率的に実装する方法があります。これらの機能は頻繁に使われるからです。たとえば多くの FPGA は乗算器をハードブロックとして備えており、"assign x = a * b;" のような演算を高速なクロック周波数で実行できます。
ただし、こうした乗算器の正確な仕様は異なることがあります。ある FPGA では、この乗算器ブロックのオペランドは 18 ビットの符号付き整数です。つまり、この幅以下のオペランド同士の乗算は、オペランドの一方が 19 ビット幅になるときよりもはるかに高いクロック周波数で動きます。これも、FPGA のロジックブロックを知ることがなぜ重要なのかを示す例です。たった 1 ビット余分なだけで、クロック周波数がかなり下がりえます。別の FPGA ファミリでは、オペランド幅が違うまったく別の話になることに注意してください。
配線リソースも重要です。ロジック要素は話の半分にすぎず、それらをつなぐ配線が残りの半分です。配線が混雑して遅くなるために、設計がクロック周波数に到達できないことはよくあります。これは、FPGA をロジック容量のほぼ 100% まで使うつもりで、設計に幅の広いデータバスをたくさん持つ場合に考えておくべきことです。FPGA 内の配線リソース(「ワイヤ」)には速いものもあれば遅いものもあります。速いものが使い果たされると、設計全体が遅くなります。
FIFO と BRAM も理解しておくべきです。これらは FPGA 内部のメモリリソースで、データの保存やバッファリング、クロックドメイン (clock domain) 間の受け渡しなどに常に使うことになります。FIFO の扱い方を知っているのは基本中の基本です。このサイトにはこのテーマに関する連載ページがあります。
クロックリソースはそれ自体が小さな宇宙です。PLL、クロックバッファ、そしてグローバルおよびリージョナルなクロックネットワークです。PLL は、入力クロックをロジックが実際に必要とするクロックに変換する部品です。周波数を逓倍・分周し、位相シフトも可能にします。どのクロックが位相の揃ったものか、そうでないかを知ることも重要です。たとえば、PLL が 2 つのクロックを出力し、一方が他方の 2 倍の周波数だとします。最初のクロックで動くレジスタが、2 番目のクロックで動くレジスタの出力をサンプリングするのは安全でしょうか。たいていは安全ですが、その 2 つのクロックの位相が揃っているかどうかによります。ただし、本当にそうなっているかを確認する方法を知っていなければなりません。このサイトにはこのテーマを扱ったページがあります。
次に I/O ブロックのリソースです。DDR や SERDES のような高速な I/O 信号を扱う設計では、I/O ブロックが何をしてくれるのか、そして設計のクロック周波数よりはるかに高いデータレートでの I/O をどう実現するのかを理解する必要があります。終端を追加してインピーダンス整合 (impedance matching) を助けたり、その他の低レベルの電子機能を担ったりするように設定することもできます。
そして、1 秒あたり 1 ギガビットを超えるデータレートが必要なら、マルチギガビットトランシーバ (MGT) の出番です。これは比較的高度で複雑なテーマで、特定のプロジェクトで必要でない限り、初心者向けではありません。このサイトにはこのテーマについての連載ページもあります。
最後に、少し退屈なテーマを 1 つ。コンフィギュレーションメモリとビットストリーム (bitstream) のロードです。設計が終わったからといって、毎回コンピュータから FPGA にビットストリームをロードしたいとは思いません。そこで、FPGA はフラッシュメモリから自分でロードできます。SD カードからでもかまいません。あるいは、基板上の別の部品がビットストリームを FPGA に押し込むこともできます。基板上に別のプロセッサがあるときによく選ばれる方式です。
FPGA をロードする技術に楽しいところは何もありませんが、小さなチームで働いているなら、これもあなたの担当になります。そして、基板の電源投入後どれだけ早く FPGA が起動するかという要件があることもよくあります。それを解決するのもあなたの仕事です。
このテーマに気をつけるべきもう 1 つの理由は、とくに評価ボードでは、電源投入時に FPGA がフラッシュメモリから自動的にロードされることが多いからです。さらに厄介なことに、FPGA ボードにはビットストリームをロードできるメモリソースが複数あることもよくあります。自分のプロジェクトの古いバージョンが FPGA にロードされていることに気づかないと、非常に長いデバッグにつながります。設計にどんな変更を加えても FPGA の動作が変わらないのは、毎回間違ったフラッシュメモリを更新しているからです。
タイミング
まず、タイミングとは何か(ロジック設計の文脈における話)を短く説明します。手短に言えば、FPGA の内外を問わず、すべてのデジタル信号は特定の時間幅のあいだ、通常はクロックエッジとの関係において、電気的に安定していなければなりません。そうでなければ、ロジックの動作は予測不能になります。開発ツールは、必要な箇所でこれらのタイミング要件が満たされるようにしてくれます。ただしそのためには、私たちがこれらのツールに具体的な情報を与え、しかも非常に正確に与える必要があります。加えて、ロジック設計そのものも、ツールがタイミング要件を満たせるような作り方でなければなりません。これがタイミングの話の要点です。
タイミングは、おそらく FPGA 設計者にとって最も難しい部分です。同時に、本当にマスターしてきちんと実装すべき最も重要な領域でもあります。残念なことに、このテーマをおろそかにしても、かなりうまく動く設計、あるいはもう少しで完成しそうに見える程度の設計は簡単にできてしまいます。すべて順調に動いているのに、満月の夜に突然故障を引き起こす超自然的な力が FPGA の中に潜んでいるように見えるのです。私はこの考え方を「黒魔術モード」と呼んでいて、それについての別のページがあります。
運が良ければ、タイミングを意識せずに書かれた FPGA 設計も、いくつかのタイミング制約を追加するだけで簡単に直せます。しかし、ほとんどすべてをゼロからやり直さなければならないこともあります。正しいタイミング要件を適用すると、開発ツールが要求されたクロック周波数で動かせなくなるからです。その場合は、Verilog コードそのものを書き直す必要があります。
そして本当に運が悪いと、PCB の一部を設計し直す必要が出てきます。基板上のすべての物理信号が、安定していなければならない時間枠の中で安定した電圧を持つことを保証できなくなるからです。PCB の量産承認前にきちんとタイミング解析をしていれば明るみに出たはずですが、それを怠ると、ハードウェアがその仕事に耐えられないかもしれません。
しかし、タイミングを慎重かつ正確に扱えば、FPGA は世界で最も信頼できる部品になります。多くの FPGA 設計者が、設計にわずかな変更を加えるのを恐れ、新ロットの FPGA チップが生産で使われるたびに怯えています。FPGA が少し温まると大変だと、おかしな冷却を施したりします。私が言いたいのはこうです。タイミングをきちんとやれば、心配事はすべて忘れてかまいません。
これを初日から完璧にマスターする必要があるのでしょうか。私はむしろ、はいと言いたいです。原則として、FPGA 設計者のチームの中で 1 人だけがタイミングに本当に詳しければ十分だという意見に賛成です。その 1 人になりましょう。理由は単純です。他の誰もそうならない可能性が高いからです。
このウェブサイトにはタイミングについてのかなり長い連載ページがあるので、ここで細かく説明するのはあまり意味がありません。ですから、すべての FPGA 設計者が慣れ親しんでおくべきだと私が思うテーマを簡単に列挙しておきます。
- 伝搬遅延、tsu、thold
- タイミング制約の書き方:周期制約、無関係なクロック (unrelated clocks)、タイミング例外、フォルスパス (false path) など。
- タイミングレポートの読み方:セットアップ、ホールド、スラック (slack)、クロックドメイン間の相互作用、クリティカルパス (critical path)。
- 4 コーナーのタイミング解析
- クロック周波数とジッタ (jitter)、およびタイミングクロージャに対するジッタの影響、ロック外れ、不十分な信号のサンプリング (sampling)、PLL 内でのジッタの伝搬(設計に MGT があれば、ジッタによる MGT の劣化も)。
- クロックリソース:クロックバッファ、クロック分配ツリー、クロック・スキュー (clock skew)、PLL がクロックツリーの遅延をどう補償するか、など。
- クロックドメイン間の受け渡し (clock domain crossing)。これについては専用の連載ページがあります。
エレクトロニクス
FPGA は電子デバイスであり、FPGA 設計は電気工学の中の 1 つの専門分野です。そして、回路図やデータシート、電圧と電流、信号品質、インピーダンス整合を扱う種類の電気工学です。これはすべての PCB 設計者が持っていなければならない知識であり、FPGA 設計者も同じ知識があれば、仕事はずっと楽になります。
FPGA 設計者が、FPGA が基板上の他の部品と正しくインターフェースすることを保証する役割を割り当てられるのはよくあることです。実際、PCB 設計者が、これらの部品を動かす責任から逃れるために、つなげられるものは何でも FPGA につなぐというのも珍しくありません。そのため FPGA 設計者には、PCB 上で部品同士がどうインターフェースするかについて深い理解が求められることがよくあります。高周波で切り替わる配線で対処が必要な信号品質の問題を指摘しなければならないのは、たいてい FPGA エンジニアです。
新しい PCB を設計するときには、通常、チームの FPGA 設計者がその設計を承認すること、つまり FPGA への接続が正しいかを確認することが求められます。すべての FPGA ピンがすべての用途に適しているわけではなく、特定の接続が FPGA ピンの特定のグループ(バンク)に属することが必須だったり、大幅に望ましかったりすることもあります。これらは FPGA 設計者がマスターすべきこと、少なくとも確固たる意見を持つべきことです。
FPGA 設計者が元 PCB 設計者であることは珍しくありません。基板設計から FPGA 設計への道は自然なもので、そこを歩いてきた人には明らかな強みがあります。たとえ PCB 設計者が責任を持って完璧な基板を設計したとしても、FPGA 設計者は FPGA の I/O ブロックを適切に設定するために、PCB 上の高速信号が抱える難しさを理解している必要があります。
先にも述べたとおり、すべての FPGA エンジニアがエレクトロニクスを直接扱うわけではありません。なかには、私が「処理ロジック」と呼んだ内部ロジックの開発だけを担当する人もいますし、シミュレーションと検証だけを行うためにエンジニアを雇う企業もあります。しかし、私たちのほとんどはエレクトロニクスを直接扱う仕事をしており、その場合は関連する知識がいくつか必要になります。
まずはごく基本からです。電圧、電流、抵抗、オームの法則。これがデジタル信号がある部品から別の部品へ移動する仕組みです。静電容量と、コンデンサがどう充電・放電されるかを理解しておくのも良いでしょう。そうすれば、電流と静電容量がスイッチング速度と消費電力にどう影響するかを理解できます。
回路図を読めるようになるべきです。IC、モジュール、インダクタ、電源、デジタルグラウンドとアナロググラウンド。MOSFET やバイポーラトランジスタもときどき登場するので、少なくとも見分けられるようにしましょう。MOSFET トランジスタがどう振る舞うかを知っておいて損はありません。
データシートを読むのにも多くの時間を費やすことになります。最も難しく重要なのは、データシートのタイミング仕様を、タイミング制約や FPGA 上の適切な I/O 設計に翻訳することです。基板スキューは、I/O タイミングで考慮に入れる必要があるかもしれません。
さらに、データシートの電圧・電流仕様を読み解き、FPGA の該当する I/O ブロックを正しい電圧規格で設定する責任もあります。シングルエンドと差動のインターフェース、LVCMOS、SSTL、LVDS などです。
すべての FPGA 設計者が本当にこれをきちんとやっているのでしょうか。答えはノーです。電子回路的な不手際でまったく動かないはずの設計が、完璧に動いているように見える、というのはよくあります。ある部品の出力ピンが、別の部品の入力ピンに、絶対最大定格を超える電圧を供給していることも珍しくありません。もちろん大間違いで、データシートに従えば、過大な電圧を受けた部品はいつ焼き切れてもおかしくありません。それなのに、すべてが永遠に動き続けます。そして突然壊れ、賢い人たちが、なぜそうなったのかについてくだらない言い訳を見つけ出すのです。
間違いなく PCB 設計者の責任であるテーマも、短く列挙しておきます。ただし、その人があまり優秀でない場合には、FPGA エンジニアもこれらについて多少理解していると助けになります。
- 電源と電圧レギュレータ。
- クロック発振器、リファレンスクロック、ジッタ。
- 信号品質:インピーダンス整合と終端、反射、クロストーク、EMI。
- 熱の考慮。
では、FPGA 設計者はこのすべてから実際に何を知っている必要があるのでしょうか。最初から何が決定的なのでしょうか。正直なところ、私にもはっきりとは言えません。周りにより良いチームがいればいるほど、必要なエレクトロニクスの知識は少なくなります。ただ、どの FPGA 設計者も回路図を読め、FPGA に何が接続されているかを理解でき、なぜその特定の方法で接続されているかを多かれ少なかれ理解できるべきだと思います。