take#のブログ

take#のブログ

ブログの説明を入力します。

Amebaでブログを始めよう!
エフェクタのA/Dサンプリング周波数は、CDと同じく44.1kHzとします。
手持ちの水晶は4MHzなのでFPGAで分周してタイミングを生成します。

残念ながら44.1kHzが4MHzの整数倍ではなく、等間隔にはできません。
しょうがないので10msで441回サンプルに帳尻あわせするようにします。

4MHz(250ns)で90サイクルを131回と91サイクルを310回、
それでちょうど10msにする作戦です。

回路はVerilogで記述します。
こんな感じ。

// =====================================================
// A/Dサンプリングタイミングトリガを生成するモジュール
// ベースクロックは4MHz
// サンプルタイミングは44.1kHz(=22.675736・・・us)
// 10msあたり441発のトリガを出力する。
// 90サイクルカウントを131発と91サイクルカウントで310発
// =====================================================
`timescale 1ns/1ns
module m_SAMPL_TRG
    (i_clk 
    ,i_rst_n
    ,o_trg_p
    );

    input   i_clk   ;// クロック(4MHz)
    input   i_rst_n ;// リセット
    output  o_trg_p ;// サンプルトリガ(44.1kHz)

    reg [6:0] count_div;//
    reg [8:0] count_trg;// 出力トリガの回数をカウント
    reg       o_trg_p  ;//

    wire [6:0]max_count  = (count_trg >10'd130    ) ? 7'd90 : 7'd89;
    wire      cler_div_p = (count_div == max_count) ? 1'b1  : 1'b0 ;
    wire      cler_trg_p = (count_trg == 10'd441  ) ? 1'b1  : 1'b0 ;

    //トリガ生成用カウンタ
    always@(posedge i_clk or i_rst_n)
    begin
        if(~i_rst_n)        count_div <= 7'd0;
        else if(cler_div_p) count_div <= 7'd0;
        else                count_div <= count_div + 7'd1;
    end
   
    //トリガ出力回数カウンタ
    always@(posedge i_clk or i_rst_n)
    begin
        if(~i_rst_n)        count_trg <= 9'd0;
        else if(cler_trg_p) count_trg <= 9'd0;
        else if(cler_div_p) count_trg <= count_trg + 9'd1;
        else                count_trg <= count_trg;
    end
   
    always@(posedge i_clk or i_rst_n)
    begin
        if(~i_rst_n)        o_trg_p <= 1'd0;
        else                o_trg_p <= cler_div_p;
    end

endmodule
//テストベンチ
module m_SAMPL_TRG_tb();
    reg i_clk   =0;
    reg i_rst_n =0;
    wire o_trg_p;

    m_SAMPL_TRG  m_SAMPL_TRG
    (.i_clk   (i_clk   )
    ,.i_rst_n (i_rst_n )
    ,.o_trg_p (o_trg_p )
    );

    //クロック4MHz
    always#125 i_clk = ~i_clk;

    integer cnt=0;
    //10ms毎のトリガで時刻とカウント数を表示
    always@(posedge m_SAMPL_TRG.cler_trg_p)
    begin
        $display("10ms Triger = %t[ns] cnt = %d",$time,cnt);
    end
   
    //44.1kHzトリガの回数をカウント
    always@(posedge o_trg_p)
    begin
         cnt =  cnt +1;
    end
   
    //トリガ間隔のチェック
    integer chk_time1;
    integer chk_time2;
    integer chk_time;
    always@(posedge o_trg_p)
    begin
         chk_time1 <= $time     ;
         chk_time2 <= chk_time1 ;
        if(cnt > 1)
        begin
            chk_time <= chk_time1 - chk_time2;
            if( (chk_time > 22750) || (chk_time < 22500) )
            begin
                $display("Triger Error");
            end
        end
    end

    //
    initial
    begin
        #50;
        i_rst_n=1;
        #100000050; //1秒で終了
        $stop;
    end

endmodule

***********************************************************
シミュレーションの結果は以下のとおり。
これで44.1kHzのサンプリングタイミングが作れました。

# 10ms Triger =              9999625[ns] cnt =         441
# 10ms Triger =             19999625[ns] cnt =         882
# 10ms Triger =             29999625[ns] cnt =        1323
# 10ms Triger =             39999625[ns] cnt =        1764
# 10ms Triger =             49999625[ns] cnt =        2205
# 10ms Triger =             59999625[ns] cnt =        2646
# 10ms Triger =             69999625[ns] cnt =        3087
# 10ms Triger =             79999625[ns] cnt =        3528
# 10ms Triger =             89999625[ns] cnt =        3969
# 10ms Triger =             99999625[ns] cnt =        4410
デジタル回路でエフェクタを作りたいのだが、まずはギターの音をA/D変換しなくてはいけない。

今回は5V単一電源で制作したいので、入力アンプは方電源で試作した。
ギターからの入力をコンデンサでDCカットし、5Vから作った.約2.5Vでオフセットする。
初段のアンプはボルテージフォロアで、後段で反転増幅する。

スピーカーにつなげて音が出るかチャックしてみた結果。
音は正常に出ていたし、振幅もフルスケール振れていた。

破線の部分は音出し用なので、後程A/Dコンバータへ置き換える。

ブレッドボードの様子。
今回使ったOPアンプはNJM2732D。
選定基準としては、電源電圧までフルスイング可能であること。


FPGAを使ったギター用エフェクタ。
頓挫しかかっていたが、今年こそ頑張って作る!

アメブロのパスワードも思い出せたし!

使用するのは,xilinxのXC3S250E。