FPGAでのDSP
Q形式の固定小数点演算とDSPスライスから、FIR、IIR、CIC、FFT、CORDIC、そしてモデルベースツールと手書きRTLの選択まで、信号処理がFPGAにどうマッピングされるかを解説します。
概要
デジタル信号処理は、FPGAがそのために作られたワークロードです。500 MHzで毎サンプルに乗算と加算を必要とするフィルタは、プロセッサでは追いつけないループですが、数十個の専用乗算器を並列に動かせば追いつけます。このハブは、DSP理論をある程度知っていてそれがどうハードウェアになるかを見たいエンジニアと、フィルタ仕様を渡されたRTLエンジニアのためのものです。
技の核心は算術にあります。浮動小数点は大きく遅いため、FPGAのDSPではまれです。ほぼすべてが固定小数点で、作業とは、語長を選び、どこで丸めてどこで飽和させるかを決め、結果が理想に十分近いことを証明することです。
重要な考え方
固定小数点演算とビット成長
固定小数点数とは、暗黙の2進小数点を持つ整数です。Q1.15は整数部1ビット(符号)と小数部15ビットを意味し、値は整数を32,768で割ったものです。2つのQm.n数を加算すると結果は1ビット増えることがあります。Qa.bとQc.dを乗算するとQ(a+c).(b+d)の結果になるため、16×16の乗算は32ビットになります。多数の積を合計するフィルタはさらに、タップ数のlog2程度だけ増えます。したがって各段は出力を広げるか丸めて戻すかのどちらかであり、丸めはノイズを持ち込みます。切り捨ては安価ですが偏りがあります。四捨五入(round-half-up)は加算器1個です。収束丸め(convergent rounding)は偏りを取り除きます。飽和は比較器を要しますが、大きな入力を破滅的な入力に変えてしまう桁あふれ(ラップアラウンド)を防ぎます。MATLAB Fixed-Point Designer、明示的なスケーリングを使うPythonのnumpy、HLSの任意精度型といったツールを使えば、RTLに踏み切る前に量子化をモデル化できます。
DSPスライス
ミッドレンジ以上のすべてのFPGAにはハード算術ブロックの列があります。AMDのDSP48E2は27×18ビットの符号付き乗算器、プリアダー、48ビットのALUとアキュムレータ、各段のパイプラインレジスタを含みます。Alteraの可変精度DSPブロックは18×19または27×27の乗算を行い、Arria 10以降ではネイティブの浮動小数点モードを持ちます。Lattice、Microchip、Gowin、Efinixはアキュムレータ付きの18×18乗算器を持ちます。これらのブロックをうまく使うとは、ブロックが提供するパイプラインレジスタに合わせて乗算器を定格のフルクロックで動かし、専用のカスケードパスを通してアキュムレータを連結し、長いFIRでタップ間にファブリック配線が不要になるようにすることです。
フィルタ、変換、回転
FIRフィルタは、係数で重み付けした遅延サンプルの総和です。完全並列FIRはタップごとに1個のDSPスライスを使い、クロックごとに1出力を生成します。対称FIRはプリアダーによってそれを半分にします。時分割FIRは、サンプルレートがクロックレートよりずっと低い場合に、少数のスライスを多数のタップで共有します。IIRフィルタはフィードバックを使いパイプライン化が難しいため、通常は2次セクションにとどめます。CICフィルタは、積分器とコムだけを使い、乗算器をまったく使わずに大きな係数で間引きや補間を行い、ADC直後の標準的な初段です。FFTはパイプライン型またはバースト型のアーキテクチャでバタフライから構築され、すべてのベンダーがジェネレータを提供しています。CORDICはシフトと加算で正弦、余弦、振幅、位相、回転を計算し、乗算器なしでNCOや極座標・直交座標変換器を構築する方法です。段間でサンプルレートを変えるマルチレート設計が、算術を安価に保つ鍵です。重いフィルタは、標本化定理を満たす最低のレートで動かしてください。
モデルベース設計と手書きRTLの比較
AMDのSystem Generator for DSP(現在はModel Composerの一部)とAlteraのDSP Builderを使うと、Simulink上でビットトゥルーなブロックを使って信号フローを描き、RTLを生成できます。語長の探索には速く、MATLABで暮らしているチームには向いています。生成されたRTLはツールの外で保守しにくく、ライセンスは高価で、ブロックが最新デバイスに追いつかないこともあります。手書きのRTL、または固定小数点型を使ったHLSは、どのエンジニアにも読め、通常のバージョン管理フローに収まる設計を生みます。多くのチームはPythonやMATLABでモデル化し、その後RTLを手書きしてモデルに対してビットトゥルーに検証しています。
どこから始めるか
- /learn/beginner/03-combinational-logic-and-luts/と/learn/beginner/04-registers-clocks-and-state/で、加算器とパイプラインを身につけます。
- /learn/beginner/08-counters-timers-and-debouncing/は、NCOになるアキュムレータを構築します。
- /learn/beginner/09-memories-block-ram-and-fifos/は、あらゆるフィルタにある遅延線と係数メモリを扱います。
Python製ゴールデンモデル付きの固定小数点FIR、CIC間引きフィルタ、CORDIC NCOに関する中級レッスンは準備中です。
ツールとベンダー
| ベンダー | ハード乗算器 | フィルタ・FFT IP | モデルベースツール | ハブ |
|---|---|---|---|---|
| AMD | DSP48E2(27x18)、DSP58(27x24、Versal) | FIR Compiler、FFT、CORDIC、DDS | Model Composer、Vitis HLS | /vendors/amd/ |
| Altera | 可変精度、ネイティブFP32 | FIR II、FFT、CORDIC | DSP Builder | /vendors/altera/ |
| Microchip | Mathブロック 18x18 | CoreFIR、CoreFFT | なし | /vendors/microchip/ |
| Lattice | sysDSP 18x18 | IPカタログのFIR、FFT | なし | /vendors/lattice/ |
| オープンソース | Yosysが推論 | 手書きRTL、Amaranth、SpinalHDLのライブラリ | Pythonモデル | /vendors/opensource/ |
よくある間違い
- モデルに対して量子化ノイズをシミュレーションせず、当て推量で語長を選ぶ。
- 長い累算を切り捨てておいて、DCオフセットに首をかしげる。
- パイプラインレジスタなしで合成ツールに乗算器を推論させ、DSPスライスが定格の半分のクロックで動く。
- パイプライン化できない長い組み合わせフィードバックパスを持つIIRフィルタを書く。
- CICと間引きを使えば10倍遅く動かせるのに、ADCレートでフィルタを動かす。
- モデルが浮動小数点だったからという理由で浮動小数点を使う。
さらに深く
- AMD UG579, UltraScale Architecture DSP Slice: カスケードと丸めモードを含むDSP48E2の完全な解説。
- AMD PG149, FIR Compiler: ジェネレータが行うすべてのFIRアーキテクチャ選択を示します。
- Hogenauer, “An Economical Class of Digital Filters for Decimation and Interpolation”: 1981年のCIC論文。
- Andraka, “A Survey of CORDIC Algorithms for FPGA Based Computers”: FPGA向けCORDICのリファレンス。
- Harris, Multirate Signal Processing for Communication Systems: ハードウェアを念頭に置いたマルチレート設計の標準的な書籍。