CIC滤波器的Matlab仿真与FPGA实现

CIC滤波器

1、单级CIC滤波器:

CIC滤波器的冲激响应为:

h(n)=1[0,M-1]

h(n)=0,其他

可见CIC滤波器在时域上是一个矩形窗,是一个累加器(积分器)。

 

MATLAB仿真不同长度的CIC滤波器:

M=5;      

b=ones(1,M);

[Hz,f]=freqz(b,1,1000,1024);

Plot(f*2/1000,20*log10(abs(Hz)));

由上图可知,CIC滤波器的频率响应的包络是sin(x)/x类型,长度越长,通带衰减越大,但旁辨的衰减几乎固定为13.46dB(矩形窗的频谱第一个旁辨的衰减最大为13.46dB)。阻带这么小是不能满足设计要求的,所以要多级CIC级联。

 

CIC滤波器在0Hz的增益为

abs(sin(0)/sin(0))

对上式使用洛必达法则,得

cos(wD/2)(D/2) / (cos(w/2)*1/2)=cos(0)*(D/2)/cos(0)/2=D

所以一个CIC滤波器的DC0Hz)增益等于梳状滤波器的延迟D

 

2、多级CIC:

Matlab仿真不同长度的5CIC滤波器的频谱特性。

 

M=2;         %滤波器长度

b=ones(1,M);

delta=[1,zeros(1,1023)];

s1=filter(b,1,delta);        %求取滤波器冲激响应

s2=filter(b,1,s1);           %求取滤波器冲激响应

s3=filter(b,1,s2);           %求取滤波器冲激响应

s4=filter(b,1,s3);           %求取滤波器冲激响应

s=filter(b,1,s4);            %求取滤波器冲激响应

Spec=20*log10(abs(fft(s)));%求取滤波器频谱特性

Spec2=Spec-max(Spec);

f=0:length(Spec)-1;

f=2*f/(length(Spec)-1);     %对频率轴进行归一化处理

5CIC级联,旁辨的衰减达到13.46*5=67.3dB,但同时主辨的电平值下降也比单级快得多,在通带内,通带衰减明显增加。所以CIC滤波器适合在多速率系统的前端(第一、二级),CIC滤波器的波纹较大,因为通带与采样频率的比率相对较小,随着通带与采样频率的比率的增加,就必须采用畸变较小的滤波器。

 

对于多级滤波器来说,各级的误差容限和系统的总误差容限的关系为:

ap=ap1+ap2+ap3+…..+apn

as=as1*as2*as3*…..*asn

通带容限增加时,通带衰减也增大;阻带误差容限减小(阻带衰减增大)。

 

可以总结出,多级CIC滤波器要求有用信号的频带相对于数据速率足够小,即用作窄带低通滤波器,才能满足通带容限的要求,否则CIC只能用在前端,后面要用性能较好的滤波器。在要求较高的场合,通常是CIC滤波器,半带滤波器和其它类型的FIR滤波器级联起来一起使用。

 

实际上,CIC滤波器最广泛的用处是实现抽取前端作为去假频滤波器,或内插后端作为去镜像谱滤波器,倍数小于等于7倍(3倍、5倍、7倍)。

 

为了提高在FPGA实现的运算速度并减少资源消耗,可根据Noble等式调整CIC滤波器的结构。

调换线性系统的抽取系统的处理顺序,即首先进行抽取,然后进行线性滤波,这样就可以将滤波器的长度降低M倍,即滤波器的长度抽头为原来的1/M倍。滤波器的时钟降低到1/M倍。

在内插时将滤波前置,就可以得到阶数降低为了L倍的滤波器。滤波器的时钟频率降低到1/L倍。

 

1、            Hogenauer滤波器:

采用Nobel恒等式原理,变换多级CIC滤波器结构需要采用IIR滤波器结构。

 

   通常直接在单位圆上有一个滤波器极点是危险的,但这里不一定会给我们带来麻烦,因为在传递函数H(z)中没有量化误差。CIC滤波器的系数都为1,因而可以用非常高的精度皇家马德里定点数格式表示。

    多级CIC滤波器级联,抽取因子RCIC级联系统的频率响应的影响并不大,当R大于16时,滤波器的形状变化都可以忽略,这使我们在变抽取速率系统中可以用相同的补偿FIR滤波器。

注意,Hogenauer抽取滤波器的梳状部分的延迟长度(差分延迟)N=D/R。因为按R抽取后N个样值的延迟等于按R抽取前的D个样值延迟。延迟值D的典型值为12。为了补偿CIC滤波器所造成的恶化,通常需要在多级CIC抽取后添加一个FIR滤波器(补偿器)补偿CIC滤波器不平的通带。

MATLAB仿真:

f1=1000;       %信号频率为1KHz

f2=30000;      %信号频率为40KHz

Fs=200*f1;      %采样频率为200KHz

M=5;          %CIC滤波器阶数

D=M;          %抽取因子

C=3;          %滤波器级数

N=10;         %量化位数

%产生信号

t=0:1/Fs:0.02;

c1=2*pi*f1*t;

c2=2*pi*f2*t;

si=sin(c1)+sin(c2);%产生正弦波

 

%%%%%%%%%%%%%%%%%%%%%%%%%%

%3级积分器

a=[1 -1];

g1=filter(1,a,si);

g2=filter(1,a,g1);

