« 基板チョコレートを作りました! | トップページ | FIRフィルタの実機テスト »

2017.02.02

XILINXのCoreGenでFIRフィルタを作る

FIRフィルタというのがあります。乗算と加算を繰り返してLPFやHPFを作るディジタルフィルタの代表的なやつです。

で、XILINXユーザなら、CoreGeneratorを使ってディジタルフィルタを簡単に作れるはずなのですが、使い方や精度がよくわからないのでシミュレーションしてみました。

結果としては、XILINXのFIRフィルタは25bit精度の計数が利用できて、レートの変換も自由自在という素晴らしいものでした。

sun

FIRは、入力と、遅延させたものにいろいろな係数をかけて積和したものです。

原理的には、こういう回路なのですが、

Fir1

これを真面目に作ると和の部分が非常にたくさんの値を足し算しなければならないので、大変なことになります。

そこで、いろいろなアーキテクチャが用意されています。

sun

フィルタの型

まず、Transposed Direct Formというアーキテクチャです。乗算と遅延の順序が逆になっています。これなら加算が重くならないので楽にできそうですね。

Fir3

デフォルトは、Systolic Multiply-Accumulate(シストリック:収縮の意味)というアーキテクチャになっています。SystolicなFIRというのは

Fir2

という構造をしています。上側の遅延が2段になっていて、下側の遅延が1段です。

他にはSerial Distribute Arithmetic型というのもあるそうですが、詳細は割愛します。

実装する型は、この画面で選択できます。

Fir4


それぞれの型でどういう利点があるのかを調べたところ、基本的にはSystolic型が最も優れていて何でもできます。

FIRはたくさんの乗算器を使います。FIRの計数は対照的な形をしていることが多いのですが、Systolic型を選べば対称性を利用してフィルタの次数の約半分の数の乗算器で実装できます。Transpose型では、対称性を利用した乗算器の削減ができないようです。

sun

フィルタの計数

CoreGenのFIRの画面で、最初に入力するのがフィルタの計数です。ここに入れる値で、次数と、ビット演算の精度が決まります。

フィルタの計数というのは、こういう感じの数値です。sync関数にしておけば、それなりのLPFが作れます。下の図は0.19ωcがカットオフのsinc関数です。

Fir6

上の図は41次のFIRのものですが、シミュレーションしていてよくわからなくなるので、動作テストのために中央の7個の数字だけでやってみます。

値を32767倍して、

Fir5_2

こんな感じです。すると、画面左側に周波数特性が表示されます。

Fir7_2

なんとなく、0.19のあたりでカットオフになっていますね。

この係数を入力したら、その係数の絶対値をすべて足してみてください。17858+25520+30856+32767+30856+25520+17858=181235なので、これを表現するには18bit必要です。

CoreGenは入力信号数+18bitの内部精度で演算しようとします。入力が16bitなら生の出力は34bitになります。(※切り捨てたり丸めたりして必要なビット数だけを取り出すオプションはある)

また、7シリーズの乗算器は18bit×25bitなので、計数の精度をケチっても、大きくとっても、コストは一緒です。25bitまでは乗算器のコストは追加でかかりません。また、加算部分のビット数は(たぶん)48bitあるので、そう簡単に溢れることもありません。

必要な乗算器の数=係数の数ですが、対照的にすれば約半分になります。(奇数のときには(次数+1)/2になる)

重要なことは、

  • 計算は整数で行われる。精度落ちしない。出力のときに切り捨てられる。
  • 係数の絶対値の総和を入れるのに必要十分な精度が自動的に選択される
  • 係数を25bit精度まで高めてもコストはかからない
  • 係数を対称的にすると、乗算器の使用量が約半分になる
  • 内部の演算精度を上げてもコストはかからない

です。

乗算器の数が増えないように注意しながら係数の精度を上げていったほうが良いでしょう。

sun

係数の動的変更

XILINXのFIRの素晴らしいとことは、係数を動的に変更できるところです。基本的には、coef_ldを'1'にすると係数受け入れモードになって、coef_weを'1'にしたときにcoef_dinが書き込まれます。

Use Reloadable Coefficientsをチェックすると、この機能が使えるようになります。

Fir8

注意しなければならないのは、最初に入力した係数を「対称的」にして、Coefficient StructureをInffered(推論)にすると、乗算器を減らしたアーキテクチャで作られてしまいます。こうなると、非対称な係数のフィルタにはならなくなります。

どんな係数でも再設定できるフィルタを作るには、Coefficient StructureをNon Symmetricにしておきます。もちろん、Non Symmetricにしておいて実際には対照的な係数を設定しても問題ありません。

また、Reloadableにすると、演算精度は入力ビット数+係数のビット数+log2(次数)になります。7次のFIRで、入力ビット数が16bit、係数が16bitなら、35bitになります。つまり、オーバーフローすることはありません。

係数を動的に変更するときのシミュレーション波形はこんな感じです。

Fir9_2

なお、係数はフィルタの次数の数だけ入れます。今回は7次のFIRなので、

17858,25520,30856,32767,30856,25520,17858

と7個分の値を入れています。この値は後ろから入れます。つまり、この7個の数字はa(6),a(6),a(5),a(4),a(3),a(2),a(1),a(0)と解釈されます。

対称フィルタにした場合は、a(3),a(2),a(1),a(0)の順に中央の値から順に入れます。対称フィルタの場合は係数の数が少なくなるので注意してください。

sun

演算の確認

それではインパルス応答を入れてみましょう。

ずっと0の信号を作って、ある1クロックだけ32767の信号を入れてみます。

11クロック遅れて、FIRの計数の値がそのまま出てきました。

Fir10

もちろん、どんな値を入れてもオーバーフローはしません。十分なビット精度が確保されているためです。

sun

FIRの計数はどうやって作ればいいのか

Excelを使ってSinc関数を作り、それを適当な係数をかけて整数にすればよいでしょう。

Fir11

上の表の計数だと、0.19ωcに設定してあって、特性は下の図のようになります。

Fir12

Reloadableにすると、係数が17bit精度、41タップ(6bit分)なので、39bitの精度が必要になります。

係数固定ならば、係数の絶対値の総和が299628で19bit必要になるので、35bitの精度となります。

この35bitという精度は、絶対にオーバーフローしないような安全なビット幅なので、実際に出力される値は3FFF8000程度が最大値になります。したがって、計算結果の下位19bitを切り捨てると、かなり小さな値しか出てこないことになります。

したがって、通常想定する大きさのパルスが入力されたときの最大値をあらかじめ見当を付けておき、途中の何ビットかを取り出すようにしないと、勿体ない結果となってしまいます。

このあたりは今後追求していきたいと思います。

sun

まとめ

  • 演算は整数で行われる
  • 演算結果を単純に切り捨てると、普通は結果がかなり小さくなる
  • 係数は25bitまではコストの増加はない
  • 対称的なSystolicフィルタがお得
  • Reloadableにするときには、フィルタの型によって係数を入れる順序が変わる。
  • Reloadableにすると、演算精度がオーバーフローしないように増える。

|

« 基板チョコレートを作りました! | トップページ | FIRフィルタの実機テスト »

コメント

コメントを書く



(ウェブ上には掲載しません)




« 基板チョコレートを作りました! | トップページ | FIRフィルタの実機テスト »