32位浮点加法器设计摘要:浮点数具有数值范围大,表示格式不受限制的特点,因此浮点数的应用是非常广泛的。浮点数加法运算比较复杂,算法很多,但是为了提高运算速度,大部分均是基于流水线的设计结构。本文介绍了基于IEE754标准的用Verilog语言设计的32位浮点加法器,能够实现32位浮点数的加法运算。虽然未采用流水线的设计结构但是仍然对流水线结构做了比较详细的介绍。关键字:浮点数,流水线,32位浮点数加法运算,Verilog语言设计32-bitfloatingpointadderdesignCaoChi,ShenJia-qi,ZhengYun-jia(SchoolofMechatronicEngineeringandAutomation,ShanghaiUniversity,Shanghai,China)Abstract://沈佳琪搞定Keywords:float;Assemblyline;32-bitfloating-pointadder浮点数的应用非常广泛,无论是在计算机还是微处理器中都离不开浮点数。但是浮点数的加法运算规则比较复杂不易理解掌握,而且按照传统的运算方法,运算速度较慢。因此,浮点加法器的设计采用了流水线的设计方法。32位浮点数运算的摄入处理采用了IEE754标准的“0舍1入”法。1.浮点数的介绍在处理器中,数据不仅有符号,而且经常含有小数,即既有整数部分又有小数部分。根据小数点位置是否固定,数的表示方法分为定点表示和浮点表示。浮点数就是用浮点表示法表示的实数。浮点数扩大了数的表示范围和精度。浮点数由阶符、阶码E、数符、尾数N构成。任意一个二进制数N总可以表示成如下形式:N=±M×2±𝐸。通常规定:二进制浮点数,其尾数数字部分原码的最高位为1,叫作规格化表示法。因此,扩大数的表示范围,就增加阶码的位数,要提高精度,就增加尾数的位数。浮点数表示二进制数的优势显而易见。𝐸𝑆(阶符)𝐸𝑚(阶码)𝑀𝑆(数符)𝑀𝑛(尾数)浮点数基于IEE754标准的表示形式如下:31302322032位浮点数:63625251064位浮点数:在IEEE754标准格式表示的32位浮点数中,S表示浮点数的符号位,0表示正数,1表示负数;M表示尾数,共23位,用小数表示,小数点放在尾数域的最前面;E表示阶码,共8位,采用移码方式表示正负指数。移码方法对两个指数的大小的比较和对阶操作比较方便。采用这种方式时,浮点数的指数真值e变成阶码E时,应将指数e加上一个固定的偏移地址127(二进制数01111111),即E=e+127。在IEEE754标准中,一个规格化的32位浮点数X的真值可表示为X=(-1)s×(1.M)×2E-127e=E-127一个规格化的64位浮点数x的真值为SEMSEMX=(-1)s×(1.M)×2E-1023e=E-1023为提高数据的精度,当尾数的值不为0时,尾域的最高有效位为1,否则修改阶码同时左右移动小数点,使其变成规格化表示的浮点数。这一过程称之为规格化表示。当浮点数的尾数为零时,不论阶码为何值或者阶码的值遇到比它所能表示的最小值还小时,不管其尾数为何值,计算机都把该浮点数当做零值。原码非0值浮点数的尾数值最高位必定为1,在保存浮点数时,通过尾数左移(小数点向右移动)把该位去掉,用同样多的位数能多存一位二进制数,有利于提高数据表示精度,这种处理方案称之为隐藏位技术。32位浮点数的表示范围有限,超过该范围的浮点数会产生溢出。溢出分为正上溢和负上溢。2.32位浮点数加法运算浮点数的加法运算与二进制数直接进行加法运算区别是很大的。浮点数的加法运算分为以下几个步骤:(1)0操作数的检查;(2)比较阶码大小并完成对阶;(3)尾数进行加法运算;(4)结果进行规格化处理;(5)舍入处理;(6)溢出处理。0操作数的检查是判断两个数据是否为零,若有一个数据为0则直接输出结果;比较两个数据的阶码大小,并通过尾数的移动来改变阶码使其相等。对阶的过程要遵循阶码小的向阶码大的数对齐,小阶的尾数右移,每右移一位,阶码加一。尾数求和运算与一般二进制数的加法运算相同;在尾数相加后得到的数可能不是规格化的数,为了提供运算的精度,就必须对求和的结果进行规格化处理。当运算结果溢出时,进行右归。左归时阶码做减法,右归时阶码做加法。在IEEE754标准中,舍入处理提供了四种方法:(1)就近舍入:实质上就是通常所说的“四舍五入”。(2)朝0舍入:朝数轴原点方向舍入,就是简单的截尾。无论尾数是正数还是负数,截尾都使取值的绝对值比原值的绝对值小。(3)朝+∞舍入:对正数来说,只要多余位不全为0则向最低有效位进1;对负数来说则是简单的截尾。(4)朝—∞舍入:处理方法与朝+∞舍入情况相反。对正数来说只要多余位不全为0则简单截尾;对负数来说,向最低有效位进1。(5)与一般二进制数的加法运算相似,浮点数的加法运算也要是否溢出。尾数之和出现01.xxxx或10.xxxx时,并不表示溢出,只有将此数进行右归后,再根据阶码来判断浮点运算结果是否溢出。一般说浮点是否溢出均是指上溢(正上溢、下上溢)。因此,浮点数是否溢出可由阶码来决定。从以上加法的运算过程可以看出,浮点数加法运算步骤较多,体系结构相对比较复杂,目前比较常见的浮点加法器的结构有标准算法结构、LOP算法结构、双通道算法结构。一般的标准算法结构首先比较阶数,得到阶差,根据阶差进行尾数的移位,然后送入定点加法器进行尾数相加,规格化单元对结果进行规格化,在规格化单元里有一个前导1检测电路,可检测出尾数中第一个1的位置,后移位器根据此位置对尾数进行左移,同时减去相应的值。LOP算法与标准算法的区别在于它采用前导1预测电路代替了前导1检测电路代替了前导1检测电路。LOP电路可以与尾数加法并行执行,这样减少整个系统的延迟。双通道算法的结构有两个并行的数据通道,当指数差大于1时,选择far通道,指数对阶分配较长时间,尾数运算结果规范化时的移位分配较少的时间,否则选择close通道,此时尾数最多移一位,甚至不用移位,这样可以去掉前移位器。在以上3种算法中,一般的标准算法延迟较大,但占用资源最少;双通道算法虽然延迟较小,但占用资源最多。在进行后续的流水线设计时,由于结构复杂,因而不利于流水线寄存器的插入和流水级数的划分,从而导致了时序速度的下降。LOP算法的速度和面积介于两者之间。综合比较以上三种算法以及自己知识的局限性,因此采用一般的标准算法来进行32浮点数运算加法器的设计。3.流水线设计结构流水线处理是高速设计中的一个常用设计手段。如果某个设计的处理流程分为若干个步骤,而且是整个数据处理是“单流向”的,即没有反馈或者是迭代运算,前一个步骤的输出是下一个步骤的输入则可以考虑采用流水线设计方法提系统的工作频率。流水线设计的结构如图所示:其基本结构为:将适当划分的单个操作步骤单流向串联起来。流水线操作的特点和要求是,从时间上看数据流在各个步骤的处理是连续的。如果将每个操作步骤简化假设为通过一个D触发器,那么流水线操作就类似一个移位寄存器组,数据流依次流经D触发器,完成每个步骤的操作。流水线时序设计如下图:Step1Step2Step3a1a2Step1Step2Step3b1b2a3Step1Step2Step3c1c2c3a4流水线设计的关键在于整个设计时序的合理安排。要求每个操作步骤的划分合理。如果前级操作时间恰好等于后级操作时间,设计最为简单,前级的输出直接汇入后级的输入即可。如果前级操作时间大于后级的操作时间,则需要对前级的输出数据适当缓存,才能汇入后级的输入端。如果前级操作时间恰好小于后级的操作时间,则必须通过复制逻辑,将数据分流,或者在前级对数据采用存储、后处理方式,否则会造成后级数据溢出。流水线的处理方式相当于复制了处理模块,所以通过这种方式设计的芯片频率较高。在本文中32位浮点加法器的设计虽然没有采用流水线的设计结构,但是仍然从中得到了启发。4.32位浮点加法器的Verilog设计在进行Verilog语言设计32位浮点加法器时,要先画出流程图。在画流程图之前,要理顺32位浮点加法器的顺序步骤,在此基础上画出其程图如图:从流程图可以看出,浮点加法运算器的完成可以分成阶码和尾数两部分。阶码只有加减运算(左右移位),而尾数则有加减乘除4种运算。因此,浮点加法运算器主要由两个定点运算部件组成,一个是阶码运算部件来完成阶码加减,以及控制对阶时小阶的尾数右移次数和规格化时对阶码的调整;另一个是尾数运算部件来完成尾数的加减运算并判断尾数是否已规格化。除了这两个主要的运算部件之外,还需要一个溢出电路来判断是否溢出。根据以上的流程图和分析,可以大致画出运算电路的结构图:两个操作数的阶码部分,分别放在寄存器E1和E2中,它们与并行加法器相连可以计算E1±E2。阶码比较是通过E1-E2来实现的,相减结果放在计数器E。然后按E的符号来决定哪一个阶码较大,并用E来控制其中一个尾数的移位次数。E每递减1次,相应的尾数右移一位,直到E=0为止。一旦尾数调整完毕,就可按通常的加、减方法处理,并将其结果的阶码放入E寄存器中。在画出浮点加法运算器的内部电路后,就可以用Verilog语言来编写程序了。在编写的程序中使用的是同步有限状态机来实现电路的功能的。同步有限状态机的编写在理顺了浮点加法运算的运算步骤之后,很容易可以得到电路的几个状态,以及各个状态之间相互跳并的条件。在弄清楚各个状态之间的跳并条件之后很容易就可以画出有限状态机的状态迁移图。通过有限状态机的迁移图,可以比较方便的写出状态机的Verilog语言描述。再结合电路结构框图,把电路的各部分功能加以实现填充到状态机中就完成了32位浮点加法器的Verilog语言设计。此时,可以用软件进行仿真测试,得到仿真波形如下图:图中ix,iy为数据输入信号clk为时钟信号,reset为复位信号,oz为数据输出信号,ofw为判断是否溢出的信号输出。同步有限状态机的源代码和测试程序代码如下://同步有限状态机代码----------------------modulefloatadder(clk,reset,ix,iy,oz,ofw);//定义模块端口;inputclk,reset;//时钟、复位信号;input[31:0]ix,iy;//输入信号;output[31:0]oz;//输出信号;outputofw;//溢出位信号;reg[31:0]oz;reg[23:0]xm,ym,zm;//定义尾数;reg[7:0]xe,ye,ze;//定义阶码regzs;//定义输出信号符号位regmc;//尾数相加溢出位reg[2:0]state,nextstate;//状态parameterstart=3'b000,zerock=3'b001,exequal=3'b010,addm=3'b011,infifl=3'b100,zerofl=3'b101,over=3'b110;assignofw=(state==over)?1:0;//判断溢出位//每一个时钟产生一个可能的状态变化always@(posedgeclk)if(!reset)state=start;elsestate=nextstate;//产生下一个状态的组合逻辑always@(state)case(state)start:beginxe=ix[30:23];xm={1'b1,ix[22:0]};ye=iy[30:23];ym={1'b1,iy[22:0]};nextstate=zerock;end//操作数检查,判断操作数是否为0;zerock:beginif(xm==0)begin{ze,zm}={ye,ym};nextstate=over;endelseif(ym==0)begin{ze,zm}={xe,xm};nextstate=over;endelsenextstate=exequal;end//对阶操作,使阶码相等;exequal:beginif(xe==ye)nextstate=addm;else