ラベル DFT の投稿を表示しています。 すべての投稿を表示
ラベル DFT の投稿を表示しています。 すべての投稿を表示

2016年10月10日月曜日

VIVADO_HLS 6

ソースは最終的に以下のようになった。

前回までのdirectiveの定義だと、モジュールI/Fにap_start、ap_ready等のポートが付いてしまい、信号入力 xp はvldとこれらの信号とのハンドシェイクでやり取りされる回路が生成されてしまう。

RTL版は以下のようにストローブ信号(valid信号)のみでxpを取り込んでいた。

今回はRTL版のDFT IPを高位合成版で置き換えて動かしてみたいのでI/Fもなるべく同じにしたい。そこで、dft_proc関数自体にap_ctrl_none directriveを定義してみたところxp_ap_vldだけを使うRTLが生成された。

しかしである。ここで一つ問題が発生した。C-RTL Cosimを実行しようとしたらエラーになってしまった。

ap_ctrl_noneを定義する前はエラーにならなかったので、ap_ctrl_noneを追加したことが原因と考えられるが、エラーメッセージを見る限りではap_ctrl_noneはサポートされている筈であり、問題無いように思える。。。dft_procに対してap_ctrl_noneを、入力xpに対してap_vldを定義しているがどうやらこれが原因のようだ。ということは生成されたRTLは動作しないんだろうか?と思ってRTLを見てみた。

xp_ap_vldが1のタイミングでxpをラッチしているようなので問題ない気がする。本当にOKなのかシミュレーションで確認したいのだが、Vivadoはエラーと言ってシミュレーションをさせてくれない。。。うーむ。ツールバグのような気がするんだがなぁーー
仕方がないので実機で動かしてみることにした。

合成結果をIP化してI2S IPのデザインに取り込んだ。


合成は成功した。

で、時報のデータを流してみた。

RTL版と同じ動作だ。問題なし、素晴らしい。パチパチパチパチ
やっぱり、ツールバグだと思う。

以前作ったファンクション・ジェネレータから信号を入力して色々見てみた。


周波数掃引

高域に行くに従ってスペクトルが広がっているように見えるのは、画面のフレームレートよりも周波数の掃引が速いのが原因。また、周波数が高くなるとファンクション・ジェネレータのDDSの分解能不足によると思われる高調波が発生している。

このファンクション・ジェネレータはDDSを2ch持っていて、その出力を加算したり乗算したり出来る。


CH2を10KHzの正弦波にしておき、これとCH1側は周波数掃引信号を掛けあわせた。これはDSB変調と同じなので、両側波帯が掃引する波形になる。


こちらは加算した場合

高調波が沢山でている。波形が飽和してクリッピングしているかも知れない。

音楽での応答性
このDFT IPは1サンプル毎にスペクトルが生成されるので、応答性は良い。


ということで、問題なし。素晴らしい。。
Cで回路開発ができると、例えば計算する周波数の数を変更したり、スペクトルの出し方を変えたりといったことも簡単に出来そうだ。色々と試行錯誤するには良いかも知れない。


2016年9月25日日曜日

VIVADO_HLS 5

Vivado_HLSでの開発の仕方が大体判ったので、以前Verilogで開発したDFT IPをHLSでやってみることにした。このDFT IPはAC'97 IPから出力されるAudioデータを離散フーリエ変換でスペクトルに変換するIPで、2012年10月〜2013年2月にかけて開発した。
通常、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) 部のみスペクトルが立つ筈だ。

結果
アナログ波形で見えているのが出力スペクトルで、最初に正弦波状波形から始まって段々と収斂していっているのが判る。


2015年3月22日日曜日

ZYBO 21 ( I2S コントローラの作成 12 )

今月は本業が忙しく怒涛の3月だ。

I2SコントローラIPだが、割り込み機能は確認できたので、2週間前にここまでのsnapshotをGitHubにアップした。

my_I2S_20150307.zip

さて、今日はI2Sコントローラに追加してみたいなぁ−と思いながら忙しくて出来なかった機能を追加してみた。その機能とは逆再生機能だ。このI2SコントローラIPのAXI DMACはDRAMからシングルアクセスでデータを1サンプルずつ読んでくる。つまり、ポインタは+1づつしか更新されないので、これを-1にするモードを追加すれば容易に逆再生機能を追加できる。逆再生機能を追加して何がしたいかというと、ターンテーブルにのったレコードを指で前後に擦ってつくる音楽があるが、その再生モードを実現してみたいなと思ったからだ。スクラッチミュージックとか言ったっけ?

シャッシャカ、シャッシャッシャー
Hey!  Yo !
俺はオキナワうまれー、オキナワ育ちー
地元のオタクはだいたいトモダチ! (*1)
シャッシャカ、シャッシャッシャー

*1 ウソです。 -_-;;

・・・見たいな。
そんなプレイが楽しめるかな?なんて思った。
でも、よく考えてみると逆再生だけでは実現できないようにも思える。再生速度も変調できる必要があるかも知れないのだが、まずは逆再生機能を入れてみた。

