CMP设计分享 http://blog.sciencenet.cn/u/accsys 没有逆向思维就没有科技原创。 不自信是科技创新的大敌。

博文

精确科学计算的工具:浮点加减运算器的限位数设计

已有 5192 次阅读 2010-9-22 12:00 |个人分类:教学笔记|系统分类:科研笔记| EDA, 限位数, 浮点运算器

____中秋给计算机的朋友送大礼
 
姜咏江
 
1. 前言
 
利用计算机浮点运算器能够进行精确计算吗?利用本文设计的浮点运算器就可以进行浮点方式精确计算。
 
IEEE754标准将32位数用一位表示正负号,这是一种浪费。限位数方法设计浮点运算器不用占用多余的位置表示正负,因而尾数会比IEEE754标准多出一位,同样位长表示的浮点数会比IEEE754有更大的数域。用限位数方法表示浮点数,阶码也不用使用移码。
 
2. 设计背景
 
计算机浮点运算器设计中IEEE754标准强行如下规定:
 
1. 如果指数是0 并且小数部分是0,这个数±0(和符号位相关);
 
2. 如果指数 = 2e − 1 并且小数部分是0,这个数是 ±无穷大(同样和符号位相关);
 
3. 如果指数 = 2e − 1 并且小数部分非0,这个数表示为不是一个数(NaN)。
 
这种规定不符合数值运算的规则,会造成极大偏差。
 
第一, 0无正负,0×20就是0,不应该强行规定什么所谓的±0;
 
第二, 即使指数 = 2e − 1(这里 e=8)尾数是0,此时的数值仍然是0,也不应该规定是±无穷大;
 
第三, 指数 = 2e − 1并且小数部分非0,恰是一个确定的数,强行规定“不是一个数(NaN)”更违背数学原则。
 
3. 设计方法
 
本限位数浮点加减法运算器仍然采用8位的阶码设计,由于限位数自身就表示了正负,因而阶码值的变化范围是-128~127,对阶时最大移位是255。由于“对称制”的两限位数之差等于其所代表的有符号数之差,固可以用值较大的数减去较小的数得到8位无符号移位数。为保证精确计算的需要,特设置了移出变量 space,用它来找回移位时丢失的有效部分。
 
尾数右移损失有效码与否由mov_f监控,即mov_f=1时移出的数码不全为0。
 
限位数概念之下,规定阶码8位,尾码24位时,那么32位的浮点数其表值范围为:
 
-0.16777216×2127 ~+0.16777216 ×2127
 
用二进制限位数的表示应是:
 
.100000000000000000000000×01001111111~.011111111111111111111111×01001111111
 
需要指出,限位数小数点的左方是不能够随便添加“0”的,原因是二进制限位数的最高位数码指示着该数的正负,并且小数点左面有数码就会增加限位数表数的位数。例如,0.866和.866是不同值的,前者是一个正数,而后者是一个负数。
 
因为对阶时尾数右移的位数可以通过减法运算得到,加减运算的阶码需要取较大的数,因而采用大数减小数的方式就可以直接得到右移的位数。例如,阶码运算是127-(-128),化成二进制数是
 
0111111-10000000 = 01111111 + |10000000| <=> 11111111
 
大数减小数的结果是无符号数这是可以证明的,所以右面的结果可以认定是255。
 
4. 设计的Verilog HDL语言描述
 
/*这是我65岁年初编写的程序:限位数浮点加减法设计。阶码的变化范围是-128~127,尾数右移损失有效码由mov_f监控。这里32位的浮点数表数范围是 -0.16777216 *2exp127 ~+0.16777216 *2exp127 */
 
module fudian(f_a,f_b,clk,rst,me,f_out,sub,omov,mov_f,space,osign);
 
input [31:0] f_a,f_b; //输入浮点数
 
input clk, //时钟
 
me, //选择使用
 
rst, //复位信号
 
sub; //减法控制
 
output [31:0] f_out; //结果浮点输出
 
output [23:0] omov; //参考:移动后的尾数
 
output mov_f; //参考:甩掉有效数字尾标志
 
output [255:0] space; //参考:甩掉的尾数,可以提供精确计算数据
 
output [8:0] osign; //参考:移位数
 
reg [31:0] f_out; //寄存器型输出
 
reg [8:0] osign;
 
reg [7:0] exp_out;
 
reg [7:0] exp_a,exp_b;
 
reg [8:0] sign; //保证不溢出用9位
 
reg [23:0] man_out;
 
reg [23:0] a_a,b_b,c_c;
 
reg [255:0] tru,zero,shift;
 
reg mov_flg;
 
assign space = shift;
 
assign mov_f = mov_flg;
 
assign omov = c_c;
 
always @(posedge clk or negedge rst)
 
begin
 
if (!rst)
 
begin
 
exp_a <= 8'h00;
 
exp_b <= 8'h00;
 
a_a <= 24'h000000;
 
b_b <= 24'h000000;
 
tru <= 256'hffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff;
 
zero <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
 
sign <= 9'b000000000;
 
end
 
else if (me)
 
begin
 
exp_a = f_a[31:24];
 
exp_b = f_b[31:24];
 
a_a = f_a[23:0];
 
b_b = f_b[23:0];
 
sign = exp_a - exp_b;
 
end
 
end
 
always @(posedge clk )
 
begin
 
if (!sign[8]) //exp_a > exp_b
 
begin
 
osign = sign;
 
exp_out <= f_a[31:24]; //取f_a原阶码
 
if (b_b[23]) //f_b的尾数为负数
 
{c_c,shift} <= {tru,b_b,zero} >> sign; //需要按负数扩充,然后右移
 
else {c_c,shift} <= {b_b,zero} >> sign;
 
end
 
else //差为负
 
begin
 
osign = -sign;
 
exp_out <= f_b[31:24]; //取f_b原阶码
 
if (a_a[23])
 
{c_c,shift} <= {tru,a_a,zero} >> -sign; //需要按正负数扩充
 
else
 
{c_c,shift} <= {a_a,zero} >> -sign;
 
end
 
end
 
always @(posedge clk )
 
begin
 
if (!sub) //加
 
if (!sign[8])
 
man_out <= a_a + c_c;
 
else man_out <= b_b + c_c;
 
else //减
 
if (!sign[8])
 
man_out <= a_a - c_c;
 
else man_out <= c_c - b_b;
 
end
 
always @(posedge clk )
 
begin
 
f_out <= {exp_out,man_out}; //输出
 
if (!shift)
 
mov_flg <=1'b0;
 
else mov_flg <=1'b1; //移位有损失,影响精度
 
end
 
endmodule
 
5. 仿真
 
下面是十六进制的浮点加减法运算器仿真。图1是阶码符号相反的运算,求的是十六进制的0.142176×268±0.54D101×2E5;图2是阶码符号相同的运算,求的是十六进制的0.142176×268±0.005219×273
图中sub=1为做减法运算。
 
图 1 阶码符号相反的运算
 
图 2 阶码符号相同的运算仿真
 
于2010-9-22中秋,欢迎讨论。
 
 
 


https://blog.sciencenet.cn/blog-340399-365673.html

上一篇:大学传授知识的主线不容动摇
下一篇:设计错误出在哪里?
收藏 IP: .*| 热度|

1 杨华磊

发表评论 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2024-6-18 20:40

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部