ポリフェーズフィルタの設計とFPGAへの実装

## ポリフェーズフィルタ（Poly Phase Filter）とは
信号処理、通信システムなどにおいて使用されるFIRインターポレーションフィルタやFIRデシメーションフィルタを[FPGA](https://jp.mathworks.com/discovery/fpga.html) やASICに実装する際に、ポリフェーズフィルタとすることで、フィルタの回路規模、消費電力などを削減できます。

MATLAB + DSP System Toolboxに、ポリフェーズフィルタへ係数変換機能があったので、それを使用して設計を行い、HDL Coderでコード生成を行ってFPGA実装を行ってみました。

##ポリフェーズ分解
どのように係数変換が行われるかは、こちらの記事「[ポリフェーズフィルタの基本を知る](https://edn.itmedia.co.jp/edn/articles/1009/01/news112.html)」に仕組みが書いてあるので参照してください。

## FIRデシメーションフィルタからポリフェーズフィルタへの係数変換
MATLAB + DSP System Toolboxでデシメーションフィルタの設計は以下のようにして行いました。

```matlab:decimFilterDesign.m
Fpass = 0.45;  % Passband Frequency
Fstop = 0.55;  % Stopband Frequency
Apass = 1;     % Passband Ripple (dB)
Astop = 60;    % Stopband Attenuation (dB)

h = fdesign.decimator(4, 'Lowpass', 'fp,fst,ap,ast', Fpass, Fstop, ...
    Apass, Astop);

Hd = design(h, 'equiripple', ...
    'MinOrder', 'any', ...
    'StopbandShape', 'flat', ...
    'SystemObject', true);

```
上記を実行すると間引き数４のデシメーションフィルタが設計されます。
>
> Hd = 
>   dsp.FIRDecimator のプロパティ:
> 　
>     DecimationFactor: 4
>      NumeratorSource: 'Property'
>            Numerator: [-0.0024 -0.0021 0.0068 0.0167 0.0111 … ]
>            Structure: 'Direct form'

この係数Hd.Numeratorをポリフェーズフィルタの係数に変換します。

```matlab:
ppCoef = polyphase(Hd)
```
ppCoefは4x12の行列データ（4 = デシメーションファクター）となって出てくるので、これを複数のフィルタブロックの係数パラメータとして設定します。

## フィルタ特性の確認

次のコマンドを実行してポリフェーズフィルタの周波数特性や係数情報などを確認します。

```matlab:
polyphase(Hd);
```
こちらはポリフェーズになった4つのフィルタ特性
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/f2989c80-58cd-d2ad-ee23-8b67078eec20.png)
4つのフィルタを並列接続すると、下図のポリフェーズ化する前のデシメーションフィルタの特性になります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/c8f6212a-3077-65f6-e33f-d5e5dc42fff1.png)


## シミュレーションモデルの作成と動作確認

モデル全体は下図のようにチャープ信号入力、リファレンスモデル（FIRデシメーション）、ポリフェーズフィルタを比較できるように作成しました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/e757c22d-16e0-a8a1-6fb5-fb67de2f4c37.png)

トップモデルでReferenceサブシステムとなっているのが下図のリファレンスとなるFIRデシメーションフィルタのモデルです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/aa0404c1-67ce-a441-fb4f-aa3b2962b31c.png)


フィルタの係数パラメータはdecimFilterDesign.mで計算した係数データが代入されています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/3cf2e65b-b76c-eddd-191a-22e69b41858b.png)


下図がポリフェーズフィルタのモデル。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/124f4bbd-235f-a3bd-f51b-c12e2f32f2bd.png)

フィルタ係数はpolyphase関数で計算したポリフェーズフィルタの係数を、各フィルタで各行の係数を代入して使用しています。パラメータCoefficientsの値を ppCoef(1, :) とすることで、4x12行列データ ppCoefの1行目のデータだけがパラメータとして定義されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/81f77659-57cf-d12d-8615-fbf382dbdf0f.png)


入力信号を1サンプルずつ遅延させた信号を4倍（デシメーションファクター）Downsampleして、それをシングルレートのFIRフィルタに入力します。
ここで使用しているDiscrete FIR Filter HDL Optimizedブロックは、HDL生成用に最適化されたブロックで、実装効率も良いとのこと。ただし、フィルタのタップ数によってレイテンシが発生します。2つ目のフィルタ出力のみに接続されているDelayブロック（Delay_timing_adj）は、フィルタごとに異なるレイテンシのタイミングを合わせるためのものです。
 
<br>
シミュレーションを実行してリファレンスモデルとポリフェーズフィルタに差異が無いことを確認します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/3ffa31a1-dfaf-c0f8-e8a6-4d73440defc9.png)
（上段がリファレンス、下段がポリフェーズフィルタ、中段がその差分）



## 回路規模の推定
リファレンスモデルからHDL CoderでVerilogコード生成してみます。

コード生成レポートを確認すると、
乗算器：43個
加算器：42個
になるとのこと。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/cf3a74e1-bb74-c846-a382-b161339b02a2.png)

次にポリフェーズフィルタからコード生成してみます。
乗算器：38個
加算器：47個
となったので、乗算器数が少し減りました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/9fc5b594-b436-fc54-188a-3cf327ecbbac.png)



## FPGA実装
次はFPGAツールでコンパイルして回路性能を確認してみましょう。

こちらはリファレンスモデルから生成したHDLコードのVivadoでの論理合成結果。
ターゲットデバイスはKintex-7（xc7k325t-ffg676-2）に設定してあります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/28b7b7a3-7879-d4ab-1761-2828494fa067.png)

下図はポリフェーズフィルタから生成したHDLコードの論理合成結果。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/477651/e10a2fe7-bb84-282d-3aeb-f87f3420e975.png)

LUTは逆に多くなってしまっていますが、DSPブロックの使用個数はコード生成レポートどおり43個から38個に減っています。タイミングはFmax > 400MHz程度出ているようなので、とても良い結果が得られていると思います。

## まとめ
MATLABを使ってポリフェーズフィルタの設計～FPGA実装を行ってみました。
FIRデシメーションを変換して、ポリフェーズフィルタで実装することで、LUTは少し多くなったものの、DSPブロックの使用個数削減の効果は確認できました。フィルタタップ数が多くなるともっと削減効果は出てくるものと思われます。