Divsqrt cleanup: change Q to U, commenting code

This commit is contained in:
David Harris 2023-11-10 11:21:02 -08:00
parent 953c53d065
commit 255873a50c
10 changed files with 74 additions and 61 deletions

View File

@ -45,8 +45,8 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
input logic IntDivE, W64E, input logic IntDivE, W64E,
output logic DivStickyM, output logic DivStickyM,
output logic FDivBusyE, IFDivStartE, FDivDoneE, output logic FDivBusyE, IFDivStartE, FDivDoneE,
output logic [P.NE+1:0] QeM, output logic [P.NE+1:0] UeM, // Exponent result
output logic [P.DIVb:0] QmM, output logic [P.DIVb:0] UmM, // Significand result
output logic [P.XLEN-1:0] FIntDivResultM output logic [P.XLEN-1:0] FIntDivResultM
); );
@ -74,7 +74,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
fdivsqrtpreproc #(P) fdivsqrtpreproc( // Preprocessor fdivsqrtpreproc #(P) fdivsqrtpreproc( // Preprocessor
.clk, .IFDivStartE, .Xm(XmE), .Ym(YmE), .Xe(XeE), .Ye(YeE), .clk, .IFDivStartE, .Xm(XmE), .Ym(YmE), .Xe(XeE), .Ye(YeE),
.FmtE, .SqrtE, .XZeroE, .Funct3E, .QeM, .X, .D, .CyclesE, .FmtE, .SqrtE, .XZeroE, .Funct3E, .UeM, .X, .D, .CyclesE,
// Int-specific // Int-specific
.ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE, .ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE,
.BZeroM, .nM, .mM, .AM, .BZeroM, .nM, .mM, .AM,
@ -94,7 +94,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
fdivsqrtpostproc #(P) fdivsqrtpostproc( // Postprocessor fdivsqrtpostproc #(P) fdivsqrtpostproc( // Postprocessor
.clk, .reset, .StallM, .WS, .WC, .D, .FirstU, .FirstUM, .FirstC, .clk, .reset, .StallM, .WS, .WC, .D, .FirstU, .FirstUM, .FirstC,
.SqrtE, .Firstun, .SqrtM, .SpecialCaseM, .SqrtE, .Firstun, .SqrtM, .SpecialCaseM,
.QmM, .WZeroE, .DivStickyM, .UmM, .WZeroE, .DivStickyM,
// Int-specific // Int-specific
.nM, .mM, .ALTBM, .AsM, .BsM, .BZeroM, .W64M, .RemOpM(Funct3M[1]), .AM, .nM, .mM, .ALTBM, .AsM, .BsM, .BZeroM, .W64M, .RemOpM(Funct3M[1]), .AM,
.FIntDivResultM); .FIntDivResultM);

View File

@ -68,7 +68,7 @@ module fdivsqrtcycles import cvw::*; #(parameter cvw_t P) (
if (SqrtE) fbits = Nf + 2 + 1; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 *** unclear why it works with just +1; is it related to DIVCOPIES logic below? if (SqrtE) fbits = Nf + 2 + 1; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 *** unclear why it works with just +1; is it related to DIVCOPIES logic below?
// if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2 // if (SqrtE) fbits = Nf + 2 + 2; // Nf + two fractional bits for round/guard + 2 for right shift by up to 2
else fbits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs else fbits = Nf + 2 + P.LOGR; // Nf + two fractional bits for round/guard + integer bits - try this when placing results in msbs
if (P.IDIV_ON_FPU) CyclesE = IntDivE ? ((nE + 1)/P.DIVCOPIES) : (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES); if (P.IDIV_ON_FPU) CyclesE = IntDivE ? ((nE + 1)/P.DIVCOPIES) : (fbits -1)/(P.RK) + 1;
else CyclesE = (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES); else CyclesE = (fbits + (P.LOGR*P.DIVCOPIES)-1)/(P.LOGR*P.DIVCOPIES);
end end
/* verilator lint_on WIDTH */ /* verilator lint_on WIDTH */

View File