g=filter(1,a,g2);

%D倍抽取

Cg=g(1:D:length(t));

%3级梳状滤波

b=[1 -1];

Cg1=filter(b,1,Cg);

Cg2=filter(b,1,Cg1);

Cgh=filter(b,1,Cg2);

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

 

%绘出Matlab对正弦合成信号滤波前后的时域波形

figure(1);

subplot(211);stem(si(1:300));title('Matlab仿真滤波前信号波形');

x=x(1:D:length(x));

subplot(212);stem(Cgh(1:100));title('Matlab仿真滤波后信号波形');

下面给出3CIC滤波器的在FPGA实现的Verilog代码,实现时采用了Hogenauer“剪除”理论,具体内容见《数字信号处理的FPGA实现(第三版)》Page241,作者U.Meyer-Baese先生同时给出了剪除理论的程序。

       经过比较,使用Hogenauer“剪除”理论后,使用的LE减少了近大半,而且fmax提高了不少。

 

顶层模块:

module CIC_3_STEP(

      input CLK,

                   input RST_N,

                  

                   input signed[15:0] X_IN,

                   output signed[15:0] Y_OUT,

                   output RDY,

                   output signed[19:0] INT_OUT,

                   output signed[19:0] DE_OUT

);

 //wire RDY;

//wire signed[36:0]INT_OUT;

//wire signed[36:0]DE_OUT;

        

INTEGRATED   U1(

                                               .CLK(CLK),

                                               .RST_N(RST_N),

                                               .X_IN(X_IN),

                                               .INT_OUT(INT_OUT)

                                               );

 DECIMATE  U2(

                                      .CLK(CLK),

                                      .RST_N(RST_N),

                                      .IIN(INT_OUT),

                                      .DE_OUT(DE_OUT),

                                      .RDY(RDY)

             );

                                      

COMB       U3(

                                       .CLK(CLK),

                                       .RST_N(RST_N),

                                       .RDY(RDY),

                                       .DE_OUT(DE_OUT),

                                       .Y_OUT(Y_OUT)

                                     );

 Endmodule

 

梳状模块:

module COMB(

        input CLK,

                     input RST_N,

                    

                     input RDY,

                     input signed[19:0] DE_OUT,

                     output signed[15:0] Y_OUT

);

 

reg signed[19:0]buf1;

reg signed[18:0]buf2;

reg signed[17:0]buf3;

 

reg signed[19:0]y1;

reg signed[18:0]y2;

reg signed[17:0]y3;

 

 

always @ (posedgeCLK or negedge RST_N)

  if(RST_N == 1'B0)

     begin

            buf1 <= 0;

                    buf2 <= 0;

                    buf3 <= 0;

          end

         else if(RDY == 1'B1)

          begin

            buf1 <= DE_OUT;

                    buf2 <= y1[19:1];

                    buf3 <= y2[18:1];

                   end

                  

always @ (posedgeCLK or negedge RST_N)

  if(RST_N == 1'B0)

     y1 <= 0;

  else if(RDY == 1'b1)

     y1 <= DE_OUT - buf1;

          

 

always @ (posedgeCLK or negedge RST_N)

  if(RST_N == 1'B0)

     y2 <= 0;

         else if(RDY == 1'b1)

          y2 <= y1[19:1] - buf2 ;

          

always @ (posedgeCLK or negedge RST_N)

  if(RST_N == 1'B0)

     y3 <= 0;

         else if(RDY == 1'b1)

          y3<= y2[18:1] - buf3;

            

assignY_OUT = y3[17:2];

 

endmodule

抽取模块:

odule DECIMATE(

    input CLK,

          input RST_N,

          

          input signed[19:0] IIN,

          output signed[19:0] DE_OUT,

          output RDY

);

 

reg[2:0] cnt;

reg rdy;

reg[19:0] iin_buf;

 

always @ (posedgeCLK or negedge RST_N)

   if(RST_N == 1'B0)

           begin

                      cnt <= 0;

                            rdy <= 0;

                            iin_buf <= 0;

                   end

   else if(cnt == 3'd4)

           begin

                      cnt <= 0;

                            rdy <= 1'b1;

                            iin_buf <= IIN;

                   end

         else

           begin

                     cnt <= cnt + 1'b1;

                     rdy <= 1'b0;

                    end

                    

                    

assign RDY = rdy;

assign DE_OUT =iin_buf;

 

endmodule

 

积分模块:

module INTEGRATED(

         input CLK,

                            input RST_N,

                            input signed[15:0]X_IN,

                           

                            output signed[19:0]INT_OUT

                            );

 

regsigned[22:0] int1;

regsigned[20:0] int2;

regsigned[19:0] int3;

 

//第一阶积分器

always@ (posedge CLK or negedge RST_N)                            

         if(RST_N == 1'B0)

           int1 <= 0;

         else

           int1 <= int1 + X_IN;

 

//第二阶积分器

always@ (posedge CLK or negedge RST_N)                            

         if(RST_N == 1'B0)

           int2 <= 0;

         else

           int2 <= int1[22:2] + int2;

//第三阶积分器

always@ (posedge CLK or negedge RST_N)                            

         if(RST_N == 1'B0)

           int3 <= 0;

         else

           int3 <= int2[20:1] + int3;

 

assign INT_OUT =int3;                         

                           

endmodule

  • 7
    点赞
  • 52
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值