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

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

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

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

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

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

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

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

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

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

下面是verilog代码:

module floatadd(clk, rst_n, x, y, z,overflow);

   input clk;
input rst_n;
input [31:0] x;
input [31:0] y;
output [31:0] z;
output [1:0] overflow;//0,没有溢出,1,上溢,10,下溢,11 输入不是规格化数 reg [31:0] z; // z=x+y
reg[24:0] xm, ym, zm; //尾数部分, 0+ 1+[22:0],
reg[7:0] xe, ye, ze; //阶码部分
reg[2:0] state, nextstate; //状态机
reg zsign; //z的符号位
reg [1:0] overflow; parameter start=3'b000,zerock=3'b001,exequal=3'b010,addm=3'b011,infifl=3'b100,over =3'b110; always @(posedge clk) begin
if(!rst_n)
state <= start;
else
state <= nextstate;
end //状态机进行浮点加法处理
always@(state,nextstate,xe,ye,xm,ym,ze,zm) begin
case(state)
start: //初始化,分离尾数和指数,调整符号位
begin
xe <= x[30:23];
xm <= {1'b0,1'b1,x[22:0]};
ye <= y[30:23];
ym <= {1'b0,1'b1,y[22:0]}; //判断是否溢出,大于最大浮点数,小于最小浮点数
if((xe==8'd255)||(ye==8'd255)||((xe==8'd0)&&(xm[22:0]!=23'b0))||((ye==8'd0)&&(ym[22:0]!=23'b0)) )
begin
overflow <= 2'b11;
nextstate <= start; //直接到初始化
z <= 32'b1; //直接赋值最小非规约数,
end
else
nextstate <= zerock;
end
zerock://检测x,y如果有一个为0,则跳转到over state
begin
if((x[22:0]==23'b0)&&(xe==8'b0))
begin
{zsign, ze,zm} <= {y[31],ye, ym};
nextstate <= over;
end
else
begin
if((y[22:0]==23'b0)&&(ye==8'b0))
begin
{zsign,ze,zm} <= {x[31],xe, xm};
nextstate <= over;
end
else
nextstate <= exequal;
end
end
exequal:
begin
if(xe == ye)
nextstate <= addm;
else
begin
if(xe > ye)
begin
ye <= ye + 1'b1;//阶码加1
ym[23:0] <= {1'b0, ym[23:1]};
if(ym==8'b0)
begin
zm <= xm;
ze <= xe;
zsign<=x[31];
nextstate <= over;
end
else
nextstate <= exequal; end
else
begin
xe <= xe + 1'b1;//阶码加1
xm[23:0] <= {1'b0, xm[23:1]};
if(xm==8'b0)
begin
zm <= ym;
ze <= ye;
zsign <= y[31];
nextstate <= over;
end
else
nextstate <= exequal;
end
end end
addm://尾数相加
begin
ze <= xe; if((x[31]^y[31])==1'b0) //同符号
begin
zsign = x[31];
zm <= xm + ym;
end
else
begin
if(xm>ym)
begin
zsign = x[31];
zm <= xm - ym;
end
else
begin
zsign = y[31];
zm <= ym - xm;
end end if(zm[23:0]==24'b0)
nextstate <= over;
else
nextstate <=infifl;
end
infifl://规格化处理
begin
if(zm[24]==1'b1)//有进位,或借位
begin
zm <= {1'b0,zm[24:1]};
ze <= ze + 1'b1;
nextstate <= over;
end
else
begin
if(zm[23]==1'b0)
begin
zm <= {zm[23:0],1'b0};
ze <= ze - 1'b1;
nextstate <= infifl;
end
else
begin
nextstate <= over;
end
end
end
over:
begin
z <= {zsign, ze[7:0], zm[22:0]};
//判断是否溢出,大于最大浮点数,小于最小浮点数
if(ze==8'd255 )
begin
overflow <= 2'b01;
end
else if((ze==8'd0)&&(zm[22:0]!=23'b0)) //不处理非规约数
begin
overflow <= 2'b10;
end
else
overflow <= 2'b00;
nextstate <= start;
end
default:
begin
nextstate <= start;
end
endcase end endmodule

下面是testbench代码:

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

`timescale 1ns/1ns
`define clock_period 20 module floatadd_tb;
reg [31:0] x,y; wire [31:0] z; reg clk;
reg rst_n;
wire [1:0] overflow; floatadd floatadd_0(
.clk(clk),
.rst_n(rst_n),
.x(x),
.y(y),
.add(add),
.z(z),
.overflow(overflow)
); initial clk = 0;
always #(`clock_period/2) clk = ~clk; initial begin
x = 0;
rst_n = 1'b0;
#20 rst_n = 1'b1;
#(`clock_period) x = 32'b01000000011011101001011110001101; //3.456
#(`clock_period*7) x = 32'hc2b5999a; //-90.8 end initial begin
y = 0;
#20
#(`clock_period) y = 32'b01000000010011001100110011001101;//2.4
#(`clock_period*7) y = 32'h41a3c28f;//20.47 end initial begin
#(`clock_period*100)
$stop;
end endmodule

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

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

module floataddsub(clk, rst_n, x, y, add, z,overflow);

   input clk;
input rst_n;
input [31:0] x;
input [31:0] y;
input add;
output [31:0] z;
output [1:0] overflow;
wire [31:0] y1; floatadd floatadd_0(
.clk(clk),
.rst_n(rst_n),
.x(x),
.y(y1),
.z(z),
.overflow(overflow)
);
assign y1 = add ? y:{~y[31],y[30:0]};
endmodule

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

`timescale 1ns/1ns
`define clock_period 20 module floataddsub_tb;
reg [31:0] x,y;
reg add; wire [31:0] z; reg clk;
reg rst_n;
wire [1:0] overflow; floataddsub floataddsub_0(
.clk(clk),
.rst_n(rst_n),
.x(x),
.y(y),
.add(add),
.z(z),
.overflow(overflow)
); initial
begin
clk = 1'b0;
add = 1'b0;
#(`clock_period*9)
add = 1'b1;
end
always #(`clock_period/2) clk = ~clk; initial begin
x = 0;
rst_n = 1'b0;
#20 rst_n = 1'b1;
#(`clock_period) x = 32'b01000000011011101001011110001101; //3.456
#(`clock_period*7) x = 32'hc2b5999a; //-90.8 end initial begin
y = 0;
#20
#(`clock_period) y = 32'b01000000010011001100110011001101;//2.4
#(`clock_period*7) y = 32'h41a3c28f;//20.47 end initial begin
#(`clock_period*100)
$stop;
end 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. java中的stream的Map收集器操作

    package test9; import java.util.Collections; import java.util.HashSet; import java.util.Map; import ...

  2. CSDN博客栏目设置个性化

    韩梦飞沙  韩亚飞  313134555@qq.com  yue31313  han_meng_fei_sha ====== <a href=" http://weibo.com/23 ...

  3. CF815C Karen and Supermarket

    题目链接 CF815C Karen and Supermarket 题解 只要在最大化数量的前提下,最小化花费就好了 这个数量枚举ok, dp[i][j][1/0]表示节点i的子树中买了j件商品 i ...

  4. luoguP4643 阿狸和桃子的挑战 思维

    看下数据范围: \(n \leq 14\),emmmm,状压\(dp\)的分 \(n \leq 10000, m \leq 100000\),emmmm.....???,这是什么数据范围? 再观察一下 ...

  5. HDU 4122 Alice's mooncake shop (RMQ)

    Alice's mooncake shop Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Ot ...

  6. 通过webbrowser控件获取验证码

    1.首先介绍下基本控件(拖控件大家都会,我就不一一介绍了),看下图: 2.添加MSHTML引用,步骤如下: 解决方案—右键“引用”—​添加引用—在.NET下找到Microsoft.mshtml组件—点 ...

  7. UVA 303 Pipe

    点击打开链接 题意: 求光线能达到的最大横坐标 注意光线可以和管道重合 也可以经过转折点 解法: 枚举每种光线是否能通过每个转折点的截面(线段)即可 //大白p263 #include <cma ...

  8. Java 中 byte、byte 数组和 int、long 之间的转换

    Java 中 byte 和 int 之间的转换源码: //byte 与 int 的相互转换 public static byte intToByte(int x) { return (byte) x; ...

  9. 《大话设计模式》C#/C++版pdf/源码下载

    大话设计模式(带目录完整版)[中文PDF+源代码].zip 下载地址:http://pan.baidu.com/s/1giQP4大话设计模式C++.pdf下载地址:http://pan.baidu.c ...

  10. In-Place upgrade to Team Foundation Server (TFS) 2015 from TFS 2013Team Foundation Server TFS TFS 2015 TFS upgrade TFS with Sharepoint

    This upgrade document gives detailed step by step procedure for the In-Place upgrade from TFS 2013 t ...