ΔΣーADC実験編 その28 CIC filter -> fir filter 詳細


1/64 decimation後に、fir LPFを通したsimulation 結果

 1.やっと、補償フィルタが、できました。

ROM, Single Port RAMを使った fir filter


FIR Compilerを使った DAfilter


    LUTの消費量を抑える事ができて、ホッとしています (^_^;;

    私みたいに、物忘れの激しい人間は、メモして置くのが一番ですね。

    で、 以降に、製作過程を記述しておきます。

2.戦略



    CICフィルタにより、1/64 decimationを行ったのですから

    decimatedクロック(devided_clk)は、元クロック(CLK0_OUT 50MHz)に対して、64倍の長さの周期を持っています。

    devided_clk 1周期の間に、fir ilterの計算を行えば、OKなわけです。

    で、

    このdevided_clkの1周期の間に、CLK0_OUTは64回振動しますから、これを利用して

    ROMの読み込み及び、Single port RAMへの書き込みと読み出しを、行います。

3.ROMの読み出しタイミング

    まず、ROMを作ります。



    ROMに書き込む、fir filterの係数は、64個と、1つ増やして置き、その値は ゼロ。


    テストプログラムは


    タイミングは


    negedge clkで設定しておくと

    すぐ次のposedgeで、そのアドレスのデータを、吐き出してくれます。

4.Sigle Port RAMへの書き込み及び読み出し

    Single Port RAMを作ります。




    HDL記述は

    擬似inputデータも作っています。


    ROMの場合と同じく、negedgeで設定すると

    すぐ次のposedgeで、書き込んだデータが出力されます。(write first mode)

5.Single port RAMへの書き込みの工夫

    最新のデータを、fir filterの最初のROMデータ、即ちcoef(0)=-3と掛け合わせなければなりませんから

    新たに、count(カウンター)、wr_addr(write_address),addra(read_address)の変数を設定して、

    Single Port RAMのデータ出力が、そういう並びになるように、HDL記述を書き換えます。



    擬似のinputデータ(input_data_array)は、見やすいように、addraに 10 をプラスしたものに設定しています。

    そうすっと、




6.ROMデータとSingle Port RAM出力のすり合わせ

    次に、以下のHDL記述にて、テストベンチi風のHDL記述を行います。

    今回は、posedgeで、データを拾い出します。

    このテストベンチは、ISE付属のISim simulatorでは、普通のmoduleとして記述します、便利。



    次に、擬似データをテストベンチmoduleに記述して、Single Port RAM moduleの擬似データを消します。
   
    そして、擬似データと fir filterの係数の積を蓄積する accumlatorである、accum を設定します。

    fir_result出力に、convolution結果を書き込むタイミングは、countが63の時に、なります。




    よさげですね。

    最後は、擬似データを消して、本来のHDL記述に組み込みます。



//////////////////////////////////////////////////////////////////////////////////
// Company:
// Engineer:
//
// Create Date:    15:11:40 11/06/2010
// Design Name:
// Module Name:    myADC
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//////////////////////////////////////////////////////////////////////////////////
module myADC (clk,D,neg_q,q);
 input clk;
 input D;
 output neg_q;
 output  q;
 
 reg Qinner = 0;
 wire q_inter;

/// DCM //////////////////////////////////
   wire RST_IN;
   wire CLKFX_OUT;
   wire CLKIN_IBUFG_OUT;
   wire CLK0_OUT;
   wire LOCKED_OUT;
//// fir //////////////////////////////////////
 wire signed[23:0]fir_result_signed;
 wire [23:0]fir_result_unsigned;
//// CIC////////
 wire signed[6:0]data_out_signed;
 wire [6:0]data_out_unsigned;
 wire devided_clk;

 wire signed[6:0]douta;


 myDCM instance_name (
  .CLKIN_IN(clk),
  .RST_IN(RST_IN),
  .CLKFX_OUT(CLKFX_OUT),
  .CLKIN_IBUFG_OUT(CLKIN_IBUFG_OUT),
  .CLK0_OUT(CLK0_OUT),
  .LOCKED_OUT(LOCKED_OUT)
    );
//need for 1bit ADC
  assign neg_q = ~Qinner;
// This is not a correct way  to multiply 1bit signals,but works good. 
 assign q_inter = CLKFX_OUT ~^ Qinner; //multiply 1bit singnals  : CLKFX_OUT=6.818MHz 1bit sgnal ,D=7MHz 1bit signal
 

 cic_filter cic(CLK0_OUT,q_inter,data_out_signed,devided_clk);//1/64 decimation

 my_fir my_fir(CLK0_OUT,data_out_signed,fir_result_signed);

 assign fir_result_unsigned=fir_result_signed+24'h7f_ffff;
 accum #(24) accum2(CLK0_OUT,fir_result_unsigned,q);

 always @(posedge CLK0_OUT) begin 
  Qinner = D;
 end

endmodule

  
       それらしい....                                                                     拡大

       なんとか、思い出せました  (^_^;;

H.23.02.03