RTLの方はI2S_pb_dma.vのポインタ操作部を以下のように変更した。
pb_rvsは追加した再生方向を制御するポートで、これが0の時に逆再生モードになる。
再生方向はスイッチ等で動的に変更できる必要がある。
今回はZYBOのPMOD(JE)の10番品に押しボタンスイッチを接続し、それで操作できるようにした。

で、動かしてみた。

うーむ。。やはり、速度変調も必要かな。

現行デザインにもDFT IPは組み込まれているので、逆再生時のスペクトルも見ることができる。
例えば、この曲の場合は・・・
スペクトル表示はこんなふうになる。
これはこれで、面白い・・・気がする。


2015年2月22日日曜日

ZYBO 20 ( I2S コントローラの作成 11 )

割り込みの確認も出来た。

Zynqでスタンドアローン(ベアメタル)環境で割り込み使用法について情報が少なくて困った。(探し方が悪いのかも知れないが。) ドキュメントとして唯一見つけられたのは、Xcell Jurnal 87の p38 の How to Use Interrupts on the Zynq SoC という記事だけだった。 この他にXSDKのProject TemplateのPeripheral Testsの中に割り込みを使うプログラム例があるので、これらを参考にしてプログラムを作成した。


割り込み機能の確認は、jukebox プログラムを割り込みを使うように書き換えて行った。
音楽データ用バッファのサイズは2048バイトにした。

I2SコントローラのDAC_THRレジスタをwvの中間番地に、DAC_ENDレジスタをwvの最終番地に設定し、ポインタがそこに通過した時点で割り込みを発生させ、割り込みハンドラでバッファの内容を新しいデータで更新するようにした。

以下は割り込みのセットアップを行う部分である。


割り込みハンドラ(I2SIntrHandler)
各割り込み要因に応じて、それに対応する再生の終わったバッファ領域にSDカードからデータをリードして格納する。 ファイルの終端に達した場合(これはf_eof()で判定する)は、全ての割り込みをマスクし、Circulation modeをクリアする。 すると、DMACのポインタがENDに到達した時点でDMACは動作を完了する。

割り込みハンドラを抜けるところで、xil_DCacheFlush()をコールしてデータキャッシュの内容をDRAMに吐き出させている。 これをやらないとDRAM上のバッファの内容が不完全になりバッファの折り返しの部分で音が異常になった。

メインルーチン
while (1)のループでは、音量増減のボタンや曲ジャンプボタンの判定をしながらDMACが動作完了するのを待っている。 DMACが動作完了になるかあるいは曲ジャンプボタンが押されたらループを抜け、プレイリストの次の曲の再生準備をして再びこのループに入る。


ということで、割り込み及びDMACのCirculation modeの動作確認が出来た。 \(^_^)/


2015年2月8日日曜日

ZYBO 19 ( I2S コントローラの作成 10 )

なんやかんやで、ちょっと間が空いてしまった。


スペクトルの画像をデジカメの動画撮影機能を使って撮影していたのだが、どうしても旨く撮影できないのに業を煮やして、HDMIキャプチャボックスなるものを購入した。HDMIやコンポーネントYPbPr形式の動画をUSBメモリやUSB-HDDに録画できる。

購入したサイトでは対応画質について詳しい説明はなかったのだが、購入して動かしてみたらXGA(1024 x 768)も記録できた。  記録された動画はデジタルデータをキャプチャしているだけあって綺麗だ。

上の写真の通り本体にはLINE INとMIC INのジャックも備わっているがこれは画像がコンポーネントYPbPr形式の場合にのみ使用可能で、HDMI画像の場合はHDMIのチャネルのAudioしか記録できない。  私のdvi_encはdviエンコーダIPでHDMI-Audioのエンコード機能は無いため、現状ではAudioの記録はできない。

I2Sコントローラとしては再生系の動作は割り込みを除いて一応確認できたので、今度は録音系の確認を始めた。 今回は録音系のDMAと再生系のDMAをCIRCULATIONモードで同時に動作させ、LINE INから入力した信号を録音DMACでDRAM上に保存しそれを再生DMACで再生させた。

プログラム


SSM2603の初期設定部
ADC INPUT VOLUMEレジスタのMuteをDisableにしている。


動作の様子。
こういう場面はカメラで取らざるを得ない。


この曲の録音データのスペクトル
wavデータを再生した場合と変わらないので、録音系も問題無さそうである。

次は割り込みを確認しよう。


2015年1月12日月曜日

ZYBO 18 ( I2S コントローラの作成 9 )

初回動作が旨く行かない場合がある件は、I2Sコーデックの初期化の問題とRTLのバグだった。
また、リミットサイクルについては正弦波テーブルの値を若干小さくしてみることにした。
具体的には本来の値を0.9999999倍した。

以下はテーブルのデータを生成するプログラム。

生成されるデータ ROMの初期値としてロードするため、32bit floatをhex形式で出力している。
左が本来の値で、右が縮小値



