通常、DFT演算の式は以下のような式だが、
回路はVerilogで記述し、動作検証はDegilentのAtlysボード(Spantan6)で行った。RTLにつまらないバグを仕込んでしまったのだが、それを見つけられずにかなり苦しんだ。
また、2014年11月にはZYBO(Zynq)にも実装して動作させた。
DFT IP開発時にC言語でリファレンスモデルも作成したが、今回はそれのコードを流用して高位合成用のソースを作成した。以下にソースを示す。
68行〜94行のdft_proc()がDFT演算を行う本体だ。
41行〜66行のget_arc()はsin(ω), cos(ω)を求めるルーチンで、予め計算した値を配列に持ち、表引きで値を返している。このDFT IPは単精度浮動小数で演算を行っているがアルゴリズムがIIR型のため、ずっと動作させると演算誤差が累積していき、無信号でもスペクトルが存在するように見えてしまう場合がある。その対策として三角関数の値を正規の値に縮小係数(0.9999999)を掛けた値をテーブル値としている。
テーブルの値は小数点データだが、0.123e-456の様な記述で表現してしまうと値によっては桁落ちで精度劣化してしまうので、floatとunsigned intの共用体で新しく型を定義し、テーブル値はunsigned intとしてHEX表記で記述している。この型定義はdft.hの33行目で行っている。
Directiveは以下のように設定した。
arc_tblは本来ならROMとするべきだが、ROM_T2P_BRAMという設定項目がなかったのでRAM_T2P_BRAMとした。
合成結果は以下の通り
浮動小数点演算器(加減算、乗算)にDSP48が使われている。DSPを使わないLUT型の演算器にしたいのだが、Directiveで設定できない。この段階では問答無用でDSPを使うRTLが生成されてしまうようだ。
ともあれ、HLS合成は成功した。Fmaxも150MHz位まではいけそうだ。
以下のような固定値を入力するテストベンチを書いてVivado Simulatorでシミュレーションをしてみた。固定値入力なので、出力スペクトルは最初は正弦波状になり段々収斂していって最終的には周波数0 (DC) 部のみスペクトルが立つ筈だ。
結果
アナログ波形で見えているのが出力スペクトルで、最初に正弦波状波形から始まって段々と収斂していっているのが判る。