基于VHDL语言的16阶线性相位滤波器设计.docx
- 文档编号:9622837
- 上传时间:2023-02-05
- 格式:DOCX
- 页数:26
- 大小:443.08KB
基于VHDL语言的16阶线性相位滤波器设计.docx
《基于VHDL语言的16阶线性相位滤波器设计.docx》由会员分享,可在线阅读,更多相关《基于VHDL语言的16阶线性相位滤波器设计.docx(26页珍藏版)》请在冰豆网上搜索。
基于VHDL语言的16阶线性相位滤波器设计
基于VHDL语言的16阶线性相位滤波器设计
(一)设计要求及设计原理
设计一个16阶低通FIR滤波器,采样频率
=80KHz,截止频率
=10KHz,输入输出皆为10位带符号数。
(1)FIR滤波器的基本原理
FIR滤波器的I/O关系如下:
其中,
、
分别为输入输出序列。
N为滤波器的阶数。
当冲击响应满足
时,FIR滤波器具有对称结构,即为线性相位滤波器。
(2)偶数阶线性相位滤波器的网络结构
(3)16阶线性相位滤波器的原理图
根据偶数阶线性相位滤波器的网络结构就能很容易得到16阶线性相位滤波器的原理图,如下:
(4)滤波器系数的获得
在ResponseType中选择Lowpass,在DesignMethod中选FIRWindow,因为是16阶的滤波器,所以在Specifyorder中输入15,采样频率
设为80KHz,截止频率
设为10KHz。
Kaiser窗口,Beta为0.5。
参数输入完毕点击DesignFilter即完成滤波器参数设置。
点击
即可获得滤波器的系数,如下图:
在MATLAB里面对所有数乘以2^11,即可得到各个乘法系数
滤波器系数分别为:
,
,
,
,
,
,
,
。
(二)模块电路设计
设计的滤波器由17个VHDL文件和一个总体BDF文件组成。
VHDL文件所包含的模块有三种:
寄存器、加法器和乘法器。
(1)寄存器
1寄存器原理及功能
寄存器用于寄存一组二进制代码,由15个D触发器组成。
每个D触发器具有时钟输入端、复位端、一个10位数据输入端和一个10位数据输出端。
触发器在复位端为高电平时全部清零。
在复位端为低电平时,触发器由时钟上升沿触发,上升沿后输入即被封锁。
寄存器所有的输入输出数据都是10位带符号类型的数据。
2寄存器的VHDL语言实现
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entitydff10is
port(x:
insigned(9downto0);
clk,rst:
instd_logic;
q:
outsigned(9downto0));
enddff10;
architecturedffofdff10is
begin
process(clk,rst)
variablezero:
signed(9downto0):
=(others=>'0');
begin
if(rst='1')thenq<=zero;
elsif(clk'eventandclk='1')thenq<=x;
endif;
endprocess;
enddff;
3寄存器的模块图
4寄存器的仿真波形
完全符合设计要求。
(2)加法器
1加法器原理及功能
本设计当中的所有加法器都具有两个数据输入端、一个时钟输入端和一个数据输出端。
在时钟的上升沿实现两个输入数据的加法,同时将所求的和输出,并且所有加法器输入输出都是带符号类型的数据。
为了保证加法结果的正确性,每个加法器的输出都比输入多一位,且最高位都是符号位。
根据设计原理,滤波器的加法器有三级,所不同的是,每一级加法器的输入输出数据的位数都是不一样的。
2第一级加法器的VHDL语言实现
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entityadder_layer1is
port(a,b:
insigned(9downto0);
clk:
instd_logic;
c:
outsigned(10downto0));
endadder_layer1;
architectureadder_layer1ofadder_layer1is
begin
process
variabletemp:
signed(9downto0);
variableprod:
signed(10downto0);
begin
waituntil(clk'eventandclk='1');
temp:
=a+b;
prod(9downto0):
=temp;------未扩展的加法结果
if(a(a'left)=b(b'left)andtemp(temp'left)/=b(b'left))then
prod(10):
=b(b'left);-------判断是否溢出
else
prod(10):
=temp(temp'left);-------扩展符号位
endif;
c<=prod;
endprocess;
endadder_layer1;
第一级加法器有10位输入和11位输出,最高位都是符号位。
所求和的符号位的扩展依据是,在有符号数加法器中,当两个符号位相同的操作数相加时,如果计算结果的符号位与两个操作数不同,就说明发生了溢出。
而当两个操作数的符号位不同时,则不会发生溢出。
一旦判断到发生了溢出,则所求和的符号位与两个加数的符号位相同,否则,所求和的符号位与未扩展的加法结果的符号位相同。
3第一级加法器的模块图
4第一级加法器的仿真波形
(3)第二级加法器的设计
本设计中,第二级加法器总共有四个,每个加法器都是进行了带符号类型数据的加法,因为它们的输入都来自对应的上一级乘法器的输出,所以每一个加法器的输入输出数据的位数是不一样的。
为了保证加法结果,所求的和的位数比两个加数的位数多一位。
1)第二级第一个加法器
由于两个加数a和b的位数是不一样的,a为16位,b为18位,因此,在进行加法运算之前,先将a扩展成18位,然后再求和。
和的位数为19位,比输入多一位。
1第二级第一个加法器的VHDL语言设计
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entityadder_layer21is
port(a:
insigned(15downto0);
b:
insigned(17downto0);
clk:
instd_logic;
c:
outsigned(18downto0));
endadder_layer21;
architectureadder_layer2ofadder_layer21is
begin
process
variableexp_a:
signed(17downto0);
variabletemp:
signed(17downto0);
variableprod:
signed(18downto0);
begin
waituntil(clk'eventandclk='1');
exp_a:
=a(a'left)&a(a'left)&a;---将a的位数扩展到b的位数
temp:
=exp_a+b;
prod(17downto0):
=temp;---未扩展位数
if(exp_a(exp_a'left)=b(b'left)andtemp(temp'left)/=b(b'left))then
prod(18):
=b(b'left);---扩展符号位
else
prod(18):
=temp(temp'left);---扩展符号位
endif;
c<=prod;
endprocess;
endadder_layer2;
2第二级第一个加法器的模块图
3第二级第一个加法器的仿真波形
2)第二级第二个加法器
两个加数a和b的位数不一样,a为19位,b为18位,因此,在进行加法运算之前,先将b扩展成19位,然后再求和。
和的位数为20位,比输入多一位。
1第二级第二个加法器的VHDL语言实现
代码原理和第二级第一个加法器基本相同,限于篇幅,这里没有给出具体代码,详见adder_layer22.vhd。
2第二级第二个加法器的模块图
3第二级第二个加法器的仿真波形
3)第二级第三个加法器
两个加数a和b的位数不一样,a为18位,b为20位,因此,在进行加法运算之前,先将a扩展成20位,然后再求和。
和的位数为21位,比输入多一位。
1第二级第三个加法器的VHDL语言实现
原理同上,代码见adder_layer23.vhd。
2第二级第三个加法器的模块图
3第二级第三个加法器的仿真波形
4)第二级第四个加法器
两个加数a和b的位数一样,都是21位,所以不需要扩展。
1第二级第四个加法器的VHDL语言实现
原理同上,代码见adder_layer24.vhd。
2第二级第四个加法器的模块图
3第二级第三个加法器的仿真波形
(4)第三级加法器的设计
1)第三级第一个加法器
两个加数a和b的位数不一样,a为19位,b为20位,因此,在进行加法运算之前,先将a扩展成20位,然后再求和。
和的位数为21位,比输入多一位。
1第三级第一个加法器的VHDL语言实现
原理同第二级加法器,代码见adder_layer31.vhd。
2第三级第一个加法器的模块图
3第三级第一个加法器的仿真波形
2)第三级第二个加法器
两个加数a和b的位数不一样,a为21位,b为22位,因此,在进行加法运算之前,先将a扩展成22位,然后再求和。
和的位数为23位,比输入多一位。
1第三级第二个加法器的VHDL语言实现
原理同上,代码见adder_layer32.vhd。
2第三级第二个加法器的模块图
3第三级第二个加法器的仿真波形
(5)第四级加法器的设计
两个加数a和b的位数不一样,a为21位,b为23位,因此,在进行加法运算之前,先将a扩展成23位,然后再求和。
然而根据设计原理,该加法器的输出应该是10位带符号数。
为了证明该加法器能够正常工作,这里先取24为输出。
1第四级加法器的VHDL语言实现
原理同上,代码见adder_layer4.vhd。
2第四级加法器的仿真波形
从仿真波形就可看出,该加法器是正常工作的。
3第四级加法器的模块图
如果要第四级加法器为10位输出,那么只要将输出及其赋值语句分别改为
c:
outsigned(9downto0)和c<=prod(21downto12)即可。
这里输出取24位当中第22位到第12位这10位的理由是,由于每一个乘法器的系数在处理时乘了2^11,及运算结果比实际左移了11位,所以应该将24位输出的低11位截掉。
而在剩下的13位当中取从原来的第22位到第13位这10位的原因是,若从最高位起取10位,那么最后的输出将会被缩小很多倍,所以这样做的目的是为了既能保证不丢失符号位,又能使输出不至于太小。
下图为第四级加法器的模块图。
4乘法器原理及功能
根据设计原理,所有加法器都是进行有符号数的移位乘法,即先移位,在相加。
这样做具有高效、不会占用过多的系统资源的优点。
如:
,分别先将被乘数左移8位、7位和4位相加,然后再加上它本身。
在作加法前,要分别将这四个加数进行位数扩展,具体的就是,先将被乘数、左移4位后的数和左移7位后的数扩展到19位得a0,a1,a2,即和左移8位后的数a3位数相同,然后a0加a1得b0,a2加a3得b1,最后将b0和b1相加得最终乘法结果。
所有加法的原理和加法器相同。
另外,在系数为负的情况下,先乘系数的绝对值,然后再对结果取反即可。
(6)系数为负31的乘法器
,先将被乘数左移5位,再减去被乘数,再对结果取反。
1系数为负31的乘法器的VHDL语言实现
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entitymult31is
port(clk:
instd_logic;
a:
insigned(10downto0);
b:
outsigned(15downto0));
endmult31;
architecturemultofmult31is
begin
process
variableinit:
signed(10downto0);
variableshif1,expond_a,prod:
signed(15downto0);
variables:
signed(15downto0):
="0000000000000001";
begin
waituntil(clk'eventandclk='1');
init:
=a;
shif1:
=init&"00000";---左移5位
expond_a:
=a(a'left)&a(a'left)&a(a'left)&a(a'left)&a(a'left)&init;
prod:
=shif1-expond_a;
foriin15downto0loop
if(prod(i)='1')thenprod(i):
='0';
elseprod(i):
='1';
endif;
endloop;
prod:
=prod+s;---取补
b<=prod;
endprocess;
endmult;
2系数为负31的乘法器的模块图
3系数为负31的乘法器的仿真波形
(7)系数为负88的乘法器
,先分别将被乘数左移3位再扩展两位得a0,左移4位再扩展一位得a1,左移6位得a2。
a0加a1得b0,b0加a2得c0,c0取反即为结果。
1系数为负88的乘法器的VHDL语言实现
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entitymult88is
port(clk:
instd_logic;
a:
insigned(10downto0);
b:
outsigned(17downto0));
endmult88;
architecturemultofmult88is
begin
process
variableshif1:
signed(13downto0);
variableshif2:
signed(14downto0);
variableshif3:
signed(16downto0);
variableexp1,exp2,temp1:
signed(15downto0);
variableaddtion1,temp2:
signed(16downto0);
variableaddtion2:
signed(17downto0);
begin
waituntil(clk'eventandclk='1');
shif1:
=a&"000";
shif2:
=a&"0000";
shif3:
=a&"000000";
if(shif1(shif1'left)='0')then
exp1:
="00"&shif1;
else
exp1:
="11"&shif1;
endif;
if(shif2(shif2'left)='0')then
exp2:
='0'&shif2;
else
exp2:
='1'&shif2;
endif;
temp1:
=exp1+exp2;
addtion1(15downto0):
=temp1;
if(exp1(exp1'left)=exp2(exp2'left)andtemp1(temp1'left)/=exp1(exp1'left))then
addtion1(16):
=exp2(exp2'left);
else
addtion1(16):
=temp1(temp1'left);
endif;
temp2:
=shif3+addtion1;
addtion2(16downto0):
=temp2;
if(addtion1(addtion1'left)=shif3(shif3'left)andtemp2(temp2'left)/=addtion1(addtion1'left))then
addtion2(17):
=addtion1(addtion1'left);
else
addtion2(17):
=temp2(temp2'left);
endif;
b<=0-addtion2;---取反
endprocess;
endmult;
2系数为负88的乘法器的模块图
3系数为负88的乘法器的仿真波形
(8)系数为负106的乘法器
,先分别将被乘数左移1位再扩展5位得a0,左移3位再扩展3位得a1,左移5位再扩展1位得a2,左移6位得a3,然后a0加a1得b0,a2加a3得b1,b0加b1的c0,c0取反即为结果。
1系数为负106的乘法器的VHDL语言实现
原理同上,代码见mult106.vhd。
2系数为负106的乘法器的模块图
3系数为负106的乘法器的仿真波形
(9)系数为负54的乘法器
,先分别将被乘数左移1位再扩展4位得a0,左移2位再扩展3位得a1,左移4位再扩展1位的a2,左移5位的a3。
a0加a1得b0,a1加a2得b1,b0加b1得c0,c0取反即为结果。
1系数为负54的乘法器的VHDL语言实现
原理同上,代码见mult54.vhd。
2系数为负54的乘法器的模块图
3系数为负54的乘法器的仿真波形
(10)系数为70的乘法器
,先分别将被乘数左移1位再扩展4位得a0,左移2位再扩展3位得a1,左移6位得a2。
a0加a1得b0,b0加a2的c0,c0即为结果。
1系数为70的乘法器的VHDL语言实现
libraryieee;
useieee.std_logic_1164.all;
useieee.std_logic_arith.all;
entitymult70is
port(clk:
instd_logic;
a:
insigned(10downto0);
b:
outsigned(17downto0));
endmult70;
architecturemultofmult70is
begin
process
variableshif1:
signed(11downto0);
variableshif2:
signed(12downto0);
variableshif3:
signed(16downto0);
variableexp1,exp2,temp1:
signed(15downto0);
variableaddtion1,temp2:
signed(16downto0);
variableaddtion2:
signed(17downto0);
begin
waituntil(clk'eventandclk='1');
shif1:
=a&'0';
shif2:
=a&"00";
shif3:
=a&"000000";
if(shif1(shif1'left)='0')then
exp1:
="0000"&shif1;
else
exp1:
="1111"&shif1;
endif;
if(shif2(shif2'left)='0')then
exp2:
="000"&shif2;
else
exp2:
="111"&shif2;
endif;
temp1:
=exp1+exp2;
addtion1(15downto0):
=temp1;
if(exp1(exp1'left)=exp2(exp2'left)and
temp1(temp1'left)/=exp1(exp1'left))then
addtion1(16):
=exp2(exp2'left);
else
addtion1(16):
=temp1(temp1'left);
endif;
temp2:
=shif3+addtion1;
addtion2(16downto0):
=temp2;
if(addtion1(addtion1'left)=shif3(shif3'left)and
temp2(temp2'left)/=addtion1(addtion1'left))then
addtion2(17):
=addtion1(addtion1'left);
else
addtion2(17):
=temp2(temp2'left);
endif;
b<=addtion2;
endprocess;
endmult;
2系数为70的乘法器的模块图
3系数为70的乘法器的仿真波形
(11)系数位239的乘法器
,先分别将被乘数扩展9位得a,左移4位再扩展3位得a0,左移5位再扩展2位得a1,左移6位扩展1位得a2,左移7位得a3。
a0加a1得b0,a2加a3得b1,b0加b1得c0,c0减a即为结果。
1系数位239的乘法器的VHDL语言实现
原理同上,代码见mult239.vhd。
2系数为239的乘法器的模块图
3系数为239的乘法器的仿真波形
(12)系数为401的乘法器
,先分别将被乘数左移8位得a0,左移4位再扩展4位得a1,左移7位再扩展1位得a2,左移8位得a3。
a0加a1得b0,a2加a3得b1,b0加b1即为结果。
1系数为401的乘法器的VHDL语言实现
原理同上,代码见mult401.vhd。
2系数为401的乘法器的模块图
3系数为401的乘法器的仿真波形
(12)系数为499的乘法器
,先分别将被乘数扩展7位得a0,左移1位再扩展6位得a1,左移4位再扩展3位得a2,左移5位再扩展2位得a3,左移6位再扩展1位得a4,左移7位得a5,左移8位得a6。
a0加a1得b0,a2加a3得b1,a4加a5得b2,b0加b1得c0,b2加a6的得c1,c1即为结果。
1系数为499的乘法器的VHDL语言实现
原理同上,代码见mult499.vhd。
2系数为499的乘法器的模块图
3系数为499的乘法器的仿真波形
(13)带有高频噪声的正弦波发生器
为了能够直
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 VHDL 语言 16 线性 相位 滤波器 设计