今のところこのテーブルで旨くいっている。

現状のプロジェクトのアーカイブを以下に置いた。
https://drive.google.com/folderview?id=0BynL4T1Zsl44UFBsMFVLZWRGVTQ&usp=sharing

https://github.com/BravoFpga/I2S-control-IP-for-ZYBO-zynq-

リポジトリをGitHubに変えました。 (2015/1/31)


2015年1月4日日曜日

ZYBO 17 ( I2S コントローラの作成 8 )

AXI マスタ側は一応動作するのだが、初期化の部分に問題があるようで初回動作が異常(ノイズ混じりの音になったり、再生スピードが遅く感じる)な場合がある。問題の発生頻度は起動直後が高く、一度正常に再生すると以降は安定になる。リセット周りに原因があるような気がしている。

正常動作時

前回まではwavファイルのデータをテキストに変換しCプログラムの配列としてハードコードしていたのだが、この方法は何かと不便だ。何か良い方法は無いか調べたところ、xilffsというドライバを使うとOSのないベアメタル環境でもFATフォーマットのSDカードの読み書きが出来ることが判った。そこで、 wav ファイルをFATフォーマットのSDカードに入れておいて、そこから順次メモリに読み込んで再生するように変更した。
xilffsを使うためには以下のようにBSPを設定する。


xilffsの使い方は、Vivado_SDKのインストールフォルダ下にexampleがある。


これを参考にして以下のようなプログラムにした。

この様にして色々な曲調のデータを再生させてみている。
表示されるスペクトルの変化と音の変化がほぼ完璧に同期している。また、これは思い込みかも知れないけど、スペクトルの変化具合・・・というか絵から受ける印象も曲調に一致しているようで、なかなか面白い。

そんな感じで色々な曲を連続再生して見ていたら問題が見つかった。
前回dft_ip作成時に発生した現象と似た現象が発生している。多分これは、リミットサイクルノイズだと思う。実機と同じように複数のwavファイルをCモデルで処理させたところ同様の結果になった。単精度浮動小数演算器で計算しているとは言っても量子化ノイズは完全にゼロになる訳ではないのでこうなるのは当たり前かも知れない。アキュレータで積算するときに若干の縮小係数を掛けるとか、一定サイクルでアキュムレータをクリアするとか、ある閾値以下の場合に0にするとか何らかの対策が必要なようだ。ただ、闇雲にやっても仕方ないので、当面は1曲毎にアキュムレータをリセットすることにした。




2014年12月28日日曜日

ZYBO 16 ( I2S コントローラの作成 7 )

AXI マスタ側の動作確認はまだやっていないが、dft ipの動作を先に見たくなったので、dft ipやdvi_encも追加し、AXIスレーブ側・つまり、レジスタ経由で音楽データを書いて動作させてみた。

VivadoのBlock Designを以下に示す。

I2Sからdft、hdmiまでのデータフローを考慮してブロックを並べ替えると以下のようになる。

データはI2S_ctl_0 ➔ dft_core_0 ➔ cpx_power_0 ➔ vif_0 ➔ dvi_enc_0 と流れていく。
cpx_powerはdft_coreから出力されるスペクトル値(32bit浮動小数形式の複素数)を絶対値(√(r^2 + i^2) )に変換するモジュールである。 絶対値は16bit整数に変換し、2ポートRAMに書く。

vif は表示コントローラで、cpx_powerの2ポートRAMから値を読出しグラフ化してVGAに出力する。画面解像度はXGA (1024 x 768)にしている。

プログラムは以下のようにした。



配列 wav_tbl[] に再生させたい音楽データが入る。
時報データを再生させてみた。

旨く行った。

動作環境



今度はMozartの曲をやってみた。
ちなみに音源はColumbia University Orchestraの2001年秋の演奏によるもので、archive.orgでPublic Domaindで公開されている。(https://archive.org/details/Mozart_Symphony_40)

デジカメの動画撮影機能を使って撮影していてピントが中々合ってくれないのが困りものだが、dft ip自体は期待通りに動作している。 \(^_^)/

Cモデルで動画を作成した時はグラフの横軸はログスケールとしたが、実機ではリニアスケールになっている。ログスケールにすればもっと見やすくなるかも知れない。また、vifを通常のフレームバッファにし、且つdft_coreの出力部にAXIプラグを追加して結果をDRAMに出力して、ARMのソフトウェアで加工すればもっと気の利いた表示も出来るようになるだろう。

ということで、dft ipは問題なさそうだ。次は、I2SのAXIマスタ側の動作確認をしようと思う。

将来的にはdft ipをCで書いて高位合成してどんな感じになるかも見てみたい。


ERROR: Failed to spawn fakeroot worker to run ...

なにかと忙しくてなかなか趣味の時間を確保できない。 ...orz  家の開発機のOSはLinux Mintなのだが、最近バージョンを22に更新したところ、myCNC用のpetalinuxをビルドできなくなってしまった。ビルドの途中で ERROR: Failed to spawn ...