




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
Verilog最后的私私细语-不同世界的自 营养不足。你的一次点击就能让某位穷人得到1.1杯食物。当然你可以不相信有这样的或者黄色按钮,就会出来个介绍各种商品的网页(无同时也会有人因为您的一点而得到1.1杯,D也好,灯泡也好,荧光灯也好,最重要就是要懂得用自身的光去照耀别人,光的强度都是其次。:
第3章理想时序的整 闻风色变的浮点 浮点数和单精度格 浮点数加减 实定和假定小数点的困 浮点数加减法实 实验一:浮点数加法 实验二:浮点数减法 浮点乘法和陷 实验三:浮点数乘法 浮点除法和精度流 实验三:浮点数除法 受到页数的限制,此外笔者也在上半部用光了资料...说实在非常郁闷,收料是象。好了,牢骚就先发到这里...我们继续VerilogHDL语言的学习吧。接下来的内容,同样也是爬满了刺猬和毛毛虫,问读者有没有勇气和笔者一同走下去了?呵呵,答案是...那些打开笔记的读者,在某种程度上已经有了相当的觉悟。嗯,好样!深呼吸,集中精神,放松神经,让我们继续走下去。定点整数定点整数 =(符号位定点小数7.710=(符号位码1.1.2所示:floatpi;pifloatpi;pi=3.142;if(pi==3.142)//判断pi=pi* 高级语言和编译器多么便利呀,这也是为什么人的1/3人口都是肥胖者。边缘了。笔者诚心“掌管VerilogVerilogKFCMcDolandPizzaHut、是不则不VerilogVerilog是多样。此外,Verilog料理所强调的不只是某个程度的便利和美味而已,除了色Verilog点数...”Verilog:reg[7:0]rA,rB;reg[7:0]rA,rB;always@(posedgeCLK...rData<=rA*FPGA越久。相反的,如果读者是用C语言来实现整数乘法的话(1.1.4所示)...intintdata=a*1.1.4第二个问题:“Verilog的乘法只有法而已吗?(硬件还是软件”是创作时序篇的灵感VerilogHDL语言不是快餐。要调用的ip/lpm或者消耗的逻辑资源,什么乘法都能实现呀。在学习的经过笔者遇到一种现象,原本调用ip/lpm是一件再普通为过的事情,和食用快食一样须知道,ip/lpm作为产品的一部分一定存在的问题,但是又不能把经验。所以说,如果读者打算从的ip/lpm偷学几招盖世功夫还是省了吧,看死不无法抗拒它...呵呵,话题有点扯远了。1.1.5:floatFloatMulti(floatA,floatB{floatpi; floatTemp;pi=Temp=pi*TempFloatMulti(pipi11.笔者还,VerilogHDL语言是非常自由的语言,甚至是自由到没有结构,相比C语着自定义的结构来设计专属的ip。VerilogHDL会无孔不穿。当我们在不同世界里互相“呼唤信息”的时候,一定要非常谨慎,Verilog之神为什么把笔者指引到这种窘境?笔者不懂,但是笔者相信神明的指明。floatpi;pifloatpi;pi=3.142;NumberNumberxBExpB:BaseExp:Exponent3.142x0.3142x31.42x10-普通的浮点数,数字一定会伴随价码(Exponent),3.142x100“3.142”0.3142E+1/31.42E-们要为某个寄存器赋予浮点数的值,如代码1.2.2所示:regrPi<=32'b0_rPi<=_7.0)已经支持了,但是唯一不足的是编译器会按ieeeieeeC内容更全面一点,笔者还是简单的介绍一下。IEEE对于浮点数的规定格式如表1.2.1所示。(IEEE:1.2.1价码尾数[31]-1[30..23]-8[22..0]-23[63]-1[62..52]-11[51..0]-523.1423= === =(Signx- =(符号位x-1)尾数3.142=0b(0x-1)==[[ [31][-30:23- [符][-价 尾 00b8'd1273.142浮点数源= ===++==00111]0023因此3.142的单精度表示是= 看到了吧,过程就是这样简单而已...“呜呜呜呜”读者别发出这样,笔者知道0b?”和“为什么0b是为了简化计算。至于空壳“浮点数源”都是“1.1110E-101.0111E+3”等格式。无论浮点数源是负值还是存在是不会摇,没有表示出来也不用紧。心底里就会无比和敬畏。哎~现在的人类真是可悲,原因就是我们不知道“XX”到 0111110=0b- = +(E-===-= _当我们使用高级语言的时候(C语言,我们都会过度依赖编译器。还记得笔者之前体智能为了释放这些焦虑,身体智能会影响大脑智能,然后大脑智能会以“”的方然后以满足食欲的方式去执行。基本上素食很难上瘾,唯有肉食,尤其是油腻腻食食物...不知不觉又离题了!笔者所要告知读者的是...Verilog的世界里,过度依赖编译器Verilog的自然里,我们要常常与二进制相处,相处久了自然而然会发现二一些计算工具,来简化转换工作的度。就当给自己一个训练,要征服浮点数之前就[[]]我们有4位宽的整数,为了把它区分正与负,我们会在最用“符号(Sign”来表011101112 // //10012 //1A=_B=A==B==_0.。为什么会发生这样的情形呢?原因很简单,因为单精度的尾数受到位宽基本上要注意的内容差不多就是这些问题而已,VerilogHDLQ1.A=6.751,B=4.832,A+B=6.7516.7516.75110=浮点数源=00100100110111(一部分默认空壳的符号位[31]=默认空壳的价码[30:23]= _4.83210=0000010000011(尾数太长, 一部分默认空壳的符号位[31]=默认空壳的价码[30:23]=+210= = ABregregrA<={A[31],A[30:23],2'b01,A[22:0],23'd0rB<={B[31],B[30:23],2'b01,B[22:0],23'd0首先位宽为57的rA和rB寄存器,rA寄存单精度浮点数A的预操作结果;rB则寄存单精度浮点数B的预操作结果。符号位价码隐藏位尾数尾数补偿6rA=57'b0_rB=A=5.237x10A=5.237x103,B=3.142x10-2,A+B=A.ExpB.Exp32)5//AB5B=3.142x10-=.3142x10-=.03142x10-=.003142= = B'=B'BAA+B'=5.237x103+x103=过程会比较直接一点。接下来,我们看如何用VerilogHDL语言来实现。regregrExp=A[30:23]-if(rExp[8])rExpDiff<=~rExp+1'b1;elserExpDiff<=rExp;rExprExpDiff10位,rExpAB的价码差;rExpDiff则寄存相差位数。寄存器rExp之所以要为10位位宽,是为了判断价码差的符号位。如果说明A的价码大于还是等于B。总结一下:ififrExp[8]==1thenA.Exp<ififrExp[8]==0thenA.Exp>=AB =A[30:23]-= -=rExp0ABrExpDiff0rExp[8]rExprExpDiff。rExpDiff是用来if(rExp[8]==1)beginrA[47:0]<=rA[47:0]>>rExpDiff;rA[55:48]<=rB[55:48];endelsebeginrB[47:0]<=rB[47:0]>>rExpDiff;rB[55:48]<=rA[55:48];end1.3.3if(rExp[8]==1)AB的价码,AB对齐,rA的尾数(包括补偿尾数)rA[47..0]rExpDiff位。rA的价码即,rA[55:48]rBBA对齐,rB包括补偿尾数rExpDiffrA[55:48]Q1中,AB0,rArBrArA=rB=regregTempA<=rA[56]?{rA[56],(~rA[47:0]+1'b1)}:{rA[56],rA[47:0]TempB<=rB[56]?{rB[56],(~rB[47:0]+1'b1)}:{rB[56],rB[47:0]TempB位和尾数补偿)转换为补码与否。TempQ1AB骤3会变成怎么样呢?rArA=rB=rA[56]==rB[56]==TempA=49'b0_01_regregbeginTemp<=TempA+TempB;1.3.534的存在是为了提高代码的表达能力和修改能Q1ABTempB TempA+TempB=shhm//S- H-Hidden Temp=0shm一行字,shh则是两位隐藏位;m表示尾数(包括尾数补偿3最后Temp的结果为 的符号位,和更新rExp的结果。isSign<=if(Temp[48]==1'b1)Temp<=~Temp+1'b1;//changeMberExp<={2'b00,rA[55:48]};//orrB[55:48],changerExpwithberA.Expor1.3.6很简单而已,isSignTemp[48],Temp[48]则是加减结果的符号位。然后Temp[48]1rExprA(rB的价码也是等价)。我们继续运算Q1的问题看看:TempTemp=0isSign=0;TemprExp=6:0b0b01.111111E+20b10.111111E+20b11.111111E+20b00.111111E+20b00.011111E+20b0b10.111111E+2=0b0b11.111111E+20b 0b00.111111E+20b1.11111E+110b00.011111E+20b E+02
if(Temp[47:46]==2'b10||Temp[47:46]==2'b11)beginTemp<=Temp>>1;rExp<=rExp+1'b1;endelseif(Temp[47:46]==2'b00&&Temp[45])beginTemp<=Temp<<1;rExp<=rExp-5'd1;endelseif(Temp[47:46]==2'b00&&Temp[44])beginTemp<=Temp<<2;rExp<=rExp-5'd2;endelseif(Temp[47:46]==2'b00&&Temp[43])beginTemp<=Temp<<3;rExp<=rExp-5'd3;endelseif(Temp[47:46]==2'b00&&Temp[42])beginTemp<=Temp<<4;rExp<=rExp-5'd4;endelseif(Temp[47:46]==2'b00&&Temp[41])beginTemp<=Temp<<5;rExp<=rExp-5'd5;endelseif(Temp[47:46]==2'b00&&Temp[40])beginTemp<=Temp<<6;rExp<=rExp-5'd6;endelseif(Temp[47:46]==2'b00&&Temp[39])beginTemp<=Temp<<7;rExp<=rExp-5'd7;endelseif(Temp[47:46]==2'b00&&Temp[38])beginTemp<=Temp<<8;rExp<=rExp-5'd8;endelseif(Temp[47:46]==2'b00&&Temp[37])beginTemp<=Temp<<9;rExp<=rExp-5'd9;endelseif(Temp[47:46]==2'b00&&Temp[36])beginTemp<=Temp<<10;rExp<=rExp-5'd10;endelseif(Temp[47:46]==2'b00&&Temp[35])beginTemp<=Temp<<11;rExp<=rExp-5'd11;endelseif(Temp[47:46]==2'b00&&Temp[34])beginTemp<=Temp<<12;rExp<=rExp-5'd12;endelseif(Temp[47:46]==2'b00&&Temp[33])beginTemp<=Temp<<13;rExp<=rExp-5'd13;endelseif(Temp[47:46]==2'b00&&Temp[32])beginTemp<=Temp<<14;rExp<=rExp-5'd14;endelseif(Temp[47:46]==2'b00&&Temp[31])beginTemp<=Temp<<15;rExp<=rExp-5'd15;endelseif(Temp[47:46]==2'b00&&Temp[30])beginTemp<=Temp<<16;rExp<=rExp-5'd16;endelseif(Temp[47:46]==2'b00&&Temp[29])beginTemp<=Temp<<17;rExp<=rExp-5'd17;endelseif(Temp[47:46]==2'b00&&Temp[28])beginTemp<=Temp<<18;rExp<=rExp-5'd18;endelseif(Temp[47:46]==2'b00&&Temp[27])beginTemp<=Temp<<19;rExp<=rExp-5'd19;endelseif(Temp[47:46]==2'b00&&Temp[26])beginTemp<=Temp<<20;rExp<=rExp-5'd20;endelseif(Temp[47:46]==2'b00&&Temp[25])beginTemp<=Temp<<21;rExp<=rExp-5'd21;endelseif(Temp[47:46]==2'b00&&Temp[24])beginTemp<=Temp<<22;rExp<=rExp-5'd22;endelseif(Temp[47:46]==2'b00&&Temp[23])beginTemp<=Temp<<23;rExp<=rExp-5'd23;end//elsedonothingif(Temp[47:46]==2'b01我们知道m[48]mp47:46p[45:23]之间,既是“mp[47:46]m[45:23(关于假定小数点的解释在下一个小节)shhshhshhshh sshhshhs 1.xxxxx一致。读者需要注意的TempTemp= rExp=shh 00000000001rExp0单精度格式的浮点数,价码的位宽为8,然后价码从8'b 码为8'b 那么该浮点数源的价码为E+1;反之如果价码为8'b 浮点数源的价码为E-1。换句话说,正直的价码会从8'b ,亦即E+1 ~ E-127。价码溢出的问题,最可能发生是在尾数的调整之是下溢?因此,我们为rExp10位宽寄存器。rExp[9:8]2'b11,即表示价码为下溢。喜欢抓头的同学可能又要问:“为什么认定rExp[9:8]2'b01就是发生价码上溢,其他亦然?”原因很简单,笔者举个简单的演示(1.3.2):=+=+=+--=+补=+补==1.3.20值,0值在浮点全零的状态,举个例子1.5E+2减1.5E+2。理器的指令系统会反馈zero或者infinity的错误指令。所以笔者有样学样,果真发生无限的左移调整中,价码迟早会发生下溢...举个具体的例子:0=0= 0= 0= 0=0.00000000000000000000000000xxxxx ====...1,反之不然。if(rExp[9:8]==2'b01)beginisOver<=1'b1;rResult<={1'b0,8'd127,23'd0};end //EOverflowelseif(rExp[9:8]==2'b11)beginisUnder<=1'b1;rResult<={1'b0,8'd127,23'd0};end elseif(Temp[46:23]==24'd0)beginisZero<=1'b1;rResult<={1'b0,8'd127,23'd0};end//MZeroelseif(Temp[22]==1'b1)rResult<={isSign,rExp[7:0],Temp[45:23]+1'b1};//okaywithnormalisedelserResult<={isSign,rExp[7:0],Temp[45:23]};//okaywithoutnormalise1.3.853个分支是判断尾数是4个分支大同小异,只是没有执行四TempTemp=rExp=10'b00_isSign=0Temp[22]is1then0100+1,equal6.751+4.382=====+3==Real=0101TestResult 0100RealResultTrueTrueResultTestResult6.7414.382TestResultRealResult10进制一个小节,笔者会用的实例来消除读者的迷惑。...刚开始的时候感觉有点“怪怪”的。对于拥有十10进制,即时长大了从事软件相0b1.10010b1.10010b11.0010b110.01者以1.3小节中出现的Temp[48:0]为例;隐藏 小数Temp[48] Temp[45:23]在,它的存在是介于Temp[47:46]和Temp[45:23]之间。如果小数点不存在,自然不例子1.4.3:0b1.1001E+2beforeExp=0b11.001E+110b11.001E+1afterE=0b0b0b00000()beforeExp=00000(0)1ExpExp00000(0)afterExp=0b1.1001E+2beforeExp=0b0.11001E+3afterExp=0b0b0b00000(1)beforeExp=00001()1ExpExp00001()afterExp=感觉就是这么一回事。侥幸笔者福气十足,读者也是...不然的话,心里深处会一直 的例子。在此之前,我们稍微复下单精度浮点数加减预算的几个步骤:Q2:A=3.65,B=-7.4,A+B=AA=B=__Exp-B.Exp= -=128-$A.Exp=B.ExpandA.M>>h10001101(0)>>1(括号为尾数补偿01101(0)after,A=$B.Signis1while~B.m1(B1shh011011011001101010011011after,B= shh011001101(0)B'111111 $isSign=sum.s=$sum.sis1,while~sum.m1(1,需要正值化shh11100000(0)11111(1)00000(0)00000(0)hhis2'b00,whilesum'.m<<1andsum'.exp-$sum'.exp=-1=shh00000000(0)after,00000TestTesult-00000RealResult-TrueResult-Q2简化运算(手动)的过程,读者是不是非常不习惯呢?别慌,笔者会一步一AB单精度表示的浮点数,笔者1.2~1.3小节,那么用不着重复了(页ABA符号位为1,因此B的尾数必须转换位补码形式。B重新命名为B'。isSign(emp[48],们必须把结果调整致适合“浮点数源”的格式,我们判断hh的值(隐藏位)(Temp[47:46])2'b00,此时小数点后的第一位为1(Temp[47:46]==2'b00&&Temp[45]1sum'的价码。sumsum"。最后把读者还不能习惯的话,不要勉强自己...慢慢来。Q3:A=-3.142,B=2.002,A+B=A= B= A.exp-B.exp= - 0$A.signis1,while~A.m+shh0 00111110 1000110 1001110 1001after,A= shh110 100100100000000010000011000101B111 1110$isSign=sum.s=$sum.sis1,while~sum.m+s111 11100 000010 000100 00010after,sum=$sum'.hhis2'b00,whilesum'm<<1andsum'.exp-sum".exp= -1=hh 0001001 1000101100after,sum'= TestResult-RealResult-TrueResult-Q4:A=-3.142,B=-11.519,A+B=A= B= A.exp-B.exp= =-$-2while,A.m>>2andA.exp=A.exp=B.exp=hh 00111(00)00 0001(11)>>00 0001(11)after,A=$A'.signandB.signis1,while~A.m+1,~B.m+s000 0001(11)1 11110(00)1 11111(00)1 11111(00)after,A'=s001 00111 011001 011011 01101+1after,B= shh1 11111(00)1 01101(00)B'110100(00)$isSign=sum.s=$sum.sis1,while~sum.m+shh110000100(00)10011(11)10100(11)10101(00)after,sum=$sum'.hhis2'b01,whiledonothing 10101TestResult-10101RealResult-TrueResult-Q4AB操作数均为负值(符号位,在运算预处理时双方的尾数都需(符号位,所以结果的尾数必须正值化(因为单精度浮点数是以正直表示Q5:A=2112.2012,B=-3.1429,A+B=A=A=B=_0A.exp-B.exp=-=$10meanA.exp>B.exp,whileB.m>>10andB.exp=B.exp=A.exp=hh0000)>>)after,B=$B'.signis1,while~B'.m+shh000)1)1)1)after,B'= shh001)1)B"001 )$isSign=sum.s=$sum.hhis2'b01,whiledonothingTemp[22]is1,Temp[45:23]+m ) TestResult RealResultTrueResultQ5AB操作数之间的价码差很大,因此在价码对齐的步骤里,B尾最(Temp[22])为1所以运算结果必须执行四舍五入。Q6:A=33.0451,B=-20.9466,A+B=A=A=B=1A.exp-B.exp=-=$1meanA.exp>B.exp,whileB.exp>>1andB.exp=B.exp=A.exp=hh01 0011() 10001(1) 10001(1)after,B=$B'.sis1,while~B'.m+shh0 10001(1)111 1110(0)111 1110(1)111 1110(1)after,B'= shh001 1(0)111 1110(1)B"000 1101(1)$isSign=sum.s=$sum.hhis2'b00,andTemp[44]is1,whilesum.m<<2andsum.exp-2sum'.exp=0b -2=0b00 1101(1) 10110(0) 10110(0)after,sum= 10110TestResult 10101RealResultTrueResultQ6没有什么特别之处,除了在结果调整中,隐藏位为2'b00,恰好尾数补偿的最高第和RealResult的精度有点微差,但是结果都是正确的范围之内。Q7:A=7.751,B=5.382,A+B=A=_B=A.exp-B.exp=-=$donothing shh0100010011000b0111001$isSign=sum.s=$sum.hhis2'b10,whilesum.m>>1andsum.exp+1sum'.exp=0b +1=0b11after,sum=$Temp[22]is1,whileTemp[45:23]+m00100(1)00101(0)after,sum'= 00101TestResult 00101RealResultTrueResultQ8:A= ,B=- ,A+B=A=A=B=__A.exp-B.exp= - 0$B.sis1,while~B.m+shh0 11111110000000000000000000000001100000000000000000000000111000000000000000000000001after,B= shh0 1111011000000000000000000000001B'1 11111$isSign=sum.s=$sum.sis1,while~sum.m+shh1 11111000000000000000000000000000000000000000000000000000100000000000000000000000001after,sum=$sum'.hhis2'b00andTemp[23]is1,whilesum'.m<<23andsum'.exp-sum".exp= -23=00000000000000000000000010100000000000000000000000<<0100000000000000000000000after,sum'= _00000000000000000000000TestResult- _00000000000000000000000RealResult-TrueResult-偿里巧好存在着某个值为1...给个具体一点的例子:hhhhmelseelseif(Temp[47:46]==2'b00&&Temp[23])beginTemp<=Temp<<23;rExp<=rExp-5'd23;elseif(Temp[47:46]==2'b00&&Temp[1])beginTemp<=Temp<<45;rExp<=rExp-6'd45;endelseif(Temp[47:46]==2'b00&&Temp[0])beginTemp<=Temp<<46;rExp<=rExp-6'd46;1.6.1Done_Sig[3:1]Done_Sig[0]才是传统AB32位宽的操作数输入信号,Result32位宽的输出结果。其本上就是这些而已...inputCLK,input[31:0]A,B,inputStart_Sig,output[9:0]SQ_rExp,regreg[56:0]rA,rB;regregregregisSign;//[9:8]Overfloworunderflowcheck,[7:0]usuallregisOver;regisZero;reg//expoverflowerror//expunderflowerror//mzeroerror第19~30行是相关的寄存器。rA和rB除了寄存操作数A和B以外,它还用来恢复隐藏位[47:46][22:0]TempTempATempB的运算rResultResult信号;rExp是用来寄存价码差以外,它还有后期等工作;rExpDiff是用isOver是价码上溢的标志,isUnder是价码下溢的标志,isZero是尾数零值的表示。always@(posedgeCLKornegedgeRSTn)if(!RSTn)i<=4'd0;rA<=57'd0;rB<=Temp<=49'd0;rResult<=32'd0;rExp<=10'd0;rExpDiff<=8'd0;isOver<=1'b0;isUnder<=1'b0;isZero<=1'b0;isDone<=1'b0;第35~47行是相关的复位操作,所有寄存器都elseif(Start_Sigcase(i0://InitialA,Bandotherreg.rB<={B[31],B[30:23],2'b01,B[22:0],23'd0isOver<=1'b0;isUnder<=1'b0;isZero<=i<=i+1://ifrExp[9..8]is1,meanA.Expsmallthan//whilerExp[9..8]is0,meanA.ExplargethanB.Exporsame.rExp=A[30:23]-if(rExp[8]==1)rExpDiff<=~rExp[7:0]+1'b1;elserExpDiff<=rExp[7:0];i<=i+66~67if(rExp[8]==1)则表示,如果价码差是赋值的话...2://ifA<B;A.MmoveandA.E=B.E,elseoppositeact;if(rExp[8]==1)beginrA[47:0]<=rA[47:0]>>rExpDiff;rA[55:48]<=rB[55:48];endelsebeginrB[47:0]<=rB[47:0]>>rExpDiff;rB[55:48]<=rA[55:48];endi<=i+TempA<=rA[56]?{rA[56],(~rA[47:0]+1'b1)}:{rA[56],rA[47:0]TempB<=rB[56]?{rB[56],(~rB[47:0]+1'b1)}:{rB[56],rB[47:0]};i<=i+1'b1;4://74行则相作。第78~83行是运算预处理操作,该步骤会根据操作数的符号化,是否将尾数转换为补码形式,并且寄存在操作空间TempATempB85行是加减操作。isSign<=rExp<={2'b00,rA[55:48]};//orrB[55:48],changerExpwithberA.ExporrB.Expi<=i+1'b1;结果正直化;第92行则是更新rExp。6://CheckM'hiddenbitandmodifyto//elsedonothing,canextendthehiddenbitchecki<=i+96~125行是结果调整,至于要不要继续扩展隐藏位的搜索就自己看着办(122行beginisDone<=1'b0;i<=4'd0;127~135129130131行1321338~9是用来产生assignDone_Sig={isOver,isUnder,isZero,isDone};assignResult=rResult;assignSQ_rA=rA;assignSQ_rB=rB;assignSQ_rExp=rExp;147~148152~158行则是仿真用的驱动输出。基本上浮点数加法模块`timescale1ps/1moduleregCLK;reg[31:0]A;reg[31:0]wire[3:0]wire[31:0]wirewire[9:0]SQ_rExp;wire.CLK(CLK.RSTn(RSTn.B(B RSTn=0;#10RSTn=CLK=0;forever#5CLK= regalways@(posedgeCLKornegedgeRSTnif(!RSTnA<=B<=i<=case(i0://A=3.65,B=-7.4,A+B=if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;$disy("%b",Result);elsebeginA<=32'b0_ 11010;B<=32'b1_ 1://Expundeflowif(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;elsebeginA<=32'b0_ 1101;B<=32'b1_ 11;Start_Sig<=1'b1;end ,B=- ,A+Bif(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;$disy("%b",Result);elsebeginA<=32'b0_ 11110;B<=32'b1_ 11111;Start_Sig<=1'b1;end3://Expif(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;elsebeginA<= 11111;B<= 11111;Start_Sig<=1'b1;i<=其他都不陌生。$disy是验证语言,主要是用来输出结果,用法和C语言的printf类似。顺便补上一句,$disy函数在时序的效果上和组合逻辑一样,都是即件。步骤0,2,4,5,6是用验证测该模块的通常运作,步骤1和3则是用来测试价码上溢和下溢的运作。1.6.21.6.23.657.4的运算过程,C1(CurosrC)AB入以后,并且拉高Start_Sig,在C1的未来32'b0_ 11010和 01101被输出。在C2的时候是操作数预处理,浮点数加码差的取得是“即件”)结果是8'b 1.6.31A.exp<B.expArExpDiffC4的过去值(C4的未来,A1B一样。C5的时候是运算预处理,根据rArBC5中过去的结果,rBrB的尾数必须取得补码形式,所以在C5的未来,rArBTempATempB中。C6的时候是加减运算,C6的未来中所输出的值是TempATempBC6过去中相加的结果。1.6.4C7的时候是结果预处理,isSignC7Temp[48]1。此外,根据过去值的未来输出尾数左移一位的结果,其中rExp被减去1。C9的时候是输出和个时候,rExp的过去值为10'b00_ ,其中rExp[9:8]不是2'b01或者在C9的未来,输出isSign为1,rExp为8'b ,和尾数为Temp[45:23]的结果。在这次的1.6.5C13isUnder的标志(Done_Sig[2],并且输出默认空壳的值。1.6.61.6.6同为笔者故意引起的价码上溢,C17rExp[9:8]2'b10,因此断定(Done_Sig[3]7.30911.7762112.2012-2002.2012的运算过程也差不多而已,在此笔者就不加说明了,作为补偿笔者就简化运Q9:A=2112.2012,B=-2002.2012,A+B=A=0B=_A.exp-B.exp=-=$1meanA.exp>B.expwhile,B.m>>1andB.exp=hh 10000() 11000(0)>> 11000(0)after,B=$B'.sis1,while~B'.m+shh011000(0)111(1)111(0)111(0)after,B'= shh001 111(0)B"0000(0)$isSign=sum.s=$sum.hhis2'b00andTemp[41]is1,whilesum.m<<5andsum.exp-sum'.exp= -5=hhhh000(0) 00000(0)<< 00000(0)after,sum= 00000TestResult 00000RealResultTrueResult已经买下一些微调的,所以只要在相关的步骤动一下手脚就行了。1.7.1input[31:0]A,B,inputStart_Sig,output[9:0]SQ_rExp,regreg[56:0]rA,rB;//[56]Sign,[55:48]Exponent,[47:46]HiddenBit,[45:23]Mantissa[22:0]M'resolutionreg[48:0]Temp; //[48]M'sign,[47:46]HiddenBit,[45:23]M,[22:0]M'resolutionregreg//[9:8]Overfloworunderflowcheck,[7:0]usuallreg[7:0]rExpDiff;//DifferentbetweenA.ExpandB.ExpregisSign;regregregregalways@(posedgeCLKornegedgeRSTnif(!RSTni<=rA<=rB<=rResult<=rExp<=rExpDiff<=isOver<=isUnder<=isZero<=isDone<=elseif(Start_Sigcase(i0://InitialandresultedoutrB<={B[31],B[30:23],2'b01,B[22:0],23'd0isOver<=1'b0;isUnder<=1'b0;isZero<=i<=i+1://ifrExp[9..8]is1,meanA.Expsmallthan//whilerExp[9..8]is0,meanA.ExplargethanB.ExporrExp=A[30:23]-if(rExp[8]==1)rExpDiff<=~rExp[7:0]+elserExpDiff<=i<=i+2://ifA<B;A.MmoveandA.E=B.E,elsedifferentif(rExp[8]==1)beginrA[47:0]<=rA[47:0]>>rExpDiff;rA[55:48]<=rB[55:48];elsebeginrB[47:0]<=rB[47:0]>>rExpDiff;rB[55:48]<=rA[55:48];i<=i+TempA<=rA[56]?{rA[56],(~rA[47:0]+1'b1)}:{rA[56],rA[47:0]TempB<=rB[56]?{rB[56],(~rB[47:0]+1'b1)}:{rB[56],rB[47:0]i<=i+4://beginTemp<=TempA-TempB;i<=i+1'b1;end isSign<=rExp<={2'b00,rA[55:48]};//orrB[55:48],changerExpwithberA.Expori<=i+6://CheckM'hiddenbitandmodifyin//elsedoi<=i+7://errorcheckanddecidefinalif(rExp[9:8]==2'b01)beginisOver<=1'b1;rResult<={1'b0,8'd127,23'd0}; //Eelseif(rExp[9:8]==2'b11)beginisUnder<=1'b1;rResult<={1'b0,8'd127,23'd0};end//Eelseif(Temp[46:23]==23'd0)beginisZero<=1'b1;rResult<={1'b0,8'd127,23'd0};end//Melseif(Temp[22]==1'b1)rResult<={isSign,rExp[7:0],Temp[45:23]+1'b1};//okaywithi<=i+ beginisDone<=1'b1;i<=i+1'b1;end beginisDone<=1'b0;i<=4'd0;end assignSQ_rB=assignSQ_rExp= 162.85~86行的加减操作以外,其余的内容都和浮点数加法模块一模一样。至于修改的内容,也是从原本的“+”变成“-”而已。在这里笔者再简单的复下+/-与-”运算符的时候,它会把接续的整数(二进制值转`timescale1ps/1moduleregregregreg[31:0]wire[3:0]wire[31:0] wirewirewirewire (.CLK(CLK.RSTn(RSTn.B(BRSTn=0;#10RSTn=CLK=0;forever#5CLK=regalways@(posedgeCLKornegedgeRSTnif(!RSTnA<=B<=i<=case(i0://A=3.65,B=-7.4,A-B=if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1; 11010;B<=_1://Expundeflowif(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;elsebeginA<=1101;B<=11;Start_Sig<=1'b1; ,B=- ,A-Bif(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;$disy("%b",Result);elsebeginA<=32'b0_ 11110;B<=32'b1_ 11111;Start_Sig<=1'b1;end3://Expif(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;elsebeginA<=32'b0_ 11111;B<=32'b0_ 11111;Start_Sig<=1'b1;endif(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;$disy("%b",Result); if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;elsebeginA<=if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;elsebeginA<=if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;if(Done_Sig[0])beginStart_Sig<=1'b0;i<=i+1'b1;elsebeginA<=0011100010001;B<=113.i<=02float_add_module.vt是一样的操作,但是随着操作符的不同,运算结果页随着:Q1:A=3.65,B=-7.4,A-B=A=A=_B= 1101TestResult 1101TealResultTrueResultQ2:A= ,B=- ,A-B=A=A=_B= _11111TestResult 11111RealResultTrueResultQ3:A=78992.118,B=-90116.402,A-B=A=A=B= 0001TestResult 0001RealResultTrueResult经开始偏远TrueResult了。原因是——单精度格式已经是勉强承载运算过后的结果。用一句傻瓜的话来说,8个十进制位数(包括小数Q4:A=6992.330,B=1271.004,A-B=A=A=_B= 1100TestResult 1100RealResultTrueResultQ3,Q4TestResultRealResultTrueResult。用傻瓜的话来说,7个十进制Q5:A=-1.5032,B=-8.3309,A-B=A=A=_B= _00101TestResult 00101RealResultTrueResultQ6:A=-88.8888,B=-10.9944,A-B=A=B=A=111TestResult-B=111RealResult-True6个十进制位数的结果(包括小数Q7:A=0.001584,B=0.063197,A-B=A=A=_B= _01010TestResult- 01010RealResult-TrueResult-Q8:A=-613.931,B=27.11402,A-B=A=A=B= 0010TestResult- 0010RealResult-TrueResult-Q8AB的操作数,10TestResultRealResult都偏离TrueResult。果然拥有7个十进制的位数(包括小数,单精度格式不好支持。Q9:A=44.4444,B=68.3333,A-B=A=A=B= 0110TestResult-1000RealResult-TrueResult-结果再一次的显示,6个十进制位数(包括小数)是单精度格式在加减操作中,TestResultRealResult是最接近TrueResult的。不过比较愕然的是,即使TestResult中最后几个尾数和RealResult不同,但是它们取得的结果都和TrueResult差不多。10进制的尾数作为标准的话,我们可以得出一6个十进制位数(包括小数)TrueResult的加减5.05.0x102×-2.2 =(1)5.0x102×(-1)2.2=(1×-1)5.0×2.2=(-1)11=-3个部分,就是符号位运算(正负运算,数目运算(尾而已。如果我们一意孤行使用相同的概念,以2进制的方式来实现浮点乘法的话,结果必定天珠。面,笔者已经那一套用在我们认知的里,是绝对不适合用在Verilog的世界里。我们1.110E+21.110E+2×-1.011E+3=(1)1.110E+2×(-=(1)(-1)1.110×1.011=(-1) =-1(-2=-×=+==(--3这确实是重点问题。“假定”的小数点就是“夹在最和最高第二位”之间。具体一点来说,假设A和B的乘法结果寄存在名为Temp的空间里,那么Temp[7]和Temp[6]之间就是假定的小数点。[[ [31][-30:23- [符][-价码 尾 单精度格式可以分为3部分,亦即符号位[31],价码[30~23]和尾数[22:0]。默认空壳中,除了符号位和尾数以外(全零价码的值是8'b =A'.s^=0^=Q1:A==A'.s^=0^=A=B=A'=_B'=_ =A'.exp+= +(-127=128+(129-=128+==sum.m=A'.m*=000000*= $sum.m[47]is0,whilesum.m<<0000000000000000000000000000000<<$Takeoutsum'.m[46:24],ifsum'.m[23]is1sum'.m[46:24]+_00000TestResult 00000RealResultTrueResult首先是操作数预处理,乘法运算和加减运算不一样的是,乘法运算没有“价码对齐”这一个步骤,1位而已,ilogL1.8.1所示:rA<={A[31],A[30:23],1'b1,rB<={B[31],B[30:23],1'b1,1.8.1“*”运算符取得尾数AB的相乘结果。VerilogHDL语言的实现如代码1.8.2所示:isSign<=A[31]^BDiff=rB[31:24]-8'd127;//+(~8'd127+rExp<=rA[31:24]+BDiff;//A.Exp+Temp<=rA[23:0]*1.8.24'b11114'b10004'b11114'b1000 << << << after,Exp- after,Exp-点必是[7]~[6]之间。在上面4个例子中,笔者取出最有可能得到的4大结果。一、首先是QI的结果,其中最为1所以不用调整;二、QII的结果中最值为0,所以必须左移1位;,424VerilogHDL语言来实现的话,如代码1.8.3所示:if(Temp[47]==1'b1)beginTemp<=Temp;end//donothingelseif(Temp[46]==1'b1)beginTemp<=Temp<<1;endelseif(Temp[45]==1'b1)beginTemp<=Temp<<2;rExp<=rExp-入的时候,概念会有所不同。在输出之前,我们只能从尾数的运算结果中一部分而已,假设这个运算空间为48位宽的Temp,Temp[47]必定隐藏位,然而Temp[46:24]就是我们要的部分,如果Temp[23]的值为1的话,那么须为Temp[46:24]加1。if(rExp[9:8]==2'b01)beginisOver<=1'b1;rResult<={1'b0,8'd127,23'd0};//Eelseif(rExp[9:8]==2'b11)beginisUnder<=1'b1;rResult<={1'b0,8'd127,23'd0};end//EUnderflowelseif(Temp[47:24]==23'd0)beginisZero<=1'b1;rResult<={1'b0,8'd127,23'd0};end//MZeroelseif(Temp[23]==1'b1)rResult<={isSign,rExp[7:0],Temp[46:24]+1'b1};//okaywithnormalisedelserResult<={isSign,rExp[7:0],Temp[46:24]};//okaywithout更隐蔽,更,它也是在许多浮点数乘法器设计上所犯的问题。笔者再举一个例子:Q2:A=2,B=2,A×B=(以下的过程中笔者把操作数预处理简化掉A=A=B= sum.s=A.s^B.s=0^0=sum.exp=A.exp+= +(-127=sum.msum.m=A.m*=000000*= $sum.m[47]is0,whilesum.m<< 000000000000000000000000000000<< TrueResultQ22*2也存在第一个陷阱。在结果调整中,如果尾数必须右移一位TrueResult就会和RealResult不同的结果。Q3:A=3.142,B=3.142,A×B=A=A=_B= sum.s=A.s^B.s=0^0=sum.exp=A.exp+= +(-127=sum.m=A.m*=000111*= $sum.m[47]is1,whiledo$sum.m[23]is1,whilesum.m[46:24]+h110011 0101 010after,sum=010TestResult 010RealResultTrueResultQ3Q2TestResultRealResult差十万RealResultTrueResultTestResult出现错TestResultRealResultTestResult的价码比起RealResult的价码少了一位。这又是另一个浮点乘法的阴森陷阱!...3方法的,而是两方独立运行。借此我们可5.15.1x103×2.2x102=5.1x103×0.221.101E+3×1.011E+2=1.101E+3×0.1101问题组(AB)都可以使用此方法,唯有某个“特殊条件”下,才能使用这个(注意在判断过程不包括隐藏位,但是在移位过程中却包括隐藏位)VerilogHDL语言来表示的话,代码如1.8.5所示:if(rA[31:24]==rB[31:24]&&(rA[22:0]!=23'd0&rB[22:0]!=23'd0) beginbeginrB[31:24]<=rB[31:24]+1'b1;rB[23:0]<=rB[23:0]>>1;1.8.5Q3b:A=3.142,B=3.142,A×B=A= B= sum.s=A.s^B.s=0^0=$A.exp==B.exp&&A.mandB.mnotazero(noincludehiddenbit),whileB.m>>1andB.exp+1(includehiddenbit)B'.exp= +1=h 00111 000111 00011after,B=sum.exp=A.exp+= +( -127=sum.m=A.m*= 000111* = $sum.m[47]is0,whilesum.m<<h 010010101011 0101010<<1 0101010after,sum=$sum.m[23]is0,whiledo 001TestResult010RealResultTrueResultQ3TestResultRealResult差不B1位尾数而已,用不着那if(if(rA[31:24]==rB[31:24]&&(rA[22:0]!=23'd0&rB[22:0]!=23'd0)if(rA[31:24]==rB[31:24]&&rA[22:0]==rB[22:0]before//Q3bAB...事实上,那是万万不可的动作!不相信吗?我们再运算一下Q2的问题(2*2)就知道结果了。Q2b:A=2,B=2,A×B=A=A=B= sum.s=A.s^B.s=0^0=$A.exp==B.exp&&A.m==B.m,whileB.m<<1andB.exp+B'.exp=+=h 00000>> 00000after,B=sum.exp=A.exp+= +(-127=sum.m=A.m*=000000*= $$sum.m[47]is0,whilesum.m<<2andsum.exp-sum'.exp=-1=h0 TrueResult意了这位同学...我们再运算另一个问题看看。A=B= sum.s=A.sA=B= sum.s=A.s^B.s=$A.expB.expbutA.mB.m,whiledonothingsum.exp=A.exp+= +(-127=sum.m=A.m*$sum.m[47]is1,whiledonothing Trueresult=100101*=Q4TestResultRealResultTrueResultstRsultlsult(特殊条件用,4看看。Q4b:A=273.757,B=483.265,A×B=A= B= sum.s=A.s^B.s=$A.exp==B.expandA.m!=0andB.m!=0(notincludehiddenbit),whileB.m<<1(includehiddentbit)andB.exp+1B'.exp= +1=h 01100 10110>> 10110after,B=sum.exp=A.exp+= +( -127=sum.m=A.m*=100101*=$sum.m[47]is0,whilesum.m<<h 00000111001 11000<<1 11000after,sum= TrueResultTrueResult还是有点精度上的差别。结论,我们可以证明简化版的判断逻辑只是鹌殊条件”用VerilogHDL语言来表达更简单,如代码1.8.5所示:if(if(rA[31:24]==rB[31:24]&&(rA[22:0]!=23'd0&rB[22:0]!=23'd0)||rA[31]^rB[31])beginrB[31:24]<=rB[31:24]+1'b1;rB[23:0]<=rB[23:0]>>1;endQ5A=6.3565,B=-0.0063,A×B=A=A=_B= sum.s=A.s^B.s=0^1=$sum.sis1,whileB.m<<1andB.exp+B'.exp=+1=h111011 11101>> 11101after,B=sum.exp=A.exp+= +(-127=129+(120-127==sum.m=A.m*=110011*==$sum.m[47]is0,whilesum.m<<h0101000001111 1 1000001110after,sum= 1000TestResult- 1001RealResult-TrueResult-Result差不多。发现很多的内容都无视这个问题,此外相关的也显得更疲软了,笑~笔者不知道著名的有关Pentium在浮点数运算的BUG是不是和这些陷阱有关系?但是笔者非常可1.9.1input[31:0]A,B,inputStart_Sig,output[47:0]SQ_Temp,regreg[32:0]rA,rB;//[32]Sign,[31:24]Exponent,[23]HiddenBit,[22:0]Mantissareg[47:0]Temp; //[48]M'sign,[47:46]HiddenBit,[45:23]M,[22:0]M'resolutionregregisSign;regisOver;regisZero;regalways@(posedgeCLKornegedgeRSTn)if(!RSTn)i<=4'd0;rA<=33'd0;rB<=Temp<=48'd0;rExp<=10'd0;BDiff<=10'd0;isOver<=1'b0;isUnder<=1'b0;isZero<=1'b0;isDone<=1'b0;第19~28行是相关的寄存器,rA和rB是用来寄存操作数A和B的隐藏位恢复结果,因此位if(rA[31:24]==rB[31:24]&&(rA[22:0]!=23'd0&rB[22:0]!=23'd0)||rA[31]^rB[31])beginrB[31:24]<=rB[31:24]+1'b1;rB[23:0]<=rB[23:0]>>1;endi<=i+第48~56行是操作数预处理,除了从操作数A和B恢复隐藏位以外,还有相关的错误标志寄存器(54行58~6360行是移位预处理的判断条件。在此笔者再2://ifrExp[9..8]is1,meanA.Expsmallthan//whilerExp[9..8]is0,meanA.ExplargethanB.Exporsame.BDiff=rB[31:24]-8'd127;//+(~8'd127+rExp<=rA[31:24]+BDiff;//A.Exp+B.Expi<=i+1'b1;i<=i+1'b1;if(Temp[47]==1'b1)beginTemp<=Temp;end//donothingelseif(Temp[46]==1'b1)beginTemp<=Temp<<1;endelseif(Temp[45]==1'b1)beginTemp<=Temp<<2;rExp<=rExp-i<=i+79~86行是结果调整,比起加减操作,乘法操作在该步骤显得更简单,不过5://errorcheckanddecidefinalresultif(rExp[9:8]==2'b01)beginisOver<=1'b1;rResult<={1'b0,8'd127,23'd0};end //EOverflowelseif(rExp[9:8]==2'b11)beginisUnder<=1'b1;rResult<={1'b0,8'd127,23'd0};end//EUnderflowelseif(Temp[47:24]==23'd0)beginisZero<=1'b1;rResult<={1'b0,8'd127,23'd0};end//MZeroelseif(Temp[23]==1'b1)rResult<={isSign,rExp[7:0],Temp[46:24]+1'b1};//okaywithnormalisedelserResult<={isSign,rExp[7:0],Temp[46:24]};//okaywithoutnormalisei<=i+beginisDone<=1'b1;i<=i+1'b1;beginisDone<=1'b0;i<=4'd0;的位置不同以外,还有就是第93~94行之间尾数的位置。用简单的话来说,假定小数点夹在Temp[47]~Temp[46]之间,然而输出用的尾数是Temp[46..24],最后四舍五入的判断位置是assignResult=assignSQ_rA=rA;assignSQ_rB=rB;assignSQ_rExp=rExp;assignSQ_BDiff=BDiff;121.`timescale1ps/1moduleregregreg[31:0]regwire[2:0]wire[31:0] wire[9:0]wire[47:0]wire[32:0]wire[32:0]wire[9:0] ( RSTn=0;#10RSTn=CLK
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 不会被跳墙的居间合同
- 售后服务协议合同
- 公司股份转让合同协议书详细
- 技术服务合同免税
- 墙布供货施工合同协议书
- 股权分配及股份制公司合同详解
- 产品销售与分销合同细节规定
- 汽车零部件生产技术优化合同
- 广东工贸职业技术学院《工程材料及制造基础双语》2023-2024学年第二学期期末试卷
- 兰州航空职业技术学院《中学英语教学设计》2023-2024学年第二学期期末试卷
- 关于投资协议书范本5篇
- 《反电信网络诈骗法》知识考试题库150题(含答案)
- 2025年上海市各区初三一模语文试卷(打包16套无答案)
- 2024 原发性肝癌诊疗指南 更新要点课件
- 《圆柱与圆锥-圆柱的表面积》(说课稿)-2023-2024学年六年级下册数学人教版
- 《人工智能基础》课件-AI的前世今生:她从哪里来
- 深圳市失业人员停止领取失业保险待遇申请表样表
- 英语四线三格模板
- 大智慧指标公式函数大全(完整可打印版)
- JIS G4305-2021 冷轧不锈钢板材、薄板材和带材
- (完整版)凉亭施工方案
评论
0/150
提交评论