数字滤波器的MATLAB与FPGA实现之读书笔记(二 有限字长效应)

8 篇文章 22 订阅

目录

第三章 FPGA实现数字信号处理基础

1、为什么要引入反码(补码)?

2、定点数

一、FPGA中数的运算

1、加减运算

2、乘法运算

3、除法运算

二、有限字长效应

1、滤波器系数的字长效应

2、滤波器运算中的字长效应


第三章 FPGA实现数字信号处理基础


1、为什么要引入反码(补码)?

反码的作用就相当于数学中的负数。

对于小学生来说,会做的算术题是:5-3,但是不会做3-5。于是,我们上初中的时候,数学里就引进了一个新的概念:负数。引入负数之后,本来是减法的运算就可以变成加法来实现:

3-5=3+[-5]=[-2],中括号代表“负数”,“负数”就是我们人为给出的数学术语。

对于计算机来说,会做的算术题是:5+3,但是不会做3-5。于是,我们就在编码里引进了一个新的概念:反码。引入反码之后,本来是减法的运算就可以变成加法来实现:

3-5=3+[-5]=[-2],中括号代表“反码”,“反码”就是我们人为给出的计算机术语。

这里,你一定有一个疑问:为什么计算机只会做5+3,不会做3-5。这是因为在计算机的数字电路中只有加法器,没有所谓的“减法器”。不是说计算机厂商不会设计减法器,因为聪明的人既然发明了方法能够用加法来实现减法操作,那为什么还需要画蛇添足的弄一个减法器?

接着说:那么反码要怎么定义才能实现减法变加法的功能呢?聪明的人想的办法如下:

1.正数反码保持原码不变:3=[0_0000011]

2.负数除最高位(正负符号位)外,全部取反(0变1,1变0):-5=1_0000101取反=[1_1111010]

于是3+[-5]=[-2]的计算过程为:

[0_0000011]+[1_1111010]=[1_1111101],将结果求其原码[1_0000010]

这样,这种反码方法就成功实现了目标!至于为什么,我想只有数学家能给出解释了。

补充:

反码:正数的反码还是等于原码

负数的反码就是他的原码除符号位外,按位取反。

补码:正数的补码等于他的原码
负数的补码等于反码+1。
(这只是一种算补码的方式,多数书对于补码就是这句话)

2、定点数

I、定点数

所谓定点格式,即约定机器中所有数据的小数点位置是固定不变的。通常将定点数据表示成纯小数或纯整数,为了将数表示成纯小数,通常把小数点固定在数值部分的最高位之前;而为了将数表示成纯整数,则把小数点固定在数值部分的最后面,如下图所示:

 

图中所标示的小数点在机器中是不表示出来的,而是事先约定在固定的位置。对于一台计算机,一旦确定了小数点的位置,就不再改变。

假设用n位来表示一个定点数x=x0x1x2...x(n-1),其中x0用来表示数的符号位,通常放在最左位置,并用数值0和1分别表示正号和负号,其余位数表示它的量值。如果定点数x表示纯整数,则小数点位于最低位x(n-1)的右边,数值范围是0<=|x|<=2^(n-1)-1,且,例如1111表示-7;如果定点数x表示纯小数,则小数点位于x0和x1之间,数值范围是0<=|x|<=1-2^(-(n-1)),且,例如1111表示-0.875.

 II.定点数加减运算

不论操作数是正还是负,在做补码加减法时,只需将符号位和数值部分一起参与运算,并且将符号位产生的进位丢掉即可。如:

short A=-9, B=-5;

cout<<A+B<<endl;  //-14

推导过程如下:

A的原码为:1000 0000 0000 1001,因此补码为:1111 1111 1111 0111

B的原码为:1000 0000 0000 0101,因此补码位:1111 1111 1111 1011

A+B的补码为:1 1111 1111 1111 0010,将符号位产生的进位丢掉,因此最终结果为:

1111 1111 1111 0010,结果的原码为:1000 0000 0000 1110,即-14。

III.定点数加减运算的溢出判断

1)用一位符号位判断溢出

对于加法,只有在正数加正数和负数加负数两种情况下才可能出现溢出,符号不同的两个数相加是不会溢出的。

对于减法,只有在正数减负数和负数减正数两种情况下才可能出现溢出,符号相同的两个数相减是不会溢出的。

由于减法运算在机器中是用加法器实现的,因此:不论是作加法还是减法,只要实际操作数(减法时即为被减数和“求补”之后的减数)的补码符号位相同,而结果的符号位又与操作数补码符号位不同,即为溢出。如:

在4位机中,A=5,B=-4,则A-B溢出,推导过程如下:

A的原码为0101,补码为0101;-B的原码为0100,反码为0011,补码为0100;

A-B的补码为0101+0100=1001,结果的符号位为1,而实际操作数的符号位为0,因此溢出

2)用两位符号位判断溢出

此时判断溢出的原则是:当2位符号位不同时,表示溢出;否则无溢出。不论是否发生溢出,高位符号位永远代表真正的符号。如:

