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

该篇是FPGA数字信号处理的第17篇,题接上篇,本文详细介绍多级CIC滤波器的特性、使用Verilog HDL设计多级CIC滤波器的方法。接下来两篇会介绍使用Quartus和Vivado的IP核设计CIC的方法。


多级CIC滤波器

根据上一篇可知,单级CIC滤波器的第一旁瓣电平衰减固定为13.46dB,且与滤波器的阶数无关。这个值不满足通常的阻带衰减要求,解决方法就是通过级联CIC滤波器来达到更大的阻带衰减。事实上实际应用中采用的都是多级CIC滤波器。

●频谱特性

使用MATLAB的FDATOOL工具观察多级CIC滤波器的频谱。
这里写图片描述

点击最左边的小按钮,中间选择CIC滤波器,右边级数(Number Of Sections)设置为4,表示四级CIC滤波器。这里设置为对25MHz的Fs进行5倍抽取。可以看到第一旁瓣的衰减约为48dB,大概提升了4倍。

不过增加CIC滤波器的级数也有不利的影响:通带衰减也随着增加。换句话说,对于给定的通带衰减要求,多级CIC滤波器的通带范围会随着级数的增加而不断变窄。滤波器的设计不仅要考虑阻带误差容限,还要考虑通带误差容限,设计多级CIC滤波器时要注意考虑这个问题。

其实,CIC滤波器大多应用于抗混叠抽取/内插滤波器,也是因为上述的原因。因为在抗混叠应用中,有效信号频带往往远小于采样率,因此总可以设计出同时满足通带和阻带要求的CIC滤波器。

●实现结构

理论上多级CIC滤波器可以直接由多个单级CIC滤波器级联得到,但根据Noble恒等式(“先进行抽取或者插值,再进行线性滤波”与“先进行线性滤波,再进行抽取或者插值”这两者是可以等价的),可以将多级CIC滤波器结构变换为工程中实际应用的Hogenauer CIC滤波器结构。与直接将多个单级CIC滤波器级联相比,更加节省资源,也能提高计算速度。

抽取滤波器结构如下所示:
这里写图片描述
内插滤波器结构如下所示:
这里写图片描述


FPGA设计与仿真

本设计在Vivado环境中完成并进行仿真。设计一个5阶的3级CIC滤波器,对输入数据进行5倍抽取。根据上文抽取滤波器的结构,使用Verilog HDL分别完成积分模块、抽取模块、梳状模块的设计。

●积分模块

由于积分运算会导致数据位宽扩展,首先需要确定积分器的输出数据位宽。可以借助如下公式,当输入信号为Bin位时,积分器最大可能输出位数为:
这里写图片描述
R为抽取/插值倍数,D为滤波器级数,N为滤波器阶数。本设计输入信号设置为10bit,则根据公式计算得到积分器输出数据为30Bits。设计的Verilog HDL代码如下:

`timescale 1ns / 1ps
//-----------------------------------------------------
// 多级CIC滤波器,积分器模块
//-----------------------------------------------------
module Integrated
(
    input clk, rst,
    input signed [9:0] Xin,
    output signed [29:0] Xout   //位宽由公式确定  
);

//每级积分器需要一个寄存器和一级加法器
wire signed [29:0] I1, I2, I3;
reg signed [29:0] d1, d2, d3;

//第1级积分器
always @ (posedge clk or posedge rst)
    if (rst) d1 <= 'd0;
    else d1 <= I1;            //寄存
assign I1 = d1 + {{20{Xin[9]}},Xin};  //加法

//第2级积分器
always @ (posedge clk or posedge rst)
    if (rst) d2 <= 'd0;
    else d2 <= I2;            //寄存
assign I2 = I1 + d2;          //加法

//第3级积分器
always @ (posedge clk or posedge rst)
    if (rst) d3 <= 'd0;
    else d3 <= I3;            //寄存
assign I3 = I2 + d3;          //加法

assign Xout = I3;              //积分器输出

endmodule

该模块的RTL视图如下,可以清楚的看到使用了3级寄存器和3个加法器:
这里写图片描述

●抽取模块

该模块的设计与上一篇中单级CIC的设计非常相似,只是不需要求和,每5个时钟周期抽出一个作为输出即可。同时设置一个输出有效信号,供下一级梳状 模块使用。Verilog HDL设计代码如下:

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

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

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

assign dout = dout_reg;
assign tvalid = tvalid_reg;

endmodule

●梳状模块

该模块设计与积分模块很相似,只不过是由寄存器和减法器组成的。该模块的输出即为整个CIC抽取滤波器的输出数据,位宽可由如下公式确定:
这里写图片描述
符号意义与上文的公式相同,本例中经计算CIC滤波器的输出位宽最大为17Bits。Verilog HDL设计代码如下:

`timescale 1ns / 1ps
//-----------------------------------------------------
// 多级CIC滤波器,梳状模块
//-----------------------------------------------------
module Comb
(
    input clk,    //50MHz系统时钟
    input rst,    //复位信号
    input signed [29:0] din,   //采样数据,速率为50MHz
    input tvalid,              //输入数据有效信号
    output signed [16:0] dout  //5倍抽取后数据,速率为10MHz
);

reg signed [29:0] d1,d2,d3,d4;
wire signed [29:0] C1, C2, dout_reg;

always @ (posedge clk or posedge rst)
    if (rst) begin
        d1 <= 'd0; d2 <= 'd0; d3 <= 'd0; d4 <= 'd0;
    end
    else begin
        if (tvalid) begin  //输入信号有效
            d1 <= din;     //数据寄存
            d2 <= d1;
            d3 <= C1;
            d4 <= C2;
        end
    end

assign C1 = d1 - d2;       //减法器
assign C2 = C1 - d3;
assign dout_reg = C2 - d4;
assign dout = dout_reg[16:0];   //截取有效位输出

endmodule

该模块的RTL视图如下,可以清楚的看到使用了3级寄存器和3个减法器(d1_reg仅作为对输入数据的缓存):
这里写图片描述

●综合与仿真

在顶层模块中分别实例化三个子模块,并连接起来。顶层模块的RTL视图如下所示,可以清楚地看到信号的处理流程:
这里写图片描述
为了更直观地观察效果,使用MATLAB生成一个0.25MHz+7.5Mhz的正弦混合信号,写入txt文件。编写testbench读取txt文件对信号抽取滤波,文件操作方法参考“Testbench编写指南(一)文件的读写操作https://blog.csdn.net/fpgadesigner/article/details/80470972 ”。

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

猜你喜欢

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