Divider FSM simplification

This commit is contained in:
David Harris 2021-10-10 22:24:14 -07:00
parent 75c17dc372
commit 4139f27d10
3 changed files with 16 additions and 20 deletions

View File

@ -1 +0,0 @@
vsim -do wally-buildroot.do

View File

@ -1,3 +0,0 @@
vsim -c <<!
do wally-buildroot-batch.do
!

View File

@ -38,15 +38,16 @@ module intdivrestoring (
output logic [`XLEN-1:0] QuotM, RemM output logic [`XLEN-1:0] QuotM, RemM
); );
typedef enum logic [1:0] {IDLE, BUSY, DONE} statetype;
statetype state;
logic [`XLEN-1:0] WM[`DIV_BITSPERCYCLE:0]; logic [`XLEN-1:0] WM[`DIV_BITSPERCYCLE:0];
logic [`XLEN-1:0] XQM[`DIV_BITSPERCYCLE:0]; logic [`XLEN-1:0] XQM[`DIV_BITSPERCYCLE:0];
logic [`XLEN-1:0] DinE, XinE, DnE, DAbsBE, DAbsBM, XnE, XInitE, WnM, XQnM; logic [`XLEN-1:0] DinE, XinE, DnE, DAbsBE, DAbsBM, XnE, XInitE, WnM, XQnM;
localparam STEPBITS = $clog2(`XLEN/`DIV_BITSPERCYCLE); localparam STEPBITS = $clog2(`XLEN/`DIV_BITSPERCYCLE);
logic [STEPBITS:0] step; logic [STEPBITS:0] step;
logic Div0E, Div0M; logic Div0E, Div0M;
logic DivStartE, SignXE, SignXM, SignDE, SignDM, NegWM, NegQM; logic DivStartE, SignXE, SignXM, SignDE, NegQE, NegWM, NegQM;
logic BusyE, DivDoneM;
logic [`XLEN-1:0] WNextE, XQNextE; logic [`XLEN-1:0] WNextE, XQNextE;
////////////////////////////// //////////////////////////////
@ -54,8 +55,8 @@ module intdivrestoring (
////////////////////////////// //////////////////////////////
// Divider control signals // Divider control signals
assign DivStartE = DivE & ~BusyE & ~DivDoneM & ~StallM; assign DivStartE = DivE & (state == IDLE); // & ~StallM;
assign DivBusyE = BusyE | DivStartE; assign DivBusyE = (state == BUSY) | DivStartE;
// Handle sign extension for W-type instructions // Handle sign extension for W-type instructions
generate generate
@ -71,6 +72,7 @@ module intdivrestoring (
// Extract sign bits and check fo division by zero // Extract sign bits and check fo division by zero
assign SignDE = DivSignedE & DinE[`XLEN-1]; assign SignDE = DivSignedE & DinE[`XLEN-1];
assign SignXE = DivSignedE & XinE[`XLEN-1]; assign SignXE = DivSignedE & XinE[`XLEN-1];
assign NegQE = SignDE ^ SignXE;
assign Div0E = (DinE == 0); assign Div0E = (DinE == 0);
// Take absolute value for signed operations, and negate D to handle subtraction in divider stages // Take absolute value for signed operations, and negate D to handle subtraction in divider stages
@ -91,7 +93,7 @@ module intdivrestoring (
flopen #(`XLEN) wreg(clk, DivBusyE, WNextE, WM[0]); flopen #(`XLEN) wreg(clk, DivBusyE, WNextE, WM[0]);
flopen #(`XLEN) xreg(clk, DivBusyE, XQNextE, XQM[0]); flopen #(`XLEN) xreg(clk, DivBusyE, XQNextE, XQM[0]);
flopen #(`XLEN) dabsreg(clk, DivStartE, DAbsBE, DAbsBM); flopen #(`XLEN) dabsreg(clk, DivStartE, DAbsBE, DAbsBM);
flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, SignDE, SignXE}, {Div0M, SignDM, SignXM}); flopen #(3) Div0eMReg(clk, DivStartE, {Div0E, NegQE, SignXE}, {Div0M, NegQM, NegWM});
// one copy of divstep for each bit produced per cycle // one copy of divstep for each bit produced per cycle
generate generate
@ -101,8 +103,6 @@ module intdivrestoring (
endgenerate endgenerate
// On final setp of signed operations, negate outputs as needed to get correct sign // On final setp of signed operations, negate outputs as needed to get correct sign
assign NegWM = SignXM; // Remainder should have same sign as X
assign NegQM = SignXM ^ SignDM; // Quotient should be negative if one operand is positive and the other is negative
neg #(`XLEN) qneg(XQM[0], XQnM); neg #(`XLEN) qneg(XQM[0], XQnM);
neg #(`XLEN) wneg(WM[0], WnM); neg #(`XLEN) wneg(WM[0], WnM);
// Select appropriate output: normal, negated, or for divide by zero // Select appropriate output: normal, negated, or for divide by zero
@ -115,19 +115,19 @@ module intdivrestoring (
always_ff @(posedge clk) always_ff @(posedge clk)
if (reset) begin if (reset) begin
BusyE = 0; DivDoneM = 0; step = 0; state = IDLE;
end else if (DivStartE) begin end else if (DivStartE) begin
step = 0; step = 0;
if (Div0E) DivDoneM = 1; if (Div0E) state = DONE;
else BusyE = 1; else state = BUSY;
end else if (BusyE) begin // pause one cycle at beginning of signed operations for absolute value end else if (state == BUSY) begin // pause one cycle at beginning of signed operations for absolute value
step = step + 1; step = step + 1;
if (step[STEPBITS] | (`XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions if (step[STEPBITS] | (`XLEN==64) & W64E & step[STEPBITS-1]) begin // complete in half the time for W-type instructions
BusyE = 0; state = DONE;
DivDoneM = 1;
end end
end else if (DivDoneM) begin end else if (state == DONE) begin
DivDoneM = StallM; if (StallM) state = DONE;
else state = IDLE;
end end
endmodule endmodule