跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
编程语言算法

FPGA 实现 CIC 抽取滤波器:原理、位宽计算与 Verilog 实战

CIC 滤波器作为无乘法器的 FIR 结构,在 FPGA 多速率信号处理中资源占用低。文章详解其积分梳状原理、级联对阻带抑制与通带衰减的影响,以及最大位宽计算公式。通过 3 级、抽取因子 16 的 Verilog 实例,展示了从模块设计到顶层调用的完整流程,并分析了不同参数下的仿真波形,为数字下变频系统提供实用的硬件实现参考。

孤勇者发布于 2026/3/28更新于 2026/9/1059 浏览

FPGA 实现 CIC 抽取滤波器

什么是 CIC 滤波器

CIC(级联积分梳状)滤波器是一种高效的多速率信号处理结构,本质上属于无乘法器的线性相位 FIR 滤波器。在数字下变频(DDC)和数字上变频(DUC)场景中,它凭借结构简单、仅依赖加法器和寄存器而成为首选方案。

CIC 滤波器主要有三种工作模式:

  • 抽取滤波器:将高速输入数据流降为低速输出,常用于降低采样率或 DDC 前端。
  • 插值滤波器:将低速输入升为高速输出,用于提升采样率或 DUC 后端。
  • 单纯滤波器:输入输出速率一致,主要用于移动平均滤波。

其核心由积分器(Integrator)和梳状器(Comb)组成。积分器执行累加运算,状态方程为 $y[n] = y[n-1] + x[n]$;梳状器执行差分运算,状态方程为 $y[n] = x[n] - x[n-R]$,其中 R 为抽取/插值因子。由于单级 CIC 的第一旁瓣阻带衰减固定为 13.46dB,抑制能力有限,实际工程中常通过级联多级来提升性能。可以将级联想象成多层过滤系统:一级像纱网,二级加滤布,五级则相当于经过多重净化。通常 N=5 或 N=6 能在性能和资源间取得较好平衡。

以抽取为例,假设输入采样率 Fs 为 100MHz,抽取因子为 10,则输出速率为 10MHz。数据先经过多级积分器累加,随后在降采样点进入梳状器进行微分运算,最终得到抽取后的数值。

最大位宽计算

CIC 滤波器内部全是加减法,但积分器的累加效应会导致数据位宽随级数线性增长,这是硬件实现中最关键的资源考量点。

最大位宽计算公式如下:

$$B_{max} = B_{in} + N \times \lceil \log_2(R \times M) \rceil$$

其中:

  • $B_{in}$:输入位宽
  • $R$:抽取/插值因子
  • $M$:差分延迟(通常为 1)
  • $N$:级数

举例说明:若输入位宽 16 位,抽取因子 64,级数分别为 3、5、6 时:

  • N=3:16 + 3×6 = 34 位
  • N=5:16 + 5×6 = 46 位
  • N=6:16 + 6×6 = 52 位

可见级数增加会显著消耗寄存器和逻辑资源。增加级数虽然提升了阻带抑制(抗混叠/抗镜像),但也带来了通带衰减的副作用,尤其是通带边缘信号会被削弱,因此后续往往需要级联补偿 FIR 滤波器来校正幅频响应。

Verilog 代码实现

下面给出一个具体的 FPGA 实现案例,参数设定为 3 级、抽取因子 16。代码中已去除冗余的头部注释,直接聚焦于功能逻辑。

核心模块
`timescale 1ns /1ps

module cic_down_sample#(
    parameter DATA_IN_WIDTH  = 8,
    parameter DATA_OUT_WIDTH = 8,
    parameter CIC_FACTORS    = 16, // 抽取因子
    parameter MAX_WIDTH      = 20  // 最大位宽
)(
    input               clk,
    input               rstn,
    input signed [DATA_IN_WIDTH-1:0] data_in,
    input               data_in_valid,
    output signed [DATA_OUT_WIDTH-1:0] data_out
);

    wire signed[MAX_WIDTH-1:0] add_data_0;
    wire signed[MAX_WIDTH-1:0] add_data_1;
    wire signed[MAX_WIDTH-1:0] add_data_2;
    reg  signed[MAX_WIDTH-1:0] data_0;
    reg  signed[MAX_WIDTH-1:0] data_1;
    reg  signed[MAX_WIDTH-1:0] data_2;
    
    reg [4:0] cnt_div;
    reg       sample_flag; // 采样标志
    
    reg signed[MAX_WIDTH-1:0] comb_in;
    wire signed[MAX_WIDTH-1:0] add_comb_0;
    wire signed[MAX_WIDTH-1:0] add_comb_1;
    wire signed[MAX_WIDTH-1:0] add_comb_2;
    reg  signed[MAX_WIDTH-1:0] comb_0;
    reg  signed[MAX_WIDTH-1:0] comb_1;
    reg  signed[MAX_WIDTH-1:0] comb_2;

    // 积分器部分
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            data_0 <= 'd0;
            data_1 <= 'd0;
            data_2 <= 'd0;
        end else begin
            data_0 <= add_data_0;
            data_1 <= add_data_1;
            data_2 <= add_data_2;
        end
    end

    assign add_data_0 = {{12{data_in[7]}}, data_in} + data_0;
    assign add_data_1 = add_data_0 + data_1;
    assign add_data_2 = add_data_1 + data_2;

    // 降采样计数器
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            cnt_div <= 'd0;
        end else if (cnt_div == CIC_FACTORS - 1) begin
            cnt_div <= 'd0;
        end else begin
            cnt_div <= cnt_div + 1;
        end
    end

    // 采样使能信号
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            sample_flag <= 1'b0;
        end else if (cnt_div == CIC_FACTORS - 1) begin
            sample_flag <= 1'b1;
        end else begin
            sample_flag <= 1'b0;
        end
    end

    // 梳状器输入锁存
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            comb_in <= 'd0;
        end else if (sample_flag) begin
            comb_in <= add_data_2;
        end
    end

    // 梳状器部分
    always @(posedge clk or negedge rstn) begin
        if (!rstn) begin
            comb_0 <= 'd0;
            comb_1 <= 'd0;
            comb_2 <= 'd0;
        end else if (sample_flag) begin
            comb_0 <= comb_in;
            comb_1 <= add_comb_0;
            comb_2 <= add_comb_1;
        end
    end

    assign add_comb_0 = comb_in - comb_0;
    assign add_comb_1 = add_comb_0 - comb_1;
    assign add_comb_2 = add_comb_1 - comb_2;

    // 截断输出,保留高位有效位
    assign data_out = add_comb_2[19:12];

endmodule
顶层调用示例

在顶层文件中实例化该模块,并连接时钟复位及数据接口:

`timescale 1ns /1ps

module cic_top(
    input sysclk,
    input sysrstn
);

    wire m_axis_data_tvalid;
    wire signed[7:0] m_axis_data_tdata;
    wire signed[7:0] data_out;

    // DDS 源生成测试数据
    dds_compiler_0 dds_inst (
        .aclk(sysclk),
        .m_axis_data_tvalid(m_axis_data_tvalid),
        .m_axis_data_tdata(m_axis_data_tdata)
    );

    // CIC 抽取模块实例化
    cic_down_sample #(
        .DATA_IN_WIDTH(8),
        .DATA_OUT_WIDTH(8),
        .CIC_FACTORS(16),
        .MAX_WIDTH(20)
    ) u_cic_down_sample (
        .clk(sysclk),
        .rstn(sysrstn),
        .data_in(m_axis_data_tdata),
        .data_in_valid(m_axis_data_tvalid),
        .data_out(data_out)
    );

endmodule

仿真分析

通过不同参数配置观察波形变化,有助于理解滤波器特性。

当级数为 3、抽取因子为 16 时,输出波形呈现明显的阶梯状平滑效果。若将抽取因子调整为 8,波形会更密集,但整体趋势保持一致。从仿真结果可以看出,抽取因子越小或级数越低,输出波形越平滑,但这同时也意味着旁瓣抑制能力减弱。在实际系统中,如果对带外干扰要求较高,建议在 CIC 后级联一个补偿 FIR 滤波器来修正通带波纹并增强阻带衰减。

目录

  1. FPGA 实现 CIC 抽取滤波器
  2. 什么是 CIC 滤波器
  3. 最大位宽计算
  4. Verilog 代码实现
  5. 核心模块
  6. 顶层调用示例
  7. 仿真分析

更多推荐文章

查看全部
  • 基于 Stable Diffusion 的 AI 姓氏头像生成教程
  • 红黑树进阶:手撕 STL 源码封装 RB-tree 实现 map 和 set
  • Stable Diffusion XL 文本生成图像进阶控制技巧
  • Java Web 开发入门:基础概念、环境搭建与 Servlet/JSP
  • 家庭机器人落地难点分析:技术、成本与隐私
  • MySQL 环境配置实战:CentOS 7 与 Ubuntu 双系统安装指南
  • 使用豆包平台打造专属 Python 智能助手
  • Vue3 + TypeScript Promise<string> 转 string 类型错误解析与异步处理
  • Dockerfile 核心指令详解与实战指南
  • Java 2D 技术体系与常用类详解
  • C++红黑树原理与实现
  • GitHub 代码仓库初始化与首次推送指南
  • Java 后端 Web API 开发实战:从架构到部署
  • LLM 的核心能力与局限性分析:推理、规划及世界模型
  • OpenTiny NEXT 前端智能化征文:AI 前端与 WebAgent 学习路径
  • 使用 OpenCore Legacy Patcher 为老 Mac 安装最新 macOS 系统
  • MongoDB 数据备份与恢复实战指南
  • 前端微前端架构:避免应用变成巨石单体
  • OpenAI 发布 GPT-5.3 Instant:幻觉率降低 26.8% 及 2026 全球 AI 模型排行
  • Linux 线程控制详解:资源管理与实战操作

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online