// // The rounder takes as inputs a 64-bit value to be rounded, A, the // exponent of the value to be rounded, the sign of the final result, Sign, // the precision of the results, P, and the two-bit rounding mode, rm. // It produces a rounded 52-bit result, Z, the exponent of the rounded // result, Z_exp, and a flag that indicates if the result was rounded, // Inexact. The rounding mode has the following values. // rm Modee // 00 round-to-nearest-even // 01 round-toward-zero // 10 round-toward-plus infinity // 11 round-toward-minus infinity // module rounder_div (Result, DenormIO, Flags, rm, P, OvEn, UnEn, exp_diff, sel_inv, Invalid, DenormIn, SignR, q1, qm1, qp1, q0, qm0, qp0, regr_out); input [2:0] rm; input P; input OvEn; input UnEn; input [12:0] exp_diff; input [2:0] sel_inv; input Invalid; input DenormIn; input SignR; input [63:0] q1; input [63:0] qm1; input [63:0] qp1; input [63:0] q0; input [63:0] qm0; input [63:0] qp0; input [127:0] regr_out; output [63:0] Result; output DenormIO; output [4:0] Flags; supply1 vdd; supply0 vss; wire Rsign; wire [10:0] Rexp; wire [12:0] Texp; wire [51:0] Rmant; wire [63:0] Tmant; wire [51:0] Smant; wire Rzero; wire Gdp, Gsp, G; wire UnFlow_SP, UnFlow_DP, UnderFlow; wire OvFlow_SP, OvFlow_DP, OverFlow; wire Inexact; wire Round_zero; wire Infinite; wire VeryLarge; wire Largest; wire Div0; wire Adj_exp; wire Valid; wire NaN; wire Texp_l7z; wire Texp_l7o; wire OvCon; wire [1:0] mux_mant; wire sign_rem; wire [63:0] q, qm, qp; wire exp_ovf, exp_ovfSP, exp_ovfDP; logic zero_rem; // Remainder = 0? assign zero_rem = ~(|regr_out); // Remainder Sign assign sign_rem = ~regr_out[127]; // choose correct Guard bit [1,2) or [0,1) assign Gdp = q1[63] ? q1[10] : q0[10]; assign Gsp = q1[63] ? q1[39] : q0[39]; assign G = P ? Gsp : Gdp; // Selection of Rounding (from logic/switching) assign mux_mant[1] = (SignR&rm[1]&rm[0]&G) | (!SignR&rm[1]&!rm[0]&G) | (!rm[1]&!rm[0]&G&!sign_rem) | (SignR&rm[1]&rm[0]&!zero_rem&!sign_rem) | (!SignR&rm[1]&!rm[0]&!zero_rem&!sign_rem); assign mux_mant[0] = (!SignR&rm[0]&!G&!zero_rem&sign_rem) | (!rm[1]&rm[0]&!G&!zero_rem&sign_rem) | (SignR&rm[1]&!rm[0]&!G&!zero_rem&sign_rem); // Which Q? mux2 #(64) mx1 (q0, q1, q1[63], q); mux2 #(64) mx2 (qm0, qm1, q1[63], qm); mux2 #(64) mx3 (qp0, qp1, q1[63], qp); // Choose Q, Q+1, Q-1 mux3 #(64) mx4 (q, qm, qp, mux_mant, Tmant); assign Smant = Tmant[62:11]; // Compute the value of the exponent // exponent is modified if we choose: // 1.) we choose any qm0, qp0, q0 (since we shift mant) // 2.) we choose qp and we overflow (for RU) assign exp_ovf = |{qp[62:40], (qp[39:11] & {29{~P}})}; assign Texp = exp_diff - {{12{vss}}, ~q1[63]} + {{12{vss}}, mux_mant[1]&qp1[63]&~exp_ovf}; // KEP used to be 13{vss} // Overflow only occurs for double precision, if Texp[10] to Texp[0] are // all ones. To encourage sharing with single precision overflow detection, // the lower 7 bits are tested separately. assign Texp_l7o = Texp[6]&Texp[5]&Texp[4]&Texp[3]&Texp[2]&Texp[1]&Texp[0]; assign OvFlow_DP = (~Texp[12]&Texp[11]) | (Texp[10]&Texp[9]&Texp[8]&Texp[7]&Texp_l7o); // Overflow occurs for single precision if (Texp[10] is one) and // ((Texp[9] or Texp[8] or Texp[7]) is one) or (Texp[6] to Texp[0] // are all ones. assign OvFlow_SP = Texp[10]&(Texp[9]|Texp[8]|Texp[7]|Texp_l7o); // Underflow occurs for double precision if (Texp[11]/Texp[10] is one) or // Texp[10] to Texp[0] are all zeros. assign Texp_l7z = ~Texp[6]&~Texp[5]&~Texp[4]&~Texp[3]&~Texp[2]&~Texp[1]&~Texp[0]; assign UnFlow_DP = (Texp[12]&Texp[11]) | ~Texp[11]&~Texp[10]&~Texp[9]&~Texp[8]&~Texp[7]&Texp_l7z; // Underflow occurs for single precision if (Texp[10] is zero) and // (Texp[9] or Texp[8] or Texp[7]) is zero. assign UnFlow_SP = ~Texp[10]&(~Texp[9]|~Texp[8]|~Texp[7]|Texp_l7z); // Set the overflow and underflow flags. They should not be set if // the input was infinite or NaN or the output of the adder is zero. // 00 = Valid // 10 = NaN assign Valid = (~sel_inv[2]&~sel_inv[1]&~sel_inv[0]); assign NaN = ~sel_inv[1]& sel_inv[0]; assign UnderFlow = (P & UnFlow_SP | UnFlow_DP) & Valid; assign OverFlow = (P & OvFlow_SP | OvFlow_DP) & Valid; assign Div0 = sel_inv[2]&sel_inv[1]&~sel_inv[0]; // The DenormIO is set if underflow has occurred or if their was a // denormalized input. assign DenormIO = DenormIn | UnderFlow; // The final result is Inexact if any rounding occurred ((i.e., R or S // is one), or (if the result overflows ) or (if the result underflows and the // underflow trap is not enabled)) and (value of the result was not previous set // by an exception case). assign Inexact = (G|~zero_rem|OverFlow|(UnderFlow&~UnEn))&Valid; // Set the IEEE Exception Flags: Inexact, Underflow, Overflow, Div_By_0, // Invlalid. assign Flags = {Inexact, UnderFlow, OverFlow, Div0, Invalid}; // Determine sign assign Rzero = UnderFlow | (~sel_inv[2]&sel_inv[1]&sel_inv[0]); assign Rsign = SignR; // The exponent of the final result is zero if the final result is // zero or a denorm, all ones if the final result is NaN or Infinite // or overflow occurred and the magnitude of the number is // not rounded toward from zero, and all ones with an LSB of zero // if overflow occurred and the magnitude of the number is // rounded toward zero. If the result is single precision, // Texp[7] shoud be inverted. When the Overflow trap is enabled (OvEn = 1) // and overflow occurs and the operation is not conversion, bits 10 and 9 are // inverted for double precision, and bits 7 and 6 are inverted for single precision. assign Round_zero = ~rm[1]&rm[0] | ~SignR&rm[0] | SignR&rm[1]&~rm[0]; assign VeryLarge = OverFlow & ~OvEn; assign Infinite = (VeryLarge & ~Round_zero) | sel_inv[1]; assign Largest = VeryLarge & Round_zero; assign Adj_exp = OverFlow & OvEn; assign Rexp[10:1] = ({10{~Valid}} | {Texp[10]&~Adj_exp, Texp[9]&~Adj_exp, Texp[8], (Texp[7]^P)&~(Adj_exp&P), Texp[6]&~(Adj_exp&P), Texp[5:1]} | {10{VeryLarge}})&{10{~Rzero | NaN}}; assign Rexp[0] = ({~Valid} | Texp[0] | Infinite)&(~Rzero | NaN)&~Largest; // If the result is zero or infinity, the mantissa is all zeros. // If the result is NaN, the mantissa is 10...0 // If the result the largest floating point number, the mantissa // is all ones. Otherwise, the mantissa is not changed. assign Rmant[51] = Largest | NaN | (Smant[51]&~Infinite&~Rzero); assign Rmant[50:0] = {51{Largest}} | (Smant[50:0]&{51{~Infinite&Valid&~Rzero}}); // For single precision, the 8 least significant bits of the exponent // and 23 most significant bits of the mantissa contain bits used // for the final result. A double precision result is returned if // overflow has occurred, the overflow trap is enabled, and a conversion // is being performed. assign OvCon = OverFlow & OvEn; assign Result = (P&~OvCon) ? {Rsign, Rexp[7:0], Rmant[51:29], {32{vss}}} : {Rsign, Rexp, Rmant}; endmodule // rounder