ΔΣ-ADC 実験編 その17 CICフィルタ詳細


1/128 decimation using 1st order CIC filter

 1.Lattice Diamondの BKM checkとは?



    素晴らしい機能です。


    たとえば

    CICフィルタの積分器のビット数を、適当に、仮に 41bitに設定したとします。(入力は、signed 18bit)


    BKM checkすると


    適当に設定した bit数が、

    「22bitまで、削れる」と、指示してくれるのです、 凄いで。

2.BKM checkをするには

    HDL言語による記述が、出来上がったら

    1. Synthesize Design を行います。

    2. Generate Hierachy


    3. run BKM check




    4. view Warning


    このBKM checkは、最終の JEDEC fileを生成する前にも、必ず行いましょう。

    余分なbit数を調べるために、そして、最終的に出力される波形が正しいかどうかをcheckするには

    Functional simulationも行ったほうが、いいです。

3.Functional simulationを行うには

    先ず、HDL記述の何処かに


///////////////////////////////////////////////////
 PUR  PUR_INST (.PUR (RST_PULSE));
 GSR  GSR_INST (.GSR (GSRNET));    
///////////////////////////////////////////////////

    を、挿入します。

    次に、menuから Tools ->Simulation Wizard


    後は、全部 return keyを押します。

4.CIC filter 1段で調べてみます。

    先ほど、ynを 41bitに設定しました。

    これを観察すると


    確かに、bit数が、余っているようです。



    どうやら、24bit目が、符号bitの様子です。
    
    そんなんで、bit数を調整して


    やれやれと、安心していると



    いっ! BKM checckは、「まだ 削れる」と、言っています。

    で、お教えに従いまして


    うーむ、最終出力は、正しい。

    BKMは、非常に強力な武器で、あります、御礼。

    結局


    [22:0]を主体に、最終決定しました。

    CIC filter 1段では




    勿論、 Holdでも、正常に終了します。


    で、JEDEC fileを生成し、 

    CIC filter1段で、1/32 decimationを、行いました。

 
  
    この結果は、あくまでも

    1bit delta sigma bandpass ADCの 1bit出力が、入力だという、条件です。

    以下は、CIC filter 1段の verilog記述全文です。
 
module myADC( clk,D,neg_q,q );

 input  clk;
 input  D;
 output  neg_q;
 output  q;

//////////////////////////////////////
 wire clkop;
 wire lock;
 reg Qinner=0;
 
 reg [9:0]theta=0;
 wire signed[17:0]sine;
 wire  signed[17:0]mixed_sin;
 wire signed[22:0]result_wire;   
 wire [22:0]result_wire_unsigned;
/*
////////////////////////////////////////////////////
 PUR  PUR_INST (.PUR (RST_PULSE));
 GSR  GSR_INST (.GSR (GSRNET));    
///////////////////////////////////////////////////
*/

 //use myPLL instance
 myPLL  myPLL(.CLK(clk),.CLKOP(clkop),.LOCK(lock));
 
 sin   sin(.Clock(clk), .ClkEn(1'b1), .Reset(1'b0), .Theta(theta), .Sine(sine));
 cic_filter  cic(clkop,mixed_sin,result_wire);

 assign neg_q=~Qinner;
 assign mixed_sin=(Qinner ? sine : -sine);
 assign result_wire_unsigned={~result_wire[22],result_wire[22-1:0]};
 
 accum #(23) accum(clkop,result_wire_unsigned,q);

 always@(posedge clkop) begin
  Qinner =D;
 end
 
 always@(posedge clk) begin
  theta=theta+64;
 end

endmodule


module cic_filter(clk,data_input,data_out);
 input clk;
 input signed[17:0]data_input;
 output signed[22:0]data_out;
 
 reg signed[22:0]z[1:0]; 
 reg signed[22:0]yn=0;
 reg signed[22:0]yn_1=0;
 reg signed[22:0]result=0;

 reg [5:0]count=0;
 assign data_out=result;
 
 always@(posedge clk) begin
 //scaling factor : MOVING_AVEは、省略する。
 //integrator
  yn=yn_1+data_input;
  yn_1=yn;
    
  count=count+1;
  if(count==32) begin   //decimation ratio=1/32
   z[1]=z[0]; 
   z[0]=yn;
   count=0;
  //differentiator
   result=z[0]-z[1];
  end

 end

 /*
 initial begin
  z[0]<=0;
 end
 */
endmodule

module accum(clk,VDA,cy_out);

 parameter DATA_WIDTH2=18;
 input  clk;
 input  [DATA_WIDTH2-1:0] VDA;
 output cy_out;

///// internal variables ////////
 reg [DATA_WIDTH2-1:0] R=0;
 reg cy=0;

 assign cy_out= cy;

 always @(posedge clk) begin
  {cy,R} <=R+ VDA;
 end

endmodule

 
H.22.9.2