FPGA实现级联型IIR滤波器
MATLAB仿真级联型IIR滤波器系数及运算字长的量化性能_小小低头哥的博客-CSDN博客上回使用MATLAB仿真了级联型IIR滤波器系数及运算字长,这次就叙述如何使用FPGA实现级联型IIR滤波器
由于IIR滤波器具有反馈结构,必须通过仿真确定IIR滤波器输出的范围,以进一步确定输出数据位数。
1.级联型IIR滤波器实现方法
上回使用MATLAB将8级IIR滤波器等效为3个3级IIR滤波器和一个2级IIR滤波器的级联,并最终进行了量化,根据级联型结构可以直接写出IIR滤波器的差分方程。如下
2048
y
1
(
n
)
=
30
[
x
(
n
)
+
x
(
n
−
2
)
]
+
40
x
(
n
−
1
)
−
[
−
707
y
1
(
n
−
1
)
+
212
y
1
(
n
−
2
)
]
.
.
.
.
.
.
(
1
)
2048y_1(n)=30[x(n)+x(n-2)]+40x(n-1)-[-707y_1(n-1)+212y_1(n-2)]......(1)
2048y1(n)=30[x(n)+x(n−2)]+40x(n−1)−[−707y1(n−1)+212y1(n−2)]......(1)
2048 y 2 ( n ) = 2048 [ y 1 ( n ) + y 1 ( n − 2 ) ] + 988 y 1 ( n − 1 ) − [ − 1099 y 2 ( n − 1 ) + 699 y 2 ( n − 2 ) ] . . . . . . ( 2 ) 2048y_2(n)=2048[y_1(n)+y_1(n-2)]+988y_1(n-1)-[-1099y_2(n-1)+699y_2(n-2)]......(2) 2048y2(n)=2048[y1(n)+y1(n−2)]+988y1(n−1)−[−1099y2(n−1)+699y2(n−2)]......(2)
1024 y 3 ( n ) = 1024 [ y 2 ( n ) + x ( n − 2 ) ] + 52 y 2 ( n − 1 ) − [ − 805 y 3 ( n − 1 ) + 743 y 3 ( n − 2 ) ] . . . . . . ( 3 ) 1024y_3(n)=1024[y_2(n)+x(n-2)]+52y_2(n-1)-[-805y_3(n-1)+743y_3(n-2)]......(3) 1024y3(n)=1024[y2(n)+x(n−2)]+52y2(n−1)−[−805y3(n−1)+743y3(n−2)]......(3)
2048 y ( n ) = 2048 [ y 3 ( n ) + y 3 ( n − 1 ) ] − [ − 276 y ( n − 1 ) ] . . . . . . ( 4 ) 2048y(n)=2048[y_3(n)+y_3(n-1)]-[-276y(n-1)]......(4) 2048y(n)=2048[y3(n)+y3(n−1)]−[−276y(n−1)]......(4)
也就是前一个滤波器的输出是后一个滤波器的输入
2.分析各级滤波器的输出数据范围并确定输出数据位数
由于整个IIR滤波器由4个IIR滤波器级联而成,因此需要分别仿真出各级滤波器的输出数据范围并确定各级滤波器的输出数据范围。仍然由MATLAB实现。代码如下
clear all
%My_E5_54_MatlabSim.M
%求直接型IIR滤波器的系数
[b,a] = cheby2(7,60,0.5);
%求分解出来的每个二阶IIR滤波器的分子分母系数
[b0,B,A]=My_E5_51_dir2cas(b,a);
%量化每个二阶IIR滤波器的分子分母系数
[Qb1,Qa1]=E5_52_Qcoe(b0*B(1,:),A(1,:),12);
[Qb2,Qa2]=E5_52_Qcoe(B(2,:),A(2,:),12);
[Qb3,Qa3]=E5_52_Qcoe(B(3,:),A(3,:),12);
[Qb4,Qa4]=E5_52_Qcoe(B(4,:),A(4,:),12);
%获取测试输入数据
[Q_s,Q_noise]=E5_53_NoiseAndCarrier;
%对级联型滤波器进行滤波
%对白噪声进行滤波
N1 = filter(Qb1,Qa1,Q_noise);
N2 = filter(Qb2,Qa2,N1);%级联型:上一级的输出是这一级的输入
N3 = filter(Qb3,Qa3,N2);
Nout = filter(Qb4,Qa4,N3);%得到最终滤波结果
%对合成单频信号进行滤波
S1 = filter(Qb1,Qa1,Q_s);
S2 = filter(Qb2,Qa2,S1);%级联型:上一级的输出是这一级的输入
S3 = filter(Qb3,Qa3,S2);
Sout = filter(Qb4,Qa4,S3);%得到最终滤波结果
%求取每级滤波器输出数据位宽
QN1 = ceil(log2(max(abs(N1)))+1);%计算N1所需的位数,+1是因为是有符号数
if 2^(QN1-1) == max(abs(N1)) %如果除去符号位的最大值刚好等于2的整数冥
QN1 = QN1 + 1;%那么此时要加一了,比如N1=[-612,1024],则需要12位表示
end %第11位的值表示1024(10位的表示范围是1024-1),第12位为符号位
QN2 = ceil(log2(max(abs(N2)))+1);
if 2^(QN2-1) == max(abs(N2))
QN2 = QN2 + 1;
end
QN3 = ceil(log2(max(abs(N3)))+1);
if 2^(QN3-1) == max(abs(N3))
QN3 = QN3 + 1;
end
QNout = ceil(log2(max(abs(Nout)))+1);
if 2^(QNout-1) == max(abs(Nout))
QNout = QNout + 1;
end
QS1 = ceil(log2(max(abs(S1)))+1);
if 2^(QS1-1) == max(abs(S1))
QS1 = QS1 + 1;
end
QS2 = ceil(log2(max(abs(S2)))+1);
if 2^(QS2-1) == max(abs(S2))
QS2 = QS2 + 1;
end
QS3 = ceil(log2(max(abs(S3)))+1);
if 2^(QS3-1) == max(abs(S3))
QS3 = QS3 + 1;
end
QSout = ceil(log2(max(abs(Sout)))+1);
if 2^(QSout-1) == max(abs(Sout))
QSout = QSout + 1;
end
if QN1>QS1 %保证同一级滤波器的输出位宽相同 取最大的位宽
QS1 = QN1;
else
QN1 = QS1;
end
if QN2>QS2
QS2 = QN2;
else
QN2 = QS2;
end
if QN3>QS3
QS3 = QN3;
else
QN3 = QS3;
end
if QNout>QSout
QSout = QNout;
else
QNout = QSout;
end
%求幅频响应
FNin = 20*log10(abs(fft(Q_noise))); %输入噪声的幅频响应
FNin = FNin - max(FNin);
FNout = 20*log10(abs(fft(Nout))); %滤波后噪声的幅频响应
FNout = FNout - max(FNout);
FSin = 20*log10(abs(fft(Q_s))); %输入单频合成信号的幅频响应
FSin = FSin - max(FSin);
FSout = 20*log10(abs(fft(Sout))); %滤波后单品合成信号的幅频响应
FSout = FSout - max(FSout);
%设置幅频响应的横坐标单位为Hz
fs = 2000; %采样频率为2000HZ
x_f = [0:fs/length(FSout):fs/2];
FNin = FNin(1:length(x_f));
FNout = FNout(1:length(x_f));
FSin = FSin(1:length(x_f));
FSout = FSout(1:length(x_f));
subplot(211);
plot(x_f,FNout,'-',x_f,FNin,'--');
xlabel('频率(Hz)');ylabel('幅度(dB)');title('Matlab仿真白噪声信号滤波前后的频谱');
legend('输出信号频谱','输入信号频谱');
grid;
subplot(212);
plot(x_f,FSout,'-',x_f,FSin,'--');
xlabel('频率(Hz)');ylabel('幅度(dB)');title('Matlab仿真合成单频信号滤波前后的频谱');
legend('输出信号频谱','输入信号频谱');
grid;
最后仿真结果,得到第1级IIR滤波器输出数据的位数为8比特,第2级为9比特,第3级为11比特,第4级为12比特。
3.编写Verilog HDL程序,实现级联型IIR滤波器
每个IIR滤波器的实现方法与直接型IIR滤波器的实现方法完全相同,需要注意的是根据仿真结果对IIR滤波器输出数据进行截尾即可。
由于级联型IIR滤波器阶数小。故其零极点系数的实现代码编写在同一个文件中。
顶层文件:
module Cascade_Filter_IIR(
input rst, //复位信号
input clk, //时钟信号
input signed[11:0] din, //输入数据
output signed[11:0] dout //滤波后的输出数据 仿真结果位12比特
);
//实例化第一级IIR滤波器运算模块
wire signed [7:0] Y1;
FirstTap U1(
.rst (rst),
.clk (clk),
.Xin (din),
.Yout (Y1)
);
//实例化第2级IIR滤波器运算模块
wire signed [8:0] Y2;
SecondTap U2(
.rst (rst),
.clk (clk),
.Xin (Y1),
.Yout (Y2)
);
//实例化第3级IIR滤波器运算模块
wire signed [10:0] Y3;
ThirdTap U3(
.rst (rst),
.clk (clk),
.Xin (Y2),
.Yout (Y3)
);
//实例化第4级IIR滤波器运算模块
FourthTap U4(
.rst (rst),
.clk (clk),
.Xin (Y3),
.Yout (dout)
);
endmodule
各级滤波器实现代码类似,仅仅系数不同,因此只给出第一级代码
//这是FirstTap.v文件的程序清单
module FirstTap (
rst,clk,Xin,
Yout);
input rst; //复位信号,高电平有效
input clk; //FPGA系统时钟,频率为2kHz
input signed [11:0] Xin; //数据输入频率为2kHZ
output signed [7: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 = {{7{Xin[11]}},Xin,5'd0}-{{11{Xin[11]}},Xin,1'd0}; //*30
assign XMult1 = {{7{Xin1[11]}},Xin1,5'd0}+{{9{Xin1[11]}},Xin1,3'd0}; //*40
assign XMult2 = {{7{Xin2[11]}},Xin2,5'd0}-{{11{Xin2[11]}},Xin2,1'd0}; //*30
//对滤波器系数与输入数据乘法结果进行累加
wire signed [23:0] Xout;
assign Xout = XMult0 + XMult1 + XMult2;
//极点系数的实现代码///
wire signed[7:0] Yin;
reg signed[7:0] Yin1,Yin2;
always @(posedge clk or posedge rst)
if (rst)
//初始化寄存器值为0
begin
Yin1 <= 9'd0;
Yin2 <= 9'd0;
end
else
begin
Yin1 <= Yin;
Yin2 <= Yin1;
end
//采用移位运算及加法运算实现乘法运算
wire signed [23:0] YMult1,YMult2;
wire signed [23:0] Ysum,Ydiv;
assign YMult1 = {{7{Yin1[7]}},Yin1,9'd0}+{{9{Yin1[7]}},Yin1,7'd0}+{{10{Yin1[7]}},Yin1,6'd0}+
{{15{Yin1[7]}},Yin1,1'd0}+{{16{Yin1[7]}},Yin1}; //*707
assign YMult2 = {{9{Yin2[7]}},Yin2,7'd0}+{{10{Yin2[7]}},Yin2,6'd0}+{{12{Yin2[7]}},Yin2,4'd0}-
{{14{Yin2[7]}},Yin2,2'd0}; //*212
//第一级IIR滤波器实现代码///
assign Ysum = Xout+YMult1-YMult2;
assign Ydiv = {{11{Ysum[23]}},Ysum[23:11]};//2048
//根据仿真结果可知,第一级滤波器的输出范围可用9位表示
assign Yin = (rst ? 8'd0 : Ydiv[7:0]);
//增加一级寄存器,提高运行速度
reg signed [7:0] Yout_reg ;
always @(posedge clk)
Yout_reg <= Yin;
assign Yout = Yout_reg;
endmodule
整个文件的RTL如下图所示
4.级联型IIR滤波器FPGA实现后的测试仿真
级联型IIR滤波器FPGA实现后仿真步骤及方法与直接型结构相同,仍然可分为三个步骤进行;编写M文件,生成二进制输入数据;编写Test Bench文件,采用Modelsim进行仿真;编写M文件,用MATLAB分析FPGA分析FPGA实现后的数据。这些代码和前几回相同,不再赘述,可查看往期。最后结果如图所示