在计算机中浮点数 表示通常采用IEEE754规定的格式,具体参考以下文章。

https://www.cnblogs.com/mikewolf2002/p/10095995.html

下面我们在Verilog中用状态机实现单精度浮点数的加减法功能。这个实现是多周期的单精度浮点加法。

浮点加法分为以下几个步骤:

1.初始化阶段,分离指数和尾数以及符号位。判断加数和被加数是否是规约浮点数,不是话,直接置overflow=0x11,重新进入初始化阶段,进行下一组数的加法

2.判断加数和被加数中是否有0,有零的话,可以直接得到结果。

3.对接操作,小阶向大阶对齐。

4.对接后,进行尾数相加。

5.规格化尾数,进行左规和右规处理。

6.判断是否溢出,设置overflow标志。

下面是verilog代码:

  1. module floatadd(clk, rst_n, x, y, z,overflow);
  2.  
  3. input clk;
  4. input rst_n;
  5. input [31:0] x;
  6. input [31:0] y;
  7. output [31:0] z;
  8. output [1:0] overflow;//0,没有溢出,1,上溢,10,下溢,11 输入不是规格化数
  9.  
  10. reg [31:0] z; // z=x+y
  11. reg[24:0] xm, ym, zm; //尾数部分, 0+ 1+[22:0],
  12. reg[7:0] xe, ye, ze; //阶码部分
  13. reg[2:0] state, nextstate; //状态机
  14. reg zsign; //z的符号位
  15. reg [1:0] overflow;
  16.  
  17. parameter start=3'b000,zerock=3'b001,exequal=3'b010,addm=3'b011,infifl=3'b100,over =3'b110;
  18.  
  19. always @(posedge clk) begin
  20. if(!rst_n)
  21. state <= start;
  22. else
  23. state <= nextstate;
  24. end
  25.  
  26. //状态机进行浮点加法处理
  27. always@(state,nextstate,xe,ye,xm,ym,ze,zm) begin
  28. case(state)
  29. start: //初始化,分离尾数和指数,调整符号位
  30. begin
  31. xe <= x[30:23];
  32. xm <= {1'b0,1'b1,x[22:0]};
  33. ye <= y[30:23];
  34. ym <= {1'b0,1'b1,y[22:0]};
  35.  
  36. //判断是否溢出,大于最大浮点数,小于最小浮点数
  37. if((xe==8'd255)||(ye==8'd255)||((xe==8'd0)&&(xm[22:0]!=23'b0))||((ye==8'd0)&&(ym[22:0]!=23'b0)) )
  38. begin
  39. overflow <= 2'b11;
  40. nextstate <= start; //直接到初始化
  41. z <= 32'b1; //直接赋值最小非规约数,
  42. end
  43. else
  44. nextstate <= zerock;
  45. end
  46. zerock://检测x,y如果有一个为0,则跳转到over state
  47. begin
  48. if((x[22:0]==23'b0)&&(xe==8'b0))
  49. begin
  50. {zsign, ze,zm} <= {y[31],ye, ym};
  51. nextstate <= over;
  52. end
  53. else
  54. begin
  55. if((y[22:0]==23'b0)&&(ye==8'b0))
  56. begin
  57. {zsign,ze,zm} <= {x[31],xe, xm};
  58. nextstate <= over;
  59. end
  60. else
  61. nextstate <= exequal;
  62. end
  63. end
  64. exequal:
  65. begin
  66. if(xe == ye)
  67. nextstate <= addm;
  68. else
  69. begin
  70. if(xe > ye)
  71. begin
  72. ye <= ye + 1'b1;//阶码加1
  73. ym[23:0] <= {1'b0, ym[23:1]};
  74. if(ym==8'b0)
  75. begin
  76. zm <= xm;
  77. ze <= xe;
  78. zsign<=x[31];
  79. nextstate <= over;
  80. end
  81. else
  82. nextstate <= exequal;
  83.  
  84. end
  85. else
  86. begin
  87. xe <= xe + 1'b1;//阶码加1
  88. xm[23:0] <= {1'b0, xm[23:1]};
  89. if(xm==8'b0)
  90. begin
  91. zm <= ym;
  92. ze <= ye;
  93. zsign <= y[31];
  94. nextstate <= over;
  95. end
  96. else
  97. nextstate <= exequal;
  98. end
  99. end
  100.  
  101. end
  102. addm://尾数相加
  103. begin
  104. ze <= xe;
  105.  
  106. if((x[31]^y[31])==1'b0) //同符号
  107. begin
  108. zsign = x[31];
  109. zm <= xm + ym;
  110. end
  111. else
  112. begin
  113. if(xm>ym)
  114. begin
  115. zsign = x[31];
  116. zm <= xm - ym;
  117. end
  118. else
  119. begin
  120. zsign = y[31];
  121. zm <= ym - xm;
  122. end
  123.  
  124. end
  125.  
  126. if(zm[23:0]==24'b0)
  127. nextstate <= over;
  128. else
  129. nextstate <=infifl;
  130. end
  131. infifl://规格化处理
  132. begin
  133. if(zm[24]==1'b1)//有进位,或借位
  134. begin
  135. zm <= {1'b0,zm[24:1]};
  136. ze <= ze + 1'b1;
  137. nextstate <= over;
  138. end
  139. else
  140. begin
  141. if(zm[23]==1'b0)
  142. begin
  143. zm <= {zm[23:0],1'b0};
  144. ze <= ze - 1'b1;
  145. nextstate <= infifl;
  146. end
  147. else
  148. begin
  149. nextstate <= over;
  150. end
  151. end
  152. end
  153. over:
  154. begin
  155. z <= {zsign, ze[7:0], zm[22:0]};
  156. //判断是否溢出,大于最大浮点数,小于最小浮点数
  157. if(ze==8'd255 )
  158. begin
  159. overflow <= 2'b01;
  160. end
  161. else if((ze==8'd0)&&(zm[22:0]!=23'b0)) //不处理非规约数
  162. begin
  163. overflow <= 2'b10;
  164. end
  165. else
  166. overflow <= 2'b00;
  167. nextstate <= start;
  168. end
  169. default:
  170. begin
  171. nextstate <= start;
  172. end
  173. endcase
  174.  
  175. end
  176.  
  177. endmodule

下面是testbench代码:

代码中仅有两组加法操作,以后会写出更完备的testbench代码,用c语言产生更多的测试数据,在testbench中读入。to do…

  1. `timescale 1ns/1ns
  2. `define clock_period 20
  3.  
  4. module floatadd_tb;
  5. reg [31:0] x,y;
  6.  
  7. wire [31:0] z;
  8.  
  9. reg clk;
  10. reg rst_n;
  11. wire [1:0] overflow;
  12.  
  13. floatadd floatadd_0(
  14. .clk(clk),
  15. .rst_n(rst_n),
  16. .x(x),
  17. .y(y),
  18. .add(add),
  19. .z(z),
  20. .overflow(overflow)
  21. );
  22.  
  23. initial clk = 0;
  24. always #(`clock_period/2) clk = ~clk;
  25.  
  26. initial begin
  27. x = 0;
  28. rst_n = 1'b0;
  29. #20 rst_n = 1'b1;
  30. #(`clock_period) x = 32'b01000000011011101001011110001101; //3.456
  31. #(`clock_period*7) x = 32'hc2b5999a; //-90.8
  32.  
  33. end
  34.  
  35. initial begin
  36. y = 0;
  37. #20
  38. #(`clock_period) y = 32'b01000000010011001100110011001101;//2.4
  39. #(`clock_period*7) y = 32'h41a3c28f;//20.47
  40.  
  41. end
  42.  
  43. initial begin
  44. #(`clock_period*100)
  45. $stop;
  46. end
  47.  
  48. endmodule

浮点数减法很简单,只要把减数的符号位取反就可以了。

下面是浮点加减法代码。如果add为1,执行加法操作,如果add为0,执行减法操作。

  1. module floataddsub(clk, rst_n, x, y, add, z,overflow);
  2.  
  3. input clk;
  4. input rst_n;
  5. input [31:0] x;
  6. input [31:0] y;
  7. input add;
  8. output [31:0] z;
  9. output [1:0] overflow;
  10. wire [31:0] y1;
  11.  
  12. floatadd floatadd_0(
  13. .clk(clk),
  14. .rst_n(rst_n),
  15. .x(x),
  16. .y(y1),
  17. .z(z),
  18. .overflow(overflow)
  19. );
  20. assign y1 = add ? y:{~y[31],y[30:0]};
  21. endmodule

用下面的testbench代码,实现加减法操作。

  1. `timescale 1ns/1ns
  2. `define clock_period 20
  3.  
  4. module floataddsub_tb;
  5. reg [31:0] x,y;
  6. reg add;
  7.  
  8. wire [31:0] z;
  9.  
  10. reg clk;
  11. reg rst_n;
  12. wire [1:0] overflow;
  13.  
  14. floataddsub floataddsub_0(
  15. .clk(clk),
  16. .rst_n(rst_n),
  17. .x(x),
  18. .y(y),
  19. .add(add),
  20. .z(z),
  21. .overflow(overflow)
  22. );
  23.  
  24. initial
  25. begin
  26. clk = 1'b0;
  27. add = 1'b0;
  28. #(`clock_period*9)
  29. add = 1'b1;
  30. end
  31. always #(`clock_period/2) clk = ~clk;
  32.  
  33. initial begin
  34. x = 0;
  35. rst_n = 1'b0;
  36. #20 rst_n = 1'b1;
  37. #(`clock_period) x = 32'b01000000011011101001011110001101; //3.456
  38. #(`clock_period*7) x = 32'hc2b5999a; //-90.8
  39.  
  40. end
  41.  
  42. initial begin
  43. y = 0;
  44. #20
  45. #(`clock_period) y = 32'b01000000010011001100110011001101;//2.4
  46. #(`clock_period*7) y = 32'h41a3c28f;//20.47
  47.  
  48. end
  49.  
  50. initial begin
  51. #(`clock_period*100)
  52. $stop;
  53. end
  54.  
  55. endmodule

功能仿真的波形如下:

Verilog 加法器和减法器(7)的更多相关文章

  1. Verilog 加法器和减法器(8)-串行加法器

    如果对速度要求不高,我们也可以使用串行加法器.下面通过状态机来实现串行加法器的功能. 设A=an-1an-2-a0, B=bn-1bn-2-b0,是要相加的两个无符号数,相加的和为:sum=sn-1s ...

  2. Verilog 加法器和减法器(4)

    类似于行波进位加法器,用串联的方法也能够实现多位二进制数的减法操作.  比如下图是4位二进制减法逻辑电路图. 8位二进制减法的verilog代码如下: module subn(x, y, d,cin) ...

  3. Verilog 加法器和减法器(6)

    为了减小行波进位加法器中进位传播延迟的影响,可以尝试在每一级中快速计算进位,如果能在较短时间完成计算,则可以提高加法器性能. 我们可以进行如下的推导: 设 gi=xi&yi, pi = xi ...

  4. Verilog 加法器和减法器(3)

    手工加法运算时候,我们都是从最低位的数字开始,逐位相加,直到最高位.如果第i位产生进位,就把该位作为第i+1位输入.同样的,在逻辑电路中,我们可以把一位全加器串联起来,实现多位加法,比如下面的四位加法 ...

  5. Verilog 加法器和减法器(2)

    类似半加器和全加器,也有半减器和全减器. 半减器只考虑当前两位二进制数相减,输出为差以及是否向高位借位,而全减器还要考虑当前位的低位是否曾有借位.它们的真值表如下: 对半减器,diff = x ^y, ...

  6. Verilog 加法器和减法器(1)

    两个一位的二进制数x,y相加,假设和为s,进位为cout,其真值表为: 从真值表中,我们可以得到:s = x^y, cout = x&y,实现两个一位数相加的逻辑电路称为半加器. 实现该电路的 ...

  7. Verilog 加法器和减法器(5)

    前面二进制加法运算,我们并没有提操作数是有符号数,还是无符号数.其实前面的二进制加法对于有符号数和无符号数都成立.比如前面的8位二进制加法运算,第一张图我们选radix是unsigned,表示无符号加 ...

  8. 基于Xilinx的Synthesize

    所谓综合.就是讲HDL语言.原理图等设计输入翻译成由与.或.非们和RAM.触发器登记本逻辑单元的逻辑连接(即网表).并依据目标和要求(约束条件)优化生成的逻辑连接. ISE-XST XST是Xilin ...

  9. FPGA综合工具--Synplify Pro的常用选项及命令

    最近要用到Synplify,但以前没使用过,无基础,找到一篇帖子,隧保存下来. 本文转自:http://blog.sina.com.cn/s/blog_65fe490d0100v8ax.html Sy ...

随机推荐

  1. 转载-解决ORACLE 在控制台进行exp,导出时,空表不能导出

    一.问题原因: 11G中有个新特性,当表无数据时,不分配segment,以节省空间 1.insert一行,再rollback就产生segment了. 该方法是在在空表中插入数据,再删除,则产生segm ...

  2. Cause: java.sql.SQLException: Could not retrieve transation read-only status server

    背景 最近在部署一套完整的项目,部署过程中遇到很多的问题,在来总结一些如标题的这个错误! 环境说明: 使用分布式数据库,使用的是mysql! ### Cause: java.sql.SQLExcept ...

  3. JedisConnectionException: java.net.ConnectException: Connection refused

    出现问题 我遇到的一个问题,在连接redis的时候出现了错误!错误如下: JedisConnectionException: java.net.ConnectException: Connection ...

  4. Python异常处理回顾与总结

    1 引言 在我们调试程序时,经常不可避免地出现意料之外的情况,导致程序不得不停止运行,然后提示大堆提示信息,大多是这种情况都是由异常引起的.异常的出现一方面是因为写代码时粗心导致的语法错误,这种错误在 ...

  5. 8.9 正睿暑期集训营 Day6

    目录 2018.8.9 正睿暑期集训营 Day6 A 萌新拆塔(状压DP) B 奇迹暖暖 C 风花雪月(DP) 考试代码 A B C 2018.8.9 正睿暑期集训营 Day6 时间:2.5h(实际) ...

  6. 简表-Java-Echart报表介绍

    Java后台报表尝试了很多,最终发现了一款,而且是开源的,简表地址:http://www.jatools.com/jor/.问题的引入:该报表支持嵌套,钻去,应对excel类似的报表,足够了.但是,报 ...

  7. Azure存储上传下载(断点续传)

    最近有一个客户需要将文件系统(VM搭建)迁移到Azure存储上,对于Azure存储这里就不多做介绍,但是该客户由于网络原因下载文件的时候经常出现上传中断,所以想在Azure 存储上实现下载的断点续传. ...

  8. Chrome中使用老的标题栏界面

    Chrome 69中启用了新的UI界面,看着更加秀气了. 但新UI一个不好用的地方是标签栏太高了,留给windows标题栏的空白太小,导致拖动窗口位置非常不方便,如下是一个解决方法: 在地址栏输入: ...

  9. the difference between an embOS interrupt and a zero latency interrupt

    the difference between an embOS interrupt and a zero latency interrupt is the interrupt priority lev ...

  10. bitnami下webmin安装

    下载 我在官方网站下载最新的安装包(webmin_1.670_all.deb):http://sourceforge.net/projects/webadmin/files/webmin  安装 单独 ...