1
0
mirror of https://github.com/openhwgroup/cvw synced 2025-02-11 06:05:49 +00:00

Moved negating divider otuput to M stage

This commit is contained in:
David Harris 2021-10-02 10:03:02 -04:00
parent 735132191c
commit 0e0e204d3d
3 changed files with 65 additions and 41 deletions

View File

@ -35,6 +35,23 @@ add wave -hex /testbench/dut/hart/ieu/dp/SrcAE
add wave -hex /testbench/dut/hart/ieu/dp/SrcBE add wave -hex /testbench/dut/hart/ieu/dp/SrcBE
add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE add wave -hex /testbench/dut/hart/ieu/dp/ALUResultE
#add wave /testbench/dut/hart/ieu/dp/PCSrcE #add wave /testbench/dut/hart/ieu/dp/PCSrcE
add wave /testbench/dut/hart/mdu/genblk1/div/start
add wave /testbench/dut/hart/mdu/DivBusyE
add wave /testbench/dut/hart/mdu/DivDoneE
add wave -hex /testbench/dut/hart/mdu/genblk1/div/D
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Din
add wave -hex /testbench/dut/hart/mdu/genblk1/div/X
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Win
add wave -hex /testbench/dut/hart/mdu/genblk1/div/XQin
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Wshift
add wave -hex /testbench/dut/hart/mdu/genblk1/div/XQshift
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Wnext
add wave -hex /testbench/dut/hart/mdu/genblk1/div/qi
add wave -hex /testbench/dut/hart/mdu/genblk1/div/Wprime
add wave -hex /testbench/dut/hart/mdu/genblk1/div/W
add wave -hex /testbench/dut/hart/mdu/genblk1/div/XQ
add wave -hex /testbench/dut/hart/mdu/genblk1/div/REM
add wave -divider add wave -divider
add wave -hex /testbench/dut/hart/ifu/PCM add wave -hex /testbench/dut/hart/ifu/PCM
add wave -hex /testbench/dut/hart/ifu/InstrM add wave -hex /testbench/dut/hart/ifu/InstrM
@ -48,9 +65,9 @@ add wave -hex /testbench/dut/hart/lsu/dcache/ReadDataM
add wave -hex /testbench/dut/hart/ebu/ReadDataM add wave -hex /testbench/dut/hart/ebu/ReadDataM
add wave -divider add wave -divider
add wave -hex /testbench/PCW add wave -hex /testbench/PCW
add wave -hex /testbench/InstrW #add wave -hex /testbench/InstrW
add wave -hex /testbench/dut/hart/ieu/c/InstrValidW add wave -hex /testbench/dut/hart/ieu/c/InstrValidW
add wave /testbench/InstrWName #add wave /testbench/InstrWName
add wave -hex /testbench/dut/hart/ReadDataW add wave -hex /testbench/dut/hart/ReadDataW
add wave -hex /testbench/dut/hart/ieu/dp/ResultW add wave -hex /testbench/dut/hart/ieu/dp/ResultW
add wave -hex /testbench/dut/hart/ieu/dp/RegWriteW add wave -hex /testbench/dut/hart/ieu/dp/RegWriteW

View File

