mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
added denormal input handeling - radix 4
This commit is contained in:
parent
b5c20bf112
commit
9eefba5b58
@ -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]};
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user