m基于FPGA的积分梳状CIC滤波器verilog设计
1.算法描述
积分梳状滤波器,是指该滤波器的冲激响应具有如下形式:
其物理框图如图所示:
可见,CIC滤波器是由两部分组成:累积器H1和H2梳状滤波器的级联。
现若假设用N级CIC滤波器来代替,每一级的滤波器系数长度为R,每一级的差分延迟为M,抽取数为R,那么可以得到CIC抽取滤波器结构图:
可以看到,N级CIC滤波器在功能上相当于N级完全相同的FIR滤波器的级联。如果按传统的FIR滤波器方式实现,那么N级FIR滤波器的每一级都需要RM个存储单元和一个累加器,但如果用CIC方式实现,那么N级CIC滤波器的每一级只需要M个存储单元。
通常,由于CIC滤波器的传统结构需要大量的延迟单元,这会大大增加系统的硬件资源消耗,所以,在一般情况下,CIC滤波器采用的设计结构式Hogenauer结构形式,该结构形式如下所示:
采用这种结构之后,大大降低了系统延迟单元资源。
这里设计的五级CIC滤波器。那么其基本结构如上图所示,在降采样的左右都有五个延迟单元。
但是在CIC滤波的时候,会导致输出的位宽大大增加,但是如果单独对中间的处理信号进行截位,这会导致处理精度不够,从而影响整个系统的性能,所以,这里我们首先将输入的信号进行扩展。
由于我们输入的中频信号通过ADC是位宽为14,在下变频之后,通过截位处理,其输出的数据仍为14位,所以,我们将CIC滤波的输入为14位,但是考虑到处理中间的益处情况以及保证处理精度的需要,我们首先将输入位宽扩展为40位,从而保证了处理精度以及溢出的情况。
基于FPGA的5级CIC滤波器的设计与实现
这里首先说明一下为什么使用的级别是5级。从硬件资源角度考虑,CIC滤波器的级数太高,会导致最终输出的数据位宽很大,通过简单的验证,当CIC的级数大于5的时候,输出的位宽>50。这显然会导致硬件资源的大量占用,如果CIC级数太小,比如1,2级。这在其处理效果上没有任何意义,基本无法达到预计的效果,通过仿真分析,一般情况下,选择4级,5级比较合理,因此,这里我们选择5级的CIC滤波器。
5级滤波器的基本结构为:
2.仿真效果预览
版本vivado2019.2
3.verilog核心程序
module cic_top( i_clk, //input clock i_rst, //system reset i_din, //the input datas o_clk16, //the clock 8 clock o_dout //the output of CIC ); parameter WIDTH = 48; input i_clk; input i_rst; input[13:0] i_din; output o_clk16; output[WIDTH-1:0]o_dout; wire[WIDTH-1:0] result01 ; wire[WIDTH-1:0] result02 ; wire[WIDTH-1:0] result03 ; wire[WIDTH-1:0] result04 ; wire[WIDTH-1:0] result05 ; wire[WIDTH-1:0] adders; assign adders = {i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13], i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13], i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13], i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13],i_din[13], i_din[13],i_din[13],i_din};//spread the signal //level 1 //level 1 cic_jifen cic_jifen_u1( .i_clk (i_clk), .i_rst (i_rst), .i_din (adders), .o_dout (result01) ); //level 2 //level 2 cic_jifen cic_jifen_u2( .i_clk (i_clk), .i_rst (i_rst), .i_din (result01), .o_dout (result02) ); //level 3 //level 3 cic_jifen cic_jifen_u3( .i_clk (i_clk), .i_rst (i_rst), .i_din (result02), .o_dout (result03) ); //level 4 //level 4 cic_jifen cic_jifen_u4( .i_clk (i_clk), .i_rst (i_rst), .i_din (result03), .o_dout (result04) ); //level 5 //level 5 cic_jifen cic_jifen_u5( .i_clk (i_clk), .i_rst (i_rst), .i_din (result04), .o_dout (result05) ); //================================================================ //================================================================ reg[3:0]cnt = 4'b00000; always @(posedge i_clk or posedge i_rst) begin if(i_rst) begin cnt <= 4'b0000; end else begin cnt <= cnt + 4'b0001; end end assign o_clk16 = cnt[3]; //================================================================ wire[WIDTH-1:0] result11 ; wire[WIDTH-1:0] result12 ; wire[WIDTH-1:0] result13 ; wire[WIDTH-1:0] result14 ; wire[WIDTH-1:0] result15 ; //level 1 //level 1 cic_chaf cic_chaf_u1( .i_clk (o_clk16), .i_rst (i_rst), .i_din (result05), .o_dout (result11) ); //level 2 //level 2 cic_chaf cic_chaf_u2( .i_clk (o_clk16), .i_rst (i_rst), .i_din (result11), .o_dout (result12) ); //level 3 //level 3 cic_chaf cic_chaf_u3( .i_clk (o_clk16), .i_rst (i_rst), .i_din (result12), .o_dout (result13) ); //level 4 //level 4 cic_chaf cic_chaf_u4( .i_clk (o_clk16), .i_rst (i_rst), .i_din (result13), .o_dout (result14) ); //level 5 //level 5 cic_chaf cic_chaf_u5( .i_clk (o_clk16), .i_rst (i_rst), .i_din (result14), .o_dout (result15) ); assign o_dout = result15; endmodule 01_115m