在信号处理系统中,经常需要在不同的采样率之间进行转换,例如在数字上变频/下变频过程中。本章我们将探索一种极其高效的多速率滤波器——级联积分梳状(CIC)滤波器。与需要大量乘法器的FIR滤波器不同,CIC滤波器仅由加法器、减法器和寄存器构成,资源消耗极低,非常适合用于高速、大倍数的采样率转换。
在本章的实战项目中,我们将构建一个完整的“回环”系统:首先,一个低频正弦波将通过CIC插值滤波器,将其采样率提高10倍,您将观察到波形如何因此变得更加“光滑”;随后,这个高速信号将立即送入CIC抽取滤波器,将采样率降低回原始值。我们的目标是,最终恢复出的信号与原始信号保持一致。通过这个直观的“先升后降”实验,您将深刻理解CIC滤波器在抗镜像滤波和抗混叠滤波中的核心作用,并掌握在Vivado中配置和级联CIC IP核的方法。
1项目目标
用DDS生成一个采样率为5MHz,频率为1MHz的正弦波,通过CIC插值滤波器之后,这个正弦信号的采样率变为50MHz,频率不变,正常现象应该为波形变光滑;然后再将这个采样率为50MHz,频率为1MHz的正弦波,通过CIC抽取滤波器,这个正弦信号的采样率还原为5MHz,频率不变,正常现象应该为波形变粗糙,与DDS生成的基本一致。
2 CIC滤波器简介
1. CIC滤波器核心原理
CIC (Cascaded Integrator-Comb),即级联积分梳状滤波器,是一种非常高效的多速率数字滤波器。它最大的特点是不需要乘法器,只使用加法器、减法器和寄存器,因此在FPGA和ASIC中实现时资源消耗极低,速度非常快,特别适合于高速、大规模的采样率转换。
CIC滤波器由两个基本部分组成:
积分器 (Integrator): 本质上是一个累加器。其差分方程是 y[n] = y[n-1] + x[n]。它的作用是在时域上进行累加,在频域上则是一个低通滤波器,但响应曲线非常粗糙。
梳状滤波器 (Comb): 本质上是一个延迟相减的结构。其差分方程是 y[n] = x[n] - x[n-M],其中 M 是差分延迟(Differential Delay)。它的作用是在频域上产生周期性的零点,像一 把梳子一样滤除特定频率的信号。
一个完整的N阶CIC滤波器,就是将N个积分器和N个梳状滤波器级联起来。
关键参数:
R (Rate Change Factor): 采样率转换因子。例如,抽取时,速率从 R * Fs 变为 Fs。插值时,速率从 Fs 变为 R * Fs。
N (Number of Stages): 级联的阶数。N越大,滤波器的阻带衰减越大,通带滚降(Droop)也越严重。通常取3到6阶。
M (Differential Delay): 梳状滤波器的延迟。通常取1或2。
2. CIC插值与抽取滤波器
CIC滤波器的巧妙之处在于它将采样率转换(升采样/降采样)操作放在了积分器和梳状滤波器之间,从而使得一部分电路可以工作在低速时钟下,大大节省了功耗和资源。
a) CIC抽取滤波器 (Decimator)
用于降低采样率,结构是 积分器 -> 降采样 -> 梳状滤波器。
工作流程:
高速积分: 输入的高速数据(速率为 R * Fs)首先通过N级积分器。这部分电路必须工作在高速时钟下。
降采样 (Downsample): 积分后的数据以 R 的比例进行抽取,即每 R 个数据点只保留一个。这个操作是“免费”的,只需控制后续电路的时钟使能即可。
低速梳状滤波: 降采样后的低速数据(速率为 Fs)再通过N级梳状滤波器。这部分电路工作在低速时钟下,非常节省资源。
频域特性:CIC抽取滤波器的频率响应是一个Sinc函数的N次方。它会在 Fs/R 的整数倍频率处产生频谱混叠(Aliasing)。它的主要作用是作为抗混叠滤波器,滤除大部分高频噪声,防止它们混叠到目标频带内。但由于其通带不平坦(滚降严重)且阻带衰减有限,通常后面会跟一个补偿滤波器(如FIR)来修正其响应。
b) CIC插值滤波器 (Interpolator)
用于提高采样率,结构是 梳状滤波器 -> 升采样 -> 积分器。结构正好与抽取相反。
工作流程:
低速梳状滤波: 输入的低速数据(速率为 Fs)首先通过N级梳状滤波器。这部分电路工作在低速时钟下。
升采样 (Upsample): 梳状滤波后的数据进行 R 倍插零,即在每两个原始数据点之间插入 R-1 个零。
高速积分: 升采样后的高速数据(速率为 R * Fs)通过N级积分器。积分器的累加特性可以“填补”插入的零点,实现平滑插值。这部分电路工作在高速时钟下。
频域特性:CIC插值滤波器的主要作用是作为抗镜像滤波器。升采样会在基带信号周围产生频谱镜像(Images),CIC滤波器可以滤除这些镜像。它的频率响应同样是Sinc函数的N次方,这会导致通带内的信号幅度被衰减(滚降/Droop),因此通常在CIC插值器之前会加一个预补偿滤波器(如FIR)来提前拉高信号。
3 FPGA 实现
同样这里提供了以官方IP的开发方式,但用户也可以自行尝试用纯verilog来实现这个CIC滤波器。
1.CIC IP简介
1.1
1.2
左边的Tab可以切换看到CIC的模块图(IP Symbol,管脚)、频率响应(Freq Response)等信息。右边的Tab是对CIC滤波器进行设计:
Filter Specification:
Filter Type:设置CIC滤波器模式为抽取Decimation或插值Interpolation;
Number Of Stages:设置级联的CIC滤波器级数,支持3-6级;
Differential Delay:差分延迟,可选1或者2;
Number Of Channels:支持单通道或者多通道(最大16通道)。
Sample Rate Change Specification:
Sample Rate:固定(Fixed)或者可编程(Programmable)速率改变(4~8192),
抽取因子R或插值因子R。
Hardware Oversampling Specification:
Rate Specification:Frequency Specification / Sample Period。
选择使用哪种格式来指定硬件过采样率、内核可用于处理输入样本并生成输出的时钟周期数。该值直接影响核心实现中的并行程度和使用的资源。选择频率规范时,您需要指定输入采样频率和时钟频率。这些值与其他核心参数之间的比率决定了硬件过采样率。选择采样周期时,您需要指定输入样本之间的整数个时钟周期。
Input Sample Frequency:该字段可以是整数或实值。它指定一个通道的采样频率。上限是根据时钟频率和滤波器参数(如插值率和通道数)设置的。
Clock Frequency:该字段可以是整数或实值。限制是根据采样频率、插值率和通道数设置的。注意:此字段仅影响架构选择;最终实现可能无法实现指定的时钟速率。
Sample Period:输入采样周期:输入采样之间的整数个时钟周期。当指定了多个通道时,该值应该是时分复用输入采样数据流之间的整数个时钟周期。
Numerical Precision:
Input Data Width:输入数据位宽(2-32)。
Quantization:全精度(Full Precision)或者非全精度数据输出。
Output Data Width:输出数据位宽。
Optional:
可选的映射到DSP48 Slices。
Control Options:
支持输入同步清零,支持输入时钟使能,以及输出延迟。
以上仅为粗略的简介,更多请参考官方文档-pg140-cic-compiler。
2.实验代码
以下为预开发demo的顶层:
`timescale 1ns / 1ps
module top (
input I_sysclk_p ,//100Mhz差分时钟
input I_sysclk_n ,//100Mhz差分时钟
input I_rst_n ,
output O_led
);
/******************************************************************\
变量声明
\******************************************************************/
//clock
wire clk_50m ;
wire clk_5m ;
//DDS
wire signed [ 15: 0] dds_data_1m ;
wire dds_data_1m_valid ;
wire phase_tvalid_1m ;
wire [ 31: 0] phase_tdata_1m ;
//CIC
wire cic_data_50m_ready ;
wire signed [ 15: 0] cic_data_50m ;
wire cic_data_50m_valid ;
wire cic_data_5m_ready ;
wire signed [ 15: 0] cic_data_5m ;
wire cic_data_5m_valid ;
/******************************************************************\
时钟管理模块
\******************************************************************/
clk_wiz_0 clock_and_reset
(
.clk_out1(clk_50m),
.clk_out2(clk_5m),
.clk_in1_p(I_sysclk_p),
.clk_in1_n(I_sysclk_n)
);
/******************************************************************\
DDS模块
\******************************************************************/
//dds产生采样率为5MHz的1MHz正弦信号。
dds_compiler_0 dds_32_16_1m (
.aclk(clk_5m),
.m_axis_data_tvalid(dds_data_1m_valid),
.m_axis_data_tdata(dds_data_1m),
.m_axis_phase_tvalid(phase_tvalid_1m),
.m_axis_phase_tdata(phase_tdata_1m)
);
/******************************************************************\
CIC插值模块
\******************************************************************/
cic_compiler_0 cic_inter_n5_r10 (
.aclk(clk_50m),
.s_axis_data_tdata(dds_data_1m),
.s_axis_data_tvalid(dds_data_1m_valid),
.s_axis_data_tready(cic_data_50m_ready),
.m_axis_data_tdata(cic_data_50m),
.m_axis_data_tvalid(cic_data_50m_valid)
);
/******************************************************************\
CIC抽取模块
\******************************************************************/
cic_compiler_2 cic_decim_n5_r10_0 (
.aclk(clk_50m),
.s_axis_data_tdata(cic_data_50m),
.s_axis_data_tvalid(cic_data_50m_valid),
.s_axis_data_tready(cic_data_5m_ready),
.m_axis_data_tdata(cic_data_5m),
.m_axis_data_tvalid(cic_data_5m_valid)
);
assign O_led = cic_data_5m_valid;
endmodule
| 仿真代码如下:
`timescale 1ns / 1ps
module tb_top();
//变量定义
reg I_sysclk_p;
reg I_rst_n;
wire O_led;
//信号初始化
initial begin
I_sysclk_p = 1;
I_rst_n = 0;
#300 I_rst_n = 1;
end
//100Mhz时钟
always #5 I_sysclk_p = ! I_sysclk_p ;
top top_inst (
.I_sysclk_p(I_sysclk_p),
.I_sysclk_n(~I_sysclk_p),
.I_rst_n(I_rst_n),
.O_led(O_led)
);
endmodule
|
4 实验结果
从仿真结果来看,dds_data_1m(黄色)经过CIC插值之后,cic_data_50m(紫色)波形变光滑;cic_data_50m经过CIC抽取之后,cic_data_5m(橙色)波形变粗糙,且与DDS生成的基本一致,故实验成功。
|