@ -32,8 +32,9 @@ module fdivsqrtexpcalc import cvw::*; #(parameter cvw_t P) (
input logic Sqrt, input logic Sqrt,
input logic XZero, input logic XZero,
input logic [P.DIVBLEN:0] ell, m, input logic [P.DIVBLEN:0] ell, m,
output logic [P.NE+1:0] Qe output logic [P.NE+1:0] Ue
); );
logic [P.NE-2:0] Bias; logic [P.NE-2:0] Bias;
logic [P.NE+1:0] SXExp; logic [P.NE+1:0] SXExp;
logic [P.NE+1:0] SExp; logic [P.NE+1:0] SExp;
@ -63,10 +64,14 @@ module fdivsqrtexpcalc import cvw::*; #(parameter cvw_t P) (
2'h2: Bias = (P.NE-1)'(P.H_BIAS); 2'h2: Bias = (P.NE-1)'(P.H_BIAS);
endcase endcase
end end
// Square root exponent = (Xe - l - bias) / 2 + bias; l accounts for subnorms
assign SXExp = {2'b0, Xe} - {{(P.NE+1-P.DIVBLEN){1'b0}}, ell} - (P.NE+2)'(P.BIAS); assign SXExp = {2'b0, Xe} - {{(P.NE+1-P.DIVBLEN){1'b0}}, ell} - (P.NE+2)'(P.BIAS);
assign SExp = {SXExp[P.NE+1], SXExp[P.NE+1:1]} + {2'b0, Bias}; assign SExp = {SXExp[P.NE+1], SXExp[P.NE+1:1]} + {2'b0, Bias};
// correct exponent for subnormal input's normalization shifts // division exponent = (Xe-l) - (Ye-m) + bias; l and m account for subnorms
assign DExp = ({2'b0, Xe} - {{(P.NE+1-P.DIVBLEN){1'b0}}, ell} - {2'b0, Ye} + {{(P.NE+1-P.DIVBLEN){1'b0}}, m} + {3'b0, Bias}); assign DExp = ({2'b0, Xe} - {{(P.NE+1-P.DIVBLEN){1'b0}}, ell} - {2'b0, Ye} + {{(P.NE+1-P.DIVBLEN){1'b0}}, m} + {3'b0, Bias});
assign Qe = Sqrt ? SExp : DExp;
// Select square root or division exponent
assign Ue = Sqrt ? SExp : DExp;
endmodule endmodule

View File

@ -38,14 +38,14 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
input logic [P.XLEN-1:0] AM, input logic [P.XLEN-1:0] AM,
input logic RemOpM, ALTBM, BZeroM, AsM, BsM, W64M, input logic RemOpM, ALTBM, BZeroM, AsM, BsM, W64M,
input logic [P.DIVBLEN:0] nM, mM, input logic [P.DIVBLEN:0] nM, mM,
output logic [P.DIVb:0] QmM, output logic [P.DIVb:0] UmM, // result significand
output logic WZeroE, output logic WZeroE,
output logic DivStickyM, output logic DivStickyM,
output logic [P.XLEN-1:0] FIntDivResultM output logic [P.XLEN-1:0] FIntDivResultM
); );
logic [P.DIVb+3:0] W, Sum; logic [P.DIVb+3:0] W, Sum;
logic [P.DIVb:0] PreQmM; logic [P.DIVb:0] PreUmM;
logic NegStickyM; logic NegStickyM;
logic weq0E, WZeroM; logic weq0E, WZeroM;
logic [P.XLEN-1:0] IntDivResultM; logic [P.XLEN-1:0] IntDivResultM;
@ -91,17 +91,17 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
// Determine if sticky bit is negative // *** look for ways to optimize this. Shift shouldn't be needed. // Determine if sticky bit is negative // *** look for ways to optimize this. Shift shouldn't be needed.
assign Sum = WC + WS; assign Sum = WC + WS;
assign NegStickyM = Sum[P.DIVb+3]; assign NegStickyM = Sum[P.DIVb+3];
mux2 #(P.DIVb+1) preqmmux(FirstU, FirstUM, NegStickyM, PreQmM); // Select U or U-1 depending on negative sticky bit mux2 #(P.DIVb+1) preummux(FirstU, FirstUM, NegStickyM, PreUmM); // Select U or U-1 depending on negative sticky bit
mux2 #(P.DIVb+1) qmmux(PreQmM, (PreQmM << 1), SqrtM, QmM); mux2 #(P.DIVb+1) ummux(PreUmM, (PreUmM << 1), SqrtM, UmM);
// Integer quotient or remainder correctoin, normalization, and special cases // Integer quotient or remainder correction, normalization, and special cases
if (P.IDIV_ON_FPU) begin:intpostproc // Int supported if (P.IDIV_ON_FPU) begin:intpostproc // Int supported
logic [P.DIVBLEN:0] NormShiftM; logic [P.DIVBLEN:0] NormShiftM;
logic [P.DIVb+3:0] UnsignedQuotM, NormRemM, NormRemDM, NormQuotM; logic [P.DIVb+3:0] UnsignedQuotM, NormRemM, NormRemDM, NormQuotM;
logic signed [P.DIVb+3:0] PreResultM, PreIntResultM; logic signed [P.DIVb+3:0] PreResultM, PreIntResultM;
assign W = $signed(Sum) >>> P.LOGR; assign W = $signed(Sum) >>> P.LOGR;
assign UnsignedQuotM = {3'b000, PreQmM}; assign UnsignedQuotM = {3'b000, PreUmM};
// Integer remainder: sticky and sign correction muxes // Integer remainder: sticky and sign correction muxes
assign NegQuotM = AsM ^ BsM; // Integer Quotient is negative assign NegQuotM = AsM ^ BsM; // Integer Quotient is negative

View File

@ -35,7 +35,7 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
input logic SqrtE, input logic SqrtE,
input logic XZeroE, input logic XZeroE,
input logic [2:0] Funct3E, input logic [2:0] Funct3E,
output logic [P.NE+1:0] QeM, output logic [P.NE+1:0] UeM,
output logic [P.DIVb+3:0] X, D, output logic [P.DIVb+3:0] X, D,
// Int-specific // Int-specific
input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B input logic [P.XLEN-1:0] ForwardedSrcAE, ForwardedSrcBE, // *** these are the src outputs before the mux choosing between them and PCE to put in srcA/B
@ -48,10 +48,10 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
output logic [P.XLEN-1:0] AM output logic [P.XLEN-1:0] AM
); );
logic [P.DIVb:0] Xfract, Dfract; logic [P.DIVb:0] Xnorm, Dnorm;
logic [P.DIVb:0] PreSqrtX; logic [P.DIVb:0] PreSqrtX;
logic [P.DIVb+3:0] DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed logic [P.DIVb+3:0] DivX, DivXShifted, SqrtX, PreShiftX; // Variations of dividend, to be muxed
logic [P.NE+1:0] QeE; // Quotient Exponent (FP only) logic [P.NE+1:0] UeE; // Result Exponent (FP only)
logic [P.DIVb:0] IFX, IFD; // Correctly-sized inputs for iterator, selected from int or fp input logic [P.DIVb:0] IFX, IFD; // Correctly-sized inputs for iterator, selected from int or fp input
logic [P.DIVBLEN:0] mE, nE, ell; // Leading zeros of inputs logic [P.DIVBLEN:0] mE, nE, ell; // Leading zeros of inputs
logic NumerZeroE; // Numerator is zero (X or A) logic NumerZeroE; // Numerator is zero (X or A)
@ -106,9 +106,9 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
lzc #(P.DIVb+1) lzcX (IFX, ell); lzc #(P.DIVb+1) lzcX (IFX, ell);
lzc #(P.DIVb+1) lzcY (IFD, mE); lzc #(P.DIVb+1) lzcY (IFD, mE);
// Normalization shift: shift off leading one // Normalization shift: shift leading one into most significant bit
assign Xfract = (IFX << ell); assign Xnorm = (IFX << ell);
assign Dfract = (IFD << mE); assign Dnorm = (IFD << mE);
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// Integer Right Shift to digit boundary // Integer Right Shift to digit boundary
@ -133,10 +133,11 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
logic [P.LOGRK-1:0] IntTrunc, RightShiftX; logic [P.LOGRK-1:0] IntTrunc, RightShiftX;
logic [P.DIVBLEN:0] TotalIntBits, IntSteps; logic [P.DIVBLEN:0] TotalIntBits, IntSteps;
/* verilator lint_off WIDTH */ /* verilator lint_off WIDTH */
// n = k*ceil((r+p)/rk) - 1
assign TotalIntBits = P.LOGR + p; // Total number of result bits (r integer bits plus p fractional bits) assign TotalIntBits = P.LOGR + p; // Total number of result bits (r integer bits plus p fractional bits)
assign IntTrunc = TotalIntBits % P.RK; // Truncation check for ceiling operator assign IntTrunc = TotalIntBits % P.RK; // Truncation check for ceiling operator
assign IntSteps = (TotalIntBits >> P.LOGRK) + |IntTrunc; // Number of steps for int div assign IntSteps = (TotalIntBits >> P.LOGRK) + |IntTrunc; // Number of steps for int div
assign nE = (IntSteps * P.DIVCOPIES) - 1; // Fractional digits assign nE = (IntSteps * P.DIVCOPIES) - 1; // Fractional digits = total digits - 1 integer digit
assign RightShiftX = P.RK - 1 - ((TotalIntBits - 1) % P.RK); // Right shift amount assign RightShiftX = P.RK - 1 - ((TotalIntBits - 1) % P.RK); // Right shift amount
assign DivXShifted = DivX >> RightShiftX; // shift X by up to R*K-1 to complete in nE steps assign DivXShifted = DivX >> RightShiftX; // shift X by up to R*K-1 to complete in nE steps
/* verilator lint_on WIDTH */ /* verilator lint_on WIDTH */
@ -150,18 +151,25 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
// Floating-Point Preprocessing // Floating-Point Preprocessing
// append leading 1 (for nonzero inputs) // Extend to Q4.b format
// shift square root to be in range [1/4, 1) // shift square root to be in range [1/4, 1)
// Normalized numbers are shifted right by 1 if the exponent is odd // Normalized numbers are shifted right by 1 if the exponent is odd
// Subnormal numbers have Xe = 0 and an unbiased exponent of 1-BIAS. They are shifted right if the number of leading zeros is odd. // Subnormal numbers have Xe = 0 and an unbiased exponent of 1-BIAS. They are shifted right if the number of leading zeros is odd.
// NOTE: there might be a discrepancy that X is never right shifted by 2. However // NOTE: there might be a discrepancy that X is never right shifted by 2. However
// it comes out in the wash and gives the right answer. Investigate later if possible. // it comes out in the wash and gives the right answer. Investigate later if possible. ***
////////////////////////////////////////////////////// //////////////////////////////////////////////////////
assign DivX = {3'b000, Xfract}; assign DivX = {3'b000, Xnorm}; // Zero-extend numerator for division
// Sqrt is initialized on step one as R(X-1), so depends on Radix // Sqrt is initialized on step one as R(X-1), so depends on Radix
mux2 #(P.DIVb+1) sqrtxmux(Xfract, {1'b0, Xfract[P.DIVb:1]}, (Xe[0] ^ ell[0]), PreSqrtX); // If X = 0, then special case logic sets sqrt = 0 so this portion doesn't matter
// Otherwise, X has a leading 1 after possible normalization shift and is now in range [1, 2)
// Next X is shifted right by 1 or 2 bits to range [1/4, 1) and exponent will be adjusted accordingly to be even
// Now (X-1) is negative. Formed by placing all 1s in all four integer bits (in Q4.b) form, keeping X in fraciton bits
// Then multiply by R is left shift by r (1 or 2 for radix 2 or 4)
// For Radix 2, this gives 3 leading 1s, followed by the fraction bits
// For Radix 4, this gives 2 leading 1s, followed by the fraction bits (and a zero in the lsb)
mux2 #(P.DIVb+1) sqrtxmux(Xnorm, {1'b0, Xnorm[P.DIVb:1]}, (Xe[0] ^ ell[0]), PreSqrtX);
if (P.RADIX == 2) assign SqrtX = {3'b111, PreSqrtX}; if (P.RADIX == 2) assign SqrtX = {3'b111, PreSqrtX};
else assign SqrtX = {2'b11, PreSqrtX, 1'b0}; else assign SqrtX = {2'b11, PreSqrtX, 1'b0};
mux2 #(P.DIVb+4) prexmux(DivX, SqrtX, SqrtE, PreShiftX); mux2 #(P.DIVb+4) prexmux(DivX, SqrtX, SqrtE, PreShiftX);
@ -177,11 +185,11 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
end end
// Divisior register // Divisior register
flopen #(P.DIVb+4) dreg(clk, IFDivStartE, {3'b000, Dfract}, D); flopen #(P.DIVb+4) dreg(clk, IFDivStartE, {3'b000, Dnorm}, D);
// Floating-point exponent // Floating-point exponent
fdivsqrtexpcalc #(P) expcalc(.Fmt(FmtE), .Xe, .Ye, .Sqrt(SqrtE), .XZero(XZeroE), .ell, .m(mE), .Qe(QeE)); fdivsqrtexpcalc #(P) expcalc(.Fmt(FmtE), .Xe, .Ye, .Sqrt(SqrtE), .XZero(XZeroE), .ell, .m(mE), .Ue(UeE));
flopen #(P.NE+2) expreg(clk, IFDivStartE, QeE, QeM); flopen #(P.NE+2) expreg(clk, IFDivStartE, UeE, UeM);
// Number of FSM cycles (to FSM) // Number of FSM cycles (to FSM)
fdivsqrtcycles #(P) cyclecalc(.FmtE, .SqrtE, .IntDivE, .nE, .CyclesE); fdivsqrtcycles #(P) cyclecalc(.FmtE, .SqrtE, .IntDivE, .nE, .CyclesE);

