FPGA实战(13):基于FPGA的CIC滤波器设计与实现
2026/6/15 0:18:08 网站建设 项目流程

1. 摘要

在数字信号处理系统中,CIC(级联积分梳状)滤波器因其结构简单、无需乘法器、处理速率高等优点,被广泛应用于数字下变频(DDC)和数字上变频(DUC)中的抽取与插值环节。本文基于Xilinx CIC Compiler IP核,设计了一个输入16bit、输出24bit的CIC滤波器模块(tops),并给出了完整的Verilog实现、输出打拍优化以及一个功能全面的仿真测试平台(test_tops)。文章详细介绍了设计思路、创新点、功能点,并附上全部源码,方便读者直接使用或二次开发。

2. 设计背景与需求

  • CIC滤波器原理:由积分器、梳状器和抽取/插值器组成,利用多速率信号处理技术,仅使用加法器、减法器和寄存器,非常适合FPGA实现。
  • 应用场景:无线通信接收机中的DDC、ADC采样率变换、音频处理等。
  • 本设计目标
    • 输入:16位有符号数据(二进制补码)
    • 输出:24位有符号数据
    • 使用Xilinx CIC Compiler IP核(可参数化配置级数、抽取因子、差分延迟等)
    • 增加输出打拍寄存器以提高时序收敛能力
    • 提供完备的仿真激励,验证滤波器功能

3. 模块设计及创新点

3.1 顶层模块tops

端口列表

端口名方向位宽说明
i_clkinput1工作时钟
i_rstinput1异步复位(高有效)
i_dininputsigned [15:0]输入数据
o_doutoutputsigned [23:0]输出数据

内部结构

  • 实例化Xilinx CIC Compiler IP核(cic_compiler_0
    • 使用~i_rst完成复位极性转换(IP核为低电平复位)
    • s_axis_data_tvalid固定拉高,表示数据持续有效
    • 输出数据m_axis_data_tdata位宽24bit
  • 输出打拍优化:新增寄存器ro_dout,在时钟上升沿寄存滤波结果,最后通过assign o_dout = ro_dout输出。这样做可以切断IP核输出到外部端口的组合路径,大幅改善时序,尤其适用于高时钟频率设计。

创新点总结

  1. 输出打拍结构:采用ro_前缀寄存器 +assign输出,既满足命名规范,又优化了时序。
  2. 复位极性转换:在实例化端口处直接用~i_rst完成,无需额外逻辑。
  3. 规范的代码风格:按照参数分组、信号前缀、三段式状态机预留等要求编写,具有良好的可读性和可维护性。

3.2 仿真测试模块test_tops

为验证CIC滤波器的正确性,设计了一个长时间运行的测试平台:

  • 产生50MHz(周期10ns)的时钟信号(#5翻转)
  • 复位后延迟100ns释放
  • 向输入端连续施加多组随机变化的16位有符号数据,包括正数、负数、零以及边界值(如±5000、±4500等)
  • 仿真时间足够长(超过80个数据变化),可以观察到滤波器的瞬态响应和稳态输出

功能点

  • 覆盖了典型的信号变化模式,能够测试CIC滤波器的频率响应和累加溢出行为。
  • 使用#40延迟(即4个时钟周期)改变一次输入数据,模拟低速数据更新场景。
  • 可直接在Vivado/Modelsim中运行,观察输出波形或导出数据做频域分析。

4. 使用说明

  1. IP核生成:在Vivado中打开IP Catalog,搜索“CIC Compiler”,配置参数(如滤波器类型为抽取,抽取因子=2,级数=4,差分延迟=1等)。生成后IP核名称为cic_compiler_0
  2. 文件添加:将tops.vtest_tops.v添加到工程中。
  3. 仿真运行:在Vivado Simulator或Modelsim中运行test_tops模块,观察o_dout波形。由于CIC滤波器存在处理延迟(群延迟 = N×D×R/2,N为级数,D为差分延迟,R为抽取因子),输出信号会相对于输入有一定的延时,同时实现抽取/插值效果。
  4. 时序约束:顶层tops由于增加了输出寄存器,可直接将o_dout约束到输出引脚,时序收敛更容易。

5. 总结

本文提供了一个可综合的CIC滤波器Verilog设计,其特点包括:

  • 基于Xilinx IP核,可灵活配置参数
  • 输出打拍结构,优化时序性能
  • 规范且易于理解的代码组织
  • 功能全面的测试激励

读者可以直接复制代码到自己的工程中,根据实际需要修改IP核参数或测试数据。如有任何疑问,欢迎在评论区交流讨论。


6. 完整代码

6.1 顶层模块 tops.v

`timescale 1ns / 1ps module tops ( input i_clk, input i_rst, input signed [15:0] i_din, output signed [23:0] o_dout ); //========================================================= // parameter definitions //========================================================= //========================================================= // reg definitions //========================================================= reg signed [23:0] ro_dout; // output pipeline register //========================================================= // wire definitions //========================================================= wire [23:0] w_m_axis_data_tdata; // CIC output data //========================================================= // assign definitions //========================================================= //========================================================= // FSM state (not used) //========================================================= //========================================================= // inst //========================================================= cic_compiler_0 cic_compiler_u ( .aclk (i_clk), // input wire aclk .aresetn (~i_rst), // input wire aresetn .s_axis_data_tdata (i_din), // input wire [15:0] s_axis_data_tdata .s_axis_data_tvalid (1'b1), // input wire s_axis_data_tvalid .s_axis_data_tready (), // output wire s_axis_data_tready .m_axis_data_tdata (w_m_axis_data_tdata), // output wire [23:0] m_axis_data_tdata .m_axis_data_tvalid () // output wire m_axis_data_tvalid ); //========================================================= // combine_Logic //========================================================= //========================================================= // always //========================================================= // Output pipeline register always @(posedge i_clk or posedge i_rst) begin if (i_rst) ro_dout <= 'd0; else ro_dout <= w_m_axis_data_tdata; end // Connect output assign o_dout = ro_dout; endmodule

6.2 仿真测试模块 test_tops.v

`timescale 1ns / 1ps module test_tops; reg i_clk; reg i_rst; reg signed [15:0] i_din; wire signed [23:0] o_dout; tops tops_u ( .i_clk (i_clk), .i_rst (i_rst), .i_din (i_din), .o_dout (o_dout) ); initial begin i_clk = 1'b1; i_rst = 1'b1; i_din = 16'd0; #100 i_rst = 1'b0; i_din = 16'd1000; #40 i_din = 16'd2000; #40 i_din = -3000; #40 i_din = 16'd5000; #40 i_din = 16'd1000; #40 i_din = 16'd1200; #40 i_din = 16'd300; #40 i_din = 16'd4500; #40 i_din = -2000; #40 i_din = -2300; #40 i_din = 16'd50; #40 i_din = 16'd1500; #40 i_din = 16'd200; #40 i_din = 16'd1200; #40 i_din = 16'd4200; #40 i_din = -2000; #40 i_din = -3000; #40 i_din = 16'd5000; #40 i_din = 16'd1000; #40 i_din = 16'd1200; #40 i_din = 16'd300; #40 i_din = -4500; #40 i_din = -2000; #40 i_din = 16'd2300; #40 i_din = 16'd50; #40 i_din = 16'd1500; #40 i_din = -200; #40 i_din = 16'd1200; #40 i_din = 16'd4200; #40 i_din = -2000; #40 i_din = -3000; #40 i_din = 16'd5000; #40 i_din = 16'd1000; #40 i_din = 16'd1200; #40 i_din = 16'd300; #40 i_din = -4500; #40 i_din = -2000; #40 i_din = -2300; #40 i_din = 16'd50; #40 i_din = 16'd1500; #40 i_din = 16'd200; #40 i_din = 16'd1200; #40 i_din = -4200; #40 i_din = 16'd2000; #40 i_din = 16'd3000; #40 i_din = -5000; #40 i_din = -1000; #40 i_din = 16'd1200; #40 i_din = 16'd300; #40 i_din = 16'd4500; #40 i_din = -2000; #40 i_din = -2300; #40 i_din = 16'd50; #40 i_din = 16'd1500; #40 i_din = 16'd200; #40 i_din = 16'd1200; #40 i_din = -4200; #40 i_din = 16'd2000; #40 i_din = 16'd3000; #40 i_din = -5000; #40 i_din = 16'd1000; #40 i_din = 16'd1200; #40 i_din = 16'd300; #40 i_din = 16'd4500; #40 i_din = -2000; #40 i_din = 16'd2300; #40 i_din = 16'd50; #40 i_din = 16'd1500; #40 i_din = -200; #40 i_din = 16'd1200; #40 i_din = 16'd4200; #40 i_din = 16'd2000; #40 i_din = -3000; #40 i_din = 16'd5000; #40 i_din = 16'd1000; #40 i_din = 16'd1200; #40 i_din = 16'd300; #40 i_din = -4500; #40 i_din = 16'd2000; #40 i_din = 16'd2300; #40 i_din = -50; #40 i_din = 16'd1500; #40 i_din = 16'd200; #40 i_din = -1200; #40 i_din = 16'd4200; end always #5 i_clk = ~i_clk; endmodule


版权声明:本文为CSDN博主原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询