FIR滤波器设计与仿真.docx
《FIR滤波器设计与仿真.docx》由会员分享,可在线阅读,更多相关《FIR滤波器设计与仿真.docx(40页珍藏版)》请在冰豆网上搜索。
![FIR滤波器设计与仿真.docx](https://file1.bdocx.com/fileroot1/2023-3/28/ee176ecf-8895-4fa8-867f-5f342b985c03/ee176ecf-8895-4fa8-867f-5f342b985c031.gif)
FIR滤波器设计与仿真
EDA课程设计---FIR滤波器
一、FIR数字滤波器理论简述
有限冲激响应(FIR)数字滤波器和无限冲激响应(IIR)数字滤波器广泛应用于数字信号处理系统中。
IIR数字滤波器方便简单,但它相位的非线性,要求采用全通网络进行相位校正,且稳定性难以保障。
FIR滤波器具有很好的线性相位特性,使得它越来越受到广泛的重视。
有限冲击响应(FIR)滤波器的特点:
1既具有严格的线性相位,又具有任意的幅度;
2FIR滤波器的单位抽样响应是有限长的,因而滤波器性能稳定;
3只要经过一定的延时,任何非因果有限长序列都能变成因果的有限长序列,因而能用因果系统来实现;
4FIR滤波器由于单位冲击响应是有限长的,因而可用快速傅里叶变换(FFT)算法来实现过滤信号,可大大提高运算效率。
5FIR也有利于对数字信号的处理,便于编程,用于计算的时延也小,这对实时的信号处理很重要。
6FIR滤波器比较大的缺点就是阶次相对于IIR滤波器来说要大很多。
FIR数字滤波器是一个线性时不变系统(LTI),N阶因果有限冲激响应滤波器可以用传输函数H(z)来描述,
在时域中,上述有限冲激响应滤波器的输入输出关系如下:
其中,x[n]和y[n]分别是输入和输出序列。
N阶有限冲激响应滤波器要用N+1个系数描述,通常要用N+1个乘法器和N个两输入加法器来实现。
乘法器的系数正好是传递函数的系数,因此这种结构称为直接型结构,可通过式(1.2)来实现,如图1。
图1
FIR滤波算法实际上是一种乘法累加运算,它不断地输入样本x(n),经延时Z-1,然后做乘法累加运算,再输出滤波结果y(n)。
当冲击响应满足下列条件时,FIR滤波器具有对称结构,为线性相位滤波器:
这种对称性,可使得乘法器数量减半:
对n价滤波器,当n为偶数时,乘法器的个数为n/2个;当n为奇数时,乘法器的个数为(n+1)/2个。
在电路实现中,乘法器占用的逻辑单元数较多。
乘法器的增加,意味着电路成本增加,另外对电路的工作速度也有影响。
N阶线性相位的因果FIR系统的单位冲激响应滤波器可用对称冲激响应
或者反对称冲激响应
来描述。
具有对称冲激响应的FIR传输函数的冲激响应可写成如下形式:
当N为偶数时
当N为奇数时
则FIR线性相位系统的结构可转化成如图2(a)和图2(b)所示。
图2(a)N为奇数
图2(b)N为偶数
(二)设计方案
随着数字技术日益广泛的应用,以现场可编程门阵列(FPGA)为代表的ASIC器件得到了迅速普及和发展,器件集成度和速度都在高速增长。
FPGA既具有门阵列的高逻辑密度和高可靠性,又具有可编码逻辑器件的用户可编程特性,可以减少系统设计和维护的风险,降低产品成本,缩短设计周期。
分布式算法是一种以实现乘加运算为目的的运算方法。
它与传统算法实现乘加运算的不同在于执行部分积运算的先后顺序不同。
简单地说,分布式算法在完成乘加功能时是通过将各输入数据每一对应位产生的部分积预先进相加形成相应部分积,然后在对各部门积进行累加形成最终结果,而传统算法是等到所有乘积产生之后再进行相加来完成乘加运算的。
与传统算法相比,分布式算法可极大地减少硬件电路规模,很容易实现流水线处理,提高电路的执行速度。
FPGA有着规整的内部逻辑块阵列和丰富的连线资源,特别适合细粒度和高并行度结构特点的数字信号处理任务,如FIR、FFT等。
利用FPGA实现FIR滤波器的设计过程,并且对设计中的关键技术——分布式算法进行详细描述。
二、FIR数字滤波器的设计方案:
通常采用窗函数设计FIR滤波器方法简单,但是这些滤波器的设计还不是最优的。
首先通带和阻带的波动基本上相等,另外对于大部分窗函数来说,通带内或阻带内的波动不是均匀的,通常离开过渡带时会减小。
若允许波动在整个通带内均匀分布,就会产生较小的峰值波动。
因此考虑通过某种方法,对滤波器的结构进行优化。
对于线性相位因果FIR滤波器,它的系列具有中心对称特性,即h(i)=±h(N-1-i)。
令s(i)=x(i)±x(N-1-i),对于偶对称,代入式
(1)可得:
根据要求,要设计一个输入8位,输出8位的17阶线性相位FIR滤波器,所以采用图2(a)的方式,其中输入信号范围为:
[±99,0,0,0,±70,0,0,0,±99,0,0,0,±70,…],此滤波器Fs为44kHz,Fc为10.4kHz。
MATLAB设计计算滤波器系数过程如下:
FIR滤波器参数设置,因为是17阶,所以Specifyorder处填16,h(0)=0.
FIR滤波器的幅频响应
FIR滤波器的相频响应
FIR滤波器的冲激响应
FIR滤波器系数
对FIR滤波器的系数进行调整,整数化
可得FIR滤波器的参数为[-12-181329-13-521416224214-52-132913-18-12]
根据以上所说的该思路,可以将FIR滤波器的原理图设计如下:
下面对各加法器乘法器的输出位数进行分析,对第一级加法器,输入全为8位,输出统一为9位。
对各个乘法器进行分析,12=8+4,8为2的3次方,向左移了3位,输出为12位;18=16+2,16为2的4次方,向左移了4位,输出为13位;以此类推,13乘法器输出为12位,29输出为13位,52输出为14位,162输出为16位,242输出为16位。
对剩余加法器进行分析,对输入序列进行分析,[±99,0,0,0,±70,0,0,0,±99,0,0,0,±70,…],周期为8,经分析当总值最大时,总输出应为99*18+70*29+50*70+99*162=1782+2030+3640+16038=23490,2的15次方为32768,再加上一位符号位,所以输出应为16位,由此类推,12、18乘法器输出之和为13位,13、19乘法器输出之和应为13位,总输出为14位。
另一支路上,13、52乘法器输出之和为14位,14、162乘法器输出之和为16位,其总输出之和为16位,最后这两路输出之和为16位。
将后8位舍去,加上由乘法器242输出舍取得倒的8位,总输出为8位。
至此,所有器件的输入输出都可判定。
下面进入模块设计阶段。
(三)模块电路设计
设计的FIR滤波器由19个小VHD文件和一个总体BDF文件组成,VHD文件可以分为以下四种模块:
寄存器、加法器、减法器、乘法器。
3.1寄存器
3.1.1寄存器原理
寄存器用于寄存一组二值代码,对寄存器的触发器只要求它们具有置1、置0的功能即可,因而本设计中用D触发器组成寄存器,实现寄存功能。
3.1.2寄存器要求实现的功能
在CP正跳沿前接受输入信号,正跳沿时触发翻转,正跳沿后输入即被封锁。
3.1.3寄存器的VHDL语言实现(8位)
3.1.4寄存器的模块图
3.1.5寄存器的波形仿真
完全符合设计要求。
3.2加法器
3.2.1加法器的原理
在将两个多位二进制数相加时,除了最低位以外,每一位都应该考虑来自低位的进位,即将两个对应位的加数和来自低位的进位3个数相加。
这种运算称为全加,所用的电路称为全加器。
多位加法器的构成有两种方式:
并行进位和串行进位。
并行进位加法器设有进位产生逻辑,预算速度较快;串行进位方式是将全加器级联构成多位加法器。
并行进位加法器通常比串行级联加法器占用更多的资源。
随着为数的增加,相同位数的并行加法器与串行加法器的资源占用差距也越来越大,因此,在工程中使用加法器时,要在速度和容量之间寻找平衡点。
本次设计采用的是并行加法器方式。
3.2.2加法器要求实现的功能
实现两个二进制数字的相加运算。
当到达时钟上升沿时,将两数输入,运算,输出结果。
3.2.3加法器的VHDL语言实现
(以下以12位数加16位数生成16位数的加法器为例)
3.2.4加法器的模块图
3.2.5加法器的波形仿真
完全符合设计要求。
3.3减法器
3.3.1减法器的原理
减法器的原理与加法器类似,尤其是并行式的减法器也加法器的区别仅仅在于最后的和数为两数相减。
如:
Dout<=Din2-s1;
3.3.2减法器要求实现的功能
由上面简化电路的需要,当乘法器常系数为负数的,可以取该数的模来作为乘法器的输入,其输出作为一个减法器的输入即可。
故减法器要实现两个二进制数相减的运算。
当到达时钟上升沿时,将两数输入,运算,输出结果。
3.3.3减法器的VHDL语言实现
(以下以16位数减去14位数输出16位数的减法器为例)
3.3.4减法器的模块图
3.3.5减法器的波形仿真
完全符合设计要求。
3.4乘法器
3.4.1乘法器的原理
从资源和速度考虑,常系数乘法运算可用移位相加来实现。
将常系数分解成几个2的幂的和形式。
下例为乘18电路设计,算法:
18=16+2
3.4.2乘法器要求实现的功能
实现输入带符号数据与固定数据两个二进制数的乘法运算。
当到达时钟上升沿时,将两数输入,运算,输出结果。
3.4.3乘法器的VHDL语言实现
3.4.4乘法器的模块图
3.4.5乘法器的波形仿真
完全符合设计要求。
(四)FIR滤波器整体电路
FIR滤波器的整体电路基本与其原理图类似。
整体电路如下图所示:
(五)FIR滤波器整体电路仿真结果
1、设定输入信号
根据设计要求,输入信号范围是:
[±99,0,0,0,±70,0,0,0,±99,0,0,0,±70,…]
2、输出信号理论值
由FIR数字滤波器的公式
仿真结果
(六)结论
输出结果y[n]
理论值
仿真结果
MATLAB卷积值/512
经仿真器仿真
-2.3203
-3
-3.4805
-4
2.5137
2
5.6074
5
-4.1543
-5
-12.516
-13
4.4844
4
35.289
35
42.695
41
20.734
20
7.1348
7
17.701
17
26.418
26
15.24
15
8.9121
8
24.699
24
y[0]
38.598
37
y[1]
24.699
24
y[2]
8.9121
8
y[3]
15.24
15
y[4]
24.777
24
y[5]
15.24
15
y[6]
8.9121
8
y[7]
24.699
24
y[8]
38.598
37
y[9]
24.699
24
y[10]
8.9121
8
y[11]
15.24
15
y[12]
24.777
24
y[13]
15.24
15
y[14]
8.9121
8
y[15]
24.699
24
y[16]
38.598
37
y[17]
24.699
24
经验总结:
第一遍设计时,原本d8信号是直接进入乘法器242,这样输出为15位,再经过四个延时器与左边加起来的信号同步,最后在进入一个加法器,此加法器输入信号为左边来的16位信号,和乘法器242输出的信号15位,各取前8位信号相加,输出最后结果。
理论上,无论是输入输出信号的位数,还是考虑延时同步,还是舍去的位数多少都没有问题,所以我认为这种设计是可行的。
实验总结:
本次试验确实学到了很多东西,真正做完了才发现其实没有那么难,但是在实验过程中却遇到了很多困难,由于FIR是上学期学过的知识,所以有些内容可能忘记了,要想做好这次试验一定要很清楚的懂得FIR滤波器的工作原理,所以又把以前的课本拿出来翻了一遍.在VHDL编程过程中遇到了更多的问题,有的时候由于一不小心敲错的一个符号,或者敲错了一个字母都会导致很多错误,检错也是一项很巨大的工程,这一点应该很注意,敲代码是一定要认真仔细.在这个过程中还要明白各种寄存器、加法器、乘法器的工作原理,这样才能把十几个实体完整无误的写出来。
等所有的问题都解决完了就可使仿真了,做到后来其实心里很明朗了,当初还有点模糊不清,经过这个实验,我也懂得了什么叫坚持,由于程序很复杂,我曾想过要放弃,但是觉得要是放弃了自己的努力就白费了,所以还是坚持了下来,虽然我交的迟了一些,但是我自己真正学到了东西,希望老师能够理解,谢谢老师!
--顶层模块的VJHDL实现如下:
LIBRARYIEEE;
USEIEEE.STD_LOGIC_1164.ALL;
LIBRARYwork;
ENTITYfirIS
PORT(clk:
INSTD_LOGIC;
clear:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(7DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
ENDfir;
ARCHITECTUREARTOFfirIS
--元件定义
--12位有符号数与13位有符号数相加的全加器
COMPONENTadder121313
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(11DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(12DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(12DOWNTO0));
ENDCOMPONENT;
--8位寄存器
COMPONENTregister8
PORT(clk:
INSTD_LOGIC;
clear:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(7DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
ENDCOMPONENT;
--8位有符号数与9位有符号数相加的全加器
COMPONENTadder889
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(7DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(7DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(8DOWNTO0));
ENDCOMPONENT;
--输入数据乘以12的乘法器
COMPONENTmult12
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(11DOWNTO0));
ENDCOMPONENT;
--输入数据乘以18的乘法器
COMPONENTmult18
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(12DOWNTO0));
ENDCOMPONENT;
--输入数据乘以13的乘法器
COMPONENTmult13
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(11DOWNTO0));
ENDCOMPONENT;
--输入数据乘以29的乘法器
COMPONENTmult29
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(12DOWNTO0));
ENDCOMPONENT;
--输入数据乘以52的乘法器
COMPONENTmult52
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(13DOWNTO0));
ENDCOMPONENT;
--输入数据乘以14的乘法器
COMPONENTmult14
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(11DOWNTO0));
ENDCOMPONENT;
--输入数据乘以162的乘法器
COMPONENTmult162
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(15DOWNTO0));
ENDCOMPONENT;
--8位移位寄存器
COMPONENTregister89
PORT(clk:
INSTD_LOGIC;
clear:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(7DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(8DOWNTO0));
ENDCOMPONENT;
--12位有符号数与14位有符号数相加的全加器
COMPONENTadder121414
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(11DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(13DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(13DOWNTO0));
ENDCOMPONENT;
--12位有符号数与16位有符号数相加的全加器
COMPONENTadder121616
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(11DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(15DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(15DOWNTO0));
ENDCOMPONENT;
--14位有符号数与13位有符号数相减的减法器
COMPONENTsub131314
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(12DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(12DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(13DOWNTO0));
ENDCOMPONENT;
--16位有符号数与14位有符号数相减的减法器
COMPONENTsub141616
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(13DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(15DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(15DOWNTO0));
ENDCOMPONENT;
--14位有符号数与16位有符号数相加的全加器
COMPONENTadder141616
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(13DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(15DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(15DOWNTO0));
ENDCOMPONENT;
--输入数据乘以242的乘法器
COMPONENTmult242
PORT(clk:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(8DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(15DOWNTO0));
ENDCOMPONENT;
--16位移位寄存器
COMPONENTregister16
PORT(clk:
INSTD_LOGIC;
clear:
INSTD_LOGIC;
Din:
INSTD_LOGIC_VECTOR(15DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(15DOWNTO0));
ENDCOMPONENT;
--16位加法器
COMPONENTadder888
PORT(clk:
INSTD_LOGIC;
Din1:
INSTD_LOGIC_VECTOR(15DOWNTO0);
Din2:
INSTD_LOGIC_VECTOR(15DOWNTO0);
Dout:
OUTSTD_LOGIC_VECTOR(7DOWNTO0));
ENDCOMPONENT;
--定义中间信号
SIGNALadd14:
STD_LOGIC_VECTOR(13DOWNTO0);
SIGNALadd16:
STD_LOGIC_VECTOR(15DOWNTO0);
SIGNALmul3:
STD_LOGIC_VECTOR(8DOWNTO0);
SIGNALmul4:
STD_LOGIC_VECTOR(8DOWNTO0);
SIGNALmul5:
STD_LOGIC_VECTOR(8DOWNTO0);
SIGNALmul6:
STD_LOGIC_VECTOR(8DOWNTO0);
SIGNALmul7:
STD_LOGIC_VECTOR(8DOWNTO0);
SIGNALmul8:
STD_LOGIC_VECTOR(8DOWNTO0);
SIGNALmul9:
STD_LOGIC_VECTOR(8DOWNTO0);
SIGNALSYNTHESIZED_WIRE_0:
STD_LOGIC_VECTOR(11DOWNTO0);
SIGNALSYNTHESIZED_WIRE_1:
STD_LOGIC_VECTOR(12DOWNTO0);
SIGNALSYNTHESIZED_WIRE_2:
STD_LOGIC_VECTOR(11DOWNTO0);
SIGNALSYNTHESIZED_WIRE_3:
STD_LOGIC_VECTOR(12DOWNTO0);
SIGNALSYNTHESIZED_WIRE_50:
STD_LOGIC_VECTOR(7DOWNTO0);
SIGNALSYNTHESIZED_WIRE_51:
STD_LOGIC_VECTOR(7DOWNTO0);
SIGNALSYNTHESIZED_WIRE_52:
STD_LOGIC_VECTOR(7DOWNTO0);
SIGNALSYNTHESIZED_WIRE_53:
STD_LOGIC_VECTOR(7DOWNTO0);
SIGNALSYN