Verilog编写浮点乘法器

2024-01-07 17:22:57

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

文章来源:https://blog.csdn.net/qq_33704023/article/details/135423026
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。