@ -28,9 +28,9 @@
module intdivrestoring ( module intdivrestoring (
input logic clk, input logic clk,
input logic reset, input logic reset,
input logic StallM, input logic StallM, FlushM,
input logic signedDivide, input logic SignedDivideE,
input logic start, input logic StartDivideE,
input logic [`XLEN-1:0] X, D, input logic [`XLEN-1:0] X, D,
output logic busy, done, output logic busy, done,
output logic [`XLEN-1:0] Q, REM output logic [`XLEN-1:0] Q, REM
@ -41,78 +41,84 @@ module intdivrestoring (
localparam STEPBITS = $clog2(`XLEN)-1; localparam STEPBITS = $clog2(`XLEN)-1;
logic [STEPBITS:0] step; logic [STEPBITS:0] step;
logic div0; logic div0;
logic negate, init, startd, SignX, SignD, NegW, NegQ; logic init, startd, SignX, SignD, NegW, NegQ;
logic SignedDivideM;
// *** add pipe stages to everything
// Setup for signed division // Setup for signed division
abs #(`XLEN) absd(D, Dabs); abs #(`XLEN) absd(D, Dabs);
mux2 #(`XLEN) dabsmux(D, Dabs, signedDivide, D2); mux2 #(`XLEN) dabsmux(D, Dabs, SignedDivideE, D2);
flopen #(`XLEN) dsavereg(clk, start, D2, Dsaved); flopen #(`XLEN) dsavereg(clk, StartDivideE, D2, Dsaved);
mux2 #(`XLEN) dfirstmux(Dsaved, D, start, Din); mux2 #(`XLEN) dfirstmux(Dsaved, D, StartDivideE, Din);
abs #(`XLEN) absx(X, Xabs); abs #(`XLEN) absx(X, Xabs);
mux2 #(`XLEN) xabsmux(X, Xabs, signedDivide & ~div0, X2); // need original X as remainder if doing divide by 0 mux2 #(`XLEN) xabsmux(X, Xabs, SignedDivideE & ~div0, X2); // need original X as remainder if doing divide by 0
flopen #(`XLEN) xsavereg(clk, start, X2, Xsaved); flopen #(`XLEN) xsavereg(clk, StartDivideE, X2, Xsaved);
mux2 #(`XLEN) xfirstmux(Xsaved, X, start, Xinit); mux2 #(`XLEN) xfirstmux(Xsaved, X, StartDivideE, Xinit);
mux2 #(`XLEN) wmux(W, {`XLEN{1'b0}}, init, Win); mux2 #(`XLEN) wmux(W, {`XLEN{1'b0}}, init, Win);
mux2 #(`XLEN) xmux(XQ, Xinit, init, XQin); mux2 #(`XLEN) xmux(XQ, Xinit, init, XQin);
assign DAbsB = ~Din; assign DAbsB = ~Din;
assign div0 = (Din == 0); // *** eventually replace with just the negedge saved D
// *** parameterize steps per cycle // *** parameterize steps per cycle
intdivrestoringstep step1(Win, XQin, DAbsB, W1, XQ1); intdivrestoringstep step1(Win, XQin, DAbsB, W1, XQ1);
intdivrestoringstep step2(W1, XQ1, DAbsB, W2, XQshift); // intdivrestoringstep step2(W1, XQ1, DAbsB, W2, XQshift);
intdivrestoringstep step2(W1, XQ1, DAbsB, Wnext, XQnext);
// conditionally negate outputs at end of signed operation // conditionally negate outputs at end of signed operation
// *** move into M stage
neg #(`XLEN) wneg(W, Wn); // flopen #(`XLEN) wreg(clk, StartDivideE | (busy & (~negate | NegW)), Wnext, W);
mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext); //*** // flopen #(`XLEN) xreg(clk, StartDivideE | (busy & (~negate | NegQ)), XQnext, XQ);
neg #(`XLEN) qneg(XQ, XQn); flopen #(`XLEN) wreg(clk, StartDivideE | busy, Wnext, W); // *** could become just busy once start moves to its own cycle
mux2 #(`XLEN) qnextmux(XQshift, XQn, NegQ, XQnext); flopen #(`XLEN) xreg(clk, StartDivideE | busy, XQnext, XQ);
flopen #(`XLEN) wreg(clk, start | (busy & (~negate | NegW)), Wnext, W);
flopen #(`XLEN) xreg(clk, start | (busy & (~negate | NegQ)), XQnext, XQ);
// outputs // outputs
assign div0 = (Din == 0); neg #(`XLEN) wneg(W, Wn);
mux2 #(`XLEN) qmux(XQ, {`XLEN{1'b1}}, div0, Q); // Q taken from XQ register, or all 1s when dividing by zero // mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext); //***
mux2 #(`XLEN) remmux(W, Xsaved, div0, REM); // REM taken from W register, or from X when dividing by zero neg #(`XLEN) qneg(XQ, XQn);
// mux2 #(`XLEN) qnextmux(XQshift, XQn, NegQ, XQnext);
mux3 #(`XLEN) qmux(XQ, XQn, {`XLEN{1'b1}}, {div0, NegQ}, Q); // Q taken from XQ register, or all 1s when dividing by zero ***
mux3 #(`XLEN) remmux(W, Wn, Xsaved, {div0, NegW}, REM); // REM taken from W register, or from X when dividing by zero
// busy logic // busy logic
always_ff @(posedge clk) always_ff @(posedge clk)
if (reset) begin if (reset) begin
busy = 0; done = 0; step = 0; negate = 0; busy = 0; done = 0; step = 0; //negate = 0;
end else if (start & ~StallM) begin end else if (StartDivideE & ~StallM) begin
if (div0) done = 1; if (div0) done = 1;
else begin else begin
busy = 1; step = 1; busy = 1; step = 1;
end end
end else if (busy & ~done & ~(startd & signedDivide)) begin // pause one cycle at beginning of signed operations for absolute value end else if (busy & ~done & ~(startd & SignedDivideE)) begin // pause one cycle at beginning of signed operations for absolute value
step = step + 1; step = step + 1;
if (step[STEPBITS]) begin // *** early terminate on division by 0 if (step[STEPBITS]) begin // *** early terminate on division by 0
if (signedDivide & ~negate) begin /* if (SignedDivideE & ~negate) begin
negate = 1; negate = 1;
end else begin end else begin*/
step = 0; step = 0;
busy = 0; busy = 0;
negate = 0; //negate = 0;
done = 1; done = 1;
end //end
end end
end else if (done) begin end else if (done) begin
done = 0; done = 0;
busy = 0; busy = 0;
negate = 0; //negate = 0;
end end
// initialize on the start cycle for unsigned operations, or one cycle later for signed operations (giving time for abs) // initialize on the start cycle for unsigned operations, or one cycle later for signed operations (giving time for abs)
flop #(1) initflop(clk, start, startd); flop #(1) initflop(clk, StartDivideE, startd);
mux2 #(1) initmux(start, startd, signedDivide, init); mux2 #(1) initmux(StartDivideE, startd, SignedDivideE, init);
// save signs of original inputs // save signs of original inputs
flopen #(2) signflops(clk, start, {D[`XLEN-1], X[`XLEN-1]}, {SignD, SignX}); flopenrc #(1) SignedDivideMReg(clk, reset, FlushM, ~StallM, SignedDivideE, SignedDivideM);
flopen #(2) signflops(clk, StartDivideE, {D[`XLEN-1], X[`XLEN-1]}, {SignD, SignX});
// On final setp of signed operations, negate outputs as needed // On final setp of signed operations, negate outputs as needed
assign NegW = SignX & negate; assign NegW = SignedDivideM & SignX; // & negate;
assign NegQ = (SignX ^ SignD) & negate; assign NegQ = SignedDivideM & (SignX ^ SignD); // & negate;
endmodule // muldiv endmodule // muldiv

View File

@ -56,7 +56,7 @@ module muldiv (
//logic [`XLEN-1:0] Num0, Den0; //logic [`XLEN-1:0] Num0, Den0;
// logic gclk; // logic gclk;
logic startDivideE, busy; logic StartDivideE, busy;
logic SignedDivideE; logic SignedDivideE;
logic W64M; logic W64M;
@ -77,12 +77,13 @@ module muldiv (
end end
assign SignedDivideE = ~Funct3E[0]; // simplified from (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]); assign SignedDivideE = ~Funct3E[0]; // simplified from (Funct3E[2]&~Funct3E[1]&~Funct3E[0]) | (Funct3E[2]&Funct3E[1]&~Funct3E[0]);
//intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, startDivideE, SignedDivideE); //intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, StartDivideE, SignedDivideE);
intdivrestoring div(.clk, .reset, .StallM, .signedDivide(SignedDivideE), .start(startDivideE), .X(X), .D(D), .busy(busy), .done(DivDoneE), .Q(QuotM), .REM(RemM)); intdivrestoring div(.clk, .reset, .StallM, .FlushM,
.SignedDivideE, .StartDivideE, .X(X), .D(D), .busy(busy), .done(DivDoneE), .Q(QuotM), .REM(RemM));
// Start a divide when a new division instruction is received and the divider isn't already busy or finishing // Start a divide when a new division instruction is received and the divider isn't already busy or finishing
assign startDivideE = MulDivE & Funct3E[2] & ~busy & ~DivDoneE; // *** mabye DivDone should be M stage assign StartDivideE = MulDivE & Funct3E[2] & ~busy & ~DivDoneE; // *** mabye DivDone should be M stage
assign DivBusyE = startDivideE | busy; assign DivBusyE = StartDivideE | busy;
// Select result // Select result
always_comb always_comb