一、简要概述
IIR滤波器原理以及架构在此不做阐述,如何从模拟滤波器到数字滤波器进行设计,可参考
https://blog.csdn.net/k331922164/article/details/117265704?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-117265704-blog-123083652.235%5Ev38%5Epc_relevant_anti_t3_base&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromBaidu%7ERate-1-117265704-blog-123083652.235%5Ev38%5Epc_relevant_anti_t3_base&utm_relevant_index=1
本文主要利用matlab产生IIR滤波器参数,采用级联架构,基于FPGA进行实现及仿真。
二、matlab仿真
直接附上matlab代码如下
clc;
clear all;
fs=8e6;
f1=1e5;
f2=3e6;
fc=20*f1;
N=fs/f1;%一个周期的点数
t=0:1/fs:(N*30-1)/fs;
data_bit=12;%信号量化位数
%---------IIR滤波器参数-----------------------------------
filter_bit=16;%滤波器系数量化位数
Rs=0.3;% 通带起伏
Rp = 40; % 阻带衰减
N_IIR = 4; %阶数
kindfilt=2;%滤波器类型0:巴特沃斯 1:切比雪夫I型 2:切比雪夫II型 3:椭圆滤波器 4:巴特沃斯
%----------生成混频信号--------------------
x1=sin(2*pi*f1*t);
x2=cos(2*pi*f2*t);
x3=x1+x2;
figure(1)
subplot(3,1,1)
plot(x1);
title('有用信号')
subplot(3,1,2)
plot(x2);
title('高频噪声')
subplot(3,1,3)
plot(x3);
title('混频信号')
%---量化混频信号,作为ISE仿真激励-------
s=x3/(max(abs(x3)));%归一化处理
Qs=round(s*(2^(data_bit-1)-1));%实数量化
fid=fopen('D:\desktop\stuy\coe_txt\singnal.txt','w');
fprintf(fid,'%d\n',Qs);
fprintf(fid,';');
fclose(fid);
%---------生成IIR滤波器-----------------------------------
switch kindfilt
case 0
[b,a]=butter(N_IIR,fc/2/fs,'low');%巴特沃斯
case 1
[b,a]=cheby1(N_IIR,Rs,fc/2/fs,'low');%切比雪夫I型
case 2
[b,a]=cheby2(N_IIR,Rp,fc/2/fs,'low');%切比雪夫II型
case 3
[b,a]=ellip(N_IIR,Rs,Rp,fc/2/fs,'low');%椭圆滤波器
otherwise
[b,a]=butter(N_IIR,fc/2/fs,'low');%巴特沃斯
end
figure(2)
subplot(2,1,1)
impz(b,a,N)%单位脉冲,位宽计算
title('系统的单位脉冲响应')
subplot(2,1,2)
dstep(b,a,N)%单位阶跃响应
title('系统的单位阶跃响应')%可分析输入信号经过该系统后为位宽变化情况
figure(3)
zplane(b,a);
title('零极点分布')
x4=filter(b,a,x3);
figure(4)
plot(x4)
title('IIR滤波后的有用信号')
%---------b,a直接I型系数量化-对a(1)进行2的指数级量化,便于FPGA的移位处理
m=max(max(abs(a)),max(abs(b)));%取系数最大值
qm=ceil(log2(m/a(1)));%取系数中最大值与a(1)的整数倍,量化范围
qm=a(1)*2^qm;%默认a(1)进行2的指数级量化
%qm=m;%默认参考最大值量化
QbI=round(b/qm*(2^(filter_bit-1)-1));%
QaI=round(a/qm*(2^(filter_bit-1)-1));
figure(5)
freqz(b,a);%量化前的幅频
title('IIR滤波的幅频特性')
figure(6)
freqz(QbI,QaI);%量化后的幅频图比对
title('IIR滤波直接型参数量化后的参数幅频特性')
figure(7)
x5=filter(QbI,QaI,x3);%量化后系数对信号滤波
plot(x5)
title('IIR直接型滤波参数量化后的滤波后的有用信号')
%---量化后滤波系数写入coe文本---
fid=fopen('D:\desktop\stuy\coe_txt\filter_b.coe','w');
fprintf(fid,'%d\n',QbI);
fprintf(fid,';');
fclose(fid);
fid=fopen('D:\desktop\stuy\coe_txt\filter_a.coe','w');
fprintf(fid,'%d\n',QaI);
fprintf(fid,';');
fclose(fid);
%-------sos,g级联型系数量化------------
[sos,g]=tf2sos(b,a)%生成级联型系数
sos(1,1:3)=g*sos(1,1:3)%增益值g可以分配至任意一级分子上,此处将增益分配到第一个级联分子系数上
sos=round(sos*(2^(filter_bit-1)))%系数量化,
[b1,a1] = sos2tf(sos);
figure(8)
x6=filter(b1,a1,x3);%对信号滤波
plot(x6)
title('IIR级联型参数量化后滤除干扰噪声的有用信号')
%[b0 b1 b2 a0 a1 a2] a0*yn=b0*xn+b1*x(n-1)+b2*x(n-2)-a1*y(n-1)-a2*y(n-2)
figure(9)
freqz(sos(1,1:3),sos(1,4:6));%每个级联参数分析幅频特性
%impz(sos(1,1:3),sos(1,4:6),N)
figure(10)
freqz(sos(2,1:3),sos(2,4:6));%每个级联参数分析幅频特性
2.1 FPGA的定点设计
通过仿真可知,系统阶跃响应最大值不超1.2,那么假设输入信号量化为12bit,以输入±1范围为定点,那么输入信号定点为Q(2,10),输入信号经过系统后最大值不超1.2,因此输出信号定点也为Q(2,10)。因此在设计IIR滤波器输入输出位宽时,可根据此结果进行设计
2.2 IIR参数的级联转换
根据matlab仿真的IIR参数转换,可以调用tf2sos函数直接得出级联设计结果,如下所示,增益值g可以分配至任意一级分子上,一般将增益分配到第一个级联分子系数上。
三 FPGA的IIR滤波器的实现
为便于各级可直接调用同一模块,对级联模块IIR_nTap的实现上进行通用化设计,级联架构的顶层如下,可直接调用同一模块IIR_nTap
`timescale 1ns / 1ps
//
module Cas_IIR(
input clk,
input rst_n,
input signed [11:0] Din,
output signed [11:0] Dout
);
//第一级
wire signed [11:0] Y1;
IIR_nTap #(
.datin_width(12),//输入数据宽度
.coeffct_width(18),//滤波器系数量化位数
.daout_width(12),//输出数据宽度
.b0(333),
.b1(-383),
.b2(333),
.a0(32768),
.a1(-53356),
.a2(21924)
) U0 (
.rst_n(rst_n),
.clk(clk),
.Xin(Din),
.Yout(Y1)
);
//第二级
IIR_nTap #(
.datin_width(12),//输入数据宽度
.coeffct_width(18),//滤波器系数量化位数
.daout_width(12),//输出数据宽度
.b0(32768),
.b1(-59729),
.b2(32768),
.a0(32768),
.a1(-60166),
.a2(28629)
)
U1
(
.rst_n(rst_n),
.clk(clk),
.Xin (Y1),
.Yout (Dout)
);
endmodule
IIR_nTap 的具体代码如下
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 22:48:39 05/11/2023
// Design Name:
// Module Name: First_nTap
// Project Name:
// Target Devices:
// Tool versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//
//
module IIR_nTap #(
parameter datin_width=16,//输入数据宽度
parameter daout_width=16,//输出数据宽度
parameter coeffct_width=18,//滤波器系数位数+符号位,是哪个滤波系数2bit~16bit宽度,直接改零极点参数即可
parameter b0='d21,
parameter b1=-'d24,
parameter b2='d21,
parameter a0='d2048,//移位操作,15
parameter a1=-'d3335,
parameter a2='d1370
)
(
rst_n,
clk,
Xin,
Yout
);
input rst_n; //复位信号,高电平有效
input clk; //FPGA系统时钟
input signed [datin_width-1:0] Xin; //数据输入频率为
output signed [daout_width-1:0] Yout; //滤波后的输出数据
//将输入数据存入移位寄存器中
reg signed[datin_width-1:0] Xin1,Xin2;
//对输入进行符号位扩展,并采用移位运算及加法运算实现乘法运算
wire signed [datin_width+coeffct_width-1:0] XMult0,XMult1,XMult2,Xout;
//对滤波器零点系数与输入数据乘法结果进行累加
wire signed[coeffct_width-1:0] b0_mu,b1_mu,b2_mu;//零点系数转为正值
//极点参数计算
wire signed[daout_width-1:0] Yin;
reg signed[daout_width-1:0] Yin1,Yin2;
wire signed[coeffct_width-1:0] a1_mu,a2_mu;//极点系数转为正值
wire signed [daout_width+coeffct_width-1:0] YMult1,YMult2,Aout;
wire signed [daout_width+coeffct_width:0] Ysum,Ydiv;
reg signed [daout_width-1:0] Yout_reg ;
//位宽计算函数
function integer clogb2 (input integer depth);
begin
for (clogb2=0; depth>0; clogb2=clogb2+1)
depth = depth >>1;
end
endfunction
//-------------------零点系数的实现代码------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n)
//初始化寄存器值为0
begin
Xin1 <= 'd0;
Xin2 <= 'd0;
end
else
begin
Xin1 <= Xin;
Xin2 <= Xin1;
end
assign b0_mu=(b0[coeffct_width-1])?(-b0):b0;
assign b1_mu=(b1[coeffct_width-1])?(-b1):b1;
assign b2_mu=(b2[coeffct_width-1])?(-b2):b2;//零点系数转正值比较
assign XMult0 = (b0_mu[0]?{{coeffct_width{Xin[datin_width-1]}},Xin}:0)+(b0_mu[1]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<1):0)+
(b0_mu[2]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<2):0)+(b0_mu[3]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<3):0)+
(b0_mu[4]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<4):0)+(b0_mu[5]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<5):0)+
(b0_mu[6]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<6):0)+(b0_mu[7]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<7):0)+
(b0_mu[8]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<8):0)+(b0_mu[9]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<9):0)+
(b0_mu[10]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<10):0)+(b0_mu[11]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<11):0)+
(b0_mu[12]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<12):0)+(b0_mu[13]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<13):0)+
(b0_mu[14]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<14):0)+(b0_mu[15]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<15):0)+
(b0_mu[16]?({{coeffct_width{Xin[datin_width-1]}},Xin}<<16):0); //coeffct_width-1-1 b0
assign XMult1 = (b1_mu[0]?{{coeffct_width{Xin1[datin_width-1]}},Xin1}:0)+(b1_mu[1]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<1):0)+
(b1_mu[2]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<2):0)+(b1_mu[3]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<3):0)+
(b1_mu[4]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<4):0)+(b1_mu[5]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<5):0)+
(b1_mu[6]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<6):0)+(b1_mu[7]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<7):0)+
(b1_mu[8]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<8):0)+(b1_mu[9]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<9):0)+
(b1_mu[10]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<10):0)+(b1_mu[11]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<11):0)+
(b1_mu[12]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<12):0)+(b1_mu[13]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<13):0)+
(b1_mu[14]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<14):0)+(b1_mu[15]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<15):0)+
(b1_mu[16]?({{coeffct_width{Xin1[datin_width-1]}},Xin1}<<16):0); //*-36=-4-32 coeffct_width-1-1 b1
assign XMult2 = (b2_mu[0]?{{coeffct_width{Xin2[datin_width-1]}},Xin2}:0)+(b2_mu[1]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<1):0)+
(b2_mu[2]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<2):0)+(b2_mu[3]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<3):0)+
(b2_mu[4]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<4):0)+(b2_mu[5]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<5):0)+
(b2_mu[6]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<6):0)+(b2_mu[7]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<7):0)+
(b2_mu[8]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<8):0)+(b2_mu[9]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<9):0)+
(b2_mu[10]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<10):0)+(b2_mu[11]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<11):0)+
(b2_mu[12]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<12):0)+(b2_mu[13]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<13):0)+
(b2_mu[14]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<14):0)+(b2_mu[15]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<15):0)+
(b2_mu[16]?({{coeffct_width{Xin2[datin_width-1]}},Xin2}<<16):0); //*21 coeffct_width-1-1 b2
assign Xout = (b0[coeffct_width-1]?(-XMult0):XMult0) + (b1[coeffct_width-1]?(-XMult1):XMult1) + (b2[coeffct_width-1]?(-XMult2):XMult2);
//-----------------极点系数的实现代码-------------------------------------------------------------------------------------
always @(posedge clk or negedge rst_n)
if (!rst_n)
//初始化寄存器值为0
begin
Yin1 <= 'd0;
Yin2 <= 'd0;
end
else
begin
Yin1 <= Yin;
Yin2 <= Yin1;
end
assign a1_mu=(a1[coeffct_width-1])?(-a1):a1;
assign a2_mu=(a2[coeffct_width-1])?(-a2):a2;//极点系数转正值比较
//采用移位运算及加法运算实现乘法运算
assign YMult1 = (a1_mu[0]?{{coeffct_width{Yin1[daout_width-1]}},Yin1}:0)+(a1_mu[1]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<1):0)+ //*-3934=-1111 0101 1110 a1
(a1_mu[2]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<2):0)+(a1_mu[3]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<3):0)+
(a1_mu[4]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<4):0)+(a1_mu[5]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<5):0)+
(a1_mu[6]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<6):0)+(a1_mu[7]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<7):0)+
(a1_mu[8]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<8):0)+(a1_mu[9]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<9):0)+
(a1_mu[10]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<10):0)+(a1_mu[11]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<11):0)+
(a1_mu[12]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<12):0)+(a1_mu[13]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<13):0)+
(a1_mu[14]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<14):0)+(a1_mu[15]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<15):0)+
(a1_mu[16]?({{coeffct_width{Yin1[daout_width-1]}},Yin1}<<16):0);
assign YMult2 = (a2_mu[0]?{{coeffct_width{Yin2[daout_width-1]}},Yin2}:0)+(a2_mu[1]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<1):0)+
(a2_mu[2]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<2):0)+(a2_mu[3]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<3):0)+
(a2_mu[4]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<4):0)+(a2_mu[5]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<5):0)+
(a2_mu[6]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<6):0)+(a2_mu[7]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<7):0)+
(a2_mu[8]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<8):0)+(a2_mu[9]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<9):0)+
(a2_mu[10]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<10):0)+(a2_mu[11]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<11):0)+
(a2_mu[12]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<12):0)+(a2_mu[13]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<13):0)+
(a2_mu[14]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<14):0)+(a2_mu[15]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<15):0)+
(a2_mu[16]?({{coeffct_width{Yin2[daout_width-1]}},Yin2}<<16):0); //*1892=0111 0110 0100 a2
assign Aout=(a1[coeffct_width-1]?(-YMult1):YMult1) + (a2[coeffct_width-1]?(-YMult2):YMult2);
//-----------计算最终结果-------------------------------------------------------------------------------------
//IIR滤波器实现代码
assign Ysum = {Xout[daout_width+coeffct_width-1],Xout}-{Aout[daout_width+coeffct_width-1],Aout};
assign Ydiv =(Ysum>>>(clogb2(a0)-1));// /a0
//根据仿真结果可知,第一级滤波器的输出范围
assign Yin = Ydiv[daout_width-1:0];
always @(posedge clk or negedge rst_n)
if (!rst_n)
Yout_reg <= 0;
else
Yout_reg <= Yin;
assign Yout = Yout_reg;
endmodule
四、FPGA的modelsim仿真
根据matlab的设计进行FPGA的实现,并进行modelsim仿真,仿真结果如下
仿真文件及整个系统工程文件链接如下文章来源:https://www.toymoban.com/news/detail-765626.html
https://download.csdn.net/download/qq_35028634/87922519?spm=1001.2014.3001.5503文章来源地址https://www.toymoban.com/news/detail-765626.html
到了这里,关于基于FPGA的IIR滤波器的实现的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!