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