Verilog实现IEEE 754标准单精度浮点数运算器
Verilog实现IEEE 754标准单精度浮点数运算器
本文详细介绍了如何使用Verilog实现IEEE 754标准的单精度浮点数运算器,包括浮点数的存储格式、范围、特殊数值以及加减法运算的完整流程。通过本文,读者可以深入了解计算机中浮点数的内部表示和运算原理。
一、原理分析
1.IEEE 754标准单精度浮点数
1.1 单精度浮点数的组成与存储
IEEE 754标准的单精度浮点数格式如上,总共32位,由1位符号位,8位阶码,23位尾数组成。其中符号位1表示负数,0表示正数。阶码范围为-126到127,阶码使用移码表示,偏移量为127。尾数使用原码表示,其真实值由1位符号位,1位整数位(默认为1,不在32中存储),23位小数位组成。
以上图value = 0.15625为例。
公式转换如下:
进制转化:
value = 0.15625 = 0.00101(原码)
规格化:
存入尾数:
整数1隐藏,小数01填充0,存入23位二进制中
存入阶码:
-3 = 11111101(补码)= 01111100(移码)
(这里说明一下,在计算机组成原理中,8位补码的范围是-128到127,其移码的偏移量为128,故其移码和补码的区别只有符号位不同)
1.2 范围
最大正数:
0_11111110_11111111111111111111111
最小正数:
0_00000001_00000000000000000000000
最大负数:
1_00000001_00000000000000000000000
最小负数:
1_11111110_11111111111111111111111
1.3 特殊数
无穷大(inf):当阶码 e = 11111111 且尾数全为0时,表示无穷大。
1_11111111_00000000000000000000000(负无穷)
0_11111111_00000000000000000000000(正无穷)
无效数字(NaN): 当阶码 e = 11111111 且尾数不全为0时,表示NaN。
1_11111111_XXXXXXXXXXXXXXXXXXXXXXXXXX
机器零:当阶码 e = 00000000 且尾数全为0时,表示机器零。
1_00000000_00000000000000000000000(负零)
0_00000000_00000000000000000000000(正零)
非规格数: 用于填充零附近的下溢间隙,其与规格数之间过渡很丝滑。
当阶码 e = 00000000 且尾数不全为0时,表示非规格数。该数特点如下:
阶码虽然为00000000,但仍表示指数为-126;
默认整数位为0,而不是规格数的1。
0_00000000_00000000000000000000001
(
)
2.浮点数加减法
2.1 标准流程
对阶 ——> 尾数相加 ——> 规格化 ——> 舍入 ——> 溢出判断
对阶:两个数相加减,首先比较阶数大小,将阶数小的数通过尾数右移升阶,达到和阶数大的数相同的阶数值。
尾数相加:将对阶后的两数的尾数按照定点加减运算规则相加。(将尾数化成补码相加,使用双符号位)
规格化:尾数的规格化格式为00.1xx或者11.0xx。通过左规和右规实现结果的规格化。同时需要考虑特殊数值-0.5(11.100...0)补码时不是规格化数,-1(11.00...0)补码时是规格化数。左规是尾数左移降阶,右规是尾数右移升阶。
舍入:在对阶时,尾数右移可能造成精度丢失;在规格化时,如果发生右规同样造成精度丢失。这是需要引入舍入规则,降低精度损失。0舍1入法,当被移除的最高数值位为1,在尾数的末位加1;当被移除的最高数值位为0,则舍去。恒置1法,无论移除什么数值,将尾数的末位置1.
溢出判断:当完成规格化后,由于阶码也是用双符号位和补码表示,故,当阶码符号为01时表示上溢出,当阶码符号为10时表示下溢。
2.2 适配IEEE 754标准流程
该流程参考标准流程,结合IEEE 754存储格式,做了一定程度适配。
对阶 + 舍入——> 尾数相加 ——> 规格化 ——> 溢出判断
对阶+舍入:比较对阶,同时根据溢出的数值,按照0舍1入法则,对尾数做处理。
尾数相加:由于尾数使用原码存储,为减少规格化的难度,我采用先比较符号和大小,在进行运算的方法,确保的运算可以直接用原码加减完成而不用担心发生溢出。比如一个正数A和一个负数B相加,先比较A和B的绝对值大小,若
,则采用
,且C的符号与A的符号相同;若
,则采用
,且C的符号与A的符号相反。由于A和B相加的结果可能会溢出,所以C的位数更多一位;同时为了减少规格化的硬件复杂度,将两者运算后的结果右移一位后赋值给C。
规格化:因为尾数相加的操作,C的最高两位只可能是00或者01。我们以C的第二高位为尾数的第一个1为规格进行移位,这样只会发生左规操作。故这一步同样不用配合舍入操作。
溢出判断:阶码使用移码表示,在阶码前加一位“0”参与到计算中