added denormal input handeling - radix 4

This commit is contained in:
Katherine Parry 2022-06-24 19:41:40 +00:00
parent b5c20bf112
commit 9eefba5b58
7 changed files with 54 additions and 33 deletions

View File

@ -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]};

View File

@ -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

View File

@ -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

View File

@ -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);
///////////////////////////////////////////////////////////////////////////////

View File

@ -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

View File

@ -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<<XZeroCnt, {`DIVLEN-`NF{1'b0}}};
assign PreprocY = {YManE[`NF-1:0]<<YZeroCnt, {`DIVLEN-`NF{1'b0}}};
assign X = Int ? PreprocA : PreprocX;
@ -358,9 +367,11 @@ endmodule
module expcalc(
input logic [`NE-1:0] XExpE, YExpE,
input logic XZeroE,
output logic [`NE:0] DivCalcExp
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
output logic [`NE+1:0] DivCalcExp
);
assign DivCalcExp = (XExpE - YExpE + (`NE)'(`BIAS))&{`NE+1{~XZeroE}};
// correct exponent for denormal shifts
assign DivCalcExp = (XExpE - XZeroCnt - YExpE + YZeroCnt + (`NE)'(`BIAS))&{`NE+1{~XZeroE}};
endmodule

View File

@ -69,8 +69,9 @@ module testbenchfp;
logic NegSumE;
logic ZSgnEffE;
logic PSgnE;
logic DivSgn;
logic [`NE:0] DivCalcExp;
logic DivSticky;
logic DivNegSticky;
logic [`NE+1:0] DivCalcExp;
///////////////////////////////////////////////////////////////////////////////////////////////
@ -644,8 +645,8 @@ module testbenchfp;
postprocess postprocess(.XSgnM(XSgn), .YSgnM(YSgn), .PostProcSelM(UnitVal[1:0]),
.ZExpM(ZExp), .ZDenormM(ZDenorm), .FOpCtrlM(OpCtrlVal), .Quot, .DivCalcExpM(DivCalcExp),
.XManM(XMan), .YManM(YMan), .ZManM(ZMan), .CvtCalcExpM(CvtCalcExpE),
.XNaNM(XNaN), .YNaNM(YNaN), .ZNaNM(ZNaN), .CvtResDenormUfM(CvtResDenormUfE),
.XManM(XMan), .YManM(YMan), .ZManM(ZMan), .CvtCalcExpM(CvtCalcExpE), .DivStickyM(DivSticky),
.XNaNM(XNaN), .YNaNM(YNaN), .ZNaNM(ZNaN), .CvtResDenormUfM(CvtResDenormUfE), .DivNegStickyM(DivNegSticky),
.XZeroM(XZero), .YZeroM(YZero), .ZZeroM(ZZero), .CvtShiftAmtM(CvtShiftAmtE),
.XInfM(XInf), .YInfM(YInf), .ZInfM(ZInf), .CvtResSgnM(CvtResSgnE), .FWriteIntM(WriteIntVal),
.XSNaNM(XSNaN), .YSNaNM(YSNaN), .ZSNaNM(ZSNaN), .CvtLzcInM(CvtLzcInE), .IntZeroM(IntZeroE),
@ -659,9 +660,9 @@ module testbenchfp;
fcmp fcmp (.FmtE(ModFmt), .FOpCtrlE(OpCtrlVal), .XSgnE(XSgn), .YSgnE(YSgn), .XExpE(XExp), .YExpE(YExp),
.XManE(XMan), .YManE(YMan), .XZeroE(XZero), .YZeroE(YZero), .CmpIntResE(CmpRes),
.XNaNE(XNaN), .YNaNE(YNaN), .XSNaNE(XSNaN), .YSNaNE(YSNaN), .FSrcXE(X), .FSrcYE(Y), .CmpNVE(CmpFlg[4]), .CmpFpResE(FpCmpRes));
srtradix4 srtradix4(.clk, .DivStart, .XExpE(XExp), .YExpE(YExp), .DivCalcExpE(DivCalcExp), .XZeroE(XZero),
srtradix4 srtradix4(.clk, .DivStart, .XExpE(XExp), .YExpE(YExp), .DivCalcExpE(DivCalcExp), .XZeroE(XZero), .DivStickyE(DivSticky),
.XManE(XMan), .YManE(YMan), .SrcA('0), .SrcB('0), .W64(1'b0), .Signed(1'b0), .Int(1'b0), .Sqrt(OpCtrlVal[0]),
.DivDone, .Quot, .Rem());
.DivNegStickyE(DivNegSticky), .DivDone, .Quot, .Rem());
assign CmpFlg[3:0] = 0;