FFTで周波数を測るとき、周波数分解能を上げたい場合、どうすればいいでしょうか?
周波数分解能は、fs÷サンプリングポイント数ですから、例えば5MHzサンプリングで65536ポイントのFFTを行うのであれば、分解能は約76Hzとなります。
では、さらに分解能を上げたい場合は、どうすればよいでしょうか?
簡単に思いつく方法は、一つはFFTのポイント数を増やすことです。
262144ポイントのFFTにすれば、周波数分解能は19Hzになります。
でも、FFTの計算量はN×log2(N)ですから、ポイント数を増やすと計算量が増えて効率的ではありません。
そこで、ズームFFTというものがあります。
原理は、下の図をご覧ください。
ズームFFTというのは次のような手順で行います。
- ノイズの多い入力信号がADCから入る
- BPFで目的の周波数付近を切り取る
- 正弦波を掛けて周波数をシフトさせる
- LPFで低いほうの周波数だけ残す
- デシメーションを行って、データ数を減らす
原理はこのような感じなのですが、実際に実装するにはBPFやLPFの設計、正弦波発生回路が肝になります。
まず、BPFですが、FPGAの中に入るフィルタではFIRを作るのがとても簡単です。FIRというと乗算器と加算器でたくさんの信号を足し合わせるのですが、まともなフィルタを作るには数十から100次程度のフィルタにしなければなりません。
たくさんの加算を行いますが、クロック速度に対してデータレートが遅い場合にはリソースを大幅に節約することができます。
125MHzクロックで、5MHzの信号を処理する101次フィルタの周波数特性は下の図のようになりました。
101次にもなると、たくさん48bitのDSPブロックを使うんじゃないの・・・?と思うかもしれませんが、実際に使用したDSPブロックは4個程度でした。
すっごーいお得ですね。
正弦波はDDSのような感じで位相信号を生成しますが、SINやCOSの波形を作るにはCORDIC法を使います。CORDIC法はXILINXのLogicoreを使えば難しくありません。
このコアは「位相」の信号を入れればSINとCOSが出てくるというものです。
入力する位相の情報をScaled Radianにすれば、1がπラジアン、-1が-πラジアンとして解釈されます。ただし、位相の情報は整数部が2bitある固定小数点数なので注意が必要です。
下の図のようなフォーマットになります。
出力データは18bitで取り出すようにしていますが、SINやCOSは±1の値も取りうるので、フォーマットは下の図のように整数部のある固定小数点となります。
LPFは、別の案件で使った42次のFIRフィルタを使いました。これは0.6MHz程度までを通します。

この原理でFPGAに実装して試してみました。
使用したボードはZYNQ搭載の高速AD変換ボード「Cosmo-Z」です。
まず、ファンクションジェネレータで作った410.00kHzの正弦波をCosmo-Zに入れ、FFTで見てみます。
BPFに通したスペクトラムは次のようになります。直流成分や低周波のノイズなどが削除されて、目的の信号だけが残りましたね。BPFで10dBほど減りました。
ここで、ローカル発信器の周波数を416.67kHz (=5MHz/12)
として、周波数シフトさせてみます。周波数シフトさせた結果が緑のスペクトラムです。
ローカル発信器と入力信号を乗算した6.67kHzの信号が原点付近にシフトされましたが、820kHzのほうにも高調波が出ています。
これをLPFで削ります。
すると、目的の信号だけが取り出されて残るというわけです。ただ、ちょっとLPFの効きが甘かったようで
ローカル発信機の周波数あたりに残ってしまっています。
さて、これで目的の信号が周波数ゼロ付近にシフトしたのですが、まだズームはしていません。ズームFFTをするにはデシメーションという操作が必要です。デシメーションというのは、N回に1回だけのデータを残して捨てるという操作です。
デシメーションで10個に1個だけ残すようにしたら、周波数が10倍にズームされました。
410kHzの入力信号と、局発の416.67kHzの差が、ズームされて見えているのがわかります。
このようなズーム回路ですが、使用したリソースはDSPブロックが7個、SLICEが665、BRAMが0個と、やっている演算の割にとてもコンパクトでした。
N分の1にデシメーションをかけてからFFTを行うことで、もともとのN倍の長さのFFTを行っているのと同じことになり、周波数分解能をN倍に上げることができます。ズームFFTの本質は「データを捨てる」というデシメーション操作にあるので、BPFやLPFはノイズを減らすという目的のためのものにすぎません。
ズームFFTの欠点は、必要なデータ数を集めるのにかかる時間が長くなることです。10倍にズームするならば、FFT自体の計算量は変わりませんが、必要なデータを集めるのに10倍の時間がかかってしまいます。

FPGAによるデジタル信号処理って、本当に面白いですね。
最近のコメント