diff options
Diffstat (limited to 'rtl/fpu/float/fp_cvt.sv')
| -rw-r--r-- | rtl/fpu/float/fp_cvt.sv | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/rtl/fpu/float/fp_cvt.sv b/rtl/fpu/float/fp_cvt.sv new file mode 100644 index 0000000..46efc1f --- /dev/null +++ b/rtl/fpu/float/fp_cvt.sv @@ -0,0 +1,286 @@ +import lzc_wire::*; +import fp_wire::*; + +module fp_cvt ( + input fp_cvt_f2f_in_type fp_cvt_f2f_i, + output fp_cvt_f2f_out_type fp_cvt_f2f_o, + input fp_cvt_f2i_in_type fp_cvt_f2i_i, + output fp_cvt_f2i_out_type fp_cvt_f2i_o, + input fp_cvt_i2f_in_type fp_cvt_i2f_i, + output fp_cvt_i2f_out_type fp_cvt_i2f_o, + input lzc_64_out_type lzc_o, + output lzc_64_in_type lzc_i +); + + fp_cvt_f2f_var_type v_f2f; + fp_cvt_f2i_var_type v_f2i; + fp_cvt_i2f_var_type v_i2f; + + always_comb begin + + v_f2f.data = fp_cvt_f2f_i.data; + v_f2f.fmt = fp_cvt_f2f_i.fmt; + v_f2f.rm = fp_cvt_f2f_i.rm; + v_f2f.classification = fp_cvt_f2f_i.classification; + + v_f2f.snan = v_f2f.classification[8]; + v_f2f.qnan = v_f2f.classification[9]; + v_f2f.dbz = 0; + v_f2f.infs = v_f2f.classification[0] | v_f2f.classification[7]; + v_f2f.zero = v_f2f.classification[3] | v_f2f.classification[4]; + + v_f2f.exponent_cvt = v_f2f.data[63:52]; + v_f2f.mantissa_cvt = {2'h1, v_f2f.data[51:0], 26'h0}; + + v_f2f.exponent_bias = 1920; + if (v_f2f.fmt == 1) begin + v_f2f.exponent_bias = 1024; + end + + v_f2f.sign_rnd = v_f2f.data[64]; + v_f2f.exponent_rnd = {2'h0, v_f2f.exponent_cvt} - {3'h0, v_f2f.exponent_bias}; + + v_f2f.counter_cvt = 0; + if ($signed(v_f2f.exponent_rnd) <= 0) begin + v_f2f.counter_cvt = 63; + if ($signed(v_f2f.exponent_rnd) > -63) begin + v_f2f.counter_cvt = 14'h1 - v_f2f.exponent_rnd; + end + v_f2f.exponent_rnd = 0; + end + + v_f2f.mantissa_cvt = v_f2f.mantissa_cvt >> v_f2f.counter_cvt[5:0]; + + v_f2f.mantissa_rnd = {29'h0, v_f2f.mantissa_cvt[79:55]}; + v_f2f.grs = {v_f2f.mantissa_cvt[54:53], |v_f2f.mantissa_cvt[52:0]}; + if (v_f2f.fmt == 1) begin + v_f2f.mantissa_rnd = v_f2f.mantissa_cvt[79:26]; + v_f2f.grs = {v_f2f.mantissa_cvt[25:24], |v_f2f.mantissa_cvt[23:0]}; + end + + fp_cvt_f2f_o.fp_rnd.sig = v_f2f.sign_rnd; + fp_cvt_f2f_o.fp_rnd.expo = v_f2f.exponent_rnd; + fp_cvt_f2f_o.fp_rnd.mant = v_f2f.mantissa_rnd; + fp_cvt_f2f_o.fp_rnd.rema = 2'h0; + fp_cvt_f2f_o.fp_rnd.fmt = v_f2f.fmt; + fp_cvt_f2f_o.fp_rnd.rm = v_f2f.rm; + fp_cvt_f2f_o.fp_rnd.grs = v_f2f.grs; + fp_cvt_f2f_o.fp_rnd.snan = v_f2f.snan; + fp_cvt_f2f_o.fp_rnd.qnan = v_f2f.qnan; + fp_cvt_f2f_o.fp_rnd.dbz = v_f2f.dbz; + fp_cvt_f2f_o.fp_rnd.infs = v_f2f.infs; + fp_cvt_f2f_o.fp_rnd.zero = v_f2f.zero; + fp_cvt_f2f_o.fp_rnd.diff = 1'h0; + + end + + always_comb begin + + v_f2i.data = fp_cvt_f2i_i.data; + v_f2i.op = fp_cvt_f2i_i.op.fcvt_op; + v_f2i.rm = fp_cvt_f2i_i.rm; + v_f2i.classification = fp_cvt_f2i_i.classification; + + v_f2i.flags = 0; + v_f2i.result = 0; + + v_f2i.snan = v_f2i.classification[8]; + v_f2i.qnan = v_f2i.classification[9]; + v_f2i.infs = v_f2i.classification[0] | v_f2i.classification[7]; + v_f2i.zero = 0; + + if (v_f2i.op == 0) begin + v_f2i.exponent_bias = 34; + end else if (v_f2i.op == 1) begin + v_f2i.exponent_bias = 35; + end else if (v_f2i.op == 2) begin + v_f2i.exponent_bias = 66; + end else begin + v_f2i.exponent_bias = 67; + end + + v_f2i.sign_cvt = v_f2i.data[64]; + v_f2i.exponent_cvt = v_f2i.data[63:52] - 13'd2044; + v_f2i.mantissa_cvt = {68'h1, v_f2i.data[51:0]}; + + if ((v_f2i.classification[3] | v_f2i.classification[4]) == 1) begin + v_f2i.mantissa_cvt[52] = 0; + end + + v_f2i.oor = 0; + + if ($signed(v_f2i.exponent_cvt) > $signed({5'h0, v_f2i.exponent_bias})) begin + v_f2i.oor = 1; + end else if ($signed(v_f2i.exponent_cvt) > 0) begin + v_f2i.mantissa_cvt = v_f2i.mantissa_cvt << v_f2i.exponent_cvt; + end + + v_f2i.mantissa_uint = v_f2i.mantissa_cvt[119:55]; + + v_f2i.grs = {v_f2i.mantissa_cvt[54:53], |v_f2i.mantissa_cvt[52:0]}; + v_f2i.odd = v_f2i.mantissa_uint[0] | |v_f2i.grs[1:0]; + + v_f2i.flags[0] = |v_f2i.grs; + + v_f2i.rnded = 0; + if (v_f2i.rm == 0) begin //rne + if (v_f2i.grs[2] & v_f2i.odd) begin + v_f2i.rnded = 1; + end + end else if (v_f2i.rm == 2) begin //rdn + if (v_f2i.sign_cvt & v_f2i.flags[0]) begin + v_f2i.rnded = 1; + end + end else if (v_f2i.rm == 3) begin //rup + if (~v_f2i.sign_cvt & v_f2i.flags[0]) begin + v_f2i.rnded = 1; + end + end else if (v_f2i.rm == 4) begin //rmm + if (v_f2i.grs[2] & v_f2i.flags[0]) begin + v_f2i.rnded = 1; + end + end + + v_f2i.mantissa_uint = v_f2i.mantissa_uint + {64'h0, v_f2i.rnded}; + + v_f2i.or_1 = v_f2i.mantissa_uint[64]; + v_f2i.or_2 = v_f2i.mantissa_uint[63]; + v_f2i.or_3 = |v_f2i.mantissa_uint[62:32]; + v_f2i.or_4 = v_f2i.mantissa_uint[31]; + v_f2i.or_5 = |v_f2i.mantissa_uint[30:0]; + + v_f2i.zero = v_f2i.or_1 | v_f2i.or_2 | v_f2i.or_3 | v_f2i.or_4 | v_f2i.or_5; + + v_f2i.oor_64u = v_f2i.or_1; + v_f2i.oor_64s = v_f2i.or_1; + v_f2i.oor_32u = v_f2i.or_1 | v_f2i.or_2 | v_f2i.or_3; + v_f2i.oor_32s = v_f2i.or_1 | v_f2i.or_2 | v_f2i.or_3; + + if (v_f2i.sign_cvt) begin + if (v_f2i.op == 0) begin + v_f2i.oor_32s = v_f2i.oor_32s | (v_f2i.or_4 & v_f2i.or_5); + end else if (v_f2i.op == 1) begin + v_f2i.oor = v_f2i.oor | v_f2i.zero; + end else if (v_f2i.op == 2) begin + v_f2i.oor_64s = v_f2i.oor_64s | (v_f2i.or_2 & (v_f2i.or_3 | v_f2i.or_4 | v_f2i.or_5)); + end else if (v_f2i.op == 3) begin + v_f2i.oor = v_f2i.oor | v_f2i.zero; + end + end else begin + v_f2i.oor_64s = v_f2i.oor_64s | v_f2i.or_2; + v_f2i.oor_32s = v_f2i.oor_32s | v_f2i.or_4; + end + + v_f2i.oor_64u = (v_f2i.op == 3) & (v_f2i.oor_64u | v_f2i.oor | v_f2i.infs | v_f2i.snan | v_f2i.qnan); + v_f2i.oor_64s = (v_f2i.op == 2) & (v_f2i.oor_64s | v_f2i.oor | v_f2i.infs | v_f2i.snan | v_f2i.qnan); + v_f2i.oor_32u = (v_f2i.op == 1) & (v_f2i.oor_32u | v_f2i.oor | v_f2i.infs | v_f2i.snan | v_f2i.qnan); + v_f2i.oor_32s = (v_f2i.op == 0) & (v_f2i.oor_32s | v_f2i.oor | v_f2i.infs | v_f2i.snan | v_f2i.qnan); + + if (v_f2i.sign_cvt) begin + v_f2i.mantissa_uint = -v_f2i.mantissa_uint; + end + + if (v_f2i.op == 0) begin + v_f2i.result = {32'h0, v_f2i.mantissa_uint[31:0]}; + if (v_f2i.oor_32s) begin + v_f2i.result = 64'h0000000080000000; + v_f2i.flags = 5'b10000; + end + end else if (v_f2i.op == 1) begin + v_f2i.result = {32'h0, v_f2i.mantissa_uint[31:0]}; + if (v_f2i.oor_32u) begin + v_f2i.result = 64'h00000000FFFFFFFF; + v_f2i.flags = 5'b10000; + end + end else if (v_f2i.op == 2) begin + v_f2i.result = v_f2i.mantissa_uint[63:0]; + if (v_f2i.oor_64s) begin + v_f2i.result = 64'h8000000000000000; + v_f2i.flags = 5'b10000; + end + end else if (v_f2i.op == 3) begin + v_f2i.result = v_f2i.mantissa_uint[63:0]; + if (v_f2i.oor_64u) begin + v_f2i.result = 64'hFFFFFFFFFFFFFFFF; + v_f2i.flags = 5'b10000; + end + end + + fp_cvt_f2i_o.result = v_f2i.result; + fp_cvt_f2i_o.flags = v_f2i.flags; + + end + + always_comb begin + + v_i2f.data = fp_cvt_i2f_i.data; + v_i2f.op = fp_cvt_i2f_i.op.fcvt_op; + v_i2f.fmt = fp_cvt_i2f_i.fmt; + v_i2f.rm = fp_cvt_i2f_i.rm; + + v_i2f.snan = 0; + v_i2f.qnan = 0; + v_i2f.dbz = 0; + v_i2f.infs = 0; + v_i2f.zero = 0; + + v_i2f.exponent_bias = 127; + if (v_i2f.fmt == 1) begin + v_i2f.exponent_bias = 1023; + end + + v_i2f.sign_uint = 0; + if (v_i2f.op == 0) begin + v_i2f.sign_uint = v_i2f.data[31]; + end else if (v_i2f.op == 2) begin + v_i2f.sign_uint = v_i2f.data[63]; + end + + if (v_i2f.sign_uint) begin + v_i2f.data = -v_i2f.data; + end + + v_i2f.mantissa_uint = 64'hFFFFFFFFFFFFFFFF; + v_i2f.exponent_uint = 0; + if (!v_i2f.op[1]) begin + v_i2f.mantissa_uint = {v_i2f.data[31:0], 32'h0}; + v_i2f.exponent_uint = 31; + end else if (v_i2f.op[1]) begin + v_i2f.mantissa_uint = v_i2f.data[63:0]; + v_i2f.exponent_uint = 63; + end + + v_i2f.zero = ~|v_i2f.mantissa_uint; + + lzc_i.a = v_i2f.mantissa_uint; + v_i2f.counter_uint = ~lzc_o.c; + + v_i2f.mantissa_uint = v_i2f.mantissa_uint << v_i2f.counter_uint; + + v_i2f.sign_rnd = v_i2f.sign_uint; + v_i2f.exponent_rnd = {8'h0,v_i2f.exponent_uint} + {4'h0,v_i2f.exponent_bias} - {8'h0,v_i2f.counter_uint}; + + v_i2f.mantissa_rnd = {30'h0, v_i2f.mantissa_uint[63:40]}; + v_i2f.grs = {v_i2f.mantissa_uint[39:38], |v_i2f.mantissa_uint[37:0]}; + if (v_i2f.fmt == 1) begin + v_i2f.mantissa_rnd = {1'h0, v_i2f.mantissa_uint[63:11]}; + v_i2f.grs = {v_i2f.mantissa_uint[10:9], |v_i2f.mantissa_uint[8:0]}; + end + + fp_cvt_i2f_o.fp_rnd.sig = v_i2f.sign_rnd; + fp_cvt_i2f_o.fp_rnd.expo = v_i2f.exponent_rnd; + fp_cvt_i2f_o.fp_rnd.mant = v_i2f.mantissa_rnd; + fp_cvt_i2f_o.fp_rnd.rema = 2'h0; + fp_cvt_i2f_o.fp_rnd.fmt = v_i2f.fmt; + fp_cvt_i2f_o.fp_rnd.rm = v_i2f.rm; + fp_cvt_i2f_o.fp_rnd.grs = v_i2f.grs; + fp_cvt_i2f_o.fp_rnd.snan = v_i2f.snan; + fp_cvt_i2f_o.fp_rnd.qnan = v_i2f.qnan; + fp_cvt_i2f_o.fp_rnd.dbz = v_i2f.dbz; + fp_cvt_i2f_o.fp_rnd.infs = v_i2f.infs; + fp_cvt_i2f_o.fp_rnd.zero = v_i2f.zero; + fp_cvt_i2f_o.fp_rnd.diff = 1'h0; + + end + +endmodule |
