HDL CoderはSimulinkモデルからFPGA/ASIC実装するためのVHDLまたはVerilogを生成します。 ほとんどの場合、浮動小数点演算でアルゴリズム開発を始めると思います。 一方、ハードウェアリソースは、固定的なものです。 それゆえ、ハードウェア実装する最も効率的な方法は、すべてを固定小数点に変換することでした。 固定小数点化すると、実現が簡単になります。 しかし、要求精度を満たしながら、最小のビット幅に変換するのは非常に時間がかかり、何度も修正する必要があります。
オプションFixed-Point Designerは、固定小数点化するためのガイド機能と、設定の自動化機能を提供しています。
しかし、場合によっては固定小数点化が難しいデザインがあります。たとえば、FPGAをターゲットにして、この単純な数学関数を実装したいお客様がいました。 この関数は高いダイナミックレンジを持っています。つまり、ある演算では、小数部に多くのビットが必要となり、他の場合には整数部に多くのビットを必要とするため、沢山のビットを使用せずに、ビット幅と小数点を固定することは困難です。
これをハードウェアで実装するために、お客様は固定小数点への変換を試しました。このプロセスでは、デザインを少し変更する必要がありました。
1. ビット幅を細かく調整するには、除算を逆数と乗数に分割する必要があった
2. データ型を伝搬するブロックを使用して、ビット幅が大きくなるのを抑制して、除算演算を64ビット以下に留める必要があった
3. 分子および分母の設定にデータ型変換ブロックを使用する必要があった
4. 加算器と減算器ブロックで、出力とアキュムレータのデータ型を注意深く調整する必要があった
5. 逆数演算を実現するために、ルックアップテーブルまたはニュートンラフソンアーキテクチャのどちらが適切か実験する必要があった
簡単な数学関数であっても、ダイナミックレンジが大きい場合、固定小数点への変換は簡単ではありません。
しかし、そのようなことを行わずに、浮動小数点で実装してハードウェアを構築することができればどうでしょう?
これはモータ制御系設計ではよくある問題ですので、Field Oriented Controllerのデザインの例をご紹介します。
前に見たように、浮動小数点実装のほうが適している演算があります。 例えば、フィードバックループ内の積分器のような、ダイナミックレンジが大きい、または未知のアルゴリズムです。 このFOCのモデルでは、オーバーフローを防ぐために飽和処理を追加する必要がありました。 また、atan2のように、固定小数点化が難しい演算も同様です。
このようなモデルからは、単精度浮動小数点から合成可能なHDLコードに直接変換して、あらゆる種類のFPGAやASICに実装することができます。 HDL Coderは、単精度浮動小数点モデルからベンダー依存しないHDLを生成します。対応演算器は画面のとおり広範囲でサポートされており、現在130以上のSimulinkブロックがサポートされています。 また、denormal / inf / nanなど、IEEE-754の全機能がサポートされており、広範囲の算術演算に対応しています。
HDL Coderは、浮動小数点モデルからどのようにして、ハードウェアを実現するのでしょうか? HDL Coderは、単精度データを32ビット整数に変換した後、IEEE仕様に従って符号、指数、仮数ビットに展開します。データをこれら複数のコンポーネントに分割して、固定小数点アルゴリズムとは異なる算術演算が実行されます。その後、すべてをもとに戻して、結果を単精度浮動小数点として出力します。キーポイントは、演算器の入出力は、IEEE仕様である32ビットで行われ、アルゴリズム自体は異なった演算処理を行うことです。小さいビット幅の固定小数点データ型の演算器を使用するほうが、浮動小数点データ型を使用するよりも効率的です。しかし、大きなダイナミックレンジが必要な場合は、浮動小数点のままにする方が簡単で効率的です。Simulinkモデルの一部のみを、浮動小数点でデザインすることもできます。例を見てみましょう。
このField Oriented Controllerのデザインでは、データ型がすべて単精度浮動小数点となっています。HDL Coderのプロパティには、グローバル設定の下に、浮動小数点ターゲットタブがあります。ライブラリの選択肢はここにあり、以前はFPGAベンダーのマクロライブラリにマッピングする機能を持っていましたが、それらは内部を見ることができないブラックボックスです。今回、ライブラリとして"Native Floating Point"が追加されましたが、HDLの処理内容を読んだりトレースしたりすることが可能です。また、カスタマイズ可能なオプションもいくつかあります。レイテンシ設定をして、HDLとそのテストベンチで使用することができます。ドキュメントには各演算器の最小/最大レイテンシ数がリストされています。非正規化処理のロジックを有効にすることで、より多くの回路面積を消費することは注意が必要です。さらに、仮数部の乗算手法のオプションを指定すると、1つまたは複数の乗算器リソースを使用して仮数部の乗算を処理したり、乗算器リソースを使用せずに処理したりすることもできます。
最適化設定画面にある、[リソース共有]タブを見ると、そこに浮動小数点演算器を共有するオプションがあり、デフォルトでオンになっています。また、HDL Coderでテストベンチを生成する場合、テストベンチが仮数部の最下位ビットの小さなビット誤差を無視するように、ULPエラーを指定するオプションがあります。 HDL Coderを実行してみましょう。
実行中、最適化についてもう少し詳しく見てみましょう。すべての最適化機能はネイティブ浮動小数点でもサポートされています。 最初の例はリソース共有です。これは2つの浮動小数点のSin関数演算の簡単な例で、リソース共有を有効にすると時分割多重できるので、2つの演算を1つのリソースで共有できます。
アルゴリズムレベルの共有機能はさらに強力です。 SinおよびCos演算の場合、基本的な偏角の削減演算は、両者の間で再利用できます。 このような最適化が様々提供されています。
固定小数点演算では、柔軟に設定できる利点がありますが、浮動小数点演算ではその点には欠けます。しかし、浮動小数点演算器のクオリティは非常に高く、高い精度を維持しながらも、高クロック周波数、低レイテンシ、小回路面積を実現できます。
有限のビットで無限大の実数を表現するには近似を行う必要があります。 この近似は、浮動小数点演算における丸め誤差を引き起こす可能性があります。 丸め誤差を規定するために、浮動小数点のスタンダードでは相対誤差とULP(Unit in the Last Plae)エラーを使用します。 表のとおり、HDL Coderの浮動小数点演算が示すULP値は、非常に高い精度を示しています。
HDL Coderの実行結果に戻ります。 レポートを見ると、リソースレポートにネイティブ浮動小数点セクションがあります。 各浮動小数点演算に使用されたリソースを確認することができます。 想定したとおり、浮動小数点演算ではリソースが若干大きくなります。
コードを見ると、32ビットの入力と出力があり、それらの信号は符号、指数、および仮数のコンポーネントに分割されていることがわかります。 下にスクロールすると、多くのFlipFlop記述が見えますが、これはターゲット周波数を満たすために自動的に追加されたパイプラインレジスタです。沢山のレジスタが追加されていますが、良い点は、関連したコードを確認できるところで、生成されたHDLとそのソースモデル間のトレーサビリティを取れることです。
リソースを削減したい場合は、固定小数点と浮動小数点を同じデザインで混在させることができます。 このモデルでは、主に16ビットの固定小数点を使用していますが、一部のSin/Cos演算にのみ浮動小数点を使用しています。これにより、近似計算を浮動小数点演算に置き換えることができます。 また、積分器のフィードバックループでも、小さな誤差が著しく拡大される可能性があるため、一部に浮動小数点を使用しています。 トレーサビリティを取ることができるので、コードの中のネイティブ浮動小数点演算器のインスタンスを見てから、リソースレポートを見ればどれだけ改善されたかを確認できます。
一般的に、固定小数点ロジックのほうがクオリティが良いと思われますが、高いダイナミックレンジでは浮動小数点のほうが良い結果を得ることができます。 この表は、さまざまなビット幅で生成した除算回路を比較しています。 オレンジ色で示す浮動小数点演算器は、ルックアップテーブルの使用率は高く、ロジックスライスの使用率はクロスするポイントがありますが、DSPスライスを使用せず、全体的により良いFmaxを得ることができます。
HDL Coderは、浮動小数点演算のオプションをいくつか用意しています。 ネイティブ浮動小数点は、その高い精度で様々なパラメータを設定して、ハードウェアに素早く実装できる点が優れています。 また、リソースの使用率を削減したい場合は、固定と浮動小数点のハイブリッドで、一挙両得の設計を行うことができます。 そして、高精度、高ダイナミックレンジの浮動小数点演算を行うHDL Coderのネイティブ浮動小数点は、業界標準のIEEE-754フォーマットで高品質な結果を得ることができます。