Super Sample Rate データ向け FIR フィルタ DSP Builder モデル(Mealy Machine 変形)解説

####(はじめに)
本記事は、先に投稿した記事「Super Sample Rate データ系列向けの FIR フィルタを Mealy Machine の変形で作ってみた」で作成・確認したモデルの内容や Simulation 結果の説明です。
DSP Builder (for Intel(R) FPGA) と Simulink オリジナルブロックのそれぞれで構成しています。モデルベース開発を行う方の参考になれば幸いです。

##### (モデルの主要部分の構成: DSP Builder)
もう少し詳しくモデルの構成を説明します。
![MSSR_Core.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/3004f080-3dfe-bb26-e820-aee95e093742.png)
これが DSP Builder (Advanced) で作った Super Sample Rate 向け FIR フィルタです。前後の濃い青色のブロックが ChannelIn と ChennelOut ブロックで、これで挟まれた部分がパイプライン挿入の対象になります。
３本信号が通っていて、valid, channel, data で時分割処理などが表現しやすくなっている様です。（今回は valid=1, channel=0 に上位階層で固定して入力しています）
一番下の data 信号（入力ポート名は "xr"、出力は "zr"）を要素 4 のベクトルにして　Super Sample Rate データを持たせています。真ん中の MSSR_FIR Subsystem ブロックが N=4 段の本体部分です。内容は後述します。
右下の薄青の "1L latch" が D-FF での実装を想定したレジスタです。
入力側の "0L latch" は無くても正しく動作するはずですが、レート調整用に valid=0 が時々入る様な使い方の場合に無効出力がトグルする事を防止します。

##### (モデルの主要部分の構成: Simuink)
並行して Simulink のライブラリのみで同じ Super Sample Rate の FIR フィルタを表現しています。下記がその同じ階層の構成になります。
![Simulink_MSSR_Core_Mask.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/cd6cdfef-ba0b-6585-625d-6dec8c30654b.png)
上の遅延値 16 の Sample Delay は遅延合わせ用ですので無視して構いません。
後述の様に、本体部分 "Simulink_MSSR_FIR の構造はほとんど DSP Builder の場合と同じに作っています。
ステージ数 N=4 は、ベクトルサイズの伝播ではなく、設定ファイル setup_super_mealy_fir.m で定義している dspb_fir.super_ratio =4 を参照させています。

##### (モデルの主要部分のコアの構成)
DSP Builder の場合も Simulink の場合も、組み合わせ回路(扱い)の部分の N=4 段構成は同じ構造の Subsystem を作っています。Subsystem にマスクを設定してステージ数 N (= Super Sample Rate) を設定する様にしています。
その (Simulink_)MSSR_FIR Subsystem ブロックの内部は下記の様になります。
![MSSR_4Stages.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/ea58d158-0d2a-2de4-3cea-60aafed864e5.png)
本記事では詳細は説明しませんが、ブロックのマスクの仕組みの「初期化」を M 言語で記述することによって、設定した Stage 数 N 段だけ下位の SVFIR_STAGE(_n) Subsystem をカスケード(縦続)接続する描画とステージ番号設定を行わせています。
詳細は下記記事をご覧ください。

https://qiita.com/rtl_modeler/items/42b702344d055da5c4a9

シフトと積和演算を１段分行う SVFIR_STAGE(_n) Sybsystem の内容は下記になります。
係数＋積和演算の個所は図は DSP Builder の場合ですが Simulink の場合もここだけ Gain ブロックでベクトルに対する行列ゲインに置き換えて表すことができます。
他の部分は両者共通で使える MUX/DEMUX ブロックで構成しています。


![SVFIR_STAGE.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/0a197614-42f3-dfe9-2d5c-ee8ca4a211e7.png)

入出力を下記信号でそろえて縦続（カスケード）接続を表現しやすくしています。
➀ 入出力ポート SVI-SVT ：全体の入力のスルー（入力ベクトルを分配）
➁ 入出力ポート PST-NST ：実際に多段処理される部分（状態の遷移関数の多段化）
➂ 入出力ポート RVI-RVO ：積和演算結果を出力用に積み上げる（出力ベクトルの形成）

出力にダミーが含まれるなど、冗長なところもありもう少しまとめた表現が出来そうですが、入力側と出力側をまとめると疑似的なループにでもなるのか処理がうまくいかないケースがあったのでこの表現にしています。出力のダミー部分は FIR 部分の出力側で捨てています。(Terminator ブロック)

