diff --git a/addins/riscv-arch-test b/addins/riscv-arch-test index be67c99bd..307c77b26 160000 --- a/addins/riscv-arch-test +++ b/addins/riscv-arch-test @@ -1 +1 @@ -Subproject commit be67c99bd461742aa1c100bcc0732657faae2230 +Subproject commit 307c77b26e070ae85ffea665ad9b642b40e33c86 diff --git a/pipelined/config/shared/wally-shared.vh b/pipelined/config/shared/wally-shared.vh index 3c2699da0..5db8af1cf 100644 --- a/pipelined/config/shared/wally-shared.vh +++ b/pipelined/config/shared/wally-shared.vh @@ -94,12 +94,12 @@ `define BIAS2 ((`F_SUPPORTED & (`LEN1 != `S_LEN)) ? `S_BIAS : `H_BIAS) // largest length in IEU/FPU -`define CVTLEN ((`NF<`XLEN) ? `XLEN : `NF) -`define LLEN ((`FLEN<`XLEN) ? `XLEN : `FLEN) +`define CVTLEN ((`NF<`XLEN) ? (`XLEN) : (`NF)) +`define DIVLEN ((`NF < `XLEN) ? (`XLEN) : (`NF)) +`define LLEN ((`FLEN<`XLEN) ? (`XLEN) : (`FLEN)) `define LOGCVTLEN $unsigned($clog2(`CVTLEN+1)) -`define NORMSHIFTSZ ((`CVTLEN+`NF) > (3*`NF+8) ? (`CVTLEN+`NF+1) : (3*`NF+9)) -`define CORRSHIFTSZ ((`CVTLEN+`NF) > (3*`NF+8) ? (`CVTLEN+`NF+1) : (3*`NF+6)) -`define DIVLEN ((`NF < `XLEN) ? `XLEN : `NF) +`define NORMSHIFTSZ ((`DIVLEN+`NF+3) > (3*`NF+8) ? (`DIVLEN+`NF+3) : (3*`NF+9)) +`define CORRSHIFTSZ ((`DIVLEN+`NF+3) > (3*`NF+8) ? (`DIVLEN+`NF+3) : (3*`NF+6)) // Disable spurious Verilator warnings diff --git a/pipelined/regression/sim-testfloat-batch b/pipelined/regression/sim-testfloat-batch index 002b3423f..f1178f1d2 100755 --- a/pipelined/regression/sim-testfloat-batch +++ b/pipelined/regression/sim-testfloat-batch @@ -7,4 +7,4 @@ # sqrt - test square root # all - test everything -vsim -c -do "do testfloat.do rv64fpquad all" \ No newline at end of file +vsim -c -do "do testfloat.do rv64fpquad $1" \ No newline at end of file diff --git a/pipelined/regression/wave-fpu.do b/pipelined/regression/wave-fpu.do index a58400cca..7dfec7e24 100644 --- a/pipelined/regression/wave-fpu.do +++ b/pipelined/regression/wave-fpu.do @@ -22,7 +22,7 @@ add wave -group {Divide} -noupdate /testbenchfp/srtradix4/* add wave -group {Divide} -noupdate /testbenchfp/srtradix4/qsel4/* add wave -group {Divide} -noupdate /testbenchfp/srtradix4/otfc4/* add wave -group {Divide} -noupdate /testbenchfp/srtradix4/preproc/* -add wave -group {Divide} -noupdate /testbenchfp/srtradix4/divcounter/* +add wave -group {Divide} -noupdate /testbenchfp/srtradix4/earlytermination/* add wave -group {Divide} -noupdate /testbenchfp/srtradix4/expcalc/* add wave -group {Testbench} -noupdate /testbenchfp/* add wave -group {Testbench} -noupdate /testbenchfp/readvectors/* diff --git a/pipelined/src/fpu/divshiftcalc.sv b/pipelined/src/fpu/divshiftcalc.sv index 57022e5ae..51698590e 100644 --- a/pipelined/src/fpu/divshiftcalc.sv +++ b/pipelined/src/fpu/divshiftcalc.sv @@ -2,14 +2,89 @@ module divshiftcalc( input logic [`DIVLEN+2:0] Quot, - input logic [`NE:0] DivCalcExpM, + input logic [`NE+1:0] DivCalcExpM, + input logic [`FMTBITS-1:0] FmtM, + input logic [$clog2(`DIVLEN/2+3)-1:0] EarlyTermShiftDiv2M, output logic [$clog2(`NORMSHIFTSZ)-1:0] DivShiftAmt, - output logic [`NE:0] CorrDivExp + output logic [`NORMSHIFTSZ-1:0] DivShiftIn, + output logic DivResDenorm, + output logic [`NE+1:0] DivDenormShift ); - - assign DivShiftAmt = {{$clog2(`NORMSHIFTSZ)-1{1'b0}}, ~Quot[`DIVLEN+2]}; - // the quotent is in the range [.5,2) - // if the quotent < 1 and not denormal then subtract 1 to account for the normalization shift - assign CorrDivExp = DivCalcExpM - {(`NE)'(0), ~Quot[`DIVLEN+2]}; + logic [`NE+1:0] NormShift; + logic [`NE+1:0] Nf, NfPlus1; + + // is the result denromalized + // if the exponent is 1 then the result needs to be normalized then the result is denormalizes + assign DivResDenorm = DivCalcExpM[`NE+1]|(~|DivCalcExpM[`NE+1:0]); + // select the proper fraction lengnth + if (`FPSIZES == 1) begin + assign Nf = (`NE+2)'(`NF); + assign NfPlus1 = (`NE+2)'(`NF+1); + + end else if (`FPSIZES == 2) begin + assign Nf = FmtM ? (`NE+2)'(`NF) : (`NE+2)'(`NF1); + assign NfPlus1 = FmtM ? (`NE+2)'(`NF+1) : (`NE+2)'(`NF1+1); + + end else if (`FPSIZES == 3) begin + always_comb + case (FmtM) + `FMT: begin + Nf = (`NE+2)'(`NF); + NfPlus1 = (`NE+2)'(`NF+1); + end + `FMT1: begin + Nf = (`NE+2)'(`NF1); + NfPlus1 = (`NE+2)'(`NF1+1); + end + `FMT2: begin + Nf = (`NE+2)'(`NF2); + NfPlus1 = (`NE+2)'(`NF2+1); + end + default: begin + Nf = 1'bx; + NfPlus1 = 1'bx; + end + endcase + end else if (`FPSIZES == 4) begin + always_comb + case (FmtM) + 2'h3: begin + Nf = (`NE+2)'(`Q_NF); + NfPlus1 = (`NE+2)'(`Q_NF+1); + end + 2'h1: begin + Nf = (`NE+2)'(`D_NF); + NfPlus1 = (`NE+2)'(`D_NF+1); + end + 2'h0: begin + Nf = (`NE+2)'(`S_NF); + NfPlus1 = (`NE+2)'(`S_NF+1); + end + 2'h2: begin + Nf = (`NE+2)'(`H_NF); + NfPlus1 = (`NE+2)'(`H_NF+1); + end + endcase + end + // if the result is denormalized + // 00000000x.xxxxxx... Exp = DivCalcExp + // .00000000xxxxxxx... >> NF+1 Exp = DivCalcExp+NF+1 + // .00xxxxxxxxxxxxx... << DivCalcExp+NF+1 Exp = +1 + // .0000xxxxxxxxxxx... >> 1 Exp = 1 + // Left shift amount = DivCalcExp+NF+1-1 + assign DivDenormShift = Nf+DivCalcExpM; + // if the result is normalized + // 00000000x.xxxxxx... Exp = DivCalcExp + // .00000000xxxxxxx... >> NF+1 Exp = DivCalcExp+NF+1 + // 00000000.xxxxxxx... << NF Exp = DivCalcExp+1 + // 00000000x.xxxxxx... << NF Exp = DivCalcExp (extra shift done afterwards) + // 00000000xx.xxxxx... << 1? Exp = DivCalcExp-1 (determined after) + // inital Left shift amount = NF + assign NormShift = Nf; + // if the shift amount is negitive then dont shift (keep sticky bit) + assign DivShiftAmt = (DivResDenorm ? DivDenormShift[$clog2(`NORMSHIFTSZ)-1:0]&{$clog2(`NORMSHIFTSZ){~DivDenormShift[`NE+1]}} : NormShift[$clog2(`NORMSHIFTSZ)-1:0])+{{$clog2(`NORMSHIFTSZ)-$clog2(`DIVLEN/2+3)-1{1'b0}}, EarlyTermShiftDiv2M&{$clog2(`DIVLEN/2+3){~DivDenormShift[`NE+1]}}, 1'b0}; + + // *** may be able to reduce shifter size + assign DivShiftIn = {{`NF{1'b0}}, Quot[`DIVLEN+2:0], {`NORMSHIFTSZ-`DIVLEN-3-`NF{1'b0}}}; endmodule diff --git a/pipelined/src/fpu/flags.sv b/pipelined/src/fpu/flags.sv index 3268aa1fd..ff6495dd9 100644 --- a/pipelined/src/fpu/flags.sv +++ b/pipelined/src/fpu/flags.sv @@ -88,7 +88,7 @@ module flags( // | and the exponent isn't negitive // | | if the input isnt infinity or NaN // | | | - assign Overflow = ResExpGteMax & ~FullResExp[`NE+1]&~(InfIn|NaNIn); + assign Overflow = ResExpGteMax & ~FullResExp[`NE+1]&~(InfIn|NaNIn|DivByZero); // detecting tininess after rounding // the exponent is negitive @@ -98,11 +98,11 @@ module flags( // | | | | and if the result is not exact // | | | | | and if the input isnt infinity or NaN // | | | | | | - assign Underflow = ((FullResExp[`NE+1] | (FullResExp == 0) | ((FullResExp == 1) & (RoundExp == 0) & ~(UfPlus1&UfLSBRes)))&(Round|Sticky))&~(InfIn|NaNIn); + assign Underflow = ((FullResExp[`NE+1] | (FullResExp == 0) | ((FullResExp == 1) & (RoundExp == 0) & ~(UfPlus1&UfLSBRes)))&(Round|Sticky))&~(InfIn|NaNIn|DivByZero); // Set Inexact flag if the res is diffrent from what would be outputed given infinite precision // - Don't set the underflow flag if an underflowed res isn't outputed - assign FpInexact = (Sticky|Overflow|Round|Underflow)&~(InfIn|NaNIn); + assign FpInexact = (Sticky|Overflow|Round|Underflow)&~(InfIn|NaNIn|DivByZero); // if the res is too small to be represented and not 0 // | and if the res is not invalid (outside the integer bounds) @@ -133,8 +133,9 @@ module flags( assign Invalid = SigNaN | (FmaInvalid&FmaOp) | (DivInvalid&DivOp); - - assign DivByZero = YZeroM&DivOp; + // if dividing by zero and not 0/0 + // - don't set flag if an input is NaN or Inf(IEEE says has to be a finite numerator) + assign DivByZero = YZeroM&DivOp&~(XZeroM|NaNIn|InfIn); // Combine flags // - to integer results do not set the underflow or overflow flags diff --git a/pipelined/src/fpu/fmashiftcalc.sv b/pipelined/src/fpu/fmashiftcalc.sv index 17a13dda5..2a2417281 100644 --- a/pipelined/src/fpu/fmashiftcalc.sv +++ b/pipelined/src/fpu/fmashiftcalc.sv @@ -120,8 +120,9 @@ module fmashiftcalc( // Determine the shift needed for denormal results // - if not denorm add 1 to shift out the leading 1 - assign DenormShift = PreResultDenorm ? ConvNormSumExp[$clog2(3*`NF+7)-1:0] : 1; + assign DenormShift = PreResultDenorm&~KillProdM ? ConvNormSumExp[$clog2(3*`NF+7)-1:0] : 1; // set and calculate the shift input and amount + // - shift once if killing a product and the result is denormalized assign FmaShiftIn = {3'b0, SumM}; - assign FmaShiftAmt = FmaNormCntM+DenormShift; + assign FmaShiftAmt = (FmaNormCntM&{$clog2(3*`NF+7){~KillProdM}})+DenormShift; endmodule diff --git a/pipelined/src/fpu/fpu.sv b/pipelined/src/fpu/fpu.sv index ff83079a8..aba1a8f48 100755 --- a/pipelined/src/fpu/fpu.sv +++ b/pipelined/src/fpu/fpu.sv @@ -124,7 +124,10 @@ module fpu ( //divide signals logic [`DIVLEN+2:0] Quot; - logic [`NE:0] DivCalcExpM; + logic [`NE+1:0] DivCalcExpM; + logic DivNegStickyM; + logic DivStickyM; + logic [$clog2(`DIVLEN/2+3)-1:0] EarlyTermShiftDiv2M; // result and flag signals logic [63:0] FDivResM, FDivResW; // divide/squareroot result @@ -355,11 +358,11 @@ module fpu ( assign FpLoadM = FResSelM[1]; - postprocess postprocess(.XSgnM, .YSgnM, .ZExpM, .XManM, .YManM, .ZManM, .FrmM, .FmtM, .ProdExpM, + postprocess postprocess(.XSgnM, .YSgnM, .ZExpM, .XManM, .YManM, .ZManM, .FrmM, .FmtM, .ProdExpM, .EarlyTermShiftDiv2M, .AddendStickyM, .KillProdM, .XZeroM, .YZeroM, .ZZeroM, .XInfM, .YInfM, .Quot, .ZInfM, .XNaNM, .YNaNM, .ZNaNM, .XSNaNM, .YSNaNM, .ZSNaNM, .SumM, .DivCalcExpM, - .NegSumM, .InvZM, .ZDenormM, .ZSgnEffM, .PSgnM, .FOpCtrlM, .FmaNormCntM, - .CvtCalcExpM, .CvtResDenormUfM,.CvtShiftAmtM, .CvtResSgnM, .FWriteIntM, + .NegSumM, .InvZM, .ZDenormM, .ZSgnEffM, .PSgnM, .FOpCtrlM, .FmaNormCntM, .DivNegStickyM, + .CvtCalcExpM, .CvtResDenormUfM,.CvtShiftAmtM, .CvtResSgnM, .FWriteIntM, .DivStickyM, .CvtLzcInM, .IntZeroM, .PostProcSelM, .PostProcResM, .PostProcFlgM, .FCvtIntResM); // FPU flag selection - to privileged diff --git a/pipelined/src/fpu/lzacorrection.sv b/pipelined/src/fpu/lzacorrection.sv index f06dd84a9..e5a2d5c34 100644 --- a/pipelined/src/fpu/lzacorrection.sv +++ b/pipelined/src/fpu/lzacorrection.sv @@ -3,14 +3,20 @@ module lzacorrection( input logic [`NORMSHIFTSZ-1:0] Shifted, // the shifted sum before LZA correction input logic FmaOp, + input logic DivOp, + input logic DivResDenorm, + input logic [`NE+1:0] DivCalcExpM, + input logic [`NE+1:0] DivDenormShift, input logic [`NE+1:0] ConvNormSumExp, // exponent of the normalized sum not taking into account denormal or zero results input logic PreResultDenorm, // is the result denormalized - calculated before LZA corection input logic KillProdM, // is the product set to zero input logic SumZero, output logic [`CORRSHIFTSZ-1:0] CorrShifted, // the shifted sum before LZA correction + output logic [`NE+1:0] CorrDivExp, output logic [`NE+1:0] SumExp // exponent of the normalized sum ); logic [3*`NF+5:0] CorrSumShifted; // the shifted sum after LZA correction + logic [`CORRSHIFTSZ:0] CorrQuotShifted; logic ResDenorm; // is the result denormalized logic LZAPlus1, LZAPlus2; // add one or two to the sum's exponent due to LZA correction @@ -19,11 +25,17 @@ module lzacorrection( assign LZAPlus2 = Shifted[`NORMSHIFTSZ-1]; // the only possible mantissa for a plus two is all zeroes - a one has to propigate all the way through a sum. so we can leave the bottom statement alone assign CorrSumShifted = LZAPlus1 ? Shifted[`NORMSHIFTSZ-3:1] : Shifted[`NORMSHIFTSZ-4:0]; - assign CorrShifted = FmaOp ? {CorrSumShifted, {`CORRSHIFTSZ-(3*`NF+6){1'b0}}} : Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ]; + // if the msb is 1 or the exponent was one, but the shifted quotent was < 1 (Denorm) + assign CorrQuotShifted = {LZAPlus2|(DivCalcExpM==1&~LZAPlus2) ? Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ] : {Shifted[`NORMSHIFTSZ-2:`NORMSHIFTSZ-`CORRSHIFTSZ], 1'b0}, 1'b0}; + // if the result of the divider was calculated to be denormalized, then the result was correctly normalized, so select the top shifted bits + assign CorrShifted = FmaOp ? {CorrSumShifted, {`CORRSHIFTSZ-(3*`NF+6){1'b0}}} : DivOp&~DivResDenorm ? CorrQuotShifted[`CORRSHIFTSZ-1:0] : Shifted[`NORMSHIFTSZ-1:`NORMSHIFTSZ-`CORRSHIFTSZ]; // Determine sum's exponent // if plus1 If plus2 if said denorm but norm plus 1 if said denorm but norm plus 2 assign SumExp = (ConvNormSumExp+{{`NE+1{1'b0}}, LZAPlus1&~KillProdM}+{{`NE{1'b0}}, LZAPlus2&~KillProdM, 1'b0}+{{`NE+1{1'b0}}, ~ResDenorm&PreResultDenorm&~KillProdM}+{{`NE+1{1'b0}}, &ConvNormSumExp&Shifted[3*`NF+6]&~KillProdM}) & {`NE+2{~(SumZero|ResDenorm)}}; // recalculate if the result is denormalized assign ResDenorm = PreResultDenorm&~Shifted[`NORMSHIFTSZ-3]&~Shifted[`NORMSHIFTSZ-2]; + // the quotent is in the range [.5,2) if there is no early termination + // if the quotent < 1 and not denormal then subtract 1 to account for the normalization shift + assign CorrDivExp = ((DivResDenorm)&~DivDenormShift[`NE+1]) ? (`NE+2)'(0) : DivCalcExpM - {(`NE+1)'(0), ~LZAPlus2}; endmodule \ No newline at end of file diff --git a/pipelined/src/fpu/postprocess.sv b/pipelined/src/fpu/postprocess.sv index b77b013d1..ab06a9406 100644 --- a/pipelined/src/fpu/postprocess.sv +++ b/pipelined/src/fpu/postprocess.sv @@ -49,10 +49,13 @@ module postprocess( input logic ZSgnEffM, // the modified Z sign - depends on instruction input logic PSgnM, // the product's sign input logic [2:0] FOpCtrlM, // choose which opperation (look below for values) + input logic [$clog2(`DIVLEN/2+3)-1:0] EarlyTermShiftDiv2M, input logic [$clog2(3*`NF+7)-1:0] FmaNormCntM, // the normalization shift count input logic [`NE:0] CvtCalcExpM, // the calculated expoent - input logic [`NE:0] DivCalcExpM, // the calculated expoent + input logic [`NE+1:0] DivCalcExpM, // the calculated expoent input logic CvtResDenormUfM, + input logic DivStickyM, + input logic DivNegStickyM, input logic [`LOGCVTLEN-1:0] CvtShiftAmtM, // how much to shift by input logic CvtResSgnM, // the result's sign input logic FWriteIntM, // is fp->int (since it's writting to the integer register) @@ -86,6 +89,7 @@ module postprocess( logic [$clog2(`NORMSHIFTSZ)-1:0] ShiftAmt; // normalization shift count logic [$clog2(`NORMSHIFTSZ)-1:0] DivShiftAmt; logic [`NORMSHIFTSZ-1:0] ShiftIn; // is the sum zero + logic [`NORMSHIFTSZ-1:0] DivShiftIn; logic [`NORMSHIFTSZ-1:0] Shifted; // the shifted result logic Plus1; // add one to the final result? logic IntInvalid, Overflow, Underflow, Invalid; // flags @@ -94,7 +98,7 @@ module postprocess( logic IntToFp; // is the opperation an int->fp conversion? logic ToInt; // is the opperation an fp->int conversion? logic [`NE+1:0] RoundExp; - logic [`NE:0] CorrDivExp; + logic [`NE+1:0] CorrDivExp; logic [1:0] NegResMSBS; logic CvtOp; logic FmaOp; @@ -108,6 +112,8 @@ module postprocess( logic UfLSBRes; logic Sqrt; logic [`FMTBITS-1:0] OutFmt; + logic DivResDenorm; + logic [`NE+1:0] DivDenormShift; // signals to help readability assign Signed = FOpCtrlM[0]; @@ -140,7 +146,7 @@ module postprocess( .XZeroM, .IntToFp, .OutFmt, .CvtResUf, .CvtShiftIn); fmashiftcalc fmashiftcalc(.SumM, .ZExpM, .ProdExpM, .FmaNormCntM, .FmtM, .KillProdM, .ConvNormSumExp, .ZDenormM, .SumZero, .PreResultDenorm, .FmaShiftAmt, .FmaShiftIn); - divshiftcalc divshiftcalc(.Quot, .DivCalcExpM, .CorrDivExp, .DivShiftAmt); + divshiftcalc divshiftcalc(.FmtM, .Quot, .DivCalcExpM, .EarlyTermShiftDiv2M, .DivResDenorm, .DivDenormShift, .DivShiftAmt, .DivShiftIn); always_comb case(PostProcSelM) @@ -154,7 +160,7 @@ module postprocess( end 2'b01: begin //div ***prob can take out ShiftAmt = DivShiftAmt; - ShiftIn = {Quot[`DIVLEN+1:0], {`NORMSHIFTSZ-`DIVLEN-2{1'b0}}}; + ShiftIn = DivShiftIn; end default: begin ShiftAmt = {$clog2(`NORMSHIFTSZ){1'bx}}; @@ -165,7 +171,8 @@ module postprocess( normshift normshift (.ShiftIn, .ShiftAmt, .Shifted); lzacorrection lzacorrection(.FmaOp, .KillProdM, .PreResultDenorm, .ConvNormSumExp, - .SumZero, .Shifted, .SumExp, .CorrShifted); + .DivResDenorm, .DivDenormShift, .DivOp, .DivCalcExpM, + .CorrDivExp, .SumZero, .Shifted, .SumExp, .CorrShifted); /////////////////////////////////////////////////////////////////////////////// // Rounding @@ -179,6 +186,7 @@ module postprocess( round round(.OutFmt, .FrmM, .Sticky, .AddendStickyM, .ZZeroM, .Plus1, .PostProcSelM, .CvtCalcExpM, .CorrDivExp, .InvZM, .RoundSgn, .SumExp, .FmaOp, .CvtOp, .CvtResDenormUfM, .CorrShifted, .ToInt, .CvtResUf, + .DivStickyM, .DivNegStickyM, .DivOp, .UfPlus1, .FullResExp, .ResFrac, .ResExp, .Round, .RoundAdd, .UfLSBRes, .RoundExp); /////////////////////////////////////////////////////////////////////////////// @@ -206,6 +214,7 @@ module postprocess( resultselect resultselect(.XSgnM, .ZExpM, .XManM, .YManM, .ZManM, .ZDenormM, .ZZeroM, .XZeroM, .IntInvalid, .IntZeroM, .FrmM, .OutFmt, .AddendStickyM, .KillProdM, .XNaNM, .YNaNM, .ZNaNM, .RoundAdd, .CvtResUf, .NaNIn, .IntToFp, .Int64, .Signed, .CvtOp, .FmaOp, .Plus1, .Invalid, .Overflow, .InfIn, .NegResMSBS, + .XInfM, .YInfM, .DivOp, .DivByZero, .FullResExp, .Shifted, .CvtCalcExpM, .ResSgn, .ResExp, .ResFrac, .PostProcResM, .FCvtIntResM); endmodule diff --git a/pipelined/src/fpu/resultselect.sv b/pipelined/src/fpu/resultselect.sv index 9be046a3a..d6d15e46f 100644 --- a/pipelined/src/fpu/resultselect.sv +++ b/pipelined/src/fpu/resultselect.sv @@ -7,6 +7,9 @@ module resultselect( input logic [2:0] FrmM, // rounding mode 000 = rount to nearest, ties to even 001 = round twords zero 010 = round down 011 = round up 100 = round to nearest, ties to max magnitude input logic [`FMTBITS-1:0] OutFmt, // output format input logic InfIn, + input logic XInfM, + input logic YInfM, + input logic DivOp, input logic XZeroM, input logic IntZeroM, input logic NaNIn, @@ -35,16 +38,17 @@ module resultselect( output logic [1:0] NegResMSBS, output logic [`XLEN-1:0] FCvtIntResM // final res ); - logic [`FLEN-1:0] XNaNRes, YNaNRes, ZNaNRes, InvalidRes, OfRes, KillProdRes, UfRes, NormRes; // possible results + logic [`FLEN-1:0] XNaNRes, YNaNRes, ZNaNRes, InvalidRes, OfRes, UfRes, NormRes; // possible results logic OfResMax; logic [`XLEN-1:0] OfIntRes; // the overflow result for integer output logic [`XLEN+1:0] NegRes; // the negation of the result logic KillRes; + logic SelOfRes; // does the overflow result output the maximum normalized floating point number // output infinity if the input is infinity - assign OfResMax = (~InfIn|(IntToFp&CvtOp))&((FrmM[1:0]==2'b01) | (FrmM[1:0]==2'b10&~ResSgn) | (FrmM[1:0]==2'b11&ResSgn)); + assign OfResMax = (~InfIn|(IntToFp&CvtOp))&~DivByZero&((FrmM[1:0]==2'b01) | (FrmM[1:0]==2'b10&~ResSgn) | (FrmM[1:0]==2'b11&ResSgn)); if (`FPSIZES == 1) begin @@ -59,8 +63,7 @@ module resultselect( end assign OfRes = OfResMax ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}}; - assign KillProdRes = {ResSgn, {ZExpM[`NE-1:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:0]} + (RoundAdd[`FLEN-2:0]&{`FLEN-1{AddendStickyM}})}; - assign UfRes = {ResSgn, {`FLEN-1{1'b0}}} + {(`FLEN-1)'(0),Plus1&FrmM[1]}; + assign UfRes = {ResSgn, {`FLEN-1{1'b0}}, Plus1&FrmM[1]&~(DivOp&YInfM)}; assign NormRes = {ResSgn, ResExp, ResFrac}; end else if (`FPSIZES == 2) begin //will the format conversion in killprod work in other conversions? @@ -75,8 +78,7 @@ module resultselect( assign OfRes = OutFmt ? OfResMax ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}} : OfResMax ? {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1-1{1'b1}}, 1'b0, {`NF1{1'b1}}} : {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1{1'b1}}, (`NF1)'(0)}; - assign KillProdRes = OutFmt ? {ResSgn, {ZExpM[`NE-1:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:0]} + (RoundAdd[`FLEN-2:0]&{`FLEN-1{AddendStickyM}})} : {{`FLEN-`LEN1{1'b1}}, ResSgn, {ZExpM[`NE-1], ZExpM[`NE1-2:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:`NF-`NF1]} + (RoundAdd[`NF-`NF1+`LEN1-2:`NF-`NF1]&{`LEN1-1{AddendStickyM}})}; - assign UfRes = OutFmt ? {ResSgn, {`FLEN-1{1'b0}}} + {(`FLEN-1)'(0),Plus1&FrmM[1]} : {{`FLEN-`LEN1{1'b1}}, {ResSgn, (`LEN1-1)'(0)} + {(`LEN1-1)'(0), Plus1&FrmM[1]}}; + assign UfRes = OutFmt ? {ResSgn, (`FLEN-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)} : {{`FLEN-`LEN1{1'b1}}, ResSgn, (`LEN1-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; assign NormRes = OutFmt ? {ResSgn, ResExp, ResFrac} : {{`FLEN-`LEN1{1'b1}}, ResSgn, ResExp[`NE1-1:0], ResFrac[`NF-1:`NF-`NF1]}; end else if (`FPSIZES == 3) begin @@ -93,8 +95,7 @@ module resultselect( end OfRes = OfResMax ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}}; - KillProdRes = {ResSgn, {ZExpM[`NE-1:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:0]} + (RoundAdd[`FLEN-2:0]&{`FLEN-1{AddendStickyM}})}; - UfRes = {ResSgn, {`FLEN-1{1'b0}}} + {(`FLEN-1)'(0),Plus1&FrmM[1]}; + UfRes = {ResSgn, (`FLEN-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; NormRes = {ResSgn, ResExp, ResFrac}; end `FMT1: begin @@ -107,8 +108,7 @@ module resultselect( InvalidRes = {{`FLEN-`LEN1{1'b1}}, 1'b0, {`NE1{1'b1}}, 1'b1, (`NF1-1)'(0)}; end OfRes = OfResMax ? {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1-1{1'b1}}, 1'b0, {`NF1{1'b1}}} : {{`FLEN-`LEN1{1'b1}}, ResSgn, {`NE1{1'b1}}, (`NF1)'(0)}; - KillProdRes = {{`FLEN-`LEN1{1'b1}}, ResSgn, {ZExpM[`NE-1], ZExpM[`NE1-2:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:`NF-`NF1]} + (RoundAdd[`NF-`NF1+`LEN1-2:`NF-`NF1]&{`LEN1-1{AddendStickyM}})}; - UfRes = {{`FLEN-`LEN1{1'b1}}, {ResSgn, (`LEN1-1)'(0)} + {(`LEN1-1)'(0), Plus1&FrmM[1]}}; + UfRes = {{`FLEN-`LEN1{1'b1}}, ResSgn, (`LEN1-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; NormRes = {{`FLEN-`LEN1{1'b1}}, ResSgn, ResExp[`NE1-1:0], ResFrac[`NF-1:`NF-`NF1]}; end `FMT2: begin @@ -122,8 +122,7 @@ module resultselect( end OfRes = OfResMax ? {{`FLEN-`LEN2{1'b1}}, ResSgn, {`NE2-1{1'b1}}, 1'b0, {`NF2{1'b1}}} : {{`FLEN-`LEN2{1'b1}}, ResSgn, {`NE2{1'b1}}, (`NF2)'(0)}; - KillProdRes = {{`FLEN-`LEN2{1'b1}}, ResSgn, {ZExpM[`NE-1], ZExpM[`NE2-2:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:`NF-`NF2]} + (RoundAdd[`NF-`NF2+`LEN2-2:`NF-`NF2]&{`LEN2-1{AddendStickyM}})}; - UfRes = {{`FLEN-`LEN2{1'b1}}, {ResSgn, (`LEN2-1)'(0)} + {(`LEN2-1)'(0), Plus1&FrmM[1]}}; + UfRes = {{`FLEN-`LEN2{1'b1}}, ResSgn, (`LEN2-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; NormRes = {{`FLEN-`LEN2{1'b1}}, ResSgn, ResExp[`NE2-1:0], ResFrac[`NF-1:`NF-`NF2]}; end default: begin @@ -136,7 +135,6 @@ module resultselect( InvalidRes = (`FLEN)'(0); end OfRes = (`FLEN)'(0); - KillProdRes = (`FLEN)'(0); UfRes = (`FLEN)'(0); NormRes = (`FLEN)'(0); end @@ -156,8 +154,7 @@ module resultselect( end OfRes = OfResMax ? {ResSgn, {`NE-1{1'b1}}, 1'b0, {`NF{1'b1}}} : {ResSgn, {`NE{1'b1}}, {`NF{1'b0}}}; - KillProdRes = {ResSgn, {ZExpM[`Q_NE-1:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:0]} + (RoundAdd[`FLEN-2:0]&{`FLEN-1{AddendStickyM}})}; - UfRes = {ResSgn, {`FLEN-1{1'b0}}} + {(`FLEN-1)'(0),Plus1&FrmM[1]}; + UfRes = {ResSgn, (`FLEN-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; NormRes = {ResSgn, ResExp, ResFrac}; end 2'h1: begin @@ -170,8 +167,7 @@ module resultselect( InvalidRes = {{`FLEN-`D_LEN{1'b1}}, 1'b0, {`D_NE{1'b1}}, 1'b1, (`D_NF-1)'(0)}; end OfRes = OfResMax ? {{`FLEN-`D_LEN{1'b1}}, ResSgn, {`D_NE-1{1'b1}}, 1'b0, {`D_NF{1'b1}}} : {{`FLEN-`D_LEN{1'b1}}, ResSgn, {`D_NE{1'b1}}, (`D_NF)'(0)}; - KillProdRes = {{`FLEN-`D_LEN{1'b1}}, ResSgn, {ZExpM[`NE-1], ZExpM[`D_NE-2:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:`NF-`D_NF]} + (RoundAdd[`NF-`D_NF+`D_LEN-2:`NF-`D_NF]&{`D_LEN-1{AddendStickyM}})}; - UfRes = {{`FLEN-`D_LEN{1'b1}}, {ResSgn, (`D_LEN-1)'(0)} + {(`D_LEN-1)'(0), Plus1&FrmM[1]}}; + UfRes = {{`FLEN-`D_LEN{1'b1}}, ResSgn, (`D_LEN-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; NormRes = {{`FLEN-`D_LEN{1'b1}}, ResSgn, ResExp[`D_NE-1:0], ResFrac[`NF-1:`NF-`D_NF]}; end 2'h0: begin @@ -185,8 +181,7 @@ module resultselect( end OfRes = OfResMax ? {{`FLEN-`S_LEN{1'b1}}, ResSgn, {`S_NE-1{1'b1}}, 1'b0, {`S_NF{1'b1}}} : {{`FLEN-`S_LEN{1'b1}}, ResSgn, {`S_NE{1'b1}}, (`S_NF)'(0)}; - KillProdRes = {{`FLEN-`S_LEN{1'b1}}, ResSgn, {ZExpM[`NE-1], ZExpM[`S_NE-2:1], ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:`NF-`S_NF]} + (RoundAdd[`NF-`S_NF+`S_LEN-2:`NF-`S_NF]&{`S_LEN-1{AddendStickyM}})}; - UfRes = {{`FLEN-`S_LEN{1'b1}}, {ResSgn, (`S_LEN-1)'(0)} + {(`S_LEN-1)'(0), Plus1&FrmM[1]}}; + UfRes = {{`FLEN-`S_LEN{1'b1}}, ResSgn, (`S_LEN-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; NormRes = {{`FLEN-`S_LEN{1'b1}}, ResSgn, ResExp[`S_NE-1:0], ResFrac[`NF-1:`NF-`S_NF]}; end 2'h2: begin @@ -200,9 +195,8 @@ module resultselect( end OfRes = OfResMax ? {{`FLEN-`H_LEN{1'b1}}, ResSgn, {`H_NE-1{1'b1}}, 1'b0, {`H_NF{1'b1}}} : {{`FLEN-`H_LEN{1'b1}}, ResSgn, {`H_NE{1'b1}}, (`H_NF)'(0)}; - - KillProdRes = {{`FLEN-`H_LEN{1'b1}}, ResSgn, {ZExpM[`NE-1], ZExpM[`H_NE-2:1],ZExpM[0]&~(ZDenormM|ZZeroM), ZManM[`NF-1:`NF-`H_NF]} + (RoundAdd[`NF-`H_NF+`H_LEN-2:`NF-`H_NF]&{`H_LEN-1{AddendStickyM}})}; - UfRes = {{`FLEN-`H_LEN{1'b1}}, {ResSgn, (`H_LEN-1)'(0)} + {(`H_LEN-1)'(0), Plus1&FrmM[1]}}; + // zero is exact fi dividing by infinity so don't add 1 + UfRes = {{`FLEN-`H_LEN{1'b1}}, ResSgn, (`H_LEN-2)'(0), Plus1&FrmM[1]&~(DivOp&YInfM)}; NormRes = {{`FLEN-`H_LEN{1'b1}}, ResSgn, ResExp[`H_NE-1:0], ResFrac[`NF-1:`NF-`H_NF]}; end endcase @@ -217,22 +211,20 @@ module resultselect( // - do so if the res underflows, is zero (the exp doesnt calculate correctly). or the integer input is 0 // - dont set to zero if fp input is zero but not using the fp input // - dont set to zero if int input is zero but not using the int input - assign KillRes = CvtOp ? (CvtResUf|(XZeroM&~IntToFp)|(IntZeroM&IntToFp)) : FullResExp[`NE+1];//Underflow & ~ResDenorm & (ResExp!=1); - + assign KillRes = CvtOp ? (CvtResUf|(XZeroM&~IntToFp)|(IntZeroM&IntToFp)) : FullResExp[`NE+1] | (((YInfM&~XInfM)|XZeroM)&DivOp);//Underflow & ~ResDenorm & (ResExp!=1); + assign SelOfRes = Overflow|DivByZero|(InfIn&~(YInfM&DivOp)); // output infinity with result sign if divide by zero if(`IEEE754) begin assign PostProcResM = XNaNM&~(IntToFp&CvtOp) ? XNaNRes : YNaNM&~CvtOp ? YNaNRes : ZNaNM&FmaOp ? ZNaNRes : Invalid ? InvalidRes : - Overflow|DivByZero|InfIn ? OfRes : - KillProdM&FmaOp ? KillProdRes : + SelOfRes ? OfRes : KillRes ? UfRes : NormRes; end else begin assign PostProcResM = NaNIn|Invalid ? InvalidRes : - Overflow|DivByZero|InfIn ? OfRes : - KillProdM&FmaOp ? KillProdRes : + SelOfRes ? OfRes : KillRes ? UfRes : NormRes; end diff --git a/pipelined/src/fpu/round.sv b/pipelined/src/fpu/round.sv index 73395caed..7d4153118 100644 --- a/pipelined/src/fpu/round.sv +++ b/pipelined/src/fpu/round.sv @@ -24,7 +24,9 @@ module round( input logic [`NE+1:0] SumExp, // exponent of the normalized sum input logic RoundSgn, // the result's sign input logic [`NE:0] CvtCalcExpM, // the calculated expoent - input logic [`NE:0] CorrDivExp, // the calculated expoent + input logic [`NE+1:0] CorrDivExp, // the calculated expoent + input logic DivStickyM, // sticky bit + input logic DivNegStickyM, output logic UfPlus1, // do you add or subtract on from the result output logic [`NE+1:0] FullResExp, // ResExp with bits to determine sign and overflow output logic [`NF-1:0] ResFrac, // Result fraction @@ -149,7 +151,7 @@ module round( // only add the Addend sticky if doing an FMA opperation // - the shifter shifts too far left when there's an underflow (shifting out all possible sticky bits) - assign UfSticky = AddendStickyM&FmaOp | NormSumSticky | CvtResUf&CvtOp | SumExp[`NE+1]&FmaOp; + assign UfSticky = AddendStickyM&FmaOp | NormSumSticky | CvtResUf&CvtOp | SumExp[`NE+1]&FmaOp | DivStickyM&DivOp; // determine round and LSB of the rounded value // - underflow round bit is used to determint the underflow flag @@ -223,9 +225,11 @@ module round( assign Sticky = UfSticky | UfRound; - // Deterimine if a small number was supposed to be subtrated - For Fma calculation only - assign SubBySmallNum = AddendStickyM & InvZM & ~(NormSumSticky|UfRound) & ~ZZeroM & FmaOp; - assign UfSubBySmallNum = AddendStickyM & InvZM & ~(NormSumSticky) & ~ZZeroM & FmaOp; + // Deterimine if a small number was supposed to be subtrated + // - for FMA or if division has a negitive sticky bit + assign SubBySmallNum = ((AddendStickyM&FmaOp&~ZZeroM&InvZM) | (DivNegStickyM&DivOp)) & ~(NormSumSticky|UfRound); + assign UfSubBySmallNum = ((AddendStickyM&FmaOp&~ZZeroM&InvZM) | (DivNegStickyM&DivOp)) & ~NormSumSticky; + always_comb begin // Determine if you add 1 @@ -305,7 +309,7 @@ module round( case(PostProcSelM) 2'b10: RoundExp = SumExp; // fma 2'b00: RoundExp = {CvtCalcExpM[`NE], CvtCalcExpM}&{`NE+2{~CvtResDenormUfM|CvtResUf}}; // cvt - 2'b01: RoundExp = {CorrDivExp[`NE], CorrDivExp[`NE:0]}; // divide + 2'b01: RoundExp = CorrDivExp; // divide default: RoundExp = 0; endcase diff --git a/pipelined/srt/Makefile b/pipelined/srt/Makefile index 49b21be7a..f2ed6f8ca 100644 --- a/pipelined/srt/Makefile +++ b/pipelined/srt/Makefile @@ -23,5 +23,10 @@ qslc_sqrt_r4a2: qslc_sqrt_r4a2.c gcc qslc_sqrt_r4a2.c -o qslc_sqrt_r4a2 -lm ./qslc_sqrt_r4a2 > qslc_sqrt_r4a2.sv +inttestgen: inttestgen.c + gcc -lm -o inttestgen inttestgen.c + ./inttestgen + clean: rm -f testgen exptestgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 + diff --git a/pipelined/srt/exptestgen.c b/pipelined/srt/exptestgen.c index bd51126e7..61fe74aa4 100644 --- a/pipelined/srt/exptestgen.c +++ b/pipelined/srt/exptestgen.c @@ -46,7 +46,7 @@ void main(void) int i, j; int bias = 1023; - if ((fptr = fopen("testvectors","w")) == NULL) { + if ((fptr = fopen("testvectors","w")) == NULL) { fprintf(stderr, "Couldn't write testvectors file\n"); exit(1); } diff --git a/pipelined/srt/srt-radix4.sv b/pipelined/srt/srt-radix4.sv index 8fd8d5419..179fbf45a 100644 --- a/pipelined/srt/srt-radix4.sv +++ b/pipelined/srt/srt-radix4.sv @@ -36,41 +36,45 @@ module srtradix4 ( input logic [`NE-1:0] XExpE, YExpE, input logic [`NF:0] XManE, YManE, input logic [`XLEN-1:0] SrcA, SrcB, - input logic XZeroE, + input logic XInfE, YInfE, + input logic XZeroE, YZeroE, + input logic XNaNE, YNaNE, input logic W64, // 32-bit ints on XLEN=64 input logic Signed, // Interpret integers as signed 2's complement input logic Int, // Choose integer inputs input logic Sqrt, // perform square root, not divide + output logic [$clog2(`DIVLEN/2+3)-1:0] EarlyTermShiftDiv2E, output logic DivDone, + output logic DivStickyE, + output logic DivNegStickyE, output logic [`DIVLEN+2:0] Quot, output logic [`XLEN-1:0] Rem, // *** later handle integers - output logic [`NE:0] DivCalcExpE + output logic [`NE+1:0] DivCalcExpE ); - // logic qp, qz, qm; // quotient is +1, 0, or -1 logic [3:0] q; - logic [`NE:0] DivCalcExp; - logic [`DIVLEN:0] X; + logic [`NE+1:0] DivCalcExp; + logic [`DIVLEN-1:0] X; logic [`DIVLEN-1:0] Dpreproc; logic [`DIVLEN+3:0] WS, WSA, WSN; logic [`DIVLEN+3:0] WC, WCA, WCN; logic [`DIVLEN+3:0] D, DBar, D2, DBar2, Dsel; logic [$clog2(`XLEN+1)-1:0] intExp; + logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt; logic intSign; - srtpreproc preproc(SrcA, SrcB, XManE, YManE, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, intSign); + srtpreproc preproc(.SrcA, .SrcB, .XManE, .YManE, .W64, .Signed, .Int, .Sqrt, .X, + .XZeroCnt, .YZeroCnt, .Dpreproc, .intExp, .intSign); // Top Muxes and Registers // When start is asserted, the inputs are loaded into the divider. // Otherwise, the divisor is retained and the partial remainder // is fed back for the next iteration. - // - assumed one is added here since all numbers are normlaized - // *** wait what about zero? is that specal case? can the divider handle it? // - when the start signal is asserted X and 0 are loaded into WS and WC // - otherwise load WSA into the flipflop - // *** what does N and A stand for? - // *** change shift amount for radix4 - mux2 #(`DIVLEN+4) wsmux({WSA[`DIVLEN+1:0], 2'b0}, {3'b000, X}, DivStart, WSN); + // - the assumed one is added to D since it's always normalized (and X/0 is a special case handeled by result selection) + // - XZeroE is used as the assumed one to avoid creating a sticky bit - all other numbers are normalized + mux2 #(`DIVLEN+4) wsmux({WSA[`DIVLEN+1:0], 2'b0}, {3'b000, ~XZeroE, X}, DivStart, WSN); flop #(`DIVLEN+4) wsflop(clk, WSN, WS); mux2 #(`DIVLEN+4) wcmux({WCA[`DIVLEN+1:0], 2'b0}, {`DIVLEN+4{1'b0}}, DivStart, WCN); flop #(`DIVLEN+4) wcflop(clk, WCN, WC); @@ -88,7 +92,7 @@ module srtradix4 ( qsel4 qsel4(.D, .WS, .WC, .q); // Store the expoenent and sign until division is DivDone - flopen #(`NE+1) expflop(clk, DivStart, DivCalcExp, DivCalcExpE); + flopen #(`NE+2) expflop(clk, DivStart, DivCalcExp, DivCalcExpE); // Divisor Selection logic // *** radix 4 change to choose -2 to 2 @@ -114,9 +118,10 @@ module srtradix4 ( //*** change for radix 4 otfc4 otfc4(.clk, .DivStart, .q, .Quot); - expcalc expcalc(.XExpE, .YExpE, .XZeroE, .DivCalcExp); + expcalc expcalc(.XExpE, .YExpE, .XZeroE, .XZeroCnt, .YZeroCnt, .DivCalcExp); - divcounter divcounter(clk, DivStart, DivDone); + earlytermination earlytermination(.clk, .WC, .WS, .XZeroE, .YZeroE, .XInfE, .EarlyTermShiftDiv2E, + .YInfE, .XNaNE, .YNaNE, .DivStickyE, .DivNegStickyE, .DivStart, .DivDone); endmodule @@ -124,28 +129,35 @@ endmodule // Submodules // //////////////// -///////////// -// counter // -///////////// -module divcounter(input logic clk, - input logic DivStart, - output logic DivDone); +module earlytermination( + input logic clk, + input logic [`DIVLEN+3:0] WS, WC, + input logic XInfE, YInfE, + input logic XZeroE, YZeroE, + input logic XNaNE, YNaNE, + input logic DivStart, + output logic [$clog2(`DIVLEN/2+3)-1:0] EarlyTermShiftDiv2E, + output logic DivStickyE, + output logic DivNegStickyE, + output logic DivDone); - logic [5:0] count; - - // This block of control logic sequences the divider - // through its iterations. You may modify it if you - // build a divider which completes in fewer iterations. - // You are not responsible for the (trivial) circuit - // design of the block. + logic [$clog2(`DIVLEN/2+3)-1:0] Count; + logic WZero; + assign WZero = (WS+WC == 0)|XZeroE|YZeroE|XInfE|YInfE|XNaNE|YNaNE; //*** temporary + // *** rather than Counting should just be able to check if one of the two msbs of the quotent is 1 then stop??? + assign DivDone = (DivStickyE | WZero); + assign DivStickyE = ~|Count; + assign DivNegStickyE = $signed(WS+WC) < 0; + assign EarlyTermShiftDiv2E = Count; + // +1 for setup + // `DIVLEN/2 to get required number of bits + // +1 for possible .5 and round bit + // Count down Counter always @(posedge clk) begin - DivDone = 0; - if (count == `DIVLEN/2+1) DivDone <= #1 1; - else if (DivDone | DivStart) DivDone <= #1 0; - if (DivStart) count <= #1 0; - else count <= #1 count+1; + if (DivStart) Count <= #1 `DIVLEN/2+2; + else Count <= #1 Count-1; end endmodule @@ -231,31 +243,34 @@ module srtpreproc ( input logic Signed, // Interpret integers as signed 2's complement input logic Int, // Choose integer inputs input logic Sqrt, // perform square root, not divide - output logic [`DIVLEN:0] X, + output logic [`DIVLEN-1:0] X, output logic [`DIVLEN-1:0] Dpreproc, + output logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt, output logic [$clog2(`XLEN+1)-1:0] intExp, // Quotient integer exponent output logic intSign // Quotient integer sign ); - - // logic [$clog2(`XLEN+1)-1:0] zeroCntA, zeroCntB; // logic [`XLEN-1:0] PosA, PosB; // logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY; - logic [`DIVLEN:0] PreprocA, PreprocX; + logic [`DIVLEN-1:0] PreprocA, PreprocX; logic [`DIVLEN-1:0] PreprocB, PreprocY; // assign PosA = (Signed & SrcA[`XLEN - 1]) ? -SrcA : SrcA; // assign PosB = (Signed & SrcB[`XLEN - 1]) ? -SrcB : SrcB; - // lzc #(`XLEN) lzcA (PosA, zeroCntA); // lzc #(`XLEN) lzcB (PosB, zeroCntB); + // ***can probably merge X LZC with conversion + // cout the number of leading zeros + lzc #(`NF+1) lzcA (XManE, XZeroCnt); + lzc #(`NF+1) lzcB (YManE, YZeroCnt); + // assign ExtraA = {PosA, {`DIVLEN-`XLEN{1'b0}}}; // assign ExtraB = {PosB, {`DIVLEN-`XLEN{1'b0}}}; // assign PreprocA = ExtraA << zeroCntA; // assign PreprocB = ExtraB << (zeroCntB + 1); - assign PreprocX = {XManE, {`DIVLEN-`NF{1'b0}}}; - assign PreprocY = {YManE[`NF-1:0], {`DIVLEN-`NF{1'b0}}}; + assign PreprocX = {XManE[`NF-1:0]<