CIC滤波器和FPGA实现
CIC滤波器
CIC滤波器是用不同抽样频率进行数字信号处理的一种FIR滤波器。主要用于数字信号的抽取和内插。
CIC滤波器由一对或多对积分-梳状滤波器组成,在抽取CIC中,输入信号依次经过积分、降采样,以及与积分环节数目相同的梳状滤波器。在内插CIC中,输入信号依次经过梳状滤波器,升采样,以及与梳状数目相同的积分环节。
什么是多采样率数字滤波器?
一般的滤波器都只有一种采样频率,有些情况下,系统内部需要不同采样频率的数字信号,这样就需要使用CIC滤波器对信号进行上采样或者下采样,进而获得相应采样率下的信号。
基于初始采样频率f1
,第二采样频率要么是高于f1
,要么是低于f1
。前者实现的原理是内插,后者是抽取。
抽取
含义:一个有用的正弦波模拟信号经采样频率为f1
的抽样信号抽样后得到了数字信号,很明显这个数字信号序列是在f1频率下得到的,现在,假如我隔几个点抽取一个信号,比如就是5吧,我隔5个点抽取一个信号,是不是就是相当于我采用了1/5倍f1的采样频率对模拟信号进行采样了?所以,抽取的过程就是降低抽样率的过程,但是我们知道,这是在时域的抽样,时域的抽样等于信号在频域波形的周期延拓,周期就是采样频率,所以,为了避免在频域发生频谱混叠,抽样定理也是我们要考虑的因素(通常下级需要滤波器滤出周期性频率)。
抽取造成的问题之一就是频谱的混叠。因为时域的抽样等于信号在频域波形的周期延拓,如果下采样倍数太小,就会造成频谱在频域混叠。根据采样定理,
当采样频率fs是信号(最高)频率f0的2倍时,正好不发生频谱混叠。
下采样时也要遵循相同的定理,即下采样后的采样频率fs/M,至少是信号频率f0的2倍。
下图是对信号进行f1抽样得到的频谱
故在下采样前需要对信号进行抗混叠滤波,其效果就是滤出频谱中 1/2 * (F1/M)之后的频率。
CIC
级联积分梳妆滤波器(Cascade Intergrator Comb
),将积分器和梳妆滤波器级联而得。
Need To Know:
- 低通滤波特性
- 滤波系数为1,无需对系数进行存储,节省存储单元,无需乘法器
- 结构规则,设置抽取/插值因子时候不改变滤波器整体结构。
- 输入信号通过CIC滤波器后会引起位增长问题,工程上要适当截位。
从上图可以看出:
- 在内插系统中,CIC滤波器的级联方式是:
积分器+抽样因子+梳状滤波器
。 - 积分器结构:输出延迟y(n-1)后与输入x(n)相加
- 梳状滤波器器结构:输入延迟x(n-1)后与输入x(n)相减
积分器
积分器是一个具有单极点的、同一反馈系数的IIR滤波器,积分器在时域上的表达式是:
积分器的结构如下图所示:
梳状滤波器
梳状滤波器在高采样率fs、抽取因子为R的情况下,是一个奇异的FIR滤波器,在时域上的表达式:
其中,R,M为整数,决定了梳妆滤波器的延迟长度。
基本梳状滤波器的结构是:
FPGA实现CIC滤波器
下图所示一个N级抽取系统的结构图(抽样倍数为D):
参考代码:
`timescale 1ns/1ns
module CIC #(parameter width = 12 ) (
input wire clk,
input wire rst,
input wire [ 15:0 ] decimation_ratio, //抽取因子
input wire signed [ 7:0 ] d_in,
output reg signed [ 7:0 ] d_out,
output reg d_clk //输出下采样后的时钟
) ;
reg signed[ width-1:0 ] d_tmp,
d_d_tmp ;
// Comb stage registers-梳妆滤波器
reg signed[ width-1:0 ] d6,
d_d6 ;
reg signed[ width-1:0 ] d7,
d_d7 ;
reg signed[ width-1:0 ] d8,
d_d8 ;
reg signed[ width-1:0 ] d9,
d_d9 ;
reg signed[ width-1:0 ] d10 ;
reg[ 15:0 ] count ; //抽取计数器
reg v_comb ; // Valid signal for comb section running at output rate
reg d_clk_tmp ;
// Integrator stage registers-积分器
//CIC级联数目为5
reg signed[ width-1:0 ] d1 ;
reg signed[ width-1:0 ] d2 ;
reg signed[ width-1:0 ] d3 ;
reg signed[ width-1:0 ] d4 ;
reg signed[ width-1:0 ] d5 ;
always @(posedge clk) begin
if (rst) begin
d1 <= 0 ;
d2 <= 0 ;
d3 <= 0 ;
d4 <= 0 ;
d5 <= 0 ;
count <= 0 ;
end
else begin
// Integrator section-y(n) = x(n) + y(n-1)
d1 <= d_in + d1 ;
d2 <= d1 + d2 ;
d3 <= d2 + d3 ;
d4 <= d3 + d4 ;
d5 <= d4 + d5 ;
// Decimation-抽取
if (count == decimation_ratio - 1) begin
count <= 16'b0 ;
d_tmp <= d5 ;
d_clk_tmp <= 1'b1 ;
v_comb <= 1'b1 ;
end
else if (count == decimation_ratio >> 1) begin
d_clk_tmp <= 1'b0 ;
count <= count + 16'd1 ;
v_comb <= 1'b0 ;
end
else begin
count <= count + 16'd1 ;
v_comb <= 1'b0 ;
end
end
end
always @(posedge clk) begin // Comb section running at output rate
d_clk <= d_clk_tmp ;
if (rst) begin
d6 <= 0 ;
d7 <= 0 ;
d8 <= 0 ;
d9 <= 0 ;
d10 <= 0 ;
d_d6 <= 0 ;
d_d7 <= 0 ;
d_d8 <= 0 ;
d_d9 <= 0 ;
d_out <= 8'b0 ;
end
else begin
if (v_comb) begin //v_comb set 1 when count == decimation_ratio
// Comb section-y(n) = x(n) - x(n-1)
d_d_tmp <= d_tmp ;
d6 <= d_tmp - d_d_tmp ;
d_d6 <= d6 ;
d7 <= d6 - d_d6 ;
d_d7 <= d7 ;
d8 <= d7 - d_d7 ;
d_d8 <= d8 ;
d9 <= d8 - d_d8 ;
d_d9 <= d9 ;
d10 <= d9 - d_d9 ;
d_out <= d10 >>> (width - 8) ;
end
end
end
endmodule