ステージ対応の入力(スカラー)を入力ベクトルから取り出す VectorMuxConstant ブロックは内部構成は下の図の様になります。
最近の version の DSP Builder では同機能の Simulink ブロック "Selector" がサポートされている様ですが、自分が使っている version (18.1 Standard) では対応していない様ですので、MUX/DEMUX ４段構成で作ってみました。
![VectorMuxConstant.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/5aedae3a-f0d5-6348-5ff7-9502c9b00f8f.png)
ステージ番号は expos → sel というマスクパラメータ名で下位階層に引き継がれてきます。
マスク初期化の(再)描画はせずにパラメータの表現でうまく作ろうと思うと、ベクトルの端の要素を取り出す場合、最後の DEMUX の３分岐が２分岐にならない様ダミーが必要になり、こんなトリッキーな構成になっています。入力を３つ連接する初段の MUX は不要にも思えますが、ベクトルのサイズが 1,2 の場合も対応するには必要になってきます。
（これを考えるコストが、元記事の背景の所で語ったインデックスを頑張る面倒くささと大差ない、という見方もあるかもですが、問題を局所化できる価値はあるとしてください）
![VecotrShift.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/18f99563-c4e6-498f-7b3d-6365c675c0cc.png)
シフト接続の表現は上の図の様になっています。
ベクトルのサイズは場合によっては継承でもいいのですが、ループがあるため上手く決まらないケースを回避するために、Workspace 変数 dspb_fir.n_tap の値から計算させるようにしています。

#### (トップ階層とシミュレーション）
モデルのトップ階層とシミュレーション結果を説明します。
トップ階層の構造は下記の様になっています。赤色信号が４倍速、緑色が1倍速です。（例: 1.2Gsps, 300Msps)
FIR フィルタは LPF の特性にしていますので、入力は分かりやすい Chirp 波形(または Sweep 波形、周波数が徐々に変化する正弦波)を生成し、４倍速→１倍速の Super Sample Rate 信号にしています。真ん中に縦並びで、上から DSP Builder のハードウェア化対象デザイン、Simulink の同等構成部分、最下段に４倍速のまま単純構成の FIR フィルタ計算を行う Simulink モデルの FIR フィルタを配置しています。右側の出力信号は、遅延合わせをして波形の差分を取ったり、重ね合わせたりして Scope で確認する様にしています。

![Top_super_mealy_fir.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/8af5c85d-bdf2-14b1-3e8a-51c53fd789f5.png)

入力信号の生成部分と Scope 波形を拡大してみますと下図の様になります。

- 上段：４倍速サンプルレート、離散化した Chirp 波形
- 中間：４倍速サンプルレート、遅延してベクトル化したもの
- 下段：１倍速サンプルレート、上記を Down Sampling したもの

![ChirpInWave.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/5de94748-2bf9-1d57-6a50-b05c5a86ade2.png)
元の Chirp 信号(4倍速)を 1倍速で 4 並列にして、情報(サンプル値系列)は過不足なく伝わることが分かります。入力の波高は 1 固定になっています。

出力波形は下記の様になります。遅延を合わせ、1倍速(x4 Super Sample Rate 信号)を４倍速に戻して重ね合わせ及び差分を確認しています。（遅延は DSP Builder モデルでは仕様やターゲットデバイスに応じて変化します。ChannelOut ブロックに表示されます。）
![OutWaveCompare.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/9cde8c41-62ea-0e5e-1a6a-0dd2310d7f69.png)
Chirp 信号の低周波の部分のみ通過していること、最下段の Simulink の単純表現との誤差が確認できます。DSP Bilder のほうは計算の誤差が入るのか 10^-7 程度の誤差があります。単精度浮動小数点数で仮数部が 24 bit ですので、LSB 程度で妥当な値と考えられます。

##### (動作確認用ダウンスペックモデル)
MAX10 10M08 評価キットで動かすためのダウンスペックしたモデルのメイン部分は下記になります。入出力を固定小数点数 16bit とし、計算を 16bit 半精度浮動小数点数としたので入出力付近に Convert を置いています。
Super Sample Rate のレート比も N=2 に落としています。

動作確認環境や Signal Tap II での確認結果は元の記事をご覧ください。

![EVKIT_half_dspbcore.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2270053/23079639-fc20-6b56-ad6b-e9eba68b41b7.png)

#### (まとめ)
Super Sample Rate データ系列向けの FIR フィルタを Mealy Machine の変形で作り、構成を説明しました。
組み合わせ回路対応部分をカスケード接続する為、マスクの初期化でモデル描画を行って変更にも自動的に対応する様にしています。
MUX/DEMUX を使ってシフトやベクトルからスカラーデータの取り出しを表現しています。

#### (参考：元の記事と設定スクリプト）

https://qiita.com/rtl_modeler/items/05d020b6ad6e9c0c006c

```matlab:setup_super_mealy_fir.m
dspb_fir.clock_rate  = 200;
dspb_fir.sample_time = 4;
dspb_fir.n_tap       = 9;
dspb_fir.coef        = fir1(dspb_fir.n_tap-1, .3); % fir1(dspb_fir.n_tap-1, .4);
dspb_fir.super_ratio = 4;
```