View File

@ -133,8 +133,8 @@ module fpu import cvw::*; #(parameter cvw_t P) (
logic [P.XLEN-1:0] FCvtIntResM; // fcvt integer result (for IEU) logic [P.XLEN-1:0] FCvtIntResM; // fcvt integer result (for IEU)
// divide signals // divide signals
logic [P.DIVb:0] QmM; // fdivsqrt signifcand logic [P.DIVb:0] UmM; // fdivsqrt signifcand
logic [P.NE+1:0] QeM; // fdivsqrt exponent logic [P.NE+1:0] UeM; // fdivsqrt exponent
logic DivStickyM; // fdivsqrt sticky bit logic DivStickyM; // fdivsqrt sticky bit
logic FDivDoneE, IFDivStartE; // fdivsqrt control signals logic FDivDoneE, IFDivStartE; // fdivsqrt control signals
logic [P.XLEN-1:0] FIntDivResultM; // fdivsqrt integer division result (for IEU) logic [P.XLEN-1:0] FIntDivResultM; // fdivsqrt integer division result (for IEU)
@ -242,8 +242,8 @@ module fpu import cvw::*; #(parameter cvw_t P) (
fdivsqrt #(P) fdivsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, .SqrtE(OpCtrlE[0]), .SqrtM(OpCtrlM[0]), fdivsqrt #(P) fdivsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, .SqrtE(OpCtrlE[0]), .SqrtM(OpCtrlM[0]),
.XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .FDivStartE, .IDivStartE, .XsE, .XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .FDivStartE, .IDivStartE, .XsE,
.ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .Funct3M, .IntDivE, .W64E, .ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .Funct3M, .IntDivE, .W64E,
.StallM, .FlushE, .DivStickyM, .FDivBusyE, .IFDivStartE, .FDivDoneE, .QeM, .StallM, .FlushE, .DivStickyM, .FDivBusyE, .IFDivStartE, .FDivDoneE, .UeM,
.QmM, .FIntDivResultM); .UmM, .FIntDivResultM);
// compare: fmin/fmax, flt/fle/feq // compare: fmin/fmax, flt/fle/feq
fcmp #(P) fcmp (.Fmt(FmtE), .OpCtrl(OpCtrlE), .Xs(XsE), .Ys(YsE), .Xe(XeE), .Ye(YeE), fcmp #(P) fcmp (.Fmt(FmtE), .OpCtrl(OpCtrlE), .Xs(XsE), .Ys(YsE), .Xe(XeE), .Ye(YeE),
@ -326,9 +326,9 @@ module fpu import cvw::*; #(parameter cvw_t P) (
////////////////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////////////////
postprocess #(P) postprocess(.Xs(XsM), .Ys(YsM), .Xm(XmM), .Ym(YmM), .Zm(ZmM), .Frm(FrmM), .Fmt(FmtM), postprocess #(P) postprocess(.Xs(XsM), .Ys(YsM), .Xm(XmM), .Ym(YmM), .Zm(ZmM), .Frm(FrmM), .Fmt(FmtM),
.FmaASticky(FmaAStickyM), .XZero(XZeroM), .YZero(YZeroM), .XInf(XInfM), .YInf(YInfM), .DivQm(QmM), .FmaSs(SsM), .FmaASticky(FmaAStickyM), .XZero(XZeroM), .YZero(YZeroM), .XInf(XInfM), .YInf(YInfM), .DivUm(UmM), .FmaSs(SsM),
.ZInf(ZInfM), .XNaN(XNaNM), .YNaN(YNaNM), .ZNaN(ZNaNM), .XSNaN(XSNaNM), .YSNaN(YSNaNM), .ZSNaN(ZSNaNM), .ZInf(ZInfM), .XNaN(XNaNM), .YNaN(YNaNM), .ZNaN(ZNaNM), .XSNaN(XSNaNM), .YSNaN(YSNaNM), .ZSNaN(ZSNaNM),
.FmaSm(SmM), .DivQe(QeM), .FmaAs(AsM), .FmaPs(PsM), .OpCtrl(OpCtrlM), .FmaSCnt(SCntM), .FmaSe(SeM), .FmaSm(SmM), .DivUe(UeM), .FmaAs(AsM), .FmaPs(PsM), .OpCtrl(OpCtrlM), .FmaSCnt(SCntM), .FmaSe(SeM),
.CvtCe(CeM), .CvtResSubnormUf(CvtResSubnormUfM),.CvtShiftAmt(CvtShiftAmtM), .CvtCs(CsM), .CvtCe(CeM), .CvtResSubnormUf(CvtResSubnormUfM),.CvtShiftAmt(CvtShiftAmtM), .CvtCs(CsM),
.ToInt(FWriteIntM), .DivSticky(DivStickyM), .CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM), .ToInt(FWriteIntM), .DivSticky(DivStickyM), .CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM),
.PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM)); .PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM));

View File

@ -27,8 +27,8 @@
//////////////////////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////////////////
module divshiftcalc import cvw::*; #(parameter cvw_t P) ( module divshiftcalc import cvw::*; #(parameter cvw_t P) (
input logic [P.DIVb:0] DivQm, // divsqrt significand input logic [P.DIVb:0] DivUm, // divsqrt significand
input logic [P.NE+1:0] DivQe, // divsqrt exponent input logic [P.NE+1:0] DivUe, // divsqrt exponent
output logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt, // divsqrt shift amount output logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt, // divsqrt shift amount
output logic [P.NORMSHIFTSZ-1:0] DivShiftIn, // divsqrt shift input output logic [P.NORMSHIFTSZ-1:0] DivShiftIn, // divsqrt shift input
output logic DivResSubnorm, // is the divsqrt result subnormal output logic DivResSubnorm, // is the divsqrt result subnormal
@ -41,23 +41,23 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
// is the result subnormal // is the result subnormal
// if the exponent is 1 then the result needs to be normalized then the result is Subnormalizes // if the exponent is 1 then the result needs to be normalized then the result is Subnormalizes
assign DivResSubnorm = DivQe[P.NE+1]|(~|DivQe[P.NE+1:0]); assign DivResSubnorm = DivUe[P.NE+1]|(~|DivUe[P.NE+1:0]);
// if the result is subnormal // if the result is subnormal
// 00000000x.xxxxxx... Exp = DivQe // 00000000x.xxxxxx... Exp = DivUe
// .00000000xxxxxxx... >> NF+1 Exp = DivQe+NF+1 // .00000000xxxxxxx... >> NF+1 Exp = DivUe+NF+1
// .00xxxxxxxxxxxxx... << DivQe+NF+1 Exp = +1 // .00xxxxxxxxxxxxx... << DivUe+NF+1 Exp = +1
// .0000xxxxxxxxxxx... >> 1 Exp = 1 // .0000xxxxxxxxxxx... >> 1 Exp = 1
// Left shift amount = DivQe+NF+1-1 // Left shift amount = DivUe+NF+1-1
assign DivSubnormShift = (P.NE+2)'(P.NF)+DivQe; assign DivSubnormShift = (P.NE+2)'(P.NF)+DivUe;
assign DivSubnormShiftPos = ~DivSubnormShift[P.NE+1]; assign DivSubnormShiftPos = ~DivSubnormShift[P.NE+1];
// if the result is normalized // if the result is normalized
// 00000000x.xxxxxx... Exp = DivQe // 00000000x.xxxxxx... Exp = DivUe
// .00000000xxxxxxx... >> NF+1 Exp = DivQe+NF+1 // .00000000xxxxxxx... >> NF+1 Exp = DivUe+NF+1
// 00000000.xxxxxxx... << NF Exp = DivQe+1 // 00000000.xxxxxxx... << NF Exp = DivUe+1
// 00000000x.xxxxxx... << NF Exp = DivQe (extra shift done afterwards) // 00000000x.xxxxxx... << NF Exp = DivUe (extra shift done afterwards)
// 00000000xx.xxxxx... << 1? Exp = DivQe-1 (determined after) // 00000000xx.xxxxx... << 1? Exp = DivUe-1 (determined after)
// inital Left shift amount = NF // inital Left shift amount = NF
// shift one more if the it's a minimally redundent radix 4 - one entire cycle needed for integer bit // shift one more if the it's a minimally redundent radix 4 - one entire cycle needed for integer bit
assign NormShift = (P.LOGNORMSHIFTSZ)'(P.NF); assign NormShift = (P.LOGNORMSHIFTSZ)'(P.NF);
@ -68,5 +68,5 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift; assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
// pre-shift the divider result for normalization // pre-shift the divider result for normalization
assign DivShiftIn = {{P.NF{1'b0}}, DivQm, {P.NORMSHIFTSZ-P.DIVb-1-P.NF{1'b0}}}; assign DivShiftIn = {{P.NF{1'b0}}, DivUm, {P.NORMSHIFTSZ-P.DIVb-1-P.NF{1'b0}}};
endmodule endmodule

View File

@ -48,8 +48,8 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
input logic [$clog2(3*P.NF+5)-1:0] FmaSCnt, // the normalization shift count input logic [$clog2(3*P.NF+5)-1:0] FmaSCnt, // the normalization shift count
//divide signals //divide signals
input logic DivSticky, // divider sticky bit input logic DivSticky, // divider sticky bit
input logic [P.NE+1:0] DivQe, // divsqrt exponent input logic [P.NE+1:0] DivUe, // divsqrt exponent
input logic [P.DIVb:0] DivQm, // divsqrt significand input logic [P.DIVb:0] DivUm, // divsqrt significand
// conversion signals // conversion signals
input logic CvtCs, // the result's sign input logic CvtCs, // the result's sign
input logic [P.NE:0] CvtCe, // the calculated expoent input logic [P.NE:0] CvtCe, // the calculated expoent
@ -91,7 +91,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
// division singals // division singals
logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shif amount logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shif amount
logic [P.NORMSHIFTSZ-1:0] DivShiftIn; // divsqrt shift input logic [P.NORMSHIFTSZ-1:0] DivShiftIn; // divsqrt shift input
logic [P.NE+1:0] Qe; // divsqrt corrected exponent after corretion shift logic [P.NE+1:0] Ue; // divsqrt corrected exponent after corretion shift
logic DivByZero; // divide by zero flag logic DivByZero; // divide by zero flag
logic DivResSubnorm; // is the divsqrt result subnormal logic DivResSubnorm; // is the divsqrt result subnormal
logic DivSubnormShiftPos; // is the divsqrt subnorm shift amout positive (not underflowed) logic DivSubnormShiftPos; // is the divsqrt subnorm shift amout positive (not underflowed)
@ -146,7 +146,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
fmashiftcalc #(P) fmashiftcalc(.FmaSm, .FmaSCnt, .Fmt, .NormSumExp, .FmaSe, fmashiftcalc #(P) fmashiftcalc(.FmaSm, .FmaSCnt, .Fmt, .NormSumExp, .FmaSe,
.FmaSZero, .FmaPreResultSubnorm, .FmaShiftAmt, .FmaShiftIn); .FmaSZero, .FmaPreResultSubnorm, .FmaShiftAmt, .FmaShiftIn);
divshiftcalc #(P) divshiftcalc(.DivQe, .DivQm, .DivResSubnorm, .DivSubnormShiftPos, .DivShiftAmt, .DivShiftIn); divshiftcalc #(P) divshiftcalc(.DivUe, .DivUm, .DivResSubnorm, .DivSubnormShiftPos, .DivShiftAmt, .DivShiftIn);
// select which unit's output to shift // select which unit's output to shift
always_comb always_comb
@ -174,7 +174,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
// correct for LZA/divsqrt error // correct for LZA/divsqrt error
shiftcorrection #(P) shiftcorrection(.FmaOp, .FmaPreResultSubnorm, .NormSumExp, shiftcorrection #(P) shiftcorrection(.FmaOp, .FmaPreResultSubnorm, .NormSumExp,
.DivResSubnorm, .DivSubnormShiftPos, .DivOp, .DivQe, .Qe, .FmaSZero, .Shifted, .FmaMe, .Mf); .DivResSubnorm, .DivSubnormShiftPos, .DivOp, .DivUe, .Ue, .FmaSZero, .Shifted, .FmaMe, .Mf);
/////////////////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////////////////
// Rounding // Rounding
@ -189,7 +189,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
// calulate result sign used in rounding unit // calulate result sign used in rounding unit
roundsign roundsign(.FmaOp, .DivOp, .CvtOp, .Sqrt, .FmaSs, .Xs, .Ys, .CvtCs, .Ms); roundsign roundsign(.FmaOp, .DivOp, .CvtOp, .Sqrt, .FmaSs, .Xs, .Ys, .CvtCs, .Ms);
round #(P) round(.OutFmt, .Frm, .FmaASticky, .Plus1, .PostProcSel, .CvtCe, .Qe, round #(P) round(.OutFmt, .Frm, .FmaASticky, .Plus1, .PostProcSel, .CvtCe, .Ue,
.Ms, .FmaMe, .FmaOp, .CvtOp, .CvtResSubnormUf, .Mf, .ToInt, .CvtResUf, .Ms, .FmaMe, .FmaOp, .CvtOp, .CvtResSubnormUf, .Mf, .ToInt, .CvtResUf,
.DivSticky, .DivOp, .UfPlus1, .FullRe, .Rf, .Re, .Sticky, .Round, .Guard, .Me); .DivSticky, .DivOp, .UfPlus1, .FullRe, .Rf, .Re, .Sticky, .Round, .Guard, .Me);

View File

@ -39,7 +39,7 @@ module round import cvw::*; #(parameter cvw_t P) (
// divsqrt // divsqrt
input logic DivOp, // is a division opperation being done input logic DivOp, // is a division opperation being done
input logic DivSticky, // divsqrt sticky bit input logic DivSticky, // divsqrt sticky bit
input logic [P.NE+1:0] Qe, // the divsqrt calculated expoent input logic [P.NE+1:0] Ue, // the divsqrt calculated expoent
// cvt // cvt
input logic CvtOp, // is a convert opperation being done input logic CvtOp, // is a convert opperation being done
input logic ToInt, // is the cvt op a cvt to integer input logic ToInt, // is the cvt op a cvt to integer
@ -300,8 +300,8 @@ module round import cvw::*; #(parameter cvw_t P) (
case(PostProcSel) case(PostProcSel)
2'b10: Me = FmaMe; // fma 2'b10: Me = FmaMe; // fma
2'b00: Me = {CvtCe[P.NE], CvtCe}&{P.NE+2{~CvtResSubnormUf|CvtResUf}}; // cvt 2'b00: Me = {CvtCe[P.NE], CvtCe}&{P.NE+2{~CvtResSubnormUf|CvtResUf}}; // cvt
// 2'b01: Me = DivDone ? Qe : '0; // divide // 2'b01: Me = DivDone ? Ue : '0; // divide
2'b01: Me = Qe; // divide 2'b01: Me = Ue; // divide
default: Me = '0; default: Me = '0;
endcase endcase

View File

@ -31,7 +31,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
// divsqrt // divsqrt
input logic DivOp, // is it a divsqrt opperation input logic DivOp, // is it a divsqrt opperation
input logic DivResSubnorm, // is the divsqrt result subnormal input logic DivResSubnorm, // is the divsqrt result subnormal
input logic [P.NE+1:0] DivQe, // the divsqrt result's exponent input logic [P.NE+1:0] DivUe, // the divsqrt result's exponent
input logic DivSubnormShiftPos, // is the subnorm divider shift amount positive (ie not underflowed) input logic DivSubnormShiftPos, // is the subnorm divider shift amount positive (ie not underflowed)
//fma //fma
input logic FmaOp, // is it an fma opperation input logic FmaOp, // is it an fma opperation
@ -41,7 +41,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
// output // output
output logic [P.NE+1:0] FmaMe, // exponent of the normalized sum output logic [P.NE+1:0] FmaMe, // exponent of the normalized sum
output logic [P.CORRSHIFTSZ-1:0] Mf, // the shifted sum before LZA correction output logic [P.CORRSHIFTSZ-1:0] Mf, // the shifted sum before LZA correction
output logic [P.NE+1:0] Qe // corrected exponent for divider output logic [P.NE+1:0] Ue // corrected exponent for divider
); );
logic [3*P.NF+3:0] CorrSumShifted; // the shifted sum after LZA correction logic [3*P.NF+3:0] CorrSumShifted; // the shifted sum after LZA correction
@ -61,7 +61,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
// correct the shifting of the divsqrt caused by producing a result in (2, .5] range // correct the shifting of the divsqrt caused by producing a result in (2, .5] range
// condition: if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Subnorm) // condition: if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Subnorm)
assign LeftShiftQm = (LZAPlus1|(DivQe==1&~LZAPlus1)); assign LeftShiftQm = (LZAPlus1|(DivUe==1&~LZAPlus1));
assign CorrQm0 = Shifted[P.NORMSHIFTSZ-3:P.NORMSHIFTSZ-P.CORRSHIFTSZ-2]; assign CorrQm0 = Shifted[P.NORMSHIFTSZ-3:P.NORMSHIFTSZ-P.CORRSHIFTSZ-2];
assign CorrQm1 = Shifted[P.NORMSHIFTSZ-2:P.NORMSHIFTSZ-P.CORRSHIFTSZ-1]; assign CorrQm1 = Shifted[P.NORMSHIFTSZ-2:P.NORMSHIFTSZ-P.CORRSHIFTSZ-1];
mux2 #(P.CORRSHIFTSZ) divcorrmux(CorrQm0, CorrQm1, LeftShiftQm, CorrQmShifted); mux2 #(P.CORRSHIFTSZ) divcorrmux(CorrQm0, CorrQm1, LeftShiftQm, CorrQmShifted);
@ -87,5 +87,5 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
// the quotent is in the range [.5,2) if there is no early termination // the quotent is in the range [.5,2) if there is no early termination
// if the quotent < 1 and not Subnormal then subtract 1 to account for the normalization shift // if the quotent < 1 and not Subnormal then subtract 1 to account for the normalization shift
assign Qe = (DivResSubnorm & DivSubnormShiftPos) ? '0 : DivQe - {(P.NE+1)'(0), ~LZAPlus1}; assign Ue = (DivResSubnorm & DivSubnormShiftPos) ? '0 : DivUe - {(P.NE+1)'(0), ~LZAPlus1};
endmodule endmodule