IIR滤波器的FPGA实现

生产实习著
此篇实现的是直接1型7阶切比雪夫1型低通滤波器

文章目录

  • IIR滤波器的FPGA实现
    • IIR原理
      • IIR定义
      • 模拟滤波器设计
      • 双线性变换
    • IIR系统结构
    • FPGA实现
      • MATLAB 获取系数
      • FPGA实现FIR滤波器
      • FPGA根据系统框图连线
      • MATLAB生成仿真数据
      • 写testbeach
    • 仿真结果
    • 结语

IIR原理

IIR定义

IIR(Infinite Impulse Response)无限脉冲响应数字滤波器,也叫作递归滤波器.
由差分方程:
y(n)=∑i=0Mbix(n−i)−∑i=1Naiy(n−i)y(n) = \sum^M_{i=0}b_i x(n-i) - \sum^N_{i=1}a_i y(n-i)y(n)=i=0∑M​bi​x(n−i)−i=1∑N​ai​y(n−i)
进行Z变换:
Y(z)=∑i=0Mbiz−iX(z)−∑i=1Naiz−iY(z)Y(z)=\sum_{i=0}^{M} b_{i} z^{-i} X(z)-\sum_{i=1}^{N} a_{i} z^{-i} Y(z) Y(z)=i=0∑M​bi​z−iX(z)−i=1∑N​ai​z−iY(z)
得到系统函数:
H(z)=Y(z)X(z)=∑i=0Mbiz−i1+∑i=1Naiz−iH(z)=\frac{Y(z)}{X(z)}=\frac{\sum_{i=0}^{M} b_{i} z^{-i}}{1+\sum_{i=1}^{N} a_{i} z^{-i}} H(z)=X(z)Y(z)​=1+∑i=1N​ai​z−i∑i=0M​bi​z−i​
至于为什么叫IIR,和FIR有什么区别,大家做一下z逆变换就知道了

模拟滤波器设计