x=-0.1011,y=-0.0111,则x+y溢出,推导过程如下:

x的原码为11.1011,反码为11.0100,补码为11.0101;y的原码为11.0111,反码为11.1000,补码为11.1001

因此x+y的补码为11.0101 +  11.1001 = 1 10.1110,将符号位产生的进位丢掉,则结果为10.1110,因此溢出

注:约定整数的符号位与数值位之间用逗号隔开,小数的符号位与数值位之间用小数点隔开


一、FPGA中数的运算

1、加减运算

module SymbExam (
	d1,d2,
	signed_out,unsigned_out);

	input		[3:0]d1;              //输入加数1
	input		[3:0]d2;              //输入加数2
	output 	[3:0]	unsigned_out;   //无符号加法输出
	output signed [3:0] signed_out; //有符号加法输出

	//无符号加法运算
	assign unsigned_out = d1 + d2;
	
	//有符号加法运算
	wire signed [3:0] s_d1;
	wire signed [3:0] s_d2;
	assign s_d1 = d1;
	assign s_d2 = d2;
	assign signed_out = s_d1 + s_d2;
	
endmodule



从RTL 视图看出,两者的输出结果完全相同:

原因是:对于加法、减法,无论是否为符号数运算,其结果均完全相同,因为二进制的运算规则完全相同。如果将二进制数据转换成十进制数据,就可以看出两者的差别了。

由上表我们可以得出一些结论:

2、乘法运算

3、除法运算

二、有限字长效应

1、滤波器系数的字长效应

%E3_2_QuantCoeff.m
B=8;             %量化位数
Fs=1000;         %采样频率
a=[1 1.7 0.745]; %系统函数
b=[0.05];
Ps=roots(a);
[Ph,Pf]=freqz(b,a,1024,Fs);  %求频率响应

%归一化处理
c=[a b];
Max=max(abs(c));
a=a/Max;
b=b/Max;
%截尾处理
Ra=floor(a*(2^(B-1)-1));
Rb=floor(b*(2^(B-1)-1));
PRs=roots(Ra)
[PRh,PRf]=freqz(Rb,Ra,2048,Fs);  %求频率响应

%PRmag=abs(PRh);  %幅度转换成dB单位  
%Pmag=abs(Ph);    %幅度转换成dB单位  
PRmag=20*log(abs(PRh))/log(10);  %幅度转换成dB单位  
Pmag=20*log(abs(Ph))/log(10);    %幅度转换成dB单位    
plot(Pf,Pmag,'-',PRf,PRmag,'--');
legend('原系统响应','8bit量化后的响应')
xlabel('频率(Hz)'); ylabel('幅度(dB)');
grid;


%zplane(Rb,Ra);

2、滤波器运算中的字长效应

%E3_3_QuantArith.m
x=[7/8 zeros(1,15)];
y=zeros(1,length(x));   %存放原始运算结果
B=2;                    %量化位数
Qy=zeros(1,length(x));   %存放量化运算结果
Qy2=zeros(1,length(x));  %存放量化运算结果
Qy4=zeros(1,length(x));  %存放量化运算结果
Qy6=zeros(1,length(x));  %存放量化运算结果

%系统系数
A=0.5;
b=[1];
a=[1,A];

%未经过量化处理的运算
for i=1:length(x);
    if i==1
        y(i)=x(i);
    else
        y(i)=-A*y(i-1)+x(i);
    end
end

%经过量化处理的运算
for i=1:length(x);
    if i==1
        Qy(i)=x(i);
        Qy(i)=round(Qy(i)*(2^(B-1)))/2^(B-1);
    else
        Qy(i)=-A*Qy(i-1)+x(i);
        Qy(i)=round(Qy(i)*(2^(B-1)))/2^(B-1);
    end
end
Qy2=Qy;

B=4;
%经过量化处理的运算
for i=1:length(x);
    if i==1
        Qy(i)=x(i);
        Qy(i)=round(Qy(i)*(2^(B-1)))/2^(B-1);
    else
        Qy(i)=-A*Qy(i-1)+x(i);
        Qy(i)=round(Qy(i)*(2^(B-1)))/2^(B-1);
    end
end
Qy4=Qy;

B=6;
%经过量化处理的运算
for i=1:length(x);
    if i==1
        Qy(i)=x(i);
        Qy(i)=round(Qy(i)*(2^(B-1)))/2^(B-1);
    else
        Qy(i)=-A*Qy(i-1)+x(i);
        Qy(i)=round(Qy(i)*(2^(B-1)))/2^(B-1);
    end
end
Qy6=Qy;

xa=0:1:length(x)-1;
plot(xa,y,'-',xa,Qy2,'--',xa,Qy4,'O',xa,Qy6,'+');
legend('原系统运算结果','2bit量化运算结果','4bit量化运算结果','6bit量化运算结果')
xlabel('运算次数');ylabel('滤波结果');



  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Cheeky_man

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值