This commit is contained in:
Daniel Torres 2022-07-21 12:50:04 -07:00
commit 9421b77613
13 changed files with 274 additions and 98 deletions

@ -1 +1 @@
Subproject commit 58ffa0c68c52f291d12c5902fc787d2bca94ddf9 Subproject commit 261a65e0a2d3e8d62d81b1d8fe7e309a096bc6a9

View File

@ -101,7 +101,7 @@
`define CORRSHIFTSZ ((`DIVRESLEN+`NF) > (3*`NF+8) ? (`DIVRESLEN+`NF) : (3*`NF+6)) `define CORRSHIFTSZ ((`DIVRESLEN+`NF) > (3*`NF+8) ? (`DIVRESLEN+`NF) : (3*`NF+6))
// division constants // division constants
`define RADIX 32'h2 `define RADIX 32'h4
`define DIVCOPIES 32'h1 `define DIVCOPIES 32'h1
`define DIVLEN ((`NF < `XLEN) ? (`XLEN) : (`NF + 3)) `define DIVLEN ((`NF < `XLEN) ? (`XLEN) : (`NF + 3))
`define EXTRAFRACBITS ((`NF<(`XLEN)) ? (`XLEN - `NF) : 3) `define EXTRAFRACBITS ((`NF<(`XLEN)) ? (`XLEN - `NF) : 3)

View File

@ -33,7 +33,7 @@ add wave -group {Divide} -group inter0 -noupdate /testbenchfp/divsqrt/srt/intera
# 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} -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/srt/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

@ -41,7 +41,8 @@ module divsqrt(
input logic XNaNE, YNaNE, input logic XNaNE, YNaNE,
input logic DivStartE, input logic DivStartE,
input logic StallM, input logic StallM,
input logic StallE, input logic StallE,
input logic SqrtE, SqrtM,
output logic DivSM, output logic DivSM,
output logic DivBusy, output logic DivBusy,
output logic DivDone, output logic DivDone,
@ -55,15 +56,15 @@ module divsqrt(
logic [`DIVLEN+3:0] WS, WC; logic [`DIVLEN+3:0] WS, WC;
logic [`DIVLEN+3:0] StickyWSA; logic [`DIVLEN+3:0] StickyWSA;
logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt; logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt;
logic [`DIVLEN-1:0] X; logic [`DIVLEN+3:0] X;
logic [`DIVLEN-1:0] Dpreproc; logic [`DIVLEN+3:0] Dpreproc;
logic [`DURLEN-1:0] Dur; logic [`DURLEN-1:0] Dur;
logic NegSticky; logic NegSticky;
srtpreproc srtpreproc(.Xm(XmE), .Dur, .Ym(YmE), .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, .XZeroCnt, .YZeroCnt);
srtfsm srtfsm(.reset, .NextWSN, .NextWCN, .WS, .WC, .Dur, .DivBusy, .clk, .DivStart(DivStartE),.StallE, .StallM, .DivDone, .XZeroE, .YZeroE, .DivSE(DivSM), .XNaNE, .YNaNE, srtfsm srtfsm(.reset, .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, .FmtE, .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, .XZeroCnt, .YZeroCnt, .FirstWS(WS), .FirstWC(WC), .NextWSN, .NextWCN, .DivStart(DivStartE), .Xe(XeE), .Ye(YeE), .XZeroE, .YZeroE,
.StickyWSA, .DivBusy, .Qm(QmM), .Rem(), .QeM); .StickyWSA, .DivBusy, .Qm(QmM), .Rem());
endmodule endmodule

View File

@ -219,8 +219,8 @@ module fctrl (
// 110 - add // 110 - add
// 111 - sub // 111 - sub
// Div: // Div:
// 0 - ??? // 0 - div
// 1 - ??? // 1 - sqrt
// Cvt Int: {Int to Fp?, 64 bit int?, signed int?} // Cvt Int: {Int to Fp?, 64 bit int?, signed int?}
// Cvt Fp: output format // Cvt Fp: output format
// 10 - to half // 10 - to half

View File

@ -259,7 +259,7 @@ module fpu (
// - fdiv // - fdiv
// - fsqrt // - fsqrt
// *** add other opperations // *** add other opperations
divsqrt divsqrt(.clk, .reset, .FmtE, .XmE, .YmE, .XeE, .YeE, 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),
.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));

View File

@ -58,6 +58,41 @@ module otfc2 (
endmodule endmodule
///////////////////////////////
// Square Root OTFC, Radix 2 //
///////////////////////////////
module sotfc2(
input logic clk,
input logic Start,
input logic sp, sn,
input logic Sqrt,
input logic [`DIVLEN+3:0] C,
output logic [`DIVLEN-2:0] Sq,
output logic [`DIVLEN+3:0] S, SM
);
// The on-the-fly converter transfers the square root
// bits to the quotient as they come.
// Use this otfc for division and square root.
logic [`DIVLEN+3:0] SNext, SMNext, SMux;
flopr #(`DIVLEN+4) SMreg(clk, Start, SMNext, SM);
mux2 #(`DIVLEN+4) Smux(SNext, {3'b000, Sqrt, {(`DIVLEN){1'b0}}}, Start, SMux);
flop #(`DIVLEN+4) Sreg(clk, SMux, S);
always_comb begin
if (sp) begin
SNext = S | (C & ~(C << 1));
SMNext = S;
end else if (sn) begin
SNext = SM | (C & ~(C << 1));
SMNext = SM;
end else begin // If sp and sn are not true, then sz is
SNext = S;
SMNext = SM | (C & ~(C << 1));
end
end
assign Sq = S[`DIVLEN] ? S[`DIVLEN-1:1] : S[`DIVLEN-2:0];
endmodule
module otfc4 ( module otfc4 (
input logic [3:0] q, input logic [3:0] q,
@ -110,3 +145,38 @@ module otfc4 (
// Final Qmeint is in the range [.5, 2) // Final Qmeint is in the range [.5, 2)
endmodule endmodule
///////////////////////////////
// Square Root OTFC, Radix 4 //
///////////////////////////////
module sotfc4(
input logic [3:0] s,
input logic Sqrt,
input logic [`DIVLEN+3:0] S, SM,
input logic [`DIVLEN+3:0] C,
output logic [`DIVLEN+3:0] SNext, SMNext
);
// The on-the-fly converter transfers the square root
// bits to the quotient as they come.
// Use this otfc for division and square root.
always_comb begin
if (s[3]) begin
SNext = S | ((C << 1)&~(C << 2));
SMNext = S | (C&~(C << 1));
end else if (s[2]) begin
SNext = S | (C&~(C << 1));
SMNext = S;
end else if (s[1]) begin
SNext = SM | (C&~(C << 2));
SMNext = SM | ((C << 1)&~(C << 2));
end else if (s[0]) begin
SNext = SM | ((C << 1)&~(C << 2));
SMNext = SM | (C&~(C << 1));
end else begin // If sp and sn are not true, then sz is
SNext = S;
SMNext = SM | (C & ~(C << 2));
end
end
endmodule

View File

@ -62,9 +62,36 @@ module qsel2 ( // *** eventually just change to 4 bits
// assign #1 qn = magnitude & sign; // assign #1 qn = magnitude & sign;
endmodule endmodule
////////////////////////////////////
// Adder Input Generation, Radix 2 //
////////////////////////////////////
module fgen2 (
input logic sp, sn,
input logic [`DIVLEN+3:0] C, S, SM,
output logic [`DIVLEN+3:0] F
);
logic [`DIVLEN+3:0] FP, FN, FZ;
// Generate for both positive and negative bits
assign FP = ~(S << 1) & C;
assign FN = (SM << 1) | (C & (~C << 2));
assign FZ = '0;
// Choose which adder input will be used
always_comb
if (sp) F = FP;
else if (sn) F = FN;
else F = FZ;
// assign F = sp ? FP : (sn ? FN : FZ);
endmodule
module qsel4 ( module qsel4 (
input logic [`DIVLEN+3:0] D, input logic [`DIVLEN+3:0] D,
input logic [`DIVLEN+3:0] WS, WC, input logic [`DIVLEN+3:0] WS, WC,
input logic Sqrt,
output logic [3:0] q output logic [3:0] q
); );
logic [6:0] Wmsbs; logic [6:0] Wmsbs;
@ -91,45 +118,77 @@ module qsel4 (
else if(w2>=4) QSel4[i] = 4'b0100; else if(w2>=4) QSel4[i] = 4'b0100;
else if(w2>=-4) QSel4[i] = 4'b0000; else if(w2>=-4) QSel4[i] = 4'b0000;
else if(w2>=-13) QSel4[i] = 4'b0010; else if(w2>=-13) QSel4[i] = 4'b0010;
else QSel4[i] = 4'b0001; else QSel4[i] = 4'b0001;
1: if(w2>=14) QSel4[i] = 4'b1000; 1: if(w2>=14) QSel4[i] = 4'b1000;
else if(w2>=4) QSel4[i] = 4'b0100; else if(w2>=4) QSel4[i] = 4'b0100;
else if(w2>=-6) QSel4[i] = 4'b0000; else if(w2>=-5) QSel4[i] = 4'b0000; // was -6
else if(w2>=-15) QSel4[i] = 4'b0010; else if(~Sqrt&(w2>=-15)) QSel4[i] = 4'b0010; // divide case
else QSel4[i] = 4'b0001; else if( Sqrt&(w2>=-14)) QSel4[i] = 4'b0010; // sqrt case
else QSel4[i] = 4'b0001;
2: if(w2>=15) QSel4[i] = 4'b1000; 2: if(w2>=15) QSel4[i] = 4'b1000;
else if(w2>=4) QSel4[i] = 4'b0100; else if(w2>=4) QSel4[i] = 4'b0100;
else if(w2>=-6) QSel4[i] = 4'b0000; else if(w2>=-6) QSel4[i] = 4'b0000;
else if(w2>=-16) QSel4[i] = 4'b0010; else if(w2>=-16) QSel4[i] = 4'b0010;
else QSel4[i] = 4'b0001; else QSel4[i] = 4'b0001;
3: if(w2>=16) QSel4[i] = 4'b1000; 3: if(w2>=16) QSel4[i] = 4'b1000;
else if(w2>=4) QSel4[i] = 4'b0100; else if(w2>=4) QSel4[i] = 4'b0100;
else if(w2>=-6) QSel4[i] = 4'b0000; else if(w2>=-6) QSel4[i] = 4'b0000;
else if(w2>=-18) QSel4[i] = 4'b0010; else if(w2>=-17) QSel4[i] = 4'b0010; // was -18
else QSel4[i] = 4'b0001; else QSel4[i] = 4'b0001;
4: if(w2>=18) QSel4[i] = 4'b1000; 4: if(w2>=18) QSel4[i] = 4'b1000;
else if(w2>=6) QSel4[i] = 4'b0100; else if(w2>=6) QSel4[i] = 4'b0100;
else if(w2>=-8) QSel4[i] = 4'b0000; else if(w2>=-6) QSel4[i] = 4'b0000; // was -8
else if(w2>=-20) QSel4[i] = 4'b0010; else if(~Sqrt&(w2>=-20)) QSel4[i] = 4'b0010; // divide case
else QSel4[i] = 4'b0001; else if( Sqrt&(w2>=-18)) QSel4[i] = 4'b0010; // sqrt case
else QSel4[i] = 4'b0001;
5: if(w2>=20) QSel4[i] = 4'b1000; 5: if(w2>=20) QSel4[i] = 4'b1000;
else if(w2>=6) QSel4[i] = 4'b0100; else if(w2>=6) QSel4[i] = 4'b0100;
else if(w2>=-8) QSel4[i] = 4'b0000; else if(w2>=-8) QSel4[i] = 4'b0000;
else if(w2>=-20) QSel4[i] = 4'b0010; else if(w2>=-20) QSel4[i] = 4'b0010;
else QSel4[i] = 4'b0001; else QSel4[i] = 4'b0001;
6: if(w2>=20) QSel4[i] = 4'b1000; 6: if(w2>=20) QSel4[i] = 4'b1000;
else if(w2>=8) QSel4[i] = 4'b0100; else if(w2>=8) QSel4[i] = 4'b0100;
else if(w2>=-8) QSel4[i] = 4'b0000; else if(w2>=-8) QSel4[i] = 4'b0000;
else if(w2>=-22) QSel4[i] = 4'b0010; else if(w2>=-22) QSel4[i] = 4'b0010;
else QSel4[i] = 4'b0001; else QSel4[i] = 4'b0001;
7: if(w2>=24) QSel4[i] = 4'b1000; 7: if(w2>=22) QSel4[i] = 4'b1000; // was 24
else if(w2>=8) QSel4[i] = 4'b0100; else if(w2>=8) QSel4[i] = 4'b0100;
else if(w2>=-8) QSel4[i] = 4'b0000; else if(w2>=-8) QSel4[i] = 4'b0000;
else if(w2>=-24) QSel4[i] = 4'b0010; else if(w2>=-23) QSel4[i] = 4'b0010; // was -24
else QSel4[i] = 4'b0001; else QSel4[i] = 4'b0001;
endcase endcase
end end
end end
assign q = QSel4[{Dmsbs,Wmsbs}]; assign q = QSel4[{Dmsbs,Wmsbs}];
endmodule endmodule
////////////////////////////////////
// Adder Input Generation, Radix 4 //
////////////////////////////////////
module fgen4 (
input logic [3:0] s,
input logic [`DIVLEN+3:0] C, S, SM,
output logic [`DIVLEN+3:0] F
);
logic [`DIVLEN+3:0] F2, F1, F0, FN1, FN2;
// Generate for both positive and negative bits
assign F2 = (~S << 2) & (C << 2);
assign F1 = ~(S << 1) & C;
assign F0 = '0;
assign FN1 = (SM << 1) | (C & ~(C << 2));
assign FN2 = (SM << 2) | ((C << 2)&~(C <<4));
// Choose which adder input will be used
always_comb
if (s[3]) F = F2;
else if (s[2]) F = F1;
else if (s[1]) F = FN1;
else if (s[0]) F = FN2;
else F = F0;
// assign F = sp ? FP : (sn ? FN : FZ);
endmodule

View File

@ -34,18 +34,17 @@ module srt(
input logic clk, input logic clk,
input logic DivStart, input logic DivStart,
input logic DivBusy, input logic DivBusy,
input logic [`FMTBITS-1:0] FmtE,
input logic [`NE-1:0] Xe, Ye, input logic [`NE-1:0] Xe, Ye,
input logic XZeroE, YZeroE, input logic XZeroE, YZeroE,
input logic [`DIVLEN-1:0] X, input logic Sqrt,
input logic [`DIVLEN-1:0] Dpreproc, input logic [`DIVLEN+3:0] X,
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt, input logic [`DIVLEN+3:0] Dpreproc,
input logic NegSticky, input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
input logic NegSticky,
output logic [`QLEN-1-(`RADIX/4):0] Qm, output logic [`QLEN-1-(`RADIX/4):0] Qm,
output logic [`DIVLEN+3:0] NextWSN, NextWCN, output logic [`DIVLEN+3:0] NextWSN, NextWCN,
output logic [`DIVLEN+3:0] StickyWSA, output logic [`DIVLEN+3:0] StickyWSA,
output logic [`DIVLEN+3:0] FirstWS, FirstWC, output logic [`DIVLEN+3:0] FirstWS, FirstWC,
output logic [`NE+1:0] QeM,
output logic [`XLEN-1:0] Rem output logic [`XLEN-1:0] Rem
); );
@ -59,13 +58,19 @@ module srt(
logic [`QLEN-1:0] QM[`DIVCOPIES-1:0]; logic [`QLEN-1:0] QM[`DIVCOPIES-1:0];
logic [`QLEN-1:0] QNext[`DIVCOPIES-1:0]; logic [`QLEN-1:0] QNext[`DIVCOPIES-1:0];
logic [`QLEN-1:0] QMNext[`DIVCOPIES-1:0]; logic [`QLEN-1:0] QMNext[`DIVCOPIES-1:0];
logic [`DIVLEN+3:0] S[`DIVCOPIES-1:0]; //***change to QLEN???
logic [`DIVLEN+3:0] SM[`DIVCOPIES-1:0];
logic [`DIVLEN+3:0] SNext[`DIVCOPIES-1:0];
logic [`DIVLEN+3:0] SMNext[`DIVCOPIES-1:0];
logic [`DIVLEN+3:0] C[`DIVCOPIES-1:0];
/* verilator lint_on UNOPTFLAT */ /* verilator lint_on UNOPTFLAT */
logic [`DIVLEN+3:0] WSN, WCN; logic [`DIVLEN+3:0] WSN, WCN;
logic [`DIVLEN+3:0] D, DBar, D2, DBar2; logic [`DIVLEN+3:0] D, DBar, D2, DBar2;
logic [`NE+1:0] Qe;
logic [$clog2(`XLEN+1)-1:0] intExp; logic [$clog2(`XLEN+1)-1:0] intExp;
logic intSign; logic intSign;
logic [`QLEN-1:0] QMMux; logic [`QLEN-1:0] QMMux;
logic [`DIVLEN+3:0] CMux;
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.
@ -83,13 +88,13 @@ module srt(
assign NextWCN = {WCA[`DIVCOPIES-1][`DIVLEN+1:0], 2'b0}; assign NextWCN = {WCA[`DIVCOPIES-1][`DIVLEN+1:0], 2'b0};
end end
mux2 #(`DIVLEN+4) wsmux(NextWSN, {3'b000, ~XZeroE, X}, DivStart, WSN); mux2 #(`DIVLEN+4) wsmux(NextWSN, X, DivStart, WSN);
flopen #(`DIVLEN+4) wsflop(clk, DivStart|DivBusy, WSN, WS[0]); flopen #(`DIVLEN+4) wsflop(clk, DivStart|DivBusy, WSN, WS[0]);
mux2 #(`DIVLEN+4) wcmux(NextWCN, {`DIVLEN+4{1'b0}}, DivStart, WCN); mux2 #(`DIVLEN+4) wcmux(NextWCN, {`DIVLEN+4{1'b0}}, DivStart, WCN);
flopen #(`DIVLEN+4) wcflop(clk, DivStart|DivBusy, WCN, WC[0]); flopen #(`DIVLEN+4) wcflop(clk, DivStart|DivBusy, WCN, WC[0]);
flopen #(`DIVLEN+4) dflop(clk, DivStart, {4'b0001, Dpreproc}, D); flopen #(`DIVLEN+4) dflop(clk, DivStart, Dpreproc, D);
flopen #(`NE+2) expflop(clk, DivStart, Qe, QeM); mux2 #(`DIVLEN+4) Cmux({2'b11, C[`DIVCOPIES-1][`DIVLEN+3:2]}, {5'b11111, Sqrt, {(`DIVLEN-2){1'b0}}}, DivStart, CMux);
flop #(`DIVLEN+4) 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
@ -102,8 +107,9 @@ module srt(
genvar i; genvar i;
generate generate
for(i=0; $unsigned(i)<`DIVCOPIES; i++) begin : interations for(i=0; $unsigned(i)<`DIVCOPIES; i++) begin : interations
divinteration divinteration(.D, .DBar, .D2, .DBar2, divinteration divinteration(.D, .DBar, .D2, .DBar2, .Sqrt,
.WS(WS[i]), .WC(WC[i]), .WSA(WSA[i]), .WCA(WCA[i]), .Q(Q[i]), .QM(QM[i]), .QNext(QNext[i]), .QMNext(QMNext[i])); .WS(WS[i]), .WC(WC[i]), .WSA(WSA[i]), .WCA(WCA[i]), .Q(Q[i]), .QM(QM[i]), .QNext(QNext[i]), .QMNext(QMNext[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][`DIVLEN+1:0], 1'b0};
@ -111,9 +117,12 @@ module srt(
end else begin end else begin
assign WS[i+1] = {WSA[i][`DIVLEN+1:0], 2'b0}; assign WS[i+1] = {WSA[i][`DIVLEN+1:0], 2'b0};
assign WC[i+1] = {WCA[i][`DIVLEN+1:0], 2'b0}; assign WC[i+1] = {WCA[i][`DIVLEN+1:0], 2'b0};
assign C[i+1] = {2'b11, C[i][`DIVLEN+3: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];
assign S[i+1] = SNext[i];
assign SM[i+1] = SMNext[i];
end end
end end
endgenerate endgenerate
@ -123,16 +132,27 @@ module srt(
flopenr #(`QLEN) Qreg(clk, DivStart, DivBusy, QNext[`DIVCOPIES-1], Q[0]); flopenr #(`QLEN) Qreg(clk, DivStart, DivBusy, QNext[`DIVCOPIES-1], Q[0]);
flopen #(`QLEN) QMreg(clk, DivBusy, QMMux, QM[0]); flopen #(`QLEN) QMreg(clk, DivBusy, QMMux, QM[0]);
assign Qm = NegSticky ? QM[0][`QLEN-1-(`RADIX/4):0] : Q[0][`QLEN-1-(`RADIX/4):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]);
always_comb
if(Sqrt)
if(NegSticky) Qm = SM[0][`QLEN-1-(`RADIX/4):0];
else Qm = S[0][`QLEN-1-(`RADIX/4):0];
else
if(NegSticky) Qm = QM[0][`QLEN-1-(`RADIX/4):0];
else Qm = Q[0][`QLEN-1-(`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][`DIVLEN+2:0], 1'b0};
else else
assign StickyWSA = {WSA[1][`DIVLEN+2:0], 1'b0}; assign StickyWSA = {WSA[1][`DIVLEN+2:0], 1'b0};
expcalc expcalc(.FmtE, .Xe, .Ye, .XZeroE, .XZeroCnt, .YZeroCnt, .Qe);
endmodule endmodule
@ -145,8 +165,12 @@ module divinteration (
input logic [`DIVLEN+3:0] D, input logic [`DIVLEN+3:0] D,
input logic [`DIVLEN+3:0] DBar, D2, DBar2, input logic [`DIVLEN+3:0] DBar, D2, DBar2,
input logic [`QLEN-1:0] Q, QM, input logic [`QLEN-1:0] Q, QM,
input logic [`DIVLEN+3:0] S, SM,
input logic [`DIVLEN+3:0] WS, WC, input logic [`DIVLEN+3:0] WS, WC,
input logic [`DIVLEN+3:0] C,
input logic Sqrt,
output logic [`QLEN-1:0] QNext, QMNext, output logic [`QLEN-1:0] QNext, QMNext,
output logic [`DIVLEN+3:0] SNext, SMNext,
output logic [`DIVLEN+3:0] WSA, WCA output logic [`DIVLEN+3:0] WSA, WCA
); );
/* verilator lint_on UNOPTFLAT */ /* verilator lint_on UNOPTFLAT */
@ -154,6 +178,8 @@ module divinteration (
logic [`DIVLEN+3:0] Dsel; logic [`DIVLEN+3:0] Dsel;
logic [3:0] q; logic [3:0] q;
logic qp, qz;//, qn; logic qp, qz;//, qn;
logic [`DIVLEN+3:0] F;
logic [`DIVLEN+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)
@ -166,7 +192,8 @@ module divinteration (
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[`DIVLEN+3:`DIVLEN], WC[`DIVLEN+3:`DIVLEN], qp, qz);//, qn);
end else begin end else begin
qsel4 qsel4(.D, .WS, .WC, .q); qsel4 qsel4(.D, .WS, .WC, .Sqrt, .q);
fgen4 fgen4(.s(q), .C, .S, .SM, .F);
end end
if(`RADIX == 2) begin : dsel if(`RADIX == 2) begin : dsel
@ -184,16 +211,18 @@ module divinteration (
end end
// Partial Product Generation // Partial Product Generation
// WSA, WCA = WS + WC - qD // WSA, WCA = WS + WC - qD
assign AddIn = Sqrt ? F : Dsel;
if (`RADIX == 2) begin : csa if (`RADIX == 2) begin : csa
csa #(`DIVLEN+4) csa(WS, WC, Dsel, qp, WSA, WCA); csa #(`DIVLEN+4) csa(WS, WC, AddIn, qp, WSA, WCA);
end else begin end else begin
csa #(`DIVLEN+4) csa(WS, WC, Dsel, |q[3:2], WSA, WCA); csa #(`DIVLEN+4) csa(WS, WC, AddIn, |q[3:2], 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);
end end
endmodule endmodule
@ -220,40 +249,3 @@ module csa #(parameter N=69) (
assign out2 = {in1[N-2:0] & (in2[N-2:0] | in3[N-2:0]) | assign out2 = {in1[N-2:0] & (in2[N-2:0] | in3[N-2:0]) |
(in2[N-2:0] & in3[N-2:0]), cin}; (in2[N-2:0] & in3[N-2:0]), cin};
endmodule endmodule
module expcalc(
input logic [`FMTBITS-1:0] FmtE,
input logic [`NE-1:0] Xe, Ye,
input logic XZeroE,
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
output logic [`NE+1:0] Qe
);
logic [`NE-2:0] Bias;
if (`FPSIZES == 1) begin
assign Bias = (`NE-1)'(`BIAS);
end else if (`FPSIZES == 2) begin
assign Bias = FmtE ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1);
end else if (`FPSIZES == 3) begin
always_comb
case (FmtE)
`FMT: Bias = (`NE-1)'(`BIAS);
`FMT1: Bias = (`NE-1)'(`BIAS1);
`FMT2: Bias = (`NE-1)'(`BIAS2);
default: Bias = 'x;
endcase
end else if (`FPSIZES == 4) begin
always_comb
case (FmtE)
2'h3: Bias = (`NE-1)'(`Q_BIAS);
2'h1: Bias = (`NE-1)'(`D_BIAS);
2'h0: Bias = (`NE-1)'(`S_BIAS);
2'h2: Bias = (`NE-1)'(`H_BIAS);
endcase
end
// correct exponent for denormalized input's normalization shifts
assign Qe = ({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{~XZeroE}};
endmodule

View File

@ -31,16 +31,25 @@
`include "wally-config.vh" `include "wally-config.vh"
module srtpreproc ( module srtpreproc (
input logic clk,
input logic DivStart,
input logic [`NF:0] Xm, Ym, input logic [`NF:0] Xm, Ym,
output logic [`DIVLEN-1:0] X, input logic [`NE-1:0] Xe, Ye,
output logic [`DIVLEN-1:0] Dpreproc, input logic [`FMTBITS-1:0] Fmt,
input logic Sqrt,
input logic XZero,
output logic [`NE+1:0] QeM,
output logic [`DIVLEN+3:0] X,
output logic [`DIVLEN+3:0] Dpreproc,
output logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt, 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 [`DIVLEN-1:0] PreprocA, PreprocX; logic [`NF-1:0] PreprocA, PreprocX;
logic [`DIVLEN-1:0] PreprocB, PreprocY; logic [`NF-1:0] PreprocB, PreprocY;
logic [`NF+3:0] SqrtX;
logic [`NE+1:0] Qe;
// assign PosA = (Signed & SrcA[`XLEN - 1]) ? -SrcA : SrcA; // assign PosA = (Signed & SrcA[`XLEN - 1]) ? -SrcA : SrcA;
// assign PosB = (Signed & SrcB[`XLEN - 1]) ? -SrcB : SrcB; // assign PosB = (Signed & SrcB[`XLEN - 1]) ? -SrcB : SrcB;
@ -49,23 +58,22 @@ module srtpreproc (
// ***can probably merge X LZC with conversion // ***can probably merge X LZC with conversion
// cout the number of leading zeros // cout the number of leading zeros
lzc #(`NF+1) lzcA (Xm, XZeroCnt); lzc #(`NF+1) lzcX (Xm, XZeroCnt);
lzc #(`NF+1) lzcB (Ym, YZeroCnt); lzc #(`NF+1) lzcY (Ym, YZeroCnt);
// assign ExtraA = {PosA, {`DIVLEN-`XLEN{1'b0}}}; // assign ExtraA = {PosA, {`DIVLEN-`XLEN{1'b0}}};
// assign ExtraB = {PosB, {`DIVLEN-`XLEN{1'b0}}}; // assign ExtraB = {PosB, {`DIVLEN-`XLEN{1'b0}}};
// assign PreprocA = ExtraA << zeroCntA; // assign PreprocA = ExtraA << zeroCntA;
// assign PreprocB = ExtraB << (zeroCntB + 1); // assign PreprocB = ExtraB << (zeroCntB + 1);
assign PreprocX = {Xm[`NF-1:0]<<XZeroCnt, {`DIVLEN-`NF{1'b0}}}; assign PreprocX = Xm[`NF-1:0]<<XZeroCnt;
assign PreprocY = {Ym[`NF-1:0]<<YZeroCnt, {`DIVLEN-`NF{1'b0}}}; assign PreprocY = Ym[`NF-1:0]<<YZeroCnt;
assign X = PreprocX; assign SqrtX = Xe[0] ? {3'b110, ~XZero, PreprocX} : {2'b11, ~XZero, PreprocX, 1'b0};
assign Dpreproc = PreprocY; assign X = Sqrt ? {SqrtX, {`DIVLEN-`NF{1'b0}}} : {3'b000, ~XZero, PreprocX, {`DIVLEN-`NF{1'b0}}};
assign Dpreproc = {4'b0001, /*Int ? PreprocB : */PreprocY, {`DIVLEN-`NF{1'b0}}};
assign Dur = (`DURLEN)'(`FPDUR); assign Dur = (`DURLEN)'(`FPDUR);
// assign intExp = zeroCntB - zeroCntA + 1;
// assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
// radix 2 radix 4 // radix 2 radix 4
// 1 copies DIVLEN+2 DIVLEN+2/2 // 1 copies DIVLEN+2 DIVLEN+2/2
@ -76,6 +84,52 @@ module srtpreproc (
// DIVRESLEN = DIVLEN or DIVLEN+2 // DIVRESLEN = DIVLEN or DIVLEN+2
// r = 1 or 2 // r = 1 or 2
// DIVRESLEN/(r*`DIVCOPIES) // DIVRESLEN/(r*`DIVCOPIES)
flopen #(`NE+2) expflop(clk, DivStart, Qe, QeM);
expcalc expcalc(.Fmt, .Xe, .Ye, .Sqrt, .XZero, .XZeroCnt, .YZeroCnt, .Qe);
endmodule endmodule
module expcalc(
input logic [`FMTBITS-1:0] Fmt,
input logic [`NE-1:0] Xe, Ye,
input logic Sqrt,
input logic XZero,
input logic [$clog2(`NF+2)-1:0] XZeroCnt, YZeroCnt,
output logic [`NE+1:0] Qe
);
logic [`NE-2:0] Bias;
logic [`NE-1:0] SExp, SXExp;
logic [`NE+1:0] DExp;
if (`FPSIZES == 1) begin
assign Bias = (`NE-1)'(`BIAS);
end else if (`FPSIZES == 2) begin
assign Bias = Fmt ? (`NE-1)'(`BIAS) : (`NE-1)'(`BIAS1);
end else if (`FPSIZES == 3) begin
always_comb
case (Fmt)
`FMT: Bias = (`NE-1)'(`BIAS);
`FMT1: Bias = (`NE-1)'(`BIAS1);
`FMT2: Bias = (`NE-1)'(`BIAS2);
default: Bias = 'x;
endcase
end else if (`FPSIZES == 4) begin
always_comb
case (Fmt)
2'h3: Bias = (`NE-1)'(`Q_BIAS);
2'h1: Bias = (`NE-1)'(`D_BIAS);
2'h0: Bias = (`NE-1)'(`S_BIAS);
2'h2: Bias = (`NE-1)'(`H_BIAS);
endcase
end
assign SXExp = Xe - (`NE)'(`BIAS);
assign SExp = {1'b0, SXExp[`NE-1:1]} + Bias;
// 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 Qe = Sqrt ? {2'b0, SExp} : DExp;
endmodule

View File

@ -2,7 +2,7 @@
// srt.sv // srt.sv
// //
// Written: David_Harris@hmc.edu 13 January 2022 // Written: David_Harris@hmc.edu 13 January 2022
// Modified: cturek@hmc.edu June 2022 // Modified: cturek@hmc.edu July 2022
// //
// Purpose: Combined Divide and Square Root Floating Point and Integer Unit // Purpose: Combined Divide and Square Root Floating Point and Integer Unit
// //

View File

@ -72,7 +72,7 @@ module testbench;
// Equip Int test or Sqrt test // Equip Int test or Sqrt test
assign Int = 1'b0; assign Int = 1'b0;
assign Sqrt = 1'b1; assign Sqrt = 1'b0;
// Divider // Divider
srt srt(.clk, .Start(req), srt srt(.clk, .Start(req),
@ -101,7 +101,7 @@ module testbench;
begin begin
testnum = 0; testnum = 0;
errors = 0; errors = 0;
$readmemh ("sqrttestvectors", Tests); $readmemh ("testvectors", Tests);
Vec = Tests[testnum]; Vec = Tests[testnum];
a = Vec[`mema]; a = Vec[`mema];
{asign, aExp, afrac} = a; {asign, aExp, afrac} = a;

View File

@ -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), divsqrt divsqrt(.clk, .reset, .FmtE(ModFmt), .XmE(Xm), .YmE(Ym), .XeE(Xe), .YeE(Ye), .SqrtE(1'b0), .SqrtM(1'b0),
.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);