浮点数表示
以32位浮点数标准为例
S:数符,0为正1为负。
阶码e:8位,阶码=阶码真值+127。阶码采用移码来表示,即阶码真值=e-127。
尾数m:23位,采用隐含尾数最高位1的表示方法,实际尾数为24位,尾数真值=1+尾数。
这种格式的非0浮点数真值为:
浮点数除法运算原理
1、符号位的处理
符号相同则商为正,符号不同则商为负。可以直接使用异或。
计算方法仍然是符号位的异或运算:result_sign = sign_a ^ sign_b。
2、指数的相减
除法的指数部分由被除数的指数减去除数的指数,再加上偏移量(Bias)。
计算公式:exp_tmp = exp_a - exp_b + bias;
这里偏移量固定为127。如果此时考虑到尾数除法结果,已知规格化浮点数尾数代表的1.xxx(大于1小于2)这样两个数据相除其结果,如果被除数尾数大于除数尾数,结果必定大于1,是规格化的。如果被除数尾数小于除数尾数,结果必定小于1。是非规格话的,所以此时,可以直接根据大小选择不同的偏置量加减。
3、尾数的相除
被除数的尾数除以除数的尾数,计算商的尾数。
计算公式mr=ma/mb。
对于单精度浮点数,尾数共计23位,加上隐藏位的1,共计24位尾数。其形式为
常规除法计算
如何计算二进制小数的除法
可以将二进制小数放大,将被除数放大更多的倍数获取结果的精确位数。
牛顿迭代法计算
也可以使用牛顿迭代法进行迭代运算,通过提前计算1/B近似值,使用除数的尾数的高位来进行选择近似值。
通过近似值使用牛顿迭代公式计算出1/B的精确值。
再通过乘法运算
A*(1/B)
计算出A/B的结果。
4、规格化舍入和溢出
规格化过程确保结果的尾数在标准范围内。如果除法结果尾数的最高有效位小于1,则需要对尾数进行左移,同时减少指数。
尾数进行适当的舍入。
检查是否发生指数溢出或下溢,并根据需要处理。
5、最终的结果
最终的符号、指数和尾数经过处理后重新组合成一个符合IEEE 754标准的浮点数,并返回这个结果。
浮点数除法verilog仅仿真代码
使用常规除法计算。
// *********************************************************************************/
// Project Name :
// Author : i_huyi
// Email : i_huyi@qq.com
// Creat Time : 2025/3/24 16:15:19
// File Name : .v
// Module Name :
// Called By :
// Abstract :
//
// CopyRight(c) 2020, xxx xxx xxx Co., Ltd..
// All Rights Reserved
//
// *********************************************************************************/
// Modification History:
// 1. initial
// *********************************************************************************/
// *************************
// MODULE DEFINITION
// *************************
`timescale 1 ns / 1 ps
module float_div#(
parameter U_DLY = 1)(
input [31:0] a , // (input )
input [31:0] b , // (input )
output [31:0] result , // (output)
output reg invalid , // (output)
output reg div_by_zero // (output));
//----------------------------------------------
// localparam
//----------------------------------------------//----------------------------------------------
// register
//----------------------------------------------
// 正常数值计算
reg [7:0] final_exp ;
reg [22:0] final_frac ;
reg [47:0] frac_calculation ; // 48位中间结果
reg [7:0] exp_tmp ;
reg [23:0] ma ;
reg [23:0] mb ; //----------------------------------------------
// wire
//----------------------------------------------
// 浮点结构解析
wire sign_a ;
wire [7:0] exp_a ;
wire [22:0] frac_a ; wire sign_b ;
wire [7:0] exp_b ;
wire [22:0] frac_b ;
// 特殊值标志
wire a_zero ;
wire b_zero ;
wire a_inf ;
wire b_inf ;
wire a_nan ;
wire b_nan ;
wire alb ; // 符号计算
wire result_sign ; //----------------------------------------------
// assign
//----------------------------------------------
// 浮点结构解析
assign sign_a = a[31] ;
assign exp_a = a[30:23] ;
assign frac_a = a[22:0] ;
assign sign_b = b[31] ;
assign exp_b = b[30:23] ;
assign frac_b = b[22:0] ;
// 特殊值标志
assign a_zero = (exp_a == 0) && (frac_a == 0) ;
assign b_zero = (exp_b == 0) && (frac_b == 0) ;
assign a_inf = (exp_a == 8'hFF) && (frac_a == 0);
assign b_inf = (exp_b == 8'hFF) && (frac_b == 0);
assign a_nan = (exp_a == 8'hFF) && (frac_a != 0);
assign b_nan = (exp_b == 8'hFF) && (frac_b != 0);
assign alb = (frac_a<frac_b) ? 1'b1 : 1'b0 ;
// 符号计算
assign result_sign = sign_a ^ sign_b;assign result = {result_sign, final_exp, final_frac};
//------------------------------------------------------------
//------------------------------------------------------------
// 异常处理逻辑
always @(*) begindiv_by_zero = ( b_zero && !a_zero && !a_nan);invalid = (a_nan || b_nan) || (a_inf && b_inf) || (a_zero && b_zero);
end
//------------------------------------------------------------
//------------------------------------------------------------
always @(*) beginif (invalid || div_by_zero) beginfinal_exp = 8'hFF; // NaN或Inf标志final_frac = a_nan ? {1'b1, frac_a[21:0]} : (b_nan ? {1'b1, frac_b[21:0]} : 0);endelse if (a_inf || b_zero) beginfinal_exp = 8'hFF; // 无穷大final_frac = 0;endelse if (a_zero || b_inf) begin final_exp = 0; // 零final_frac = 0;endelse begin// 指数计算(带偏置调整)if(alb == 1'b1)exp_tmp = exp_a - exp_b + 126;elseexp_tmp = exp_a - exp_b + 127;// 尾数处理(添加隐含位)ma = {1'b1, frac_a};mb = {1'b1, frac_b};// 尾数除法(定点数扩展)frac_calculation = (ma << 24) / mb; //Q24.24格式// 规格化处理// 1.0 ≤ 结果 <2.0if(frac_calculation[24]==1'b1)beginif(frac_calculation[0]==1'b1)final_frac = frac_calculation[23:1] + 1'b1;elsefinal_frac = frac_calculation[23:1];endelse beginfinal_frac = frac_calculation[22:0];end// 指数溢出处理if (exp_tmp > 254) begin final_exp = 8'hFF;final_frac = 0;endelse if (exp_tmp < 1) begin final_exp = 0;final_frac = 0;endelse beginfinal_exp = exp_tmp[7:0];endend
end//------------------------------------------------------------
//------------------------------------------------------------
endmodule
仿真tb
// 测试平台
module tb;reg [31:0] a, b;wire [31:0] result;wire invalid, div_by_zero;float_div u_float_div (.a (a ), // (input ).b (b ), // (input ).result (result ), // (output).invalid (invalid ), // (output).div_by_zero (div_by_zero ) // (output)
);initial begin// 正常除法 1.5 / 1.25 = 1.2a = 32'h3FC00000; // 1.5b = 32'h3FA00000; // 1.25#10;a = 32'h3FA00000; // 1.5b = 32'h3FC00000; // 1.25#10;a = 32'h437F8000; // 255.5b = 32'h40C80000; // 6.25#10;a = 32'hC299E76D; //-76.952b = 32'h4300999A; //128.6#10;a = 32'h3A210244; //0.0006142b = 32'hBE009D49; //-0.1256#10;$finish;end
endmodule
仿真结果