32 位浮点数据格式: A = (- 1) S ×M ×2E-127。其中乘法器运算操作分4步进行。
浮点数据格式如下:
S:符号位?1Bit
Exp:阶码位? 7Bits
Sig:尾码位 24Bits
(1) 确定结果的符号, 对A 和B 的符号位做异或操作。?
(2) 计算阶码, 两数相乘, 结果的阶码是两数的阶码相加, 由于A 和B 都是偏移码, 因此需要从中减去偏移码值127,得到A 和B 的实际阶码, 然后相加, 得到的是结果的阶码, 再把他加上127, 变成偏移码。?
(3) 尾数相乘,A 和B 的实际尾数分别为24位数, 即1×Ma 和1×Mb, 最高位1是隐藏位, 浮点数据格式只显示后23位, 所以尾数相乘结果应为一个48位的数据。?
(4) 尾数规格化, 需要把尾数相乘的48位结果数据变成24 位的数据, 分3步进行:?
① 如果乘积的整数位为01, 则尾数已经是规格化了;如果乘积的整数位为10, 11, 则需要把尾数右移1位, 同时把结果阶码加1。?
② 对尾数进行舍入操作, 使尾数为24位, 包括整数的隐藏位。?
③ 把结果数据处理为32位符合IEEE浮点数标准的结果。包括1位符号位, 8位结果阶码位, 结果23尾数位。
说明:
1.在Verilog实现中实现加减127可以通过第8Bit位取反并低位加1实现
2.本文不对浮点乘法运算算法说明,只描述具体实现
浮点数符号位流程图:
浮点数阶码与尾码位流程图:
贴Chisel生成的Verilog代码:
module float_mul(
input clock,
input reset,
input [31:0] io_a,
input [31:0] io_b,
input io_in_en,
output [31:0] io_c,
output io_out_en
);
reg [8:0] a_exp_r; // @[float_mul.scala 19:26]
reg [31:0] _RAND_0;
reg [8:0] b_exp_r; // @[float_mul.scala 20:26]
reg [31:0] _RAND_1;
reg _T_3; // @[Reg.scala 15:16]
reg [31:0] _RAND_2;
reg _T_4; // @[Reg.scala 15:16]
reg [31:0] _RAND_3;
reg sign; // @[Reg.scala 15:16]
reg [31:0] _RAND_4;
reg [8:0] exp_r; // @[float_mul.scala 24:24]
reg [31:0] _RAND_5;
reg [49:0] r_fra_r; // @[float_mul.scala 25:26]
reg [63:0] _RAND_6;
reg [22:0] fra_r; // @[float_mul.scala 27:24]
reg [31:0] _RAND_7;
reg [7:0] exp; // @[float_mul.scala 28:24]
reg [31:0] _RAND_8;
reg [22:0] fra; // @[float_mul.scala 29:24]
reg [31:0] _RAND_9;
reg _T_5; // @[Reg.scala 15:16]
reg [31:0] _RAND_10;
reg _T_6; // @[Reg.scala 15:16]
reg [31:0] _RAND_11;
reg out_en_r; // @[Reg.scala 15:16]
reg [31:0] _RAND_12;
reg _T_7; // @[Reg.scala 15:16]
reg [31:0] _RAND_13;
wire _T_14; // @[float_mul.scala 40:29]
wire _T_16; // @[float_mul.scala 40:51]
reg zero_en; // @[Reg.scala 15:16]
reg [31:0] _RAND_14;
wire [8:0] _T_8; // @[Cat.scala 29:58]
wire yc; // @[float_mul.scala 38:25]
wire _T_19; // @[float_mul.scala 42:22]
wire [7:0] _T_21; // @[Cat.scala 29:58]
wire [7:0] a_exp; // @[float_mul.scala 42:45]
wire _T_25; // @[float_mul.scala 43:22]
wire [7:0] _T_27; // @[Cat.scala 29:58]
wire [7:0] b_exp; // @[float_mul.scala 43:45]
wire [23:0] a_fra; // @[Cat.scala 29:58]
wire [23:0] b_fra; // @[Cat.scala 29:58]
wire [49:0] r_fra_w; // @[float_mul.scala 48:28]
wire _T_37; // @[float_mul.scala 53:22]
wire _T_39; // @[float_mul.scala 58:28]
wire [7:0] _T_41; // @[Cat.scala 29:58]
wire [8:0] _T_47; // @[float_mul.scala 71:37]
wire [1:0] _T_49; // @[float_mul.scala 71:71]
wire [8:0] _GEN_17; // @[float_mul.scala 71:54]
wire [8:0] _T_52; // @[float_mul.scala 71:54]
wire [8:0] _T_55; // @[float_mul.scala 71:78]
wire [47:0] _T_57; // @[float_mul.scala 73:34]
wire [8:0] _T_59; // @[Cat.scala 29:58]
wire [8:0] _T_61; // @[Cat.scala 29:58]
wire [47:0] _GEN_14; // @[float_mul.scala 62:27]
assign _T_14 = io_a[30:0] == 31'h0; // @[float_mul.scala 40:29]
assign _T_16 = io_b[30:0] == 31'h0; // @[float_mul.scala 40:51]
assign _T_8 = {sign,exp}; // @[Cat.scala 29:58]
assign yc = exp_r[8] != exp_r[7]; // @[float_mul.scala 38:25]
assign _T_19 = ~io_a[30]; // @[float_mul.scala 42:22]
assign _T_21 = {_T_19,io_a[29:23]}; // @[Cat.scala 29:58]
assign a_exp = _T_21 + 8'h1; // @[float_mul.scala 42:45]
assign _T_25 = ~io_b[30]; // @[float_mul.scala 43:22]
assign _T_27 = {_T_25,io_b[29:23]}; // @[Cat.scala 29:58]
assign b_exp = _T_27 + 8'h1; // @[float_mul.scala 43:45]
assign a_fra = {1'h1,io_a[22:0]}; // @[Cat.scala 29:58]
assign b_fra = {1'h1,io_b[22:0]}; // @[Cat.scala 29:58]
assign r_fra_w = r_fra_r >> r_fra_r[47]; // @[float_mul.scala 48:28]
assign _T_37 = yc | zero_en; // @[float_mul.scala 53:22]
assign _T_39 = ~exp_r[7]; // @[float_mul.scala 58:28]
assign _T_41 = {_T_39,exp_r[6:0]}; // @[Cat.scala 29:58]
assign _T_47 = $signed(a_exp_r) + $signed(b_exp_r); // @[float_mul.scala 71:37]
assign _T_49 = r_fra_r[48:47]; // @[float_mul.scala 71:71]
assign _GEN_17 = {{7{_T_49[1]}},_T_49}; // @[float_mul.scala 71:54]
assign _T_52 = $signed(_T_47) + $signed(_GEN_17); // @[float_mul.scala 71:54]
assign _T_55 = $signed(_T_52) - 9'sh1; // @[float_mul.scala 71:78]
assign _T_57 = a_fra * b_fra; // @[float_mul.scala 73:34]
assign _T_59 = {a_exp[7],a_exp}; // @[Cat.scala 29:58]
assign _T_61 = {b_exp[7],b_exp}; // @[Cat.scala 29:58]
assign _GEN_14 = reset ? 48'h0 : _T_57; // @[float_mul.scala 62:27]
assign io_c = {_T_8,fra}; // @[float_mul.scala 36:14]
assign io_out_en = out_en_r; // @[float_mul.scala 35:19]
`ifdef RANDOMIZE_GARBAGE_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_INVALID_ASSIGN
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_REG_INIT
`define RANDOMIZE
`endif
`ifdef RANDOMIZE_MEM_INIT
`define RANDOMIZE
`endif
`ifndef RANDOM
`define RANDOM $random
`endif
`ifdef RANDOMIZE_MEM_INIT
integer initvar;
`endif
`ifndef SYNTHESIS
initial begin
`ifdef RANDOMIZE
`ifdef INIT_RANDOM
`INIT_RANDOM
`endif
`ifndef VERILATOR
`ifdef RANDOMIZE_DELAY
#`RANDOMIZE_DELAY begin end
`else
#0.002 begin end
`endif
`endif
`ifdef RANDOMIZE_REG_INIT
_RAND_0 = {1{`RANDOM}};
a_exp_r = _RAND_0[8:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_1 = {1{`RANDOM}};
b_exp_r = _RAND_1[8:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_2 = {1{`RANDOM}};
_T_3 = _RAND_2[0:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_3 = {1{`RANDOM}};
_T_4 = _RAND_3[0:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_4 = {1{`RANDOM}};
sign = _RAND_4[0:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_5 = {1{`RANDOM}};
exp_r = _RAND_5[8:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_6 = {2{`RANDOM}};
r_fra_r = _RAND_6[49:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_7 = {1{`RANDOM}};
fra_r = _RAND_7[22:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_8 = {1{`RANDOM}};
exp = _RAND_8[7:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_9 = {1{`RANDOM}};
fra = _RAND_9[22:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_10 = {1{`RANDOM}};
_T_5 = _RAND_10[0:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_11 = {1{`RANDOM}};
_T_6 = _RAND_11[0:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_12 = {1{`RANDOM}};
out_en_r = _RAND_12[0:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_13 = {1{`RANDOM}};
_T_7 = _RAND_13[0:0];
`endif // RANDOMIZE_REG_INIT
`ifdef RANDOMIZE_REG_INIT
_RAND_14 = {1{`RANDOM}};
zero_en = _RAND_14[0:0];
`endif // RANDOMIZE_REG_INIT
`endif // RANDOMIZE
end // initial
`endif // SYNTHESIS
always @(posedge clock) begin
if (reset) begin
a_exp_r <= 9'h0;
end else begin
a_exp_r <= _T_59;
end
if (reset) begin
b_exp_r <= 9'h0;
end else begin
b_exp_r <= _T_61;
end
_T_3 <= io_a[31] != io_b[31];
_T_4 <= _T_3;
sign <= _T_4;
if (reset) begin
exp_r <= 9'sh0;
end else begin
exp_r <= _T_55;
end
r_fra_r <= {{2'd0}, _GEN_14};
if (reset) begin
fra_r <= 23'h0;
end else begin
fra_r <= r_fra_w[45:23];
end
if (reset) begin
exp <= 8'h0;
end else if (_T_37) begin
exp <= 8'h0;
end else begin
exp <= _T_41;
end
if (reset) begin
fra <= 23'h0;
end else if (_T_37) begin
fra <= 23'h0;
end else begin
fra <= fra_r;
end
_T_5 <= io_in_en;
_T_6 <= _T_5;
out_en_r <= _T_6;
_T_7 <= _T_14 | _T_16;
zero_en <= _T_7;
end
endmodule