TK80/BSの

シンセシステムを復活/拡張したい〜

その28

デジタルラダーフィルタと
EGの実験
2018年
9月16
HLSのC++の機能で、ap_fixed.hをインクルードすると、任意精度固 定少数点が使えるようになります。<全体ビット数、整数部ビット数>で定義します。素のCで固定少数点を使う場合には自分で少数点の位置を管理し、乗算、除算はシフト処理が必要です。それに比べると非常に楽になります。特に変数のビット長が40や36など半端な長さが使えるようになり、リソースの節約になります。下の上ウインド は素のCから移行したソースで、ダミーデータの入力データはlong  longの64ビット長(整数部48、少数部16)になっています。下ウインドは任意精度固定少数点の40ビット(整数部24、少数部16)を使っています。任意精度固定少数点は新しいが増えたのと同じで、直接1や−1などを直接代入したり、四則演算もそのままできるようになります。注意点として、定数と演算する時は次の例のようにキャストしないとエラーが出ます。例:Y=(fix24_16)0.3*X;


以前はテストベンチ側で1次ローパスフィルタの3つの係数a0、b0、b1を計算してラダーフィルタの引数に渡していました。DSP48Eの使用数を見積るために、引数をカットオフ周波数フィードバック係数に変更して、
ラダーフィルタ関数内で係数の計算を行います。とりあえず、固定少数点を24/16の計40ビットにした場合です。以前と同様にDSP48Eは16個使われています。


1次ローパスフィルタのiir_lpf1〜4は同じ計算をしていますが、計算結果を後から使うため、4つ別に定義していました。以前と同様に、これを1つにして、固定少数点を20/16計36ビットにして確認をします。DSP48Eが8個に減りました。


上記の固定少数点を20/12計32ビットに縮小した場合です。32ビットは切りが良いです。DSP48Eが6個減りました。


固定少数点20/12計32ビットCシミュレーション結果のグラフです。少数点が12ビットでも問題無さそうです。各ビットの小数点値を確認しておきます。
01 0.50000000
02 0.25000000
03 0.12500000
04 0.06250000
05 0.03125000
06 0.01562500
07 0.00781250
08 0.00390625
09 0.00195312
10 0.00097656
11 0.00048828
12 0.00024414



ソースの抜粋です。本体関数とiir_lpf最適化指示です。乗算除算を同時に1つのみ、インターフェースをap_ctrl_chainに設定しました。


引数をカットオフ周波数とフィードバック係数にしたので本体内で各係数a0、b0、b1都度計算します。設定が変わってもダイナミックに計算できます。


また、iir_lpfが1個なので、各計算値を本体内で保持する必要があります。


タイミング解析です。
引数をカットオフ周波数とフィードバック係数すると、計算量が増えて100MHzでは動作できなくなりますが、33.3MHzでは動作が可能で、レイテンシ120になりました。この部分はSPI−DACと同じ15.36MHzで動作させる予定なので問題なさそうです。


アナライザのウインドでレイテンシを確認します。レイテンシの大部分が除算に使われていることが分かります。その後、IP化しておきます。


以前に作成した、DDSの方形波をSPI−DACに出力するロジックにIP化したラダーフィルタを1個だけ組み込んでみます。DDSから入力して、SPI−DACに出力します。カットオフ周波数は10KHz、フィードバック係数は2.0です。


合成後、インプリします。なぜかラダーフィルタ部のDSP48Eの使用量が8個に増えています。DDS部でも1chあたり2個使っているので、現状で24個になっています。


回路図も確認しておきます。DDS−DCO−>ダラーフィルタ(iir_lpf)>SPI−DAC用シフトレジスタに接続されていのが分かります。


9月17日
EG (エンベロープジェネレータ)を作成します。まず、gccで基本動作の確認をします。EGの波形はコンデンサの充放電波形のexp(−t)系の過度現象を使 いますが、これをFPGAにそのまま実装するのはリソースを使いそうです。exp()の代わりに、積算型のべき乗の関数を作りました。EGは連続して計算するの で、結果を残しておい て、関数が呼ばれたら1回計算して戻ります。
関数の戻り値はプラス乗なので、マイナス乗にするには割り算します。


上の積算型のべき乗の関数を使って、コンデンサの充放電波形を作ってみます。充放電は無限に続くので、充電時は0.98上限に、放電時は0.02下限にして終了するようにしました。


CSVを作って、オープンオフィスに読み込み、グラフ化しました。充放電波形の生成分の動作は問題ないようです。


続いて、普通のEGです。アタックディケイサスティーンリリースでステートを作成し、サスティーン以外は上記の積算型のべき乗関数を呼びます。C言語では外からのゲートのON/OFF制御ができないので、プログラム内で適当に待ちを作って、それらしく動作させます。下はアタックとディケイのステート分です。ロジックにする時は例えば、アタック中にゲートがOFFになった時の処理も必要です。


べき乗関数のタイミング設定(テストのためアタック、ディケイ、リリースに共通)を1.2、サスティーンレベルを0.5に設定して、CSVを生成します。


オー プンオフィスでグラフ化しました。正常動作しているようです。動作はゲートONで0.98になるまで充電し、その後、サスティーンレベルに向けて放電しま す。サスティーンレベル以下になったら、ゲートがOFFになるまで、そのまします。ゲートがOFFになったら0に向けて放電し、0.02以下になったら終了します。


別の設定です、左はサスティーンレベルに、タイミングを早くしたもの。右はサスティーンレベル0.3に、タイミングを遅くした時です。


上記と同じ浮動小数点処理のまま、HLSに移行して、Cシミュレーションします。結果は良好です。


続いて、合成します。DSP48は5個使われています。後で固定少数点版を作成して比べる予定です。


ラダーフィルタの動作確認をしました。24KHzのフルスイングの波形が出ています。本来は660Hzの方形波にフィードバックが掛かった波形のはずですが、動作不良です。24KHzはサンプリング周波数の半分です。FPGA内のロジアナ機能のILA使って動作の確認をする必要があります。



9月22日
上記のラダーフィルタの不具合を確認します。HLSに戻って確認します。具合の出ている、C++のap_fixed.hを使って固定少数点を20/12計32ビットにしたバージョンです。Cシミュレーションでは正常ですが、C/RTL協調シミュレーションでは出力値が異常です。


波形でも24KHzで0xFFFF0x0000のフルスイングが出ています。アナログディスカバリの波形が台形になっていたのはDACのスルーレートの影響で、データが24KHzのフルスイングそのものでした。Cシミュレーション後にC/RTL協調シミュレーションの結果を確認しないで、IP化して組み込んだのが原因でした。後で不具合の原因を確認します。


下はC/RTL協調シミュレーションも正常に動作している、自作の48ビット16ビット合計64ビットの固定小数点用の乗算/除算関数を呼び、引数をカットオフ周波数フィードバック係数に変更してたバージョンです。


波形の戻り値正常出ています。とりあえず、このバージョンIP化して、再組み込みしてみます。


DDS−DOCとSPI−DACの間に上記のラダーフィルタを入れました。アナログディスカバリでSPI−DACの出力確認します。入力は660Hz方形波、カットオフ10KHz、フィードバック係数2.0の波形です。オープンオフィスで出したシミュレーション結果の波形と同じになりました。基本的な部分は正常動作しているようです。フィードバックを大きくして、共振するとSPI−DACの入力範囲を超えて波形が反転しますが、これは後で対策します。また、小さい周期的なノイズ混じっているようです。これも後で調べる必要があります。


9月23日

XADC2〜4を外部のボリュームに接続してAD変換し、カットオフ外部CV入力、フィードバック係数(レゾナンス)を制御します。XADC1はDDS−DCOの外部周波数変調入力ですが、現状は未接続です。


アナログディスカバリのウインドを動画キャプチャしました。入力は660Hzの方形波で、中央のボリュームは外部CVで外部から三角波のLFOを入れました。カットオフLFOレベルレゾナンスの順で変化さ せています。音はスピーカから出して、ノートPCの内蔵マイク経由で入力しました。約6MバイトのMP4ファイルです。


9月24日
続いて、MC80+パスに接続して、音出ししてみます。久しぶりにTK80から出力してみました。左チャンネルがDDS−DCO(方形波)とダラーフィルタで、右チャンネルが旧DCO(方形波)とダイオードラダーフィルタです。左チャンネルはボリュームを色々と調整して変化を出しています。後段は共に既存シンセのVCAを経由してミキサに接続し、その後PC経由でMP3に録音しました。


SPI−DACの入力範囲を超えた時の波形です。符号が反転しているので、これは制限しないといけないです。


9月25日
アパートのPCで
C++のap_fixed.hを使って固定少数点を20/12計32ビットにしたバージョンの確認をします。DRCエラーが2つ出ていました。エラーコードはWEBで調べると、スケジューリングに間に合っていないというエラーのようです。tmp_28とtmp_32はいずれもsdiv(符号付の除算器)に関係して、最適化支指示sdiv同時1つという指定が守れていないということのようです。


上記でも示したレイテンシの非常に長いのが
sdivのtmp_28とtmp_32です。


ソースコードのsdiv最適化指示ALLOCATIONを削除してみます。


C/RTL協調シミュレーションを行うと戻り値が正常になりました。リソースも確認しておきます。DSP48Eの使用量は6個です。



波形
先頭の2つの戻り値を確認します。32ビット(20/12)で0.06320.2192になっています。正常動作しています。後でもう一度IP化して、組み込んで動作確認します。


9月27日
C++のap_fixed.hを使った固定少数点20/12計32ビットをIP化して組み込みました。正常動作しました。


リソースを確認します。DSP48Eはラダーフィルタ部でやはり8個使われてます。この調子だと8ch分のロジックがArtix−7の35Tには入らなそうです。Digikeyやマウザーで100Tの載ったボードが入手できます。価格は35Tのプラス1万円くらいです。






back