« Cosmo-Zのアルミケースに新型が登場 | トップページ | TrenzElectonic社のTE0808-03-02I-Sスタータキット »

2017.04.28

FPGAにズームFFTを実装

FFTで周波数を測るとき、周波数分解能を上げたい場合、どうすればいいでしょうか?

周波数分解能は、fs÷サンプリングポイント数ですから、例えば5MHzサンプリングで65536ポイントのFFTを行うのであれば、分解能は約76Hzとなります。

では、さらに分解能を上げたい場合は、どうすればよいでしょうか?

簡単に思いつく方法は、一つはFFTのポイント数を増やすことです。

262144ポイントのFFTにすれば、周波数分解能は19Hzになります。

でも、FFTの計算量はN×log2(N)ですから、ポイント数を増やすと計算量が増えて効率的ではありません。

そこで、ズームFFTというものがあります。

原理は、下の図をご覧ください。

Zf1

ズームFFTというのは次のような手順で行います。

  1. ノイズの多い入力信号がADCから入る
  2. BPFで目的の周波数付近を切り取る
  3. 正弦波を掛けて周波数をシフトさせる
  4. LPFで低いほうの周波数だけ残す
  5. デシメーションを行って、データ数を減らす

Zf2

原理はこのような感じなのですが、実際に実装するにはBPFやLPFの設計、正弦波発生回路が肝になります。

まず、BPFですが、FPGAの中に入るフィルタではFIRを作るのがとても簡単です。FIRというと乗算器と加算器でたくさんの信号を足し合わせるのですが、まともなフィルタを作るには数十から100次程度のフィルタにしなければなりません。

たくさんの加算を行いますが、クロック速度に対してデータレートが遅い場合にはリソースを大幅に節約することができます。

125MHzクロックで、5MHzの信号を処理する101次フィルタの周波数特性は下の図のようになりました。

Bpf_2

101次にもなると、たくさん48bitのDSPブロックを使うんじゃないの・・・?と思うかもしれませんが、実際に使用したDSPブロックは4個程度でした。

すっごーいお得ですね。

正弦波はDDSのような感じで位相信号を生成しますが、SINやCOSの波形を作るにはCORDIC法を使います。CORDIC法はXILINXのLogicoreを使えば難しくありません。

Cordic1 Cordic2_2 Cordic3

このコアは「位相」の信号を入れればSINとCOSが出てくるというものです。

入力する位相の情報をScaled Radianにすれば、1がπラジアン、-1が-πラジアンとして解釈されます。ただし、位相の情報は整数部が2bitある固定小数点数なので注意が必要です。

下の図のようなフォーマットになります。

Sradian

出力データは18bitで取り出すようにしていますが、SINやCOSは±1の値も取りうるので、フォーマットは下の図のように整数部のある固定小数点となります。

Sincos

 

LPFは、別の案件で使った42次のFIRフィルタを使いました。これは0.6MHz程度までを通します。

Lpf

sun

この原理でFPGAに実装して試してみました。

使用したボードはZYNQ搭載の高速AD変換ボード「Cosmo-Z」です。

Cosmozc

まず、ファンクションジェネレータで作った410.00kHzの正弦波をCosmo-Zに入れ、FFTで見てみます。

Fft_raw

BPFに通したスペクトラムは次のようになります。直流成分や低周波のノイズなどが削除されて、目的の信号だけが残りましたね。BPFで10dBほど減りました。

Bpf_4

ここで、ローカル発信器の周波数を416.67kHz (=5MHz/12) として、周波数シフトさせてみます。周波数シフトさせた結果が緑のスペクトラムです。

Mult

ローカル発信器と入力信号を乗算した6.67kHzの信号が原点付近にシフトされましたが、820kHzのほうにも高調波が出ています。

これをLPFで削ります。

Lpf_2

すると、目的の信号だけが取り出されて残るというわけです。ただ、ちょっとLPFの効きが甘かったようで ローカル発信機の周波数あたりに残ってしまっています。

さて、これで目的の信号が周波数ゼロ付近にシフトしたのですが、まだズームはしていません。ズームFFTをするにはデシメーションという操作が必要です。デシメーションというのは、N回に1回だけのデータを残して捨てるという操作です。

デシメーションで10個に1個だけ残すようにしたら、周波数が10倍にズームされました。

Zoom

Zoom2

410kHzの入力信号と、局発の416.67kHzの差が、ズームされて見えているのがわかります。

このようなズーム回路ですが、使用したリソースはDSPブロックが7個、SLICEが665、BRAMが0個と、やっている演算の割にとてもコンパクトでした。

N分の1にデシメーションをかけてからFFTを行うことで、もともとのN倍の長さのFFTを行っているのと同じことになり、周波数分解能をN倍に上げることができます。ズームFFTの本質は「データを捨てる」というデシメーション操作にあるので、BPFやLPFはノイズを減らすという目的のためのものにすぎません。

ズームFFTの欠点は、必要なデータ数を集めるのにかかる時間が長くなることです。10倍にズームするならば、FFT自体の計算量は変わりませんが、必要なデータを集めるのに10倍の時間がかかってしまいます。

sun

FPGAによるデジタル信号処理って、本当に面白いですね。

 

|

« Cosmo-Zのアルミケースに新型が登場 | トップページ | TrenzElectonic社のTE0808-03-02I-Sスタータキット »

コメント

こんにちは。

「BFPで切り取って正弦波で周波数シフトしたあとBPF」

していますが、せっかくCORDICで正弦波と余弦波を同時生成していますので、複素周波数シフトしてはいかがでしょうか。

フロントのBPFが不要になります。

投稿: 酔漢 | 2017.04.30 11:09

複素周波数シフトについて、本を読んで調べてみました。
確かにいけそうですね。

見たい周波数を変えときにBPFの通過帯域を変えなくてよくなるので便利そうですね。
BPFよりLPFのほうが作りやすいので。

投稿: なひたふ | 2017.05.12 13:57

コメントを書く



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




« Cosmo-Zのアルミケースに新型が登場 | トップページ | TrenzElectonic社のTE0808-03-02I-Sスタータキット »