divider sizes reworked to match book

This commit is contained in:
Katherine Parry 2022-07-22 22:02:04 +00:00
parent d95b266d49
commit ee7932c804
18 changed files with 269 additions and 224 deletions

@ -1 +1 @@
Subproject commit 307c77b26e070ae85ffea665ad9b642b40e33c86 Subproject commit be67c99bd461742aa1c100bcc0732657faae2230

View File

@ -32,7 +32,7 @@
`define DESIGN_COMPILER 0 `define DESIGN_COMPILER 0
// RV32 or RV64: XLEN = 32 or 64 // RV32 or RV64: XLEN = 32 or 64
`define XLEN 64 `define XLEN 32
// IEEE 754 compliance // IEEE 754 compliance
`define IEEE754 0 `define IEEE754 0

View File

@ -102,8 +102,9 @@
// division constants // division constants
`define RADIX 32'h4 `define RADIX 32'h4
`define DIVCOPIES 32'h1 `define DIVCOPIES 32'h4
`define DIVLEN ((`NF < `XLEN) ? (`XLEN) : (`NF + 3)) `define DIVLEN ((`NF < `XLEN) ? (`XLEN) : (`NF + 3))
`define DIVN (`NF < `XLEN ? `XLEN : `NF+1) // length of input
`define EXTRAFRACBITS ((`NF<(`XLEN)) ? (`XLEN - `NF) : 3) `define EXTRAFRACBITS ((`NF<(`XLEN)) ? (`XLEN - `NF) : 3)
`define EXTRAINTBITS ((`NF<(`XLEN)) ? 0 : (`NF - `XLEN + 3)) `define EXTRAINTBITS ((`NF<(`XLEN)) ? 0 : (`NF - `XLEN + 3))
`define DIVRESLEN ((`NF>`XLEN) ? `NF+4 : `XLEN) `define DIVRESLEN ((`NF>`XLEN) ? `NF+4 : `XLEN)
@ -113,6 +114,7 @@
`define FPDUR ((`DIVLEN+(`LOGR*`DIVCOPIES)-1)/(`LOGR*`DIVCOPIES)+(`RADIX/4)) `define FPDUR ((`DIVLEN+(`LOGR*`DIVCOPIES)-1)/(`LOGR*`DIVCOPIES)+(`RADIX/4))
`define DURLEN ($clog2(`FPDUR+1)) `define DURLEN ($clog2(`FPDUR+1))
`define QLEN (`FPDUR*`LOGR*`DIVCOPIES) `define QLEN (`FPDUR*`LOGR*`DIVCOPIES)
`define DIVb (`FPDUR*`LOGR*`DIVCOPIES)-1
`define USE_SRAM 0 `define USE_SRAM 0

View File

@ -32,8 +32,9 @@ add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srt/*
add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/* add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/*
# add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/otfc/otfc2/* # add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/otfc/otfc2/*
# add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/qsel/qsel2/* # add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/qsel/qsel2/*
add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/interations[0]/divinteration/genblk1/qsel4/*
add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srtpreproc/* add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srtpreproc/*
# add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srt/expcalc/* add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srtpreproc/expcalc/*
add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srtfsm/* add wave -group {Divide} -noupdate /testbenchfp/divsqrt/srtfsm/*
add wave -group {Testbench} -noupdate /testbenchfp/* add wave -group {Testbench} -noupdate /testbenchfp/*
add wave -group {Testbench} -noupdate /testbenchfp/readvectors/* add wave -group {Testbench} -noupdate /testbenchfp/readvectors/*

View File

@ -1,8 +1,9 @@
`include "wally-config.vh" `include "wally-config.vh"
module divshiftcalc( module divshiftcalc(
input logic [`QLEN-1-(`RADIX/4):0] DivQm, input logic [`DIVb-(`RADIX/4):0] DivQm,
input logic [`FMTBITS-1:0] Fmt, input logic [`FMTBITS-1:0] Fmt,
input logic Sqrt,
input logic [`DURLEN-1:0] DivEarlyTermShift, input logic [`DURLEN-1:0] DivEarlyTermShift,
input logic [`NE+1:0] DivQe, input logic [`NE+1:0] DivQe,
output logic [$clog2(`NORMSHIFTSZ)-1:0] DivShiftAmt, output logic [$clog2(`NORMSHIFTSZ)-1:0] DivShiftAmt,
@ -34,8 +35,8 @@ module divshiftcalc(
assign NormShift = (`NE+2)'(`NF); assign NormShift = (`NE+2)'(`NF);
// if the shift amount is negitive then dont shift (keep sticky bit) // if the shift amount is negitive then dont shift (keep sticky bit)
// need to multiply the early termination shift by LOGR*DIVCOPIES = left shift of log2(LOGR*DIVCOPIES) // need to multiply the early termination shift by LOGR*DIVCOPIES = left shift of log2(LOGR*DIVCOPIES)
assign DivShiftAmt = (DivResDenorm ? DivDenormShift[$clog2(`NORMSHIFTSZ)-1:0]&{$clog2(`NORMSHIFTSZ){~DivDenormShift[`NE+1]}} : NormShift[$clog2(`NORMSHIFTSZ)-1:0])+{{$clog2(`NORMSHIFTSZ)-`DURLEN-$clog2(`LOGR*`DIVCOPIES){1'b0}}, DivEarlyTermShift&{`DURLEN{~DivDenormShift[`NE+1]}}, {$clog2(`LOGR*`DIVCOPIES){1'b0}}}; assign DivShiftAmt = (DivResDenorm ? DivDenormShift[$clog2(`NORMSHIFTSZ)-1:0]&{$clog2(`NORMSHIFTSZ){~DivDenormShift[`NE+1]}} : NormShift[$clog2(`NORMSHIFTSZ)-1:0])+{{$clog2(`NORMSHIFTSZ)-`DURLEN-$clog2(`LOGR*`DIVCOPIES){1'b0}}, DivEarlyTermShift&{`DURLEN{~(DivDenormShift[`NE+1]|Sqrt)}}, {$clog2(`LOGR*`DIVCOPIES){1'b0}}};
assign DivShiftIn = {{`NF{1'b0}}, DivQm, {`NORMSHIFTSZ-`QLEN+(`RADIX/4)-`NF{1'b0}}}; assign DivShiftIn = {{`NF{1'b0}}, DivQm, {`NORMSHIFTSZ-`DIVb+1+(`RADIX/4)-`NF{1'b0}}};
endmodule endmodule

View File

@ -34,6 +34,7 @@ module divsqrt(
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic [`FMTBITS-1:0] FmtE, input logic [`FMTBITS-1:0] FmtE,
input logic XsE,
input logic [`NF:0] XmE, YmE, input logic [`NF:0] XmE, YmE,
input logic [`NE-1:0] XeE, YeE, input logic [`NE-1:0] XeE, YeE,
input logic XInfE, YInfE, input logic XInfE, YInfE,
@ -48,23 +49,22 @@ module divsqrt(
output logic DivDone, output logic DivDone,
output logic [`NE+1:0] QeM, output logic [`NE+1:0] QeM,
output logic [`DURLEN-1:0] EarlyTermShiftM, output logic [`DURLEN-1:0] EarlyTermShiftM,
output logic [`QLEN-1-(`RADIX/4):0] QmM output logic [`DIVb-(`RADIX/4):0] QmM
// output logic [`XLEN-1:0] RemM, // output logic [`XLEN-1:0] RemM,
); );
logic [`DIVLEN+3:0] NextWSN, NextWCN; logic [`DIVb+3:0] NextWSN, NextWCN;
logic [`DIVLEN+3:0] WS, WC; logic [`DIVb+3:0] WS, WC;
logic [`DIVLEN+3:0] StickyWSA; logic [`DIVb+3:0] StickyWSA;
logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt; logic [`DIVb:0] X;
logic [`DIVLEN+3:0] X; logic [`DIVN-2:0] Dpreproc;
logic [`DIVLEN+3:0] Dpreproc;
logic [`DURLEN-1:0] Dur; logic [`DURLEN-1:0] Dur;
logic NegSticky; logic NegSticky;
srtpreproc srtpreproc(.clk, .DivStart(DivStartE), .Xm(XmE), .QeM, .Xe(XeE), .Fmt(FmtE), .Ye(YeE), .Sqrt(SqrtE), .Dur, .Ym(YmE), .XZero(XZeroE), .X, .Dpreproc, .XZeroCnt, .YZeroCnt); srtpreproc srtpreproc(.clk, .DivStart(DivStartE), .Xm(XmE), .QeM, .Xe(XeE), .Fmt(FmtE), .Ye(YeE), .Sqrt(SqrtE), .Dur, .Ym(YmE), .XZero(XZeroE), .X, .Dpreproc);
srtfsm srtfsm(.reset, .NextWSN, .NextWCN, .WS, .WC, .Dur, .DivBusy, .clk, .DivStart(DivStartE),.StallE, .StallM, .DivDone, .XZeroE, .YZeroE, .DivSE(DivSM), .XNaNE, .YNaNE, srtfsm srtfsm(.reset, .XsE, .SqrtE, .NextWSN, .NextWCN, .WS, .WC, .Dur, .DivBusy, .clk, .DivStart(DivStartE),.StallE, .StallM, .DivDone, .XZeroE, .YZeroE, .DivSE(DivSM), .XNaNE, .YNaNE,
.StickyWSA, .XInfE, .YInfE, .NegSticky(NegSticky), .EarlyTermShiftE(EarlyTermShiftM)); .StickyWSA, .XInfE, .YInfE, .NegSticky(NegSticky), .EarlyTermShiftE(EarlyTermShiftM));
srt srt(.clk, .Sqrt(SqrtM), .X,.Dpreproc, .NegSticky, .XZeroCnt, .YZeroCnt, .FirstWS(WS), .FirstWC(WC), .NextWSN, .NextWCN, .DivStart(DivStartE), .Xe(XeE), .Ye(YeE), .XZeroE, .YZeroE, srt srt(.clk, .Sqrt(SqrtM), .X,.Dpreproc, .NegSticky, .FirstWS(WS), .FirstWC(WC), .NextWSN, .NextWCN, .DivStart(DivStartE), .Xe(XeE), .Ye(YeE), .XZeroE, .YZeroE,
.StickyWSA, .DivBusy, .Qm(QmM), .Rem()); .StickyWSA, .DivBusy, .Qm(QmM));
endmodule endmodule

View File

@ -178,14 +178,14 @@ module fctrl (
// enables: // enables:
// X - all except int->fp, store, load, mv int->fp // X - all except int->fp, store, load, mv int->fp
// Y - all except cvt, mv, load, class // Y - all except cvt, mv, load, class, sqrt
// Z - fma ops only // Z - fma ops only
// load/store mv int->fp cvt int->fp // load/store mv int->fp cvt int->fp
assign XEnE = ~(((FResSelE==2'b10)&~FWriteIntE)|((FResSelE==2'b11)&FRegWriteE)|((FResSelE==2'b01)&(PostProcSelE==2'b00)&OpCtrlE[2])); assign XEnE = ~(((FResSelE==2'b10)&~FWriteIntE)|((FResSelE==2'b11)&FRegWriteE)|((FResSelE==2'b01)&(PostProcSelE==2'b00)&OpCtrlE[2]));
// load/class mv cvt // load/class mv cvt
assign YEnE = ~(((FResSelE==2'b10)&(FWriteIntE|FRegWriteE))|(FResSelE==2'b11)|((FResSelE==2'b01)&(PostProcSelE==2'b00))); assign YEnE = ~(((FResSelE==2'b10)&(FWriteIntE|FRegWriteE))|(FResSelE==2'b11)|((FResSelE==2'b01)&((PostProcSelE==2'b00)|((PostProcSelE==2'b01)&OpCtrlE[0]))));
assign ZEnE = (PostProcSelE==2'b10)&(FResSelE==2'b01)&(~OpCtrlE[2]|OpCtrlE[1]); assign ZEnE = (PostProcSelE==2'b10)&(FResSelE==2'b01)&(~OpCtrlE[2]|OpCtrlE[1]);
assign YEnForwardE = ~(((FResSelE==2'b10)&(FWriteIntE|FRegWriteE))|(FResSelE==2'b11)|((FResSelE==2'b01)&(PostProcSelE==2'b00))); assign YEnForwardE = ~(((FResSelE==2'b10)&(FWriteIntE|FRegWriteE))|(FResSelE==2'b11)|((FResSelE==2'b01)&((PostProcSelE==2'b00)|((PostProcSelE==2'b01)&OpCtrlE[0]))));
assign ZEnForwardE = (PostProcSelE==2'b10)&(FResSelE==2'b01)&~OpCtrlE[2]; assign ZEnForwardE = (PostProcSelE==2'b10)&(FResSelE==2'b01)&~OpCtrlE[2];
// Final Res Sel: // Final Res Sel:

View File

@ -126,11 +126,11 @@ module flags(
// | | | | and if the result is not exact // | | | | and if the result is not exact
// | | | | | and if the input isnt infinity or NaN // | | | | | and if the input isnt infinity or NaN
// | | | | | | // | | | | | |
assign Underflow = ((FullRe[`NE+1] | (FullRe == 0) | ((FullRe == 1) & (Me == 0) & ~(UfPlus1&UfL)))&(R|S))&~(InfIn|NaNIn|DivByZero); assign Underflow = ((FullRe[`NE+1] | (FullRe == 0) | ((FullRe == 1) & (Me == 0) & ~(UfPlus1&UfL)))&(R|S))&~(InfIn|NaNIn|DivByZero|Invalid);
// Set Inexact flag if the res is diffrent from what would be outputed given infinite precision // 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 // - Don't set the underflow flag if an underflowed res isn't outputed
assign FpInexact = (S|Overflow|R)&~(InfIn|NaNIn|DivByZero); assign FpInexact = (S|Overflow|R)&~(InfIn|NaNIn|DivByZero|Invalid);
// if the res is too small to be represented and not 0 // if the res is too small to be represented and not 0
// | and if the res is not invalid (outside the integer bounds) // | and if the res is not invalid (outside the integer bounds)
@ -163,7 +163,7 @@ module flags(
// if dividing by zero and not 0/0 // 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) // - don't set flag if an input is NaN or Inf(IEEE says has to be a finite numerator)
assign DivByZero = YZero&DivOp&~(XZero|NaNIn|InfIn); assign DivByZero = YZero&DivOp&~Sqrt&~(XZero|NaNIn|InfIn);
// Combine flags // Combine flags
// - to integer results do not set the underflow or overflow flags // - to integer results do not set the underflow or overflow flags

View File

@ -125,7 +125,7 @@ module fpu (
logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder) logic [`CVTLEN-1:0] CvtLzcInE, CvtLzcInM; // input to the Leading Zero Counter (priority encoder)
//divide signals //divide signals
logic [`QLEN-1-(`RADIX/4):0] QmM; logic [`DIVb-(`RADIX/4):0] QmM;
logic [`NE+1:0] QeE, QeM; logic [`NE+1:0] QeE, QeM;
logic DivSE, DivSM; logic DivSE, DivSM;
logic DivDoneM; logic DivDoneM;
@ -260,7 +260,7 @@ module fpu (
// - fsqrt // - fsqrt
// *** add other opperations // *** add other opperations
divsqrt divsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, .SqrtE(OpCtrlE[0]), .SqrtM(OpCtrlM[0]), divsqrt divsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, .SqrtE(OpCtrlE[0]), .SqrtM(OpCtrlM[0]),
.XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .DivStartE(DivStartE), .XInfE, .YInfE, .XZeroE, .YZeroE, .XNaNE, .YNaNE, .DivStartE(DivStartE), .XsE,
.StallE, .StallM, .DivSM, .DivBusy(FDivBusyE), .QeM, //***change divbusyE to M signal .StallE, .StallM, .DivSM, .DivBusy(FDivBusyE), .QeM, //***change divbusyE to M signal
.EarlyTermShiftM, .QmM, .DivDone(DivDoneM)); .EarlyTermShiftM, .QmM, .DivDone(DivDoneM));
// compare // compare

View File

@ -32,16 +32,16 @@
module otfc2 ( module otfc2 (
input logic qp, qz, input logic qp, qz,
input logic [`QLEN-1:0] Q, QM, input logic [`DIVb:0] Q, QM,
output logic [`QLEN-1:0] QNext, QMNext output logic [`DIVb:0] QNext, QMNext
); );
// The on-the-fly converter transfers the quotient // The on-the-fly converter transfers the quotient
// bits to the quotient as they come. // bits to the quotient as they come.
// Use this otfc for division only. // Use this otfc for division only.
logic [`QLEN-2:0] QR, QMR; logic [`DIVb-1:0] QR, QMR;
assign QR = Q[`QLEN-2:0]; assign QR = Q[`DIVb-1:0];
assign QMR = QM[`QLEN-2:0]; // Shifted Q and QM assign QMR = QM[`DIVb-1:0]; // Shifted Q and QM
always_comb begin always_comb begin
if (qp) begin if (qp) begin
@ -96,8 +96,8 @@ endmodule
module otfc4 ( module otfc4 (
input logic [3:0] q, input logic [3:0] q,
input logic [`QLEN-1:0] Q, QM, input logic [`DIVb:0] Q, QM,
output logic [`QLEN-1:0] QNext, QMNext output logic [`DIVb:0] QNext, QMNext
); );
// The on-the-fly converter transfers the quotient // The on-the-fly converter transfers the quotient
@ -113,7 +113,7 @@ module otfc4 (
// QR and QMR are the shifted versions of Q and QM. // QR and QMR are the shifted versions of Q and QM.
// They are treated as [N-1:r] size signals, and // They are treated as [N-1:r] size signals, and
// discard the r most significant bits of Q and QM. // discard the r most significant bits of Q and QM.
logic [`QLEN-3:0] QR, QMR; logic [`DIVb-2:0] QR, QMR;
// shift Q (quotent) and QM (quotent-1) // shift Q (quotent) and QM (quotent-1)
// if q = 2 Q = {Q, 10} QM = {Q, 01} // if q = 2 Q = {Q, 10} QM = {Q, 01}
@ -122,8 +122,8 @@ module otfc4 (
// else if q = -1 Q = {QM, 11} QM = {QM, 10} // else if q = -1 Q = {QM, 11} QM = {QM, 10}
// else if q = -2 Q = {QM, 10} QM = {QM, 01} // else if q = -2 Q = {QM, 10} QM = {QM, 01}
assign QR = Q[`QLEN-3:0]; assign QR = Q[`DIVb-2:0];
assign QMR = QM[`QLEN-3:0]; // Shifted Q and QM assign QMR = QM[`DIVb-2:0]; // Shifted Q and QM
always_comb begin always_comb begin
if (q[3]) begin // +2 if (q[3]) begin // +2
QNext = {QR, 2'b10}; QNext = {QR, 2'b10};

View File

@ -60,7 +60,7 @@ module postprocess (
input logic DivS, input logic DivS,
input logic DivDone, input logic DivDone,
input logic [`NE+1:0] DivQe, input logic [`NE+1:0] DivQe,
input logic [`QLEN-1-(`RADIX/4):0] DivQm, input logic [`DIVb-(`RADIX/4):0] DivQm,
// conversion signals // conversion signals
input logic CvtCs, // the result's sign input logic CvtCs, // the result's sign
input logic [`NE:0] CvtCe, // the calculated expoent input logic [`NE:0] CvtCe, // the calculated expoent
@ -154,7 +154,7 @@ module postprocess (
.XZero, .IntToFp, .OutFmt, .CvtResUf, .CvtShiftIn); .XZero, .IntToFp, .OutFmt, .CvtResUf, .CvtShiftIn);
fmashiftcalc fmashiftcalc(.FmaSm, .Ze, .FmaPe, .FmaSCnt, .Fmt, .FmaKillProd, .NormSumExp, .FmaSe, fmashiftcalc fmashiftcalc(.FmaSm, .Ze, .FmaPe, .FmaSCnt, .Fmt, .FmaKillProd, .NormSumExp, .FmaSe,
.FmaSZero, .FmaPreResultDenorm, .FmaShiftAmt, .FmaShiftIn); .FmaSZero, .FmaPreResultDenorm, .FmaShiftAmt, .FmaShiftIn);
divshiftcalc divshiftcalc(.Fmt, .DivQe, .DivQm, .DivEarlyTermShift, .DivResDenorm, .DivDenormShift, .DivShiftAmt, .DivShiftIn); divshiftcalc divshiftcalc(.Fmt, .Sqrt, .DivQe, .DivQm, .DivEarlyTermShift, .DivResDenorm, .DivDenormShift, .DivShiftAmt, .DivShiftIn);
always_comb always_comb
case(PostProcSel) case(PostProcSel)
@ -199,7 +199,7 @@ module postprocess (
roundsign roundsign(.FmaPs, .FmaAs, .FmaInvA, .FmaOp, .DivOp, .CvtOp, .FmaNegSum, roundsign roundsign(.FmaPs, .FmaAs, .FmaInvA, .FmaOp, .DivOp, .CvtOp, .FmaNegSum,
.FmaSs, .Xs, .Ys, .CvtCs, .Ms); .Sqrt, .FmaSs, .Xs, .Ys, .CvtCs, .Ms);
round round(.OutFmt, .Frm, .S, .FmaZmS, .Plus1, .PostProcSel, .CvtCe, .Qe, round round(.OutFmt, .Frm, .S, .FmaZmS, .Plus1, .PostProcSel, .CvtCe, .Qe,
.Ms, .FmaMe, .FmaOp, .CvtOp, .CvtResDenormUf, .Mf, .ToInt, .CvtResUf, .Ms, .FmaMe, .FmaOp, .CvtOp, .CvtResDenormUf, .Mf, .ToInt, .CvtResUf,

View File

@ -89,17 +89,17 @@ module fgen2 (
endmodule endmodule
module qsel4 ( module qsel4 (
input logic [`DIVLEN+3:0] D, input logic [`DIVN-2:0] D,
input logic [`DIVLEN+3:0] WS, WC, input logic [`DIVb+3:0] WS, WC,
input logic Sqrt, input logic Sqrt,
output logic [3:0] q output logic [3:0] q
); );
logic [6:0] Wmsbs; logic [6:0] Wmsbs;
logic [7:0] PreWmsbs; logic [7:0] PreWmsbs;
logic [2:0] Dmsbs; logic [2:0] Dmsbs;
assign PreWmsbs = WC[`DIVLEN+3:`DIVLEN-4] + WS[`DIVLEN+3:`DIVLEN-4]; assign PreWmsbs = WC[`DIVb+3:`DIVb-4] + WS[`DIVb+3:`DIVb-4];
assign Wmsbs = PreWmsbs[7:1]; assign Wmsbs = PreWmsbs[7:1];
assign Dmsbs = D[`DIVLEN-1:`DIVLEN-3]; assign Dmsbs = D[`DIVN-2:`DIVN-4];//|{3{D[`DIVN-2]&Sqrt}};
// D = 0001.xxx... // D = 0001.xxx...
// Dmsbs = | | // Dmsbs = | |
// W = xxxx.xxx... // W = xxxx.xxx...
@ -177,8 +177,8 @@ module fgen4 (
assign F2 = (~S << 2) & (C << 2); assign F2 = (~S << 2) & (C << 2);
assign F1 = ~(S << 1) & C; assign F1 = ~(S << 1) & C;
assign F0 = '0; assign F0 = '0;
assign FN1 = (SM << 1) | (C & ~(C << 2)); assign FN1 = (SM << 1) | (C & ~(C << 3));
assign FN2 = (SM << 2) | ((C << 2)&~(C <<4)); assign FN2 = (SM << 2) | ((C << 2)&~(C << 4));
// Choose which adder input will be used // Choose which adder input will be used

View File

@ -34,6 +34,7 @@ module roundsign(
input logic Xs, input logic Xs,
input logic Ys, input logic Ys,
input logic FmaNegSum, input logic FmaNegSum,
input logic Sqrt,
input logic FmaOp, input logic FmaOp,
input logic DivOp, input logic DivOp,
input logic CvtOp, input logic CvtOp,
@ -44,7 +45,7 @@ module roundsign(
logic Qs; logic Qs;
assign Qs = Xs^Ys; assign Qs = Xs^(Ys&~Sqrt);
// Sign for rounding calulation // Sign for rounding calulation
assign Ms = (FmaSs&FmaOp) | (CvtCs&CvtOp) | (Qs&DivOp); assign Ms = (FmaSs&FmaOp) | (CvtCs&CvtOp) | (Qs&DivOp);

View File

@ -37,40 +37,43 @@ module srt(
input logic [`NE-1:0] Xe, Ye, input logic [`NE-1:0] Xe, Ye,
input logic XZeroE, YZeroE, input logic XZeroE, YZeroE,
input logic Sqrt, input logic Sqrt,
input logic [`DIVLEN+3:0] X, input logic [`DIVb:0] X,
input logic [`DIVLEN+3:0] Dpreproc, input logic [`DIVN-2:0] Dpreproc,
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
input logic NegSticky, input logic NegSticky,
output logic [`QLEN-1-(`RADIX/4):0] Qm, output logic [`DIVb-(`RADIX/4):0] Qm,
output logic [`DIVLEN+3:0] NextWSN, NextWCN, output logic [`DIVb+3:0] NextWSN, NextWCN,
output logic [`DIVLEN+3:0] StickyWSA, output logic [`DIVb+3:0] StickyWSA,
output logic [`DIVLEN+3:0] FirstWS, FirstWC, output logic [`DIVb+3:0] FirstWS, FirstWC
output logic [`XLEN-1:0] Rem
); );
//QLEN = 1.(number of bits created for division)
// N is NF+1 or XLEN
// WC/WS is dependent on D so 4.N-1 ie N+3 bits or N+2:0 + one more bit in fraction for possible sqrt right shift
// D is 1.N-1, but the msb is always 1 so 0.N-1 or N-1 bits or N-1:0
// Dsel should match WC/WS so 4.N-1 ie N+3 bits or N+2:0
// Q/QM/S/SM should be 1.b so b+1 bits or b:0
// C needs to be the lenght of the final fraction 0.b so b or b-1:0
/* verilator lint_off UNOPTFLAT */ /* verilator lint_off UNOPTFLAT */
logic [`DIVLEN+3:0] WSA[`DIVCOPIES-1:0]; logic [`DIVb+3:0] WSA[`DIVCOPIES-1:0]; // Q4.b
logic [`DIVLEN+3:0] WCA[`DIVCOPIES-1:0]; logic [`DIVb+3:0] WCA[`DIVCOPIES-1:0]; // Q4.b
logic [`DIVLEN+3:0] WS[`DIVCOPIES-1:0]; logic [`DIVb+3:0] WS[`DIVCOPIES-1:0]; // Q4.b
logic [`DIVLEN+3:0] WC[`DIVCOPIES-1:0]; logic [`DIVb+3:0] WC[`DIVCOPIES-1:0]; // Q4.b
logic [`QLEN-1:0] Q[`DIVCOPIES-1:0]; logic [`DIVb:0] Q[`DIVCOPIES-1:0]; // U1.b
logic [`QLEN-1:0] QM[`DIVCOPIES-1:0]; logic [`DIVb:0] QM[`DIVCOPIES-1:0];// 1.b
logic [`QLEN-1:0] QNext[`DIVCOPIES-1:0]; logic [`DIVb:0] QNext[`DIVCOPIES-1:0];// U1.b
logic [`QLEN-1:0] QMNext[`DIVCOPIES-1:0]; logic [`DIVb:0] QMNext[`DIVCOPIES-1:0];// U1.b
logic [`DIVLEN+3:0] S[`DIVCOPIES-1:0]; //***change to QLEN??? logic [`DIVb:0] S[`DIVCOPIES-1:0];// U1.b
logic [`DIVLEN+3:0] SM[`DIVCOPIES-1:0]; logic [`DIVb:0] SM[`DIVCOPIES-1:0];// U1.b
logic [`DIVLEN+3:0] SNext[`DIVCOPIES-1:0]; logic [`DIVb:0] SNext[`DIVCOPIES-1:0];// U1.b
logic [`DIVLEN+3:0] SMNext[`DIVCOPIES-1:0]; logic [`DIVb:0] SMNext[`DIVCOPIES-1:0];// U1.b
logic [`DIVLEN+3:0] C[`DIVCOPIES-1:0]; logic [`DIVb-1:0] C[`DIVCOPIES-1:0]; // 0.b
/* verilator lint_on UNOPTFLAT */ /* verilator lint_on UNOPTFLAT */
logic [`DIVLEN+3:0] WSN, WCN; logic [`DIVb+3:0] WSN, WCN; // Q4.N-1
logic [`DIVLEN+3:0] D, DBar, D2, DBar2; logic [`DIVN-2:0] D; // U0.N-1
logic [$clog2(`XLEN+1)-1:0] intExp; logic [`DIVb+3:0] DBar, D2, DBar2; // Q4.N-1
logic intSign; logic [`DIVb:0] QMMux;
logic [`QLEN-1:0] QMMux; logic [`DIVb-1:0] CMux;
logic [`DIVLEN+3:0] CMux; logic [`DIVb:0] SMux;
logic [`DIVLEN+3:0] SMux;
// Top Muxes and Registers // Top Muxes and Registers
// When start is asserted, the inputs are loaded into the divider. // When start is asserted, the inputs are loaded into the divider.
@ -81,27 +84,28 @@ module srt(
// - the assumed one is added to D since it's always normalized (and X/0 is a special case handeled by result selection) // - 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 // - XZeroE is used as the assumed one to avoid creating a sticky bit - all other numbers are normalized
if (`RADIX == 2) begin : nextw if (`RADIX == 2) begin : nextw
assign NextWSN = {WSA[`DIVCOPIES-1][`DIVLEN+2:0], 1'b0}; assign NextWSN = {WSA[`DIVCOPIES-1][`DIVb+2:0], 1'b0};
assign NextWCN = {WCA[`DIVCOPIES-1][`DIVLEN+2:0], 1'b0}; assign NextWCN = {WCA[`DIVCOPIES-1][`DIVb+2:0], 1'b0};
end else begin end else begin
assign NextWSN = {WSA[`DIVCOPIES-1][`DIVLEN+1:0], 2'b0}; assign NextWSN = {WSA[`DIVCOPIES-1][`DIVb+1:0], 2'b0};
assign NextWCN = {WCA[`DIVCOPIES-1][`DIVLEN+1:0], 2'b0}; assign NextWCN = {WCA[`DIVCOPIES-1][`DIVb+1:0], 2'b0};
end end
mux2 #(`DIVLEN+4) wsmux(NextWSN, X, DivStart, WSN); mux2 #(`DIVb+4) wsmux(NextWSN, {3'b0, X}, DivStart, WSN);
flopen #(`DIVLEN+4) wsflop(clk, DivStart|DivBusy, WSN, WS[0]); flopen #(`DIVb+4) wsflop(clk, DivStart|DivBusy, WSN, WS[0]);
mux2 #(`DIVLEN+4) wcmux(NextWCN, {`DIVLEN+4{1'b0}}, DivStart, WCN); mux2 #(`DIVb+4) wcmux(NextWCN, '0, DivStart, WCN);
flopen #(`DIVLEN+4) wcflop(clk, DivStart|DivBusy, WCN, WC[0]); flopen #(`DIVb+4) wcflop(clk, DivStart|DivBusy, WCN, WC[0]);
flopen #(`DIVLEN+4) dflop(clk, DivStart, Dpreproc, D); flopen #(`DIVN-1) dflop(clk, DivStart, Dpreproc, D);
mux2 #(`DIVLEN+4) Cmux({2'b11, C[`DIVCOPIES-1][`DIVLEN+3:2]}, {5'b11111, Sqrt, {(`DIVLEN-2){1'b0}}}, DivStart, CMux); mux2 #(`DIVb) Cmux({2'b11, C[`DIVCOPIES-1][`DIVb-1:2]}, {Sqrt, {(`DIVb-1){1'b0}}}, DivStart, CMux);
flop #(`DIVLEN+4) cflop(clk, CMux, C[0]); flop #(`DIVb) cflop(clk, CMux, C[0]);
// Divisor Selections // Divisor Selections
// - choose the negitive version of what's being selected // - choose the negitive version of what's being selected
assign DBar = ~D; // - D is only the fraction
assign DBar = {3'b111, 1'b0, ~D, {`DIVb-`DIVN+1{1'b1}}};
if(`RADIX == 4) begin : d2 if(`RADIX == 4) begin : d2
assign DBar2 = {~D[`DIVLEN+2:0], 1'b1}; assign DBar2 = {2'b11, 1'b0, ~D, {`DIVb+2-`DIVN{1'b1}}};
assign D2 = {D[`DIVLEN+2:0], 1'b0}; assign D2 = {2'b0, 1'b1, D, {`DIVb+2-`DIVN{1'b0}}};
end end
genvar i; genvar i;
@ -112,12 +116,13 @@ module srt(
.C(C[i]), .S(S[i]), .SM(SM[i]), .SNext(SNext[i]), .SMNext(SMNext[i])); .C(C[i]), .S(S[i]), .SM(SM[i]), .SNext(SNext[i]), .SMNext(SMNext[i]));
if(i<(`DIVCOPIES-1)) begin if(i<(`DIVCOPIES-1)) begin
if (`RADIX==2)begin if (`RADIX==2)begin
assign WS[i+1] = {WSA[i][`DIVLEN+1:0], 1'b0}; assign WS[i+1] = {WSA[i][`DIVb+2:0], 1'b0};
assign WC[i+1] = {WCA[i][`DIVLEN+1:0], 1'b0}; assign WC[i+1] = {WCA[i][`DIVb+2:0], 1'b0};
assign C[i+1] = {1'b1, C[i][`DIVb-1:1]};
end else begin end else begin
assign WS[i+1] = {WSA[i][`DIVLEN+1:0], 2'b0}; assign WS[i+1] = {WSA[i][`DIVb+1:0], 2'b0};
assign WC[i+1] = {WCA[i][`DIVLEN+1:0], 2'b0}; assign WC[i+1] = {WCA[i][`DIVb+1:0], 2'b0};
assign C[i+1] = {2'b11, C[i][`DIVLEN+3:2]}; assign C[i+1] = {2'b11, C[i][`DIVb-1:2]};
end end
assign Q[i+1] = QNext[i]; assign Q[i+1] = QNext[i];
assign QM[i+1] = QMNext[i]; assign QM[i+1] = QMNext[i];
@ -128,30 +133,30 @@ module srt(
endgenerate endgenerate
// if starting a new divison set Q to 0 and QM to -1 // if starting a new divison set Q to 0 and QM to -1
mux2 #(`QLEN) QMmux(QMNext[`DIVCOPIES-1], {`QLEN{1'b1}}, DivStart, QMMux); mux2 #(`DIVb+1) QMmux(QMNext[`DIVCOPIES-1], '1, DivStart, QMMux);
flopenr #(`QLEN) Qreg(clk, DivStart, DivBusy, QNext[`DIVCOPIES-1], Q[0]); flopenr #(`DIVb+1) Qreg(clk, DivStart, DivBusy, QNext[`DIVCOPIES-1], Q[0]);
flopen #(`QLEN) QMreg(clk, DivBusy, QMMux, QM[0]); flopen #(`DIVb+1) QMreg(clk, DivBusy, QMMux, QM[0]);
flopr #(`DIVLEN+4) SMreg(clk, DivStart, SMNext[`DIVCOPIES-1], SM[0]);
mux2 #(`DIVLEN+4) Smux(SNext[`DIVCOPIES-1], {3'b000, Sqrt, {(`DIVLEN){1'b0}}}, DivStart, SMux);
flop #(`DIVLEN+4) Sreg(clk, SMux, S[0]);
flopr #(`DIVb+1) SMreg(clk, DivStart, SMNext[`DIVCOPIES-1], SM[0]);
mux2 #(`DIVb+1) Smux(SNext[`DIVCOPIES-1], {Sqrt, {(`DIVb){1'b0}}}, DivStart, SMux);
flop #(`DIVb+1) Sreg(clk, SMux, S[0]);
// division takes the result from the next cycle, which is shifted to the left one more time so the square root also needs to be shifted
always_comb always_comb
if(Sqrt) if(Sqrt) // sqrt ouputs in the range (1, .5]
if(NegSticky) Qm = SM[0][`QLEN-1-(`RADIX/4):0]; if(NegSticky) Qm = {SM[0][`DIVb-1-(`RADIX/4):0], 1'b0};
else Qm = S[0][`QLEN-1-(`RADIX/4):0]; else Qm = {S[0][`DIVb-1-(`RADIX/4):0], 1'b0};
else else
if(NegSticky) Qm = QM[0][`QLEN-1-(`RADIX/4):0]; if(NegSticky) Qm = QM[0][`DIVb-(`RADIX/4):0];
else Qm = Q[0][`QLEN-1-(`RADIX/4):0]; else Qm = Q[0][`DIVb-(`RADIX/4):0];
assign FirstWS = WS[0]; assign FirstWS = WS[0];
assign FirstWC = WC[0]; assign FirstWC = WC[0];
if(`RADIX==2) if(`RADIX==2)
if (`DIVCOPIES == 1) if (`DIVCOPIES == 1)
assign StickyWSA = {WSA[0][`DIVLEN+2:0], 1'b0}; assign StickyWSA = {WSA[0][`DIVb+2:0], 1'b0};
else else
assign StickyWSA = {WSA[1][`DIVLEN+2:0], 1'b0}; assign StickyWSA = {WSA[1][`DIVb+2:0], 1'b0};
endmodule endmodule
@ -162,24 +167,24 @@ endmodule
/* verilator lint_off UNOPTFLAT */ /* verilator lint_off UNOPTFLAT */
module divinteration ( module divinteration (
input logic [`DIVLEN+3:0] D, input logic [`DIVN-2:0] D,
input logic [`DIVLEN+3:0] DBar, D2, DBar2, input logic [`DIVb+3:0] DBar, D2, DBar2,
input logic [`QLEN-1:0] Q, QM, input logic [`DIVb:0] Q, QM,
input logic [`DIVLEN+3:0] S, SM, input logic [`DIVb:0] S, SM,
input logic [`DIVLEN+3:0] WS, WC, input logic [`DIVb+3:0] WS, WC,
input logic [`DIVLEN+3:0] C, input logic [`DIVb-1:0] C,
input logic Sqrt, input logic Sqrt,
output logic [`QLEN-1:0] QNext, QMNext, output logic [`DIVb:0] QNext, QMNext,
output logic [`DIVLEN+3:0] SNext, SMNext, output logic [`DIVb:0] SNext, SMNext,
output logic [`DIVLEN+3:0] WSA, WCA output logic [`DIVb+3:0] WSA, WCA
); );
/* verilator lint_on UNOPTFLAT */ /* verilator lint_on UNOPTFLAT */
logic [`DIVLEN+3:0] Dsel; logic [`DIVb+3:0] Dsel;
logic [3:0] q; logic [3:0] q;
logic qp, qz;//, qn; logic qp, qz;
logic [`DIVLEN+3:0] F; logic [`DIVb+3:0] F;
logic [`DIVLEN+3:0] AddIn; logic [`DIVb+3:0] AddIn;
// Qmient Selection logic // Qmient Selection logic
// Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm) // Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
@ -190,21 +195,21 @@ module divinteration (
// 0010 = -1 // 0010 = -1
// 0001 = -2 // 0001 = -2
if(`RADIX == 2) begin : qsel if(`RADIX == 2) begin : qsel
qsel2 qsel2(WS[`DIVLEN+3:`DIVLEN], WC[`DIVLEN+3:`DIVLEN], qp, qz);//, qn); qsel2 qsel2(WS[`DIVb+3:`DIVb], WC[`DIVb+3:`DIVb], qp, qz);
end else begin end else begin
qsel4 qsel4(.D, .WS, .WC, .Sqrt, .q); qsel4 qsel4(.D, .WS, .WC, .Sqrt, .q);
fgen4 fgen4(.s(q), .C, .S, .SM, .F); // fgen4 fgen4(.s(q), .C, .S, .SM, .F);
end end
if(`RADIX == 2) begin : dsel if(`RADIX == 2) begin : dsel
assign Dsel = {`DIVLEN+4{~qz}}&(qp ? DBar : D); assign Dsel = {`DIVb+4{~qz}}&(qp ? DBar : {3'b0, 1'b1, D, {`DIVb-`DIVN+1{1'b0}}});
end else begin end else begin
always_comb always_comb
case (q) case (q)
4'b1000: Dsel = DBar2; 4'b1000: Dsel = DBar2;
4'b0100: Dsel = DBar; 4'b0100: Dsel = DBar;
4'b0000: Dsel = '0; 4'b0000: Dsel = '0;
4'b0010: Dsel = D; 4'b0010: Dsel = {3'b0, 1'b1, D, {`DIVb-`DIVN+1{1'b0}}};
4'b0001: Dsel = D2; 4'b0001: Dsel = D2;
default: Dsel = 'x; default: Dsel = 'x;
endcase endcase
@ -213,16 +218,16 @@ module divinteration (
// WSA, WCA = WS + WC - qD // WSA, WCA = WS + WC - qD
assign AddIn = Sqrt ? F : Dsel; assign AddIn = Sqrt ? F : Dsel;
if (`RADIX == 2) begin : csa if (`RADIX == 2) begin : csa
csa #(`DIVLEN+4) csa(WS, WC, AddIn, qp, WSA, WCA); csa #(`DIVb+4) csa(WS, WC, AddIn, qp, WSA, WCA);
end else begin end else begin
csa #(`DIVLEN+4) csa(WS, WC, AddIn, |q[3:2], WSA, WCA); csa #(`DIVb+4) csa(WS, WC, AddIn, |q[3:2]&~Sqrt, WSA, WCA);
end end
if (`RADIX == 2) begin : otfc if (`RADIX == 2) begin : otfc
otfc2 otfc2(.qp, .qz, .Q, .QM, .QNext, .QMNext); otfc2 otfc2(.qp, .qz, .Q, .QM, .QNext, .QMNext);
end else begin end else begin
otfc4 otfc4(.q, .Q, .QM, .QNext, .QMNext); otfc4 otfc4(.q, .Q, .QM, .QNext, .QMNext);
sotfc4 sotfc4(.s(q), .Sqrt, .C, .S, .SM, .SNext, .SMNext); // sotfc4 sotfc4(.s(q), .Sqrt, .C, .S, .SM, .SNext, .SMNext);
end end
endmodule endmodule

View File

@ -33,14 +33,16 @@
module srtfsm( module srtfsm(
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic [`DIVLEN+3:0] NextWSN, NextWCN, WS, WC, input logic [`DIVb+3:0] NextWSN, NextWCN, WS, WC,
input logic XInfE, YInfE, input logic XInfE, YInfE,
input logic XZeroE, YZeroE, input logic XZeroE, YZeroE,
input logic XNaNE, YNaNE, input logic XNaNE, YNaNE,
input logic DivStart, input logic DivStart,
input logic XsE,
input logic SqrtE,
input logic StallE, input logic StallE,
input logic StallM, input logic StallM,
input logic [`DIVLEN+3:0] StickyWSA, input logic [`DIVb+3:0] StickyWSA,
input logic [`DURLEN-1:0] Dur, input logic [`DURLEN-1:0] Dur,
output logic [`DURLEN-1:0] EarlyTermShiftE, output logic [`DURLEN-1:0] EarlyTermShiftE,
output logic DivSE, output logic DivSE,
@ -55,11 +57,11 @@ module srtfsm(
logic [`DURLEN-1:0] step; logic [`DURLEN-1:0] step;
logic WZero; logic WZero;
//logic [$clog2(`DIVLEN/2+3)-1:0] Dur; //logic [$clog2(`DIVLEN/2+3)-1:0] Dur;
logic [`DIVLEN+3:0] W; logic [`DIVb+3:0] W;
//flopen #($clog2(`DIVLEN/2+3)) durflop(clk, DivStart, CalcDur, Dur); //flopen #($clog2(`DIVLEN/2+3)) durflop(clk, DivStart, CalcDur, Dur);
assign DivBusy = (state == BUSY); assign DivBusy = (state == BUSY);
assign WZero = ((NextWSN^NextWCN)=={NextWSN[`DIVLEN+2:0]|NextWCN[`DIVLEN+2:0], 1'b0}); assign WZero = ((NextWSN^NextWCN)=={NextWSN[`DIVb+2:0]|NextWCN[`DIVb+2:0], 1'b0});
// calculate sticky bit // calculate sticky bit
// - there is a chance that a value is subtracted infinitly, resulting in an exact QM result // - there is a chance that a value is subtracted infinitly, resulting in an exact QM result
// this is only a problem on radix 2 (and pssibly maximally redundant 4) since minimally redundant // this is only a problem on radix 2 (and pssibly maximally redundant 4) since minimally redundant
@ -70,7 +72,7 @@ module srtfsm(
assign DivSE = |W; assign DivSE = |W;
assign DivDone = (state == DONE); assign DivDone = (state == DONE);
assign W = WC+WS; assign W = WC+WS;
assign NegSticky = W[`DIVLEN+3]; //*** is there a better way to do this??? assign NegSticky = W[`DIVb+3];
assign EarlyTermShiftE = step; assign EarlyTermShiftE = step;
always_ff @(posedge clk) begin always_ff @(posedge clk) begin
@ -78,7 +80,7 @@ module srtfsm(
state <= #1 IDLE; state <= #1 IDLE;
end else if (DivStart&~StallE) begin end else if (DivStart&~StallE) begin
step <= Dur; step <= Dur;
if (XZeroE|YZeroE|XInfE|YInfE|XNaNE|YNaNE) state <= #1 DONE; if (XZeroE|YZeroE|XInfE|YInfE|XNaNE|YNaNE|(XsE&SqrtE)) state <= #1 DONE;
else state <= #1 BUSY; else state <= #1 BUSY;
end else if (state == BUSY) begin end else if (state == BUSY) begin
if ((~|step[`DURLEN-1:1]&step[0])|WZero) begin if ((~|step[`DURLEN-1:1]&step[0])|WZero) begin

View File

@ -39,16 +39,16 @@ module srtpreproc (
input logic Sqrt, input logic Sqrt,
input logic XZero, input logic XZero,
output logic [`NE+1:0] QeM, output logic [`NE+1:0] QeM,
output logic [`DIVLEN+3:0] X, output logic [`DIVb:0] X,
output logic [`DIVLEN+3:0] Dpreproc, output logic [`DIVN-2:0] Dpreproc,
output logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
output logic [`DURLEN-1:0] Dur output logic [`DURLEN-1:0] Dur
); );
// logic [`XLEN-1:0] PosA, PosB; // logic [`XLEN-1:0] PosA, PosB;
// logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY; // logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY;
logic [`NF-1:0] PreprocA, PreprocX; logic [`NF-1:0] PreprocA, PreprocX;
logic [`NF-1:0] PreprocB, PreprocY; logic [`NF-1:0] PreprocB, PreprocY;
logic [`NF+3:0] SqrtX; logic [`NF+1:0] SqrtX;
logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt;
logic [`NE+1:0] Qe; logic [`NE+1:0] Qe;
// assign PosA = (Signed & SrcA[`XLEN - 1]) ? -SrcA : SrcA; // assign PosA = (Signed & SrcA[`XLEN - 1]) ? -SrcA : SrcA;
@ -70,9 +70,9 @@ module srtpreproc (
assign PreprocY = Ym[`NF-1:0]<<YZeroCnt; assign PreprocY = Ym[`NF-1:0]<<YZeroCnt;
assign SqrtX = Xe[0] ? {3'b110, ~XZero, PreprocX} : {2'b11, ~XZero, PreprocX, 1'b0}; assign SqrtX = Xe[0]^XZeroCnt[0] ? {1'b0, ~XZero, PreprocX} : {~XZero, PreprocX, 1'b0};
assign X = Sqrt ? {SqrtX, {`DIVLEN-`NF{1'b0}}} : {3'b000, ~XZero, PreprocX, {`DIVLEN-`NF{1'b0}}}; assign X = Sqrt ? {SqrtX, {`DIVb-1-`NF{1'b0}}} : {~XZero, PreprocX, {`DIVb-`NF{1'b0}}};
assign Dpreproc = {4'b0001, /*Int ? PreprocB : */PreprocY, {`DIVLEN-`NF{1'b0}}}; assign Dpreproc = {PreprocY, {`DIVN-1-`NF{1'b0}}};
assign Dur = (`DURLEN)'(`FPDUR); assign Dur = (`DURLEN)'(`FPDUR);
// radix 2 radix 4 // radix 2 radix 4
@ -99,7 +99,8 @@ module expcalc(
output logic [`NE+1:0] Qe output logic [`NE+1:0] Qe
); );
logic [`NE-2:0] Bias; logic [`NE-2:0] Bias;
logic [`NE-1:0] SExp, SXExp; logic [`NE+1:0] SXExp;
logic [`NE+1:0] SExp;
logic [`NE+1:0] DExp; logic [`NE+1:0] DExp;
if (`FPSIZES == 1) begin if (`FPSIZES == 1) begin
@ -126,10 +127,10 @@ module expcalc(
2'h2: Bias = (`NE-1)'(`H_BIAS); 2'h2: Bias = (`NE-1)'(`H_BIAS);
endcase endcase
end end
assign SXExp = Xe - (`NE)'(`BIAS); assign SXExp = {2'b0, Xe} - {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, XZeroCnt} - (`NE+1)'(`BIAS);
assign SExp = {1'b0, SXExp[`NE-1:1]} + Bias; assign SExp = {SXExp[`NE+1], SXExp[`NE+1:1]} + {2'b0, Bias};
// correct exponent for denormalized input's normalization shifts // correct exponent for denormalized input's normalization shifts
assign DExp = ({2'b0, Xe} - {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, XZeroCnt} - {2'b0, Ye} + {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, YZeroCnt} + {3'b0, Bias})&{`NE+2{~XZero}}; assign DExp = ({2'b0, Xe} - {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, XZeroCnt} - {2'b0, Ye} + {{`NE+1-$unsigned($clog2(`NF+2)){1'b0}}, YZeroCnt} + {3'b0, Bias})&{`NE+2{~XZero}};
assign Qe = Sqrt ? {2'b0, SExp} : DExp; assign Qe = Sqrt ? SExp : DExp;
endmodule endmodule

View File

@ -8,7 +8,7 @@
/* #includes */ /* #includes */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <math.h> #include <math.h>
/* Constants */ /* Constants */

View File

@ -80,7 +80,7 @@ module testbenchfp;
logic CvtResSgnE; logic CvtResSgnE;
logic [`NE:0] CvtCalcExpE; // the calculated expoent logic [`NE:0] CvtCalcExpE; // the calculated expoent
logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by logic [`LOGCVTLEN-1:0] CvtShiftAmtE; // how much to shift by
logic [`QLEN-1-(`RADIX/4):0] Quot; logic [`DIVb-(`RADIX/4):0] Quot;
logic CvtResDenormUfE; logic CvtResDenormUfE;
logic [`DURLEN-1:0] EarlyTermShift; logic [`DURLEN-1:0] EarlyTermShift;
logic DivStart, DivBusy; logic DivStart, DivBusy;
@ -256,16 +256,16 @@ module testbenchfp;
Fmt = {Fmt, 2'b11}; Fmt = {Fmt, 2'b11};
end end
end end
// if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tested if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tested
// // add the square-root tests/op-ctrls/unit/fmt // add the square-root tests/op-ctrls/unit/fmt
// Tests = {Tests, f128sqrt}; Tests = {Tests, f128sqrt};
// OpCtrl = {OpCtrl, `SQRT_OPCTRL}; OpCtrl = {OpCtrl, `SQRT_OPCTRL};
// WriteInt = {WriteInt, 1'b0}; WriteInt = {WriteInt, 1'b0};
// for(int i = 0; i<5; i++) begin for(int i = 0; i<5; i++) begin
// Unit = {Unit, `DIVUNIT}; Unit = {Unit, `DIVUNIT};
// Fmt = {Fmt, 2'b11}; Fmt = {Fmt, 2'b11};
// end end
// end end
if (TEST === "fma" | TEST === "all") begin // if fused-mutliply-add is being tested if (TEST === "fma" | TEST === "all") begin // if fused-mutliply-add is being tested
Tests = {Tests, f128fma}; Tests = {Tests, f128fma};
OpCtrl = {OpCtrl, `FMA_OPCTRL}; OpCtrl = {OpCtrl, `FMA_OPCTRL};
@ -383,16 +383,16 @@ module testbenchfp;
Fmt = {Fmt, 2'b01}; Fmt = {Fmt, 2'b01};
end end
end end
// if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tessted if (TEST === "sqrt" | TEST === "all") begin // if square-root is being tessted
// // add the correct tests/op-ctrls/unit/fmt to their lists // add the correct tests/op-ctrls/unit/fmt to their lists
// Tests = {Tests, f64sqrt}; Tests = {Tests, f64sqrt};
// OpCtrl = {OpCtrl, `SQRT_OPCTRL}; OpCtrl = {OpCtrl, `SQRT_OPCTRL};
// WriteInt = {WriteInt, 1'b0}; WriteInt = {WriteInt, 1'b0};
// for(int i = 0; i<5; i++) begin for(int i = 0; i<5; i++) begin
// Unit = {Unit, `DIVUNIT}; Unit = {Unit, `DIVUNIT};
// Fmt = {Fmt, 2'b01}; Fmt = {Fmt, 2'b01};
// end end
// end end
if (TEST === "fma" | TEST === "all") begin // if the fused multiply add is being tested if (TEST === "fma" | TEST === "all") begin // if the fused multiply add is being tested
Tests = {Tests, f64fma}; Tests = {Tests, f64fma};
OpCtrl = {OpCtrl, `FMA_OPCTRL}; OpCtrl = {OpCtrl, `FMA_OPCTRL};
@ -494,16 +494,16 @@ module testbenchfp;
Fmt = {Fmt, 2'b00}; Fmt = {Fmt, 2'b00};
end end
end end
// if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested
// // add the correct tests/op-ctrls/unit/fmt to their lists // add the correct tests/op-ctrls/unit/fmt to their lists
// Tests = {Tests, f32sqrt}; Tests = {Tests, f32sqrt};
// OpCtrl = {OpCtrl, `SQRT_OPCTRL}; OpCtrl = {OpCtrl, `SQRT_OPCTRL};
// WriteInt = {WriteInt, 1'b0}; WriteInt = {WriteInt, 1'b0};
// for(int i = 0; i<5; i++) begin for(int i = 0; i<5; i++) begin
// Unit = {Unit, `DIVUNIT}; Unit = {Unit, `DIVUNIT};
// Fmt = {Fmt, 2'b00}; Fmt = {Fmt, 2'b00};
// end end
// end end
if (TEST === "fma" | TEST === "all") begin // if fma is being tested if (TEST === "fma" | TEST === "all") begin // if fma is being tested
Tests = {Tests, f32fma}; Tests = {Tests, f32fma};
OpCtrl = {OpCtrl, `FMA_OPCTRL}; OpCtrl = {OpCtrl, `FMA_OPCTRL};
@ -587,16 +587,16 @@ module testbenchfp;
Fmt = {Fmt, 2'b10}; Fmt = {Fmt, 2'b10};
end end
end end
// if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested if (TEST === "sqrt" | TEST === "all") begin // if sqrt is being tested
// // add the correct tests/op-ctrls/unit/fmt to their lists // add the correct tests/op-ctrls/unit/fmt to their lists
// Tests = {Tests, f16sqrt}; Tests = {Tests, f16sqrt};
// OpCtrl = {OpCtrl, `SQRT_OPCTRL}; OpCtrl = {OpCtrl, `SQRT_OPCTRL};
// WriteInt = {WriteInt, 1'b0}; WriteInt = {WriteInt, 1'b0};
// for(int i = 0; i<5; i++) begin for(int i = 0; i<5; i++) begin
// Unit = {Unit, `DIVUNIT}; Unit = {Unit, `DIVUNIT};
// Fmt = {Fmt, 2'b10}; Fmt = {Fmt, 2'b10};
// end end
// end end
if (TEST === "fma" | TEST === "all") begin // if fma is being tested if (TEST === "fma" | TEST === "all") begin // if fma is being tested
Tests = {Tests, f16fma}; Tests = {Tests, f16fma};
OpCtrl = {OpCtrl, `FMA_OPCTRL}; OpCtrl = {OpCtrl, `FMA_OPCTRL};
@ -697,7 +697,7 @@ module testbenchfp;
fcmp fcmp (.Fmt(ModFmt), .OpCtrl(OpCtrlVal), .Xs, .Ys, .Xe, .Ye, fcmp fcmp (.Fmt(ModFmt), .OpCtrl(OpCtrlVal), .Xs, .Ys, .Xe, .Ye,
.Xm, .Ym, .XZero, .YZero, .CmpIntRes(CmpRes), .Xm, .Ym, .XZero, .YZero, .CmpIntRes(CmpRes),
.XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes)); .XNaN, .YNaN, .XSNaN, .YSNaN, .X, .Y, .CmpNV(CmpFlg[4]), .CmpFpRes(FpCmpRes));
divsqrt divsqrt(.clk, .reset, .FmtE(ModFmt), .XmE(Xm), .YmE(Ym), .XeE(Xe), .YeE(Ye), .SqrtE(1'b0), .SqrtM(1'b0), divsqrt divsqrt(.clk, .reset, .XsE(Xs), .FmtE(ModFmt), .XmE(Xm), .YmE(Ym), .XeE(Xe), .YeE(Ye), .SqrtE(OpCtrlVal[0]), .SqrtM(OpCtrlVal[0]),
.XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero), .XNaNE(XNaN), .YNaNE(YNaN), .DivStartE(DivStart), .XInfE(XInf), .YInfE(YInf), .XZeroE(XZero), .YZeroE(YZero), .XNaNE(XNaN), .YNaNE(YNaN), .DivStartE(DivStart),
.StallE(1'b0), .StallM(1'b0), .DivSM(DivSticky), .DivBusy, .QeM(DivCalcExp), .StallE(1'b0), .StallM(1'b0), .DivSM(DivSticky), .DivBusy, .QeM(DivCalcExp),
.EarlyTermShiftM(EarlyTermShift), .QmM(Quot), .DivDone); .EarlyTermShiftM(EarlyTermShift), .QmM(Quot), .DivDone);
@ -1007,40 +1007,72 @@ module readvectors (
end end
endcase endcase
`DIVUNIT: `DIVUNIT:
case (Fmt) if(OpCtrl[0])
2'b11: begin // quad case (Fmt)
X = TestVector[8+3*(`Q_LEN)-1:8+2*(`Q_LEN)]; 2'b11: begin // quad
Y = TestVector[8+2*(`Q_LEN)-1:8+(`Q_LEN)]; X = TestVector[8+2*(`Q_LEN)-1:8+(`Q_LEN)];
Ans = TestVector[8+(`Q_LEN-1):8]; Ans = TestVector[8+(`Q_LEN-1):8];
if (~clk) #5; if (~clk) #5;
DivStart = 1'b1; #10 // one clk cycle DivStart = 1'b1; #10 // one clk cycle
DivStart = 1'b0; DivStart = 1'b0;
end end
2'b01: if (`D_SUPPORTED)begin // double 2'b01: if (`D_SUPPORTED)begin // double
X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+3*(`D_LEN)-1:8+2*(`D_LEN)]}; X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+(`D_LEN)]};
Y = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+(`D_LEN)]}; Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]};
Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]}; if (~clk) #5;
if (~clk) #5; DivStart = 1'b1; #10
DivStart = 1'b1; #10 DivStart = 1'b0;
DivStart = 1'b0; end
end 2'b00: if (`S_SUPPORTED)begin // single
2'b00: if (`S_SUPPORTED)begin // single X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+1*(`S_LEN)]};
X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+3*(`S_LEN)-1:8+2*(`S_LEN)]}; Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]};
Y = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+1*(`S_LEN)]}; if (~clk) #5;
Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]}; DivStart = 1'b1; #10
if (~clk) #5; DivStart = 1'b0;
DivStart = 1'b1; #10 end
DivStart = 1'b0; 2'b10: begin // half
end X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+(`H_LEN)]};
2'b10: begin // half Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]};
X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+3*(`H_LEN)-1:8+2*(`H_LEN)]}; if (~clk) #5;
Y = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+(`H_LEN)]}; DivStart = 1'b1; #10
Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]}; DivStart = 1'b0;
if (~clk) #5; end
DivStart = 1'b1; #10 endcase
DivStart = 1'b0; else
end case (Fmt)
endcase 2'b11: begin // quad
X = TestVector[8+3*(`Q_LEN)-1:8+2*(`Q_LEN)];
Y = TestVector[8+2*(`Q_LEN)-1:8+(`Q_LEN)];
Ans = TestVector[8+(`Q_LEN-1):8];
if (~clk) #5;
DivStart = 1'b1; #10 // one clk cycle
DivStart = 1'b0;
end
2'b01: if (`D_SUPPORTED)begin // double
X = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+3*(`D_LEN)-1:8+2*(`D_LEN)]};
Y = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+2*(`D_LEN)-1:8+(`D_LEN)]};
Ans = {{`FLEN-`D_LEN{1'b1}}, TestVector[8+(`D_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
2'b00: if (`S_SUPPORTED)begin // single
X = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+3*(`S_LEN)-1:8+2*(`S_LEN)]};
Y = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+2*(`S_LEN)-1:8+1*(`S_LEN)]};
Ans = {{`FLEN-`S_LEN{1'b1}}, TestVector[8+(`S_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
2'b10: begin // half
X = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+3*(`H_LEN)-1:8+2*(`H_LEN)]};
Y = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+2*(`H_LEN)-1:8+(`H_LEN)]};
Ans = {{`FLEN-`H_LEN{1'b1}}, TestVector[8+(`H_LEN-1):8]};
if (~clk) #5;
DivStart = 1'b1; #10
DivStart = 1'b0;
end
endcase
`CMPUNIT: `CMPUNIT:
case (Fmt) case (Fmt)
2'b11: begin // quad 2'b11: begin // quad
@ -1259,7 +1291,7 @@ module readvectors (
end end
assign XEn = ~((Unit == `CVTINTUNIT)&OpCtrl[2]); assign XEn = ~((Unit == `CVTINTUNIT)&OpCtrl[2]);
assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT)); assign YEn = ~((Unit == `CVTINTUNIT)|(Unit == `CVTFPUNIT)|((Unit == `DIVUNIT)&OpCtrl[0]));
assign ZEn = (Unit == `FMAUNIT); assign ZEn = (Unit == `FMAUNIT);
unpack unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze, unpack unpack(.X, .Y, .Z, .Fmt(ModFmt), .Xs, .Ys, .Zs, .Xe, .Ye, .Ze,