mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Divsqrt cleanup: change Q to U, commenting code
This commit is contained in:
parent
953c53d065
commit
255873a50c
@ -45,8 +45,8 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
|
||||
input logic IntDivE, W64E,
|
||||
output logic DivStickyM,
|
||||
output logic FDivBusyE, IFDivStartE, FDivDoneE,
|
||||
output logic [P.NE+1:0] QeM,
|
||||
output logic [P.DIVb:0] QmM,
|
||||
output logic [P.NE+1:0] UeM, // Exponent result
|
||||
output logic [P.DIVb:0] UmM, // Significand result
|
||||
output logic [P.XLEN-1:0] FIntDivResultM
|
||||
);
|
||||
|
||||
@ -74,7 +74,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
fdivsqrtpreproc #(P) fdivsqrtpreproc( // Preprocessor
|
||||
.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
|
||||
.ForwardedSrcAE, .ForwardedSrcBE, .IntDivE, .W64E, .ISpecialCaseE,
|
||||
.BZeroM, .nM, .mM, .AM,
|
||||
@ -94,7 +94,7 @@ module fdivsqrt import cvw::*; #(parameter cvw_t P) (
|
||||
fdivsqrtpostproc #(P) fdivsqrtpostproc( // Postprocessor
|
||||
.clk, .reset, .StallM, .WS, .WC, .D, .FirstU, .FirstUM, .FirstC,
|
||||
.SqrtE, .Firstun, .SqrtM, .SpecialCaseM,
|
||||
.QmM, .WZeroE, .DivStickyM,
|
||||
.UmM, .WZeroE, .DivStickyM,
|
||||
// Int-specific
|
||||
.nM, .mM, .ALTBM, .AsM, .BsM, .BZeroM, .W64M, .RemOpM(Funct3M[1]), .AM,
|
||||
.FIntDivResultM);
|
||||
|
@ -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 + 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
|
||||
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);
|
||||
end
|
||||
/* verilator lint_on WIDTH */
|
||||
|
@ -32,8 +32,9 @@ module fdivsqrtexpcalc import cvw::*; #(parameter cvw_t P) (
|
||||
input logic Sqrt,
|
||||
input logic XZero,
|
||||
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+1:0] SXExp;
|
||||
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);
|
||||
endcase
|
||||
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 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 Qe = Sqrt ? SExp : DExp;
|
||||
|
||||
// Select square root or division exponent
|
||||
assign Ue = Sqrt ? SExp : DExp;
|
||||
endmodule
|
||||
|
@ -38,14 +38,14 @@ module fdivsqrtpostproc import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.XLEN-1:0] AM,
|
||||
input logic RemOpM, ALTBM, BZeroM, AsM, BsM, W64M,
|
||||
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 DivStickyM,
|
||||
output logic [P.XLEN-1:0] FIntDivResultM
|
||||
);
|
||||
|
||||
logic [P.DIVb+3:0] W, Sum;
|
||||
logic [P.DIVb:0] PreQmM;
|
||||
logic [P.DIVb:0] PreUmM;
|
||||
logic NegStickyM;
|
||||
logic weq0E, WZeroM;
|
||||
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.
|
||||
assign Sum = WC + WS;
|
||||
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) qmmux(PreQmM, (PreQmM << 1), SqrtM, QmM);
|
||||
mux2 #(P.DIVb+1) preummux(FirstU, FirstUM, NegStickyM, PreUmM); // Select U or U-1 depending on negative sticky bit
|
||||
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
|
||||
logic [P.DIVBLEN:0] NormShiftM;
|
||||
logic [P.DIVb+3:0] UnsignedQuotM, NormRemM, NormRemDM, NormQuotM;
|
||||
logic signed [P.DIVb+3:0] PreResultM, PreIntResultM;
|
||||
|
||||
assign W = $signed(Sum) >>> P.LOGR;
|
||||
assign UnsignedQuotM = {3'b000, PreQmM};
|
||||
assign UnsignedQuotM = {3'b000, PreUmM};
|
||||
|
||||
// Integer remainder: sticky and sign correction muxes
|
||||
assign NegQuotM = AsM ^ BsM; // Integer Quotient is negative
|
||||
|
@ -35,7 +35,7 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||
input logic SqrtE,
|
||||
input logic XZeroE,
|
||||
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,
|
||||
// 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
|
||||
@ -48,10 +48,10 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||
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+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.DIVBLEN:0] mE, nE, ell; // Leading zeros of inputs
|
||||
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) lzcY (IFD, mE);
|
||||
|
||||
// Normalization shift: shift off leading one
|
||||
assign Xfract = (IFX << ell);
|
||||
assign Dfract = (IFD << mE);
|
||||
// Normalization shift: shift leading one into most significant bit
|
||||
assign Xnorm = (IFX << ell);
|
||||
assign Dnorm = (IFD << mE);
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// 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.DIVBLEN:0] TotalIntBits, IntSteps;
|
||||
/* 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 IntTrunc = TotalIntBits % P.RK; // Truncation check for ceiling operator
|
||||
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 DivXShifted = DivX >> RightShiftX; // shift X by up to R*K-1 to complete in nE steps
|
||||
/* verilator lint_on WIDTH */
|
||||
@ -150,18 +151,25 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
//////////////////////////////////////////////////////
|
||||
// Floating-Point Preprocessing
|
||||
// append leading 1 (for nonzero inputs)
|
||||
// Extend to Q4.b format
|
||||
// shift square root to be in range [1/4, 1)
|
||||
// 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.
|
||||
// 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
|
||||
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};
|
||||
else assign SqrtX = {2'b11, PreSqrtX, 1'b0};
|
||||
mux2 #(P.DIVb+4) prexmux(DivX, SqrtX, SqrtE, PreShiftX);
|
||||
@ -177,11 +185,11 @@ module fdivsqrtpreproc import cvw::*; #(parameter cvw_t P) (
|
||||
end
|
||||
|
||||
// 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
|
||||
fdivsqrtexpcalc #(P) expcalc(.Fmt(FmtE), .Xe, .Ye, .Sqrt(SqrtE), .XZero(XZeroE), .ell, .m(mE), .Qe(QeE));
|
||||
flopen #(P.NE+2) expreg(clk, IFDivStartE, QeE, QeM);
|
||||
fdivsqrtexpcalc #(P) expcalc(.Fmt(FmtE), .Xe, .Ye, .Sqrt(SqrtE), .XZero(XZeroE), .ell, .m(mE), .Ue(UeE));
|
||||
flopen #(P.NE+2) expreg(clk, IFDivStartE, UeE, UeM);
|
||||
|
||||
// Number of FSM cycles (to FSM)
|
||||
fdivsqrtcycles #(P) cyclecalc(.FmtE, .SqrtE, .IntDivE, .nE, .CyclesE);
|
||||
|
@ -133,8 +133,8 @@ module fpu import cvw::*; #(parameter cvw_t P) (
|
||||
logic [P.XLEN-1:0] FCvtIntResM; // fcvt integer result (for IEU)
|
||||
|
||||
// divide signals
|
||||
logic [P.DIVb:0] QmM; // fdivsqrt signifcand
|
||||
logic [P.NE+1:0] QeM; // fdivsqrt exponent
|
||||
logic [P.DIVb:0] UmM; // fdivsqrt signifcand
|
||||
logic [P.NE+1:0] UeM; // fdivsqrt exponent
|
||||
logic DivStickyM; // fdivsqrt sticky bit
|
||||
logic FDivDoneE, IFDivStartE; // fdivsqrt control signals
|
||||
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]),
|
||||
.XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .FDivStartE, .IDivStartE, .XsE,
|
||||
.ForwardedSrcAE, .ForwardedSrcBE, .Funct3E, .Funct3M, .IntDivE, .W64E,
|
||||
.StallM, .FlushE, .DivStickyM, .FDivBusyE, .IFDivStartE, .FDivDoneE, .QeM,
|
||||
.QmM, .FIntDivResultM);
|
||||
.StallM, .FlushE, .DivStickyM, .FDivBusyE, .IFDivStartE, .FDivDoneE, .UeM,
|
||||
.UmM, .FIntDivResultM);
|
||||
|
||||
// compare: fmin/fmax, flt/fle/feq
|
||||
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),
|
||||
.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),
|
||||
.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),
|
||||
.ToInt(FWriteIntM), .DivSticky(DivStickyM), .CvtLzcIn(CvtLzcInM), .IntZero(IntZeroM),
|
||||
.PostProcSel(PostProcSelM), .PostProcRes(PostProcResM), .PostProcFlg(PostProcFlgM), .FCvtIntRes(FCvtIntResM));
|
||||
|
@ -27,8 +27,8 @@
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
module divshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
input logic [P.DIVb:0] DivQm, // divsqrt significand
|
||||
input logic [P.NE+1:0] DivQe, // divsqrt exponent
|
||||
input logic [P.DIVb:0] DivUm, // divsqrt significand
|
||||
input logic [P.NE+1:0] DivUe, // divsqrt exponent
|
||||
output logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt, // divsqrt shift amount
|
||||
output logic [P.NORMSHIFTSZ-1:0] DivShiftIn, // divsqrt shift input
|
||||
output logic DivResSubnorm, // is the divsqrt result subnormal
|
||||
@ -41,23 +41,23 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// is the result subnormal
|
||||
// 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
|
||||
// 00000000x.xxxxxx... Exp = DivQe
|
||||
// .00000000xxxxxxx... >> NF+1 Exp = DivQe+NF+1
|
||||
// .00xxxxxxxxxxxxx... << DivQe+NF+1 Exp = +1
|
||||
// 00000000x.xxxxxx... Exp = DivUe
|
||||
// .00000000xxxxxxx... >> NF+1 Exp = DivUe+NF+1
|
||||
// .00xxxxxxxxxxxxx... << DivUe+NF+1 Exp = +1
|
||||
// .0000xxxxxxxxxxx... >> 1 Exp = 1
|
||||
// Left shift amount = DivQe+NF+1-1
|
||||
assign DivSubnormShift = (P.NE+2)'(P.NF)+DivQe;
|
||||
// Left shift amount = DivUe+NF+1-1
|
||||
assign DivSubnormShift = (P.NE+2)'(P.NF)+DivUe;
|
||||
assign DivSubnormShiftPos = ~DivSubnormShift[P.NE+1];
|
||||
|
||||
// if the result is normalized
|
||||
// 00000000x.xxxxxx... Exp = DivQe
|
||||
// .00000000xxxxxxx... >> NF+1 Exp = DivQe+NF+1
|
||||
// 00000000.xxxxxxx... << NF Exp = DivQe+1
|
||||
// 00000000x.xxxxxx... << NF Exp = DivQe (extra shift done afterwards)
|
||||
// 00000000xx.xxxxx... << 1? Exp = DivQe-1 (determined after)
|
||||
// 00000000x.xxxxxx... Exp = DivUe
|
||||
// .00000000xxxxxxx... >> NF+1 Exp = DivUe+NF+1
|
||||
// 00000000.xxxxxxx... << NF Exp = DivUe+1
|
||||
// 00000000x.xxxxxx... << NF Exp = DivUe (extra shift done afterwards)
|
||||
// 00000000xx.xxxxx... << 1? Exp = DivUe-1 (determined after)
|
||||
// inital Left shift amount = NF
|
||||
// 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);
|
||||
@ -68,5 +68,5 @@ module divshiftcalc import cvw::*; #(parameter cvw_t P) (
|
||||
assign DivShiftAmt = DivResSubnorm ? DivSubnormShiftAmt : NormShift;
|
||||
|
||||
// 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
|
||||
|
@ -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
|
||||
//divide signals
|
||||
input logic DivSticky, // divider sticky bit
|
||||
input logic [P.NE+1:0] DivQe, // divsqrt exponent
|
||||
input logic [P.DIVb:0] DivQm, // divsqrt significand
|
||||
input logic [P.NE+1:0] DivUe, // divsqrt exponent
|
||||
input logic [P.DIVb:0] DivUm, // divsqrt significand
|
||||
// conversion signals
|
||||
input logic CvtCs, // the result's sign
|
||||
input logic [P.NE:0] CvtCe, // the calculated expoent
|
||||
@ -91,7 +91,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
||||
// division singals
|
||||
logic [P.LOGNORMSHIFTSZ-1:0] DivShiftAmt; // divsqrt shif amount
|
||||
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 DivResSubnorm; // is the divsqrt result subnormal
|
||||
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,
|
||||
.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
|
||||
always_comb
|
||||
@ -174,7 +174,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
||||
|
||||
// correct for LZA/divsqrt error
|
||||
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
|
||||
@ -189,7 +189,7 @@ module postprocess import cvw::*; #(parameter cvw_t P) (
|
||||
// calulate result sign used in rounding unit
|
||||
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,
|
||||
.DivSticky, .DivOp, .UfPlus1, .FullRe, .Rf, .Re, .Sticky, .Round, .Guard, .Me);
|
||||
|
||||
|
@ -39,7 +39,7 @@ module round import cvw::*; #(parameter cvw_t P) (
|
||||
// divsqrt
|
||||
input logic DivOp, // is a division opperation being done
|
||||
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
|
||||
input logic CvtOp, // is a convert opperation being done
|
||||
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)
|
||||
2'b10: Me = FmaMe; // fma
|
||||
2'b00: Me = {CvtCe[P.NE], CvtCe}&{P.NE+2{~CvtResSubnormUf|CvtResUf}}; // cvt
|
||||
// 2'b01: Me = DivDone ? Qe : '0; // divide
|
||||
2'b01: Me = Qe; // divide
|
||||
// 2'b01: Me = DivDone ? Ue : '0; // divide
|
||||
2'b01: Me = Ue; // divide
|
||||
default: Me = '0;
|
||||
endcase
|
||||
|
||||
|
@ -31,7 +31,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
|
||||
// divsqrt
|
||||
input logic DivOp, // is it a divsqrt opperation
|
||||
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)
|
||||
//fma
|
||||
input logic FmaOp, // is it an fma opperation
|
||||
@ -41,7 +41,7 @@ module shiftcorrection import cvw::*; #(parameter cvw_t P) (
|
||||
// output
|
||||
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.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
|
||||
@ -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
|
||||
// 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 CorrQm1 = Shifted[P.NORMSHIFTSZ-2:P.NORMSHIFTSZ-P.CORRSHIFTSZ-1];
|
||||
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
|
||||
// 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
|
||||
|
Loading…
Reference in New Issue
Block a user