IIR的特点是:非线性相位、消耗资源少。
IIR滤波器的系统函数与差分方程如下所示:
由差分方程可知IIR滤波器存在反馈,因此在FPGA设计时要考虑到有限字长效应带来的影响。差分方程中包括两个部分:输入信号x(n)的M节延时网络,相当于FIR的网络结构,实现系统的零点;输出信号y(n)的N节延时网络,作为系统的反馈,实现系统的极点。
直接由差分方程得到的IIR滤波器称为直接I型结构,如下图所示,左边为零点部分,右边为极点部分:
如果由IIR的系统函数出发,视作两个系统的级联,并且合并公共的延时支路,得到的IIR滤波器称为直接II型结构,如下图所示:
很明显,直接I型结构需要2N个延时单元;直接II型结构仅需要N个延时单元,使用FPGA设计时采用直接II型结构可以节省一些资源。
级联型结构与直接型结构相比:
1.每一个级联部分中的反馈网络很少,易于控制有限字长效应带来的影响,且IIR滤波器的阶数一般较小。
2.便于准确实现数字滤波器的零/极点,每一级分开调整。
3.运算速度快;占用资源少(除法采用移位)。
4.若除法采用移位,每一级都需要用近似移位实现除法运算,与理想误差较大。
设计一个4阶IIR低通滤波器,采样频率为8MHz,截至频率为2MHz,阻带衰减为40dB,滤波器量化位数12bits。
第一级滤波器
其中系数乘法用移位和加法代替,有利于减少乘法器资源。
module FirstTap (
rst,clk,Xin,
Yout);
input rst; //复位信号,高电平有效
input clk; //FPGA系统时钟,频率为2kHz
input signed [11:0] Xin; //数据输入频率为2kHZ
output signed [11:0] Yout; //滤波后的输出数据
//零点系数的实现代码/
//将输入数据存入移位寄存器中
reg signed[11:0] Xin1,Xin2;
always @(posedge clk or posedge rst)
if (rst)
//初始化寄存器值为0
begin
Xin1 <= 12'd0;
Xin2 <= 12'd0;
end
else
begin
Xin1 <= Xin;
Xin2 <= Xin1;
end
//采用移位运算及加法运算实现乘法运算
wire signed [23:0] XMult0,XMult1,XMult2;
assign XMult0 = {{6{Xin[11]}},Xin,6'd0}+{{7{Xin[11]}},Xin,5'd0}-{{11{Xin[11]}},Xin,1'd0}; //*94
assign XMult1 = {{5{Xin1[11]}},Xin1,7'd0}+{{9{Xin1[11]}},Xin1,3'd0}+{{10{Xin1[11]}},Xin1,2'd0}; //*140 (2^7+ 2^3 + 2^2)
assign XMult2 = {{6{Xin2[11]}},Xin2,6'd0}+{{7{Xin2[11]}},Xin2,5'd0}-{{11{Xin2[11]}},Xin2,1'd0}; //*94
//对滤波器系数与输入数据乘法结果进行累加
wire signed [23:0] Xout;
assign Xout = XMult0 + XMult1 + XMult2;
//极点系数的实现代码///
wire signed[11:0] Yin;
reg signed[11:0] Yin1,Yin2;
always @(posedge clk or posedge rst)
if (rst)
//初始化寄存器值为0
begin
Yin1 <= 12'd0;
Yin2 <= 12'd0;
end
else
begin
Yin1 <= Yin;
Yin2 <= Yin1;
end
//采用移位运算及加法运算实现乘法运算
wire signed [23:0] YMult1,YMult2;
wire signed [23:0] Ysum,Ydiv;
assign YMult1 = {{2{Yin1[11]}},Yin1,10'd0}+{{5{Yin1[11]}},Yin1,7'd0}+{{6{Yin1[11]}},Yin1,6'd0}-
{{11{Yin1[11]}},Yin1,1'd0}-{{12{Yin1[11]}},Yin1}; //*1213=1024+128+64-2-1
assign YMult2 = {{4{Yin2[11]}},Yin2,8'd0}+{{9{Yin2[11]}},Yin2,3'd0}+{{10{Yin2[11]}},Yin2,2'd0}; //*268=256+8+4
//第一级IIR滤波器实现代码///
assign Ysum = Xout+YMult1-YMult2;
assign Ydiv = {{11{Ysum[23]}},Ysum[23:11]};//2048
//根据仿真结果可知,第一级滤波器的输出范围可用9位表示
assign Yin = (rst ? 12'd0 : Ydiv[11:0]);
//增加一级寄存器,提高运行速度
reg signed [11:0] Yout_reg ;
always @(posedge clk)
Yout_reg <= Yin;
assign Yout = Yout_reg;
endmodule
第二级滤波器
module SecondTap (
rst,clk,Xin,
Yout);
input rst; //复位信号,高电平有效
input clk; //FPGA系统时钟,频率为2kHz
input signed [11:0] Xin; //数据输入频率为2kHZ
output signed [11:0] Yout; //滤波后的输出数据
//零点系数的实现代码/
//将输入数据存入移位寄存器中
reg signed[11:0] Xin1,Xin2;
always @(posedge clk or posedge rst)
if (rst)
//初始化寄存器值为0
begin
Xin1 <= 12'd0;
Xin2 <= 12'd0;
end
else
begin
Xin1 <= Xin;
Xin2 <= Xin1;
end
//采用移位运算及加法运算实现乘法运算
wire signed [23:0] XMult0,XMult1,XMult2;
assign XMult0 = {{1{Xin[11]}},Xin,11'd0}; //*2048
assign XMult1 = {{4{Xin1[11]}},Xin1,8'd0}+{{6{Xin1[11]}},Xin1,6'd0}+{{10{Xin1[11]}},Xin1,2'd0}; //*324=256+64+4
assign XMult2 = {{1{Xin2[11]}},Xin2,11'd0}; //*2048
//对滤波器系数与输入数据乘法结果进行累加
wire signed [23:0] Xout;
assign Xout = XMult0 + XMult1 + XMult2;
//极点系数的实现代码///
wire signed[11:0] Yin;
reg signed[11:0] Yin1,Yin2;
always @(posedge clk or posedge rst)
if (rst)
//初始化寄存器值为0
begin
Yin1 <= 12'd0;
Yin2 <= 12'd0;
end
else
begin
Yin1 <= Yin;
Yin2 <= Yin1;
end
//采用移位运算及加法运算实现乘法运算
wire signed [23:0] YMult1,YMult2;
wire signed [23:0] Ysum,Ydiv;
assign YMult1 = {{1{Yin1[11]}},Yin1,11'd0}-{{5{Yin1[11]}},Yin1,7'd0}-{{9{Yin1[11]}},Yin1,3'd0}-
{{10{Yin1[11]}},Yin1,2'd0}-{{12{Yin1[11]}},Yin1}; //*1907=2048-128-8-4-1
assign YMult2 = {{2{Yin2[11]}},Yin2,10'd0}+{{5{Yin2[11]}},Yin2,7'd0}+{{8{Yin2[11]}},Yin2,4'd0}+
{{11{Yin2[11]}},Yin2,1'd0}+{{12{Yin2[11]}},Yin2}; //*1171=1024+128+16+2+1
//第一级IIR滤波器实现代码///
assign Ysum = Xout+YMult1-YMult2;
assign Ydiv = {{11{Ysum[23]}},Ysum[23:11]};//2048
//根据仿真结果可知,第一级滤波器的输出范围可用9位表示
assign Yin = (rst ? 12'd0 : Ydiv[11:0]);
//增加一级寄存器,提高运行速度
reg signed [11:0] Yout_reg ;
always @(posedge clk)
Yout_reg <= Yin;
assign Yout = Yout_reg;
endmodule
顶层模块
module IIRCas (
rst,clk,Xin,
Yout);
input rst; //复位信号,高电平有效
input clk; //FPGA系统时钟,频率为8MHz
input signed [11:0] Xin; //数据输入频率为8MHZ
output signed [11:0] Yout; //滤波后的输出数据
//实例化第一级滤波器运算模块
wire signed [11:0] Y1;
FirstTap U1 (
.rst (rst),
.clk (clk),
.Xin (Xin),
.Yout (Y1));
//实例化第二级滤波器运算模块
SecondTap U2 (
.rst (rst),
.clk (clk),
.Xin (Y1),
.Yout (Yout));
endmodule
如何快速设计一个IIR滤波器