diff --git a/pipelined/src/fpu/divshiftcalc.sv b/pipelined/src/fpu/divshiftcalc.sv index 57022e5ae..398e8f467 100644 --- a/pipelined/src/fpu/divshiftcalc.sv +++ b/pipelined/src/fpu/divshiftcalc.sv @@ -2,9 +2,9 @@ module divshiftcalc( input logic [`DIVLEN+2:0] Quot, - input logic [`NE:0] DivCalcExpM, + input logic [`NE+1:0] DivCalcExpM, output logic [$clog2(`NORMSHIFTSZ)-1:0] DivShiftAmt, - output logic [`NE:0] CorrDivExp + output logic [`NE+1:0] CorrDivExp ); assign DivShiftAmt = {{$clog2(`NORMSHIFTSZ)-1{1'b0}}, ~Quot[`DIVLEN+2]}; diff --git a/pipelined/src/fpu/flags.sv b/pipelined/src/fpu/flags.sv index 3268aa1fd..122df8b21 100644 --- a/pipelined/src/fpu/flags.sv +++ b/pipelined/src/fpu/flags.sv @@ -133,8 +133,8 @@ module flags( assign Invalid = SigNaN | (FmaInvalid&FmaOp) | (DivInvalid&DivOp); - - assign DivByZero = YZeroM&DivOp; + // if dividing by zero and not 0/0 + assign DivByZero = YZeroM&DivOp&~XZeroM; // Combine flags // - to integer results do not set the underflow or overflow flags diff --git a/pipelined/src/fpu/fpu.sv b/pipelined/src/fpu/fpu.sv index ff83079a8..2f43b27d4 100755 --- a/pipelined/src/fpu/fpu.sv +++ b/pipelined/src/fpu/fpu.sv @@ -124,7 +124,9 @@ module fpu ( //divide signals logic [`DIVLEN+2:0] Quot; - logic [`NE:0] DivCalcExpM; + logic [`NE+1:0] DivCalcExpM; + logic DivNegStickyM; + logic DivStickyM; // result and flag signals logic [63:0] FDivResM, FDivResW; // divide/squareroot result @@ -358,8 +360,8 @@ module fpu ( postprocess postprocess(.XSgnM, .YSgnM, .ZExpM, .XManM, .YManM, .ZManM, .FrmM, .FmtM, .ProdExpM, .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/postprocess.sv b/pipelined/src/fpu/postprocess.sv index b77b013d1..9516e223f 100644 --- a/pipelined/src/fpu/postprocess.sv +++ b/pipelined/src/fpu/postprocess.sv @@ -51,8 +51,10 @@ module postprocess( input logic [2:0] FOpCtrlM, // choose which opperation (look below for values) 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) @@ -94,7 +96,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; @@ -179,6 +181,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); /////////////////////////////////////////////////////////////////////////////// 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/srt-radix4.sv b/pipelined/srt/srt-radix4.sv index 8fd8d5419..eface008d 100644 --- a/pipelined/srt/srt-radix4.sv +++ b/pipelined/srt/srt-radix4.sv @@ -42,23 +42,27 @@ module srtradix4 ( input logic Int, // Choose integer inputs input logic Sqrt, // perform square root, not divide 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 [`NE+1:0] DivCalcExp; logic [`DIVLEN: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. @@ -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 @@ -113,8 +117,10 @@ module srtradix4 ( //*** change for radix 4 otfc4 otfc4(.clk, .DivStart, .q, .Quot); + assign DivStickyE = (WS+WC) != 0; //replace with early termination + assign DivNegStickyE = $signed(WS+WC) < 0; //replace with early termination - expcalc expcalc(.XExpE, .YExpE, .XZeroE, .DivCalcExp); + expcalc expcalc(.XExpE, .YExpE, .XZeroE, .XZeroCnt, .YZeroCnt, .DivCalcExp); divcounter divcounter(clk, DivStart, DivDone); @@ -233,11 +239,10 @@ module srtpreproc ( input logic Sqrt, // perform square root, not divide output logic [`DIVLEN: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; @@ -245,17 +250,21 @@ module srtpreproc ( // 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<