问答 店铺
热搜: ZYNQ FPGA discuz

QQ登录

只需一步,快速开始

微信登录

微信扫码,快速开始

微信扫一扫 分享朋友圈

已有 31 人浏览分享

开启左侧

第八章CIC 插值滤波器与CIC抽取滤波器回环

[复制链接]
31 0
       在信号处理系统中,经常需要在不同的采样率之间进行转换,例如在数字上变频/下变频过程中。本章我们将探索一种极其高效的多速率滤波器——级联积分梳状(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
image.jpg
1.2
image.jpg
       左边的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:输入采样周期:输入采样之间的整数个时钟周期。当指定了多个通道时,该值应该是时分复用输入采样数据流之间的整数个时钟周期。
image.jpg
       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生成的基本一致,故实验成功。
image.jpg

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

0

关注

10

粉丝

150

主题
精彩推荐
热门资讯
    网友晒图
      图文推荐
        
        • 微信公众平台

        • 扫描访问手机版