赞
踩
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代码如下
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));%每个级联参数分析幅频特性
通过仿真可知,系统阶跃响应最大值不超1.2,那么假设输入信号量化为12bit,以输入±1范围为定点,那么输入信号定点为Q(2,10),输入信号经过系统后最大值不超1.2,因此输出信号定点也为Q(2,10)。因此在设计IIR滤波器输入输出位宽时,可根据此结果进行设计
根据matlab仿真的IIR参数转换,可以调用tf2sos函数直接得出级联设计结果,如下所示,增益值g可以分配至任意一级分子上,一般将增益分配到第一个级联分子系数上。
为便于各级可直接调用同一模块,对级联模块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
根据matlab的设计进行FPGA的实现,并进行modelsim仿真,仿真结果如下
仿真文件及整个系统工程文件链接如下
https://download.csdn.net/download/qq_35028634/87922519?spm=1001.2014.3001.5503
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。