要提及到模拟滤波器设计的理由很简单,就是因为设计IIR的一般是先设计好相应的模拟滤波器,然后再利用双线性变换转换成数字滤波器,在这里我们介绍一个切比雪夫1型滤波器:
他的幅度平方函数长这个样:
Gn(ω)=∣Hn(jω)∣=11+ϵ2Tn2(ωω0)G_{n}(\omega)=\left|H_{n}(j \omega)\right|=\frac{1}{\sqrt{1+\epsilon^{2} T_{n}^{2}\left(\frac{\omega}{\omega_{0}}\right)}} Gn​(ω)=∣Hn​(jω)∣=1+ϵ2Tn2​(ω0​ω​)​1​
当ω=ω0\omega = \omega_0ω=ω0​时有:
∣H(ω0)∣=11+ϵ2\left|H\left(\omega_{0}\right)\right|=\frac{1}{\sqrt{1+\epsilon^{2}}} ∣H(ω0​)∣=1+ϵ2​1​
其中,Tn(ωω0)T_{n}\left(\frac{\omega}{\omega_{0}}\right)Tn​(ω0​ω​)是n阶切比雪夫多项式,定义为:
{Tn(ωω0)=cos⁡(n⋅arccos⁡ωω0);0≤ω≤ω0Tn(ωω0)=cosh⁡(n⋅arccosh⁡ωω0);ω>ω0\begin{cases} T_{n}\left(\frac{\omega}{\omega_{0}}\right)=\cos \left(n \cdot \arccos \frac{\omega}{\omega_{0}}\right) ; 0 \leq \omega \leq \omega_{0}\\ T_{n}\left(\frac{\omega}{\omega_{0}}\right)=\cosh \left(n \cdot \operatorname{arccosh} \frac{\omega}{\omega_{0}}\right) ; \omega>\omega_{0} \end{cases} ⎩⎨⎧​Tn​(ω0​ω​)=cos(n⋅arccosω0​ω​);0≤ω≤ω0​Tn​(ω0​ω​)=cosh(n⋅arccoshω0​ω​);ω>ω0​​
当0<x<1时,Tn(x)T_{n}(x)Tn​(x)在0和1之间变化 ;当x>1时,cos−是虚数,所以Tn(x)T_{n}(x)Tn​(x)像双曲余弦一样单调地增加;∣Hn(w)∣对于0≤w/w0≤1呈现出在1和12ϵ2\frac1{2\epsilon^2}2ϵ21​之间的波动;而对于w/w0〉1单调地减小。需要用三个参量来确定该滤波器:ε,w0和N。在典型的设计中,用容许的通带波纹来确定ε,而用希望的通带截止频率来确定w0。然后选择合适的阶次n,以便阻带的技术要求得到满足。

上述的 滤波器设计原理看不懂没关系,因为模拟滤波器设计理论已经非常成熟了,所以我们可以借助matlab来解决
详见:Matlab的IIR Filter Design

除此之外,常见的模拟滤波器还有巴特沃斯,切比雪夫2型,椭圆型滤波器等,此处不做详述

双线性变换

这是利用反正切的方法将s域投影到z域,理解思路有很多种,大家不妨多方查阅一下资料,这里直接给出转换公式:
H(z)=Ha(s)∣s=2Ts1−z−11+z−1H(z)=H_{a}\left.(s)\right|_{s=\frac{2}{T_{s}} \frac{1-z^{-1}}{1+z^{-1}}} H(z)=Ha​(s)∣s=Ts​2​1+z−11−z−1​​

IIR系统结构

实际上从IIR的定义我们就可以直接得到直接1型:

我们不妨将ab调转过来,合并延时器,就可以得到直接2型:

不妨将系统函数定义式做一点变换,拆开每项系数:
H(z)=Y(z)X(z)=∑i=0Mbiz−i1+∑i=1Naiz−iH(z)=\frac{Y(z)}{X(z)}=\frac{\sum_{i=0}^{M} b_{i} z^{-i}}{1+\sum_{i=1}^{N} a_{i} z^{-i}} H(z)=X(z)Y(z)​=1+∑i=1N​ai​z−i∑i=0M​bi​z−i​
to:
H(z)=∏i=1Lγ0i+γ1iz−1+γ2iz−21+β1iz−1+β2iz−2=A∏i=1L1+α1iz−1+α2iz−21+β1iz−1+β2iz−2=A∏i=1LHi(z)H(z)=\prod_{i=1}^{L} \frac{\gamma_{0 i}+\gamma_{1 i} z^{-1}+\gamma_{2 i} z^{-2}}{1+\beta_{1 i} z^{-1}+\beta_{2 i} z^{-2}}=A \prod_{i=1}^{L} \frac{1+\alpha_{1 i} z^{-1}+\alpha_{2 i} z^{-2}}{1+\beta_{1 i} z^{-1}+\beta_{2 i} z^{-2}}=A \prod_{i=1}^{L} H_{i}(z) H(z)=i=1∏L​1+β1i​z−1+β2i​z−2γ0i​+γ1i​z−1+γ2i​z−2​=Ai=1∏L​1+β1i​z−1+β2i​z−21+α1i​z−1+α2i​z−2​=Ai=1∏L​Hi​(z)
得到每一个子系统Hi(z)H_i(z)Hi​(z),就可以用直接12型来表征子系统,然后再串起来,比如:


FPGA实现

这里实现的是直接1型7阶切比雪夫1型低通滤波器.思路很简单,直接将ab两路当成两个FIR滤波器就完事了

MATLAB 获取系数

获取系数有两种方法:
1. 利用函数cheby1,cheby2和butter等函数进行设计,建议回看我上面的matlab设计iir的帮助页面
2. 利用滤波器设计工具箱 filterDesigner
此处为了直观使用filterDesigner,设计完之后是这样的:

直接点Design Filter是设计出来的是直接2型的SOS(second-order sections)版也就是级联型.我们需要

  1. Edit-> Convert Structure 选Direct-Form I SOS
  2. Edit-> Convert to Single Section
  3. Ctrl +e (File->Export)导出系数

如果不慎生成了SOS的话,也可以在命令行中输入:

[Num,Den] = sos2tf(SOS,G);
进行转换,其中Num(numerator)为分子,Den(Denominator)为分母

然后对系数进行量化:

  Num = round(Num*2^9);      %最大值是2.8多,建议思考为什么是512Den = round(Den*2^9);

FPGA实现FIR滤波器

可以见我前面的FPGA/Verilog 设计FIR滤波器
我这里为了重定义系数和后续好改成SOS,做了一些小功夫和去除了累加器,自己写了个加法树.

module fir_7
#(parameter WIDTH=4'd12 , c0 = 12'b0 , c1 = 12'b0 , c2 = 12'b0 , c3 = 12'b0 , c4 = 12'b0 , c5=12'b0 , c6=12'b0 ,c7=12'b0 )
(
input rst_n ,
input clk   ,
input signed [WIDTH-1'b1:0] din,
output signed [2*WIDTH+2:0] dout
);
integer i=0;
integer j=0;reg signed [WIDTH-1'b1:0] din_delay[7:0];
always@(posedge clk or negedge rst_n)
beginif(!rst_n)beginfor(i=0;i<8;i =i+1)din_delay[i] <= 'b0;endelsebeginfor(i=1;i<8;i =i+1)din_delay[i] <= din_delay[i-1];din_delay[0] <= din;end
endreg signed [2*WIDTH-1'b1:0] din_mult[7:0];
always @ (posedge clk or negedge rst_n)
beginif(!rst_n)beginfor(j=0;j<8;j =j+1)din_mult[j] <= 'b0;endelsebegindin_mult[0] <= din_delay[0]*c0;din_mult[1] <= din_delay[1]*c1;din_mult[2] <= din_delay[2]*c2;din_mult[3] <= din_delay[3]*c3;din_mult[4] <= din_delay[4]*c4;din_mult[5] <= din_delay[5]*c5;din_mult[6] <= din_delay[6]*c6;din_mult[7] <= din_delay[7]*c7;end
endreg signed [2*WIDTH:0] din_mult1[3:0];
reg signed [2*WIDTH+1:0] din_mult2[1:0];
reg signed [2*WIDTH+2:0] din_mult3;always @ (posedge clk or negedge rst_n)
beginif(!rst_n)begindin_mult1[0] <= 'b0; din_mult1[1] <= 'b0;din_mult1[2] <= 'b0;din_mult1[3] <= 'b0;din_mult2[0] <= 'b0; din_mult2[1] <= 'b0;din_mult3    <= 'b0;endelsebegindin_mult1[0] <= din_mult[0] + din_mult[1];din_mult1[1] <= din_mult[2] + din_mult[5];din_mult1[2] <= din_mult[3] + din_mult[6];din_mult1[3] <= din_mult[4] + din_mult[7];din_mult2[0] <= din_mult1[0] + din_mult1[1];din_mult2[1] <= din_mult1[2] + din_mult1[3];din_mult3    <= din_mult2[0] + din_mult2[1];end
end
assign dout = din_mult3;endmodule

FPGA根据系统框图连线

这里比较简单,就给出个关键部分吧:

fir_7
#(.WIDTH(4'd12),.c0(12'd1), .c1(12'd7), .c2(12'd21), .c3 (12'd36),.c4(12'd36), .c5(12'd21), .c6(12'd7) ,.c7(12'd1))
zero (
.rst_n(RST_N),
.clk(CLK_50M),
.din(Yin),
.dout(Yout)
);fir_7
#(.WIDTH(4'd12),.c0(12'd256) , .c1(-12'd510), .c2(12'd875), .c3 (-12'd971),.c4(12'd838), .c5(-12'd527), .c6(12'd231) , .c7(-12'd61))
poly (
.rst_n(RST_N),
.clk(CLK_50M),
.din(din),
.dout(Xout)
);

最终生成的框图是这样的:

MATLAB生成仿真数据

由于上几次的博客生成仿真数据的脚本不怎么好用,所以找了一个更好的jio本:

 %=============设置系统参数==============%
%f1=1e6;        %设置波形频率
f2=200e3;
f3=1000e3;
Fs=10e6;        %设置采样频率
L=4096;         %数据长度
N=12;           %数据位宽
%=============产生输入信号==============%
t=0:1/Fs:(1/Fs)*(L-1);
%y1=sin(2*pi*f1*t);
y2=0.5*sin(2*pi*f2*t);
y3=0.5*sin(2*pi*f3*t);
%y4=y1+y2+y3;
y4= y2+y3;
y_n=round(y4*(2^(N-2)-1));      %N比特量化;如果有n个信号相加,则设置(N-n)
%=================画图==================%
a=10;           %改变系数可以调整显示周期
stem(t,y_n);
axis([0 L/Fs/a -2^N 2^N]);      %显示
%=============写入外部文件==============%
fid=fopen('sinx.txt','w');    %把数据写入sin_data.txt文件中,如果没有就创建该文件
for k=1:length(y_n)B_s=dec2bin(y_n(k)+((y_n(k))<0)*2^N,N);for j=1:Nif B_s(j)=='1'tb=1;elsetb=0;endfprintf(fid,'%d',tb);endfprintf(fid,'\r\n');
end
fprintf(fid,';');
fclose(fid);

写testbeach

这里只给出读取数据部分:

integer i;   //数组坐标
reg signed [11:0] stimulus[1:data_num];  //数组形式存储读出的数据
initial
beginRST_N = 1'b1;#60 RST_N = 1'b0;#60 RST_N = 1'b1; $readmemb("sinx.txt", stimulus);  //将txt文件中的数据存储在数组中i = 0;repeat(data_num*10) begin   //重复读取数组中的数据i = i + 1;din = stimulus[i%data_num]; #PERIOD;         //每个时钟读取一次end$stop;
end

仿真结果


后仿在1.2V 0度模型下最高运行速率180Mhz(板子最高200M)

结语

因为生产实习和电赛,最近不得不备一些这种小东西,会一直更新到7.26号,各位看官有兴趣的可以追踪一下.

如果csdn再不加入对verilog的支持,我就举家搬迁到简书或者自己搭一个博客了.

如果你觉得有丶收获的话

IIR滤波器的FPGA实现相关推荐

  1. 基于FPGA的IIR滤波器设计

    基于FPGA的IIR滤波器设计,使用VHDL语言. 本设计是毕设,包括论文 下面是论文目录截图: 各模块VHDL程序 时序控制模块程序 library ieee; use ieee.std_logic ...

  2. FPGA数字信号处理(六)直接型IIR滤波器Verilog设计

    该篇是FPGA数字信号处理的第六篇,2-5篇介绍了DSP系统中极其常用的FIR滤波器.本文将简单介绍另一种数字滤波器--IIR滤波器的原理,详细介绍使用Verilog HDL设计直接型IIR滤波器的方 ...

  3. FPGA数字信号处理(七)级联型IIR滤波器Verilog设计

    该篇是FPGA数字信号处理的第七篇,上一篇介绍了直接型IIR滤波器的原理,详细介绍使用Verilog HDL设计直接型IIR滤波器的方法.本文会介绍如何用Verilog HDL设计级联型IIR滤波器. ...

  4. matlab中滤波器设计与实现,基于MATLAB的IIR滤波器设计与实现

    描述 由于电力系统中非线性电子元件的大量使用,使得谐波污染问题日益严重,当谐波含量超过一定限度时就可能对电网和用户造成极大的危害,且增加线路损耗,降低线路传输能力,干扰通信信号等.因此,应该积极寻找一 ...

  5. 简谈FIR滤波器和IIR滤波器的区别

    最近总是遇到很多大侠在问滤波器相关的问题,之前对这一方面接触不是很多,最近也是在学习一些这方面的知识,今天先和大侠简单聊一聊FIR滤波器和IIR滤波器的区别,后续等研究的差不多了,再更新有关滤波器的详 ...

  6. CIC滤波器和FPGA实现

    CIC滤波器 CIC滤波器是用不同抽样频率进行数字信号处理的一种FIR滤波器.主要用于数字信号的抽取和内插. CIC滤波器由一对或多对积分-梳状滤波器组成,在抽取CIC中,输入信号依次经过积分.降采样 ...

  7. 【收藏】详解FIR滤波器和IIR滤波器的区别

    数字滤波器广泛应用于硬件电路设计,一般分为FIR滤波器和IIR滤波器.那么FIR滤波器和IIR滤波器有什么区别呢?本文通过几个例子做一个简单的总结. 一.FIR滤波器 定义: FIR滤波器是有限长单位 ...

  8. matlab iir滤波器设计 实验报告,基于MATLAB的IIR滤波器设计与实现

    由于电力系统中非线性电子元件的大量使用,使得谐波污染问题日益严重,当谐波含量超过一定限度时就可能对电网和用户造成极大的危害,且增加线路损耗,降低线路传输能力,干扰通信信号等.因此,应该积极寻找一种治理 ...

  9. butter滤波器是iir吗_如何快速设计一个IIR滤波器

    在文章如何快速设计一个FIR滤波器(一)以及如何快速设计一个FIR滤波器(二)等文章中,我们讨论了如何设计FIR(Finite Impulse Response Filter),FIR有很多优点,比如 ...

  10. [数字信号处理]IIR滤波器的间接设计(C代码)(转)

    PS:转自http://blog.csdn.net/zhoufan900428/article/details/9069475 1.模拟滤波器的设计 1.1巴特沃斯滤波器的次数 根据给定的参数设计模拟 ...

最新文章

  1. vim编辑器----常用命令
  2. Chem. Sci. | SyntaLinker: 基于Transformer神经网络的片段连接生成器
  3. 【学习心得】当程序员思路被打断
  4. 【android】 浏览文件,如浏览sd卡下的图片文件
  5. 日美“利刃”联合军演
  6. Cocos2dx 中 倒计时保留2位数写法
  7. 分区助手扩大c盘后自动修复_C盘空间不够,如何扩大?
  8. 这样的递归调用,你看出来了?
  9. 唐骏给李开复泼冷水:创业不可复制
  10. 全国计算机等级考试题库二级C操作题100套(第67套)
  11. python输出时间_Python获取并输出当前日期时间
  12. Linux学习笔记(四)-Linux常用命令
  13. 互联网浏览本地html,如何加载本地HTML文件,如果没有互联网连接
  14. 百度最全的LINUX和Redhat学习教程下载帖大全
  15. eclipse使用jsp
  16. 联想r720自带杜比驱动下载_联想Yoga 9i 拼凑产品,营销行为直呼内行
  17. 关于java Stream流将list集合分组之后与原list的集合的顺序不一致的问题
  18. Linux(四)——CROND和磁盘分区与挂载
  19. 【天下有春】剑气纵横三万里,一剑光寒十九洲
  20. Python输出16进制不带0x补零,整数转16进制,字符串转16进制

热门文章

  1. 毕业设计 python opencv 机器视觉图像拼接算法
  2. 浏览器工作原理--浏览器中的页面循环系统
  3. C# 调用Webservice实例
  4. java检测网站死链,网站死链检测工具
  5. Fedora 14 直接root登录
  6. Creative cloud登录不上、打不开、一直在加载,可能是移动宽带的问题
  7. java中用窗口求一元二次方程,《一元二次方程求解窗口——Java第十三周》
  8. 高维数据可视化之t-SNE算法
  9. 基于PHP开发的外卖订餐网站(带源码)
  10. mw150um 驱动程序win10_mercury无线网卡驱动