FPGA数字信号处理(十六)单级CIC滤波器Verilog设计

该篇是FPGA数字信号处理的第16篇,选题为多速率信号处理系统中常用的CIC滤波器。本文将详细介绍使用Verilog HDL设计单级CIC滤波器的方法。接下来几篇会介绍多级CIC滤波器的Verilog设计、使用Quartus和Vivado的IP核设计CIC的方法。

多速率信号处理的相关知识可以参考:“FPGA数字信号处理(十五)多速率FIR滤波器:https://blog.csdn.net/FPGADesigner/article/details/80875304 ”。


CIC滤波器

根据上一篇可知,多速率信号处理系统中最主要的还是滤波器的设计:抽取和内插后不能产生频谱混叠、占用资源少、运算速度快。上一篇介绍了多速率FIR滤波器,与其相比,CIC(Cascaded Integrator Comb,积分梳状)滤波器运算速度快、占用资源少、工作频率高(因为CIC只使用加法器、减法器和寄存器),在多速率信号处理系统中应用更广泛。

●频谱特性

CIC本质上其实就是一种特殊的FIR滤波器(系数都为1)。本文不用理论推导的方式,从频谱图出发更直观地观察体会CIC滤波器的特点。我们使用MATLAB的FDATOOL工具观察CIC滤波器的频谱。
这里写图片描述
点击最左边的小按钮,中间选择CIC滤波器,右边级数(Number Of Sections)设置为1,表示单级CIC滤波器。这里设置为对25MHz的Fs进行25倍抽取。可以看到第一旁瓣的衰减为13.46dB(事实上这是一个固定的值,与CIC滤波器阶数无关),这个阻带衰减远远不能满足通常的设计要求,通过级联的方式可以提高阻带衰减,在下一篇介绍多级CIC滤波器时再详细说明。

●阶数与倍数的关系

CIC滤波器通常用于抗混叠抽取/内插滤波器(抽取与内插结构见本文开头的链接)。考虑抽取/内插的过程、CIC滤波器的特性(系数为1的特殊FIR滤波器)以及FIR滤波器的实现结构,就会发现,当CIC滤波器的阶数与内插/抽取的倍数相同时,其结构更利于FPGA实现。比如抽取时,只需要将D个数据组成一组,相加作为一个输出即可(即同时完成了滤波与抽取)。

结合下面的实例理解(设CIC滤波器阶数与抽取倍数都为5):
这里写图片描述
完整的抽取过程为:CIC作为抗混叠滤波,由于系数为1,y1=x1+x2+…+x5,y2=x2+x3+…+x6,等等;得到滤波输出后,再每隔4个点(即D-1个)取一个值输出,完成5倍抽取。而这个过程恰好等效于将原始数据每5个分为一组,每组的数据分别相加作为一个输出。由此可见:当CIC滤波器与抽取倍数相同时,可以大大节省资源、减小运算量。

同理,当使用CIC完成内插滤波时,设CIC滤波器阶数与内插倍数都为5:
这里写图片描述
完整的内插过程为:每两个数据之间插入4个零值(I-1个),完成5倍内插,之后使用CIC做低通滤波,由于CIC滤波器的系数为1,滤波后的插值0变为前一个原始数据值。这个过程恰好等效于直接在两个数据之间插入前一个数据值。由此可见:当CIC滤波器与内插倍数相同时,也可以节省资源和运算。


CIC抽取滤波器的FPGA设计与仿真

使用50MHz采样率对0.25MHz的信号进行采样,由五阶CIC滤波器进行5倍抽取,将采样率降至10MHz。根据上文的介绍,设计的Verilog HDL代码如下:

`timescale 1ns / 1ps
//-------------------------------------------------------------
//  单级CIC抽取滤波器,滤波器阶数与抽取倍数相同
//-------------------------------------------------------------
module SingleCIC_Decimation
(
    input clk,    //50MHz系统时钟
    input rst,    //复位信号
    input signed [9:0] din,    //采样数据,速率为50MHz
    output tvalid,             //输出数据有效信号
    output signed [12:0] dout  //5倍抽取后数据,速率为10MHz
);

reg tvalid_reg;
reg [2:0] cnt;      //抽取控制计数器
reg signed [12:0] sum, dout_reg;

always @ (posedge clk or posedge rst)
    if (rst) begin
        cnt <= 'd0; tvalid_reg <= 1'b0;
        sum <= 'd0; dout_reg <= 'd0;
    end
    else begin
        if (cnt == 4) begin   //每隔4个数据
            tvalid_reg <= 1'b1;
            dout_reg <= sum + din;   //得到输出结果
            cnt <= 'd0;
            sum <= 'd0;
        end
        else begin
            tvalid_reg <= 1'b0;
            sum <= sum + din;     //累加
            cnt <= cnt + 1'b1;
        end
    end

assign dout = dout_reg;
assign tvalid = tvalid_reg;

endmodule

使用MATLAB生成一个0.25MHz的单频信号,写入txt文件。编写testbench读取txt文件对信号抽取滤波,文件操作方法参考“Testbench编写指南(一)文件的读写操作https://blog.csdn.net/fpgadesigner/article/details/80470972 ”。

Vivado中仿真结果如下图所示:
这里写图片描述
可以看到输出数据速率为输入数据速率的1/5,每当有新数据输出时,tvalid信号会置高1个时钟周期。将信号设置为Analog显示方式:
这里写图片描述
可以看到经过抽取滤波后,数据速率降低,但信号频率没有改变。


CIC内插滤波器的FPGA设计与仿真

使用10MHz采样率对0.25MHz的信号进行采样,由五阶CIC滤波器进行5倍内插,将采样率提高至50MHz。根据上文的介绍,内插比抽取甚至更容易理解,设计起来也非常简单,设计的Verilog HDL代码如下:

`timescale 1ns / 1ps
//-------------------------------------------------------------
//  单级CIC内插滤波器,滤波器阶数与抽取倍数相同
//-------------------------------------------------------------
module SingleCIC_Interpolation
(
    input clk,    //50MHz系统时钟
    input rst,    //复位信号
    input signed [9:0] din,    //采样数据,速率为10MHz
    output signed [9:0] dout   //5倍内插后数据,速率为50MHz
);

reg signed [9:0] dout_reg;

always @ (posedge clk or posedge rst)
    if (rst)  dout_reg <= 'd0;
    else dout_reg <= din;     

assign dout = dout_reg;

endmodule

Vivado中仿真结果如下图所示:
这里写图片描述
从结果看输入与输出是完全一样的,但实际意义不同,输入数据的速率为10MHz(每5个时钟周期输入一个数据),输出数据的速率为50MHz(每个时钟周期都输出一个数据)。

猜你喜欢

转载自blog.csdn.net/fpgadesigner/article/details/80881484