FPGAでデジタルフィルタ

by K.I
2017/04/14〜2017/06/07

Index


概要

I2Sのタイムチャート

プログラムについて


1その方が動作確認が簡単なんじゃないかと思うので。
2でも16bit以上のデータの出力方法がわからないので未確認。
3おそらく、それで良いと思うが、実際に16bitより多ビットのデータの再生が出来ていないので未確認。
4まぁ結局、それはやめたんだけれども。。

[top]

Machxo2 Breakout boardを使う

Diamondの再インストール

ピン接続

J2-1 接続 説明
113 lrclk_i LRCLK入力
115 bclk_i BCLK入力
119 data_i DATA入力
GND
121
125
127
J5-2 接続 説明
61 lrclk_o LRCLK出力(そのまま)
GND
58 bclk_o BCLK出力(そのまま)
57 data_o DATA出力(そのまま)
GND
54 datax DATA出力(フィルタ処理後)
52

LPFファイル


5多少、メニュー項目変わってるが、ほとんど同様に出来る。
6旧バージョンは、アンインストールしたはずなんだけど。
7これは、Windows7の場合。

[top]

単純に通過させる

RaspberryPiのI2S出力を接続

単純にスルーするプログラム

module through (
                input clk,
                input rst,
                output oscen,
                output [7:0] led,
                output tx,
                input rx,
                input lrclk_i,
                input bclk_i,
                input data_i,
                output lrclk_o,
                output bclk_o,
                output data_o
        );

        assign led = 8'h55;;
        assign oscen = 1;
        assign tx = 1;
        
        assign lrclk_o = lrclk_i;
assign bclk_o = bclk_i;
assign data_o = data_i;
endmodule

LRCLKの周期をカウント

module through (
                input clk,
                input rst,
                output oscen,
                output [7:0] led,
                output tx,
                input rx,
                input lrclk_i,
                input bclk_i,
                input data_i,
                output lrclk_o,
                output bclk_o,
                output data_o
        );

        reg lrclk_last;
        reg [7:0] count;
reg [7:0] count_last;
double_ff lrclk_ff (
.clk(clk),
.idata(lrclk_i),
.odata(lrclk_ix)
);
always @(posedge clk) begin
lrclk_last <= lrclk_ix;
end
always @(posedge clk or posedge rst) begin
if (rst) begin
count <= 0;
count_last <= 0;
end
else if (lrclk_last & ~lrclk_ix) begin
count_last <= count;
count <= 0;
end
else
count <= count+1;
end
assign led = ~count_last;
assign oscen = 1; assign tx = 1; assign lrclk_o = lrclk_i; assign bclk_o = bclk_i; assign data_o = data_i; endmodule

double_ffモジュール

一応シミュレーションする

クロックを観測してみる

→BCLKがノイズとして見えている →立下りが微かにブレている ......

FPGAでのデータ処理方法の検討

方法特徴欠点
1.外部クロック同期でI2S出力させて、データ処理後、I2Sクロックを生成し直す ・水晶発振器の精度でクロックを生成できる
・回路的にはシンプルになり、伝送路の品質にも影響されない
・サンプルレートを単純な分周で作れる周波数の発振器が必要12
・RaspberryPi標準で、外部クロック同期のI2S出力はできない13
2.I2S入力データをバッファに入れて、データ処理後、I2Sクロックを生成し直す ・水晶発振器の精度でクロックを生成できる
・I2S入力のクロックの精度は不要
・外部クロック同期が出来ない場合、例えばUSB Audioとかにも使えると思う
・サンプルレートを単純な分周で作れる周波数の発振器が必要
・ある程度バッファに貯めてから、再生を開始する必要がある。十分なバッファ容量14が必要
3.I2SのLRCLKとBCLKをそのまま通過させ、そのクロックに同期して処理したデータを出力 ・ほぼI2S入力のクロック精度のまま15で、出力可能
・これも外部クロック同期出来ない場合にも使える
・データ終了後も、LRCLKとBCLKが供給される必要がある
・でも、RaspberryPiのI2S出力では、データ終了でLRCLKは停止、BCLKもすぐに停止する
・クロックが供給されないと、データの最後は尻切れになる
・サンプルレートを変更したい場合には使えない

8まぁ、LPFファイルで接続を入れ替えても良いんだけど。
9レンジを上げられないので確認できないが、LRCLKのジッタも同程度と思われる。
10表示上は、1nsぐらいの時間解像度はありそうなんだけれど。
11正直、もっとジッタが大きいと思っていた。RaspberryPiのI2S出力のクロックは本当に優秀だと思う。
12そうじゃない場合は、サンプルレートに近い周波数で出力する。或いはサンプルレートに近づけるように分周を制御する。但しその場合は、ジッタが発生する。
13カーネルの改造と再コンパイルで出来るらしいが、面倒なのでやりたくない。。
14ソースの発振周波数とのズレは蓄積するため、原理的にはデータ転送して再生し直しているだけなので、バッファ容量に応じた短時間の再生しか出来ない。
15I2S入力のクロック精度が良ければ利点になるが、悪ければ欠点にもなる。
16自分はここら辺の事はよく知らないので。

[top]

1LRCLK後出力

データ取込み

半LRCLK後に出力

インプリメントで確認

クロック停止時の対策

1LRCLK後に出力

1LRCLK後出力の確認


[top]

RCフィルタの実装

RCフィルタのプログラム

RCフィルタのシミュレーション

RCフィルタの動作確認

RCフィルタをExcelで計算

Channeldout datax 計算値
1 0 0 0
1 4652 0 0
1 9211 145 145.375
1 13582 428 428.3125
1 17679 839 839.0625
1 21417 1365 1365.25
1 24721 1991 1991.625
1 27525 2701 2701.3125
1 29770 3476 3476.75
1 31412 4297 4297.6875
1 32418 5144 5144.34375
1 32766 5996 5996.3125
1 32451 6832 6832.5625
1 31478 7632 7632.59375
1 29867 8377 8377.1875
1 27651 9048 9048.5625
1 24874 9629 9629.34375
1 21593 10105 10105.40625
1 17875 10464 10464
1 13795 10695 10695.59375
1 9434 10791 10791.875
1 4883 10748 10748.59375
1 233 10564 10564.71875
1 -4421 10241 10241.15625
1 -8986 9782 9782.8125
1 -13370 9195 9195.5

RCフィルタ出力dataxは、ちゃんと計算値と一致している

RCフィルタ後の音

曲データをRCフィルタに

MaximaでRCフィルタを計算


172の補数計算なので、端数が正なら切捨て、負なら切り上げとなる。
18最初は頭の10秒だけにしたが、あまり高音が無かったので変更した。(170614)

[top]

移動平均フィルタの実装

移動平均フィルタのプログラム

曲データを移動平均フィルタに

Maximaで移動平均フィルタを計算


[top]

まとめ

デジタルフィルタ関連の記事


19まぁCの場合、大きめのレジスタで計算して、最後に必要な部分だけ出力すればいいので、簡単なんだけど。

[top]

Active-HDLの使い方

シミュレーション用プロジェクト作成

シミュレーション実行

次回からのシミュレーション起動

Active-HDLが起動しない

テストベンチ

メモ


20Active-HDLのシミュレーションは、ちょっと分からなくなることがある。

[top] [電子工作関連に戻る]

comments powered by Disqus