From fbe6e41169e2d86bc1d07f6d4f59394455a4a011 Mon Sep 17 00:00:00 2001 From: David Harris Date: Sat, 2 Oct 2021 09:19:25 -0400 Subject: [PATCH] Divide performs 2 steps per cycle --- ...intdiv_restoring.sv => intdivrestoring.sv} | 48 +++++++++++-------- wally-pipelined/src/muldiv/muldiv.sv | 13 +++-- wally-pipelined/testbench/testbench-arch.sv | 4 +- 3 files changed, 37 insertions(+), 28 deletions(-) rename wally-pipelined/src/muldiv/{intdiv_restoring.sv => intdivrestoring.sv} (82%) diff --git a/wally-pipelined/src/muldiv/intdiv_restoring.sv b/wally-pipelined/src/muldiv/intdivrestoring.sv similarity index 82% rename from wally-pipelined/src/muldiv/intdiv_restoring.sv rename to wally-pipelined/src/muldiv/intdivrestoring.sv index ea337c18..21e96c6e 100644 --- a/wally-pipelined/src/muldiv/intdiv_restoring.sv +++ b/wally-pipelined/src/muldiv/intdivrestoring.sv @@ -1,10 +1,10 @@ /////////////////////////////////////////// -// intdiv_restoring.sv +// intdivrestoring.sv // // Written: David_Harris@hmc.edu 12 September 2021 // Modified: // -// Purpose: Restoring integer division using a shift register a subtractor +// Purpose: Restoring integer division using a shift register and subtractor // // A component of the Wally configurable RISC-V project. // @@ -25,7 +25,7 @@ `include "wally-config.vh" -module intdiv_restoring ( +module intdivrestoring ( input logic clk, input logic reset, input logic StallM, @@ -36,9 +36,9 @@ module intdiv_restoring ( output logic [`XLEN-1:0] Q, REM ); - logic [`XLEN-1:0] W, W2, Win, Wshift, Wprime, Wn, Wnn, Wnext, XQ, XQin, XQshift, XQn, XQnn, XQnext, Dsaved, Din, Dabs, D2, Xabs, X2, Xsaved, Xinit; + logic [`XLEN-1:0] W, W2, Win, Wshift, Wprime, Wn, Wnn, Wnext, XQ, XQin, XQshift, XQn, XQnn, XQnext, Dsaved, Din, Dabs, D2, Xabs, X2, Xsaved, Xinit, DAbsB, W1, XQ1; logic qi, qib; // curent quotient bit - localparam STEPBITS = $clog2(`XLEN); + localparam STEPBITS = $clog2(`XLEN)-1; logic [STEPBITS:0] step; logic div0; logic negate, init, startd, SignX, SignD, NegW, NegQ; @@ -53,33 +53,25 @@ module intdiv_restoring ( mux2 #(`XLEN) xabsmux(X, Xabs, signedDivide & ~div0, X2); // need original X as remainder if doing divide by 0 flopen #(`XLEN) xsavereg(clk, start, X2, Xsaved); mux2 #(`XLEN) xfirstmux(Xsaved, X, start, Xinit); - - // restoring division + mux2 #(`XLEN) wmux(W, {`XLEN{1'b0}}, init, Win); mux2 #(`XLEN) xmux(XQ, Xinit, init, XQin); - assign {Wshift, XQshift} = {Win[`XLEN-2:0], XQin, qi}; - assign {qib, Wprime} = {1'b0, Wshift} + ~{1'b0, Din} + 1; // subtractor, carry out determines quotient bit - assign qi = ~qib; - mux2 #(`XLEN) wrestoremux(Wshift, Wprime, qi, W2); + + assign DAbsB = ~Din; + + intdivrestoringstep step1(Win, XQin, DAbsB, W1, XQ1); + intdivrestoringstep step2(W1, XQ1, DAbsB, W2, XQshift); // conditionally negate outputs at end of signed operation + // *** move into M stage neg #(`XLEN) wneg(W, Wn); -// mux2 #(`XLEN) wnegmux(W, Wn, NegW, Wnn); -// mux2 #(`XLEN) wnextmux(W2, Wnn, negate, Wnext); - mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext); + mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext); //*** neg #(`XLEN) qneg(XQ, XQn); -// mux2 #(`XLEN) qnegmux(XQ, XQn, NegQ, XQnn); -// mux2 #(`XLEN) qnextmux(XQshift, XQnn, negate, XQnext); mux2 #(`XLEN) qnextmux(XQshift, XQn, NegQ, XQnext); flopen #(`XLEN) wreg(clk, start | (busy & (~negate | NegW)), Wnext, W); flopen #(`XLEN) xreg(clk, start | (busy & (~negate | NegQ)), XQnext, XQ); - // save D, which comes from SrcAE forwarding mux and could change because register file read is stalled during divide - // flopen #(`XLEN) dreg(clk, start, D, Dsaved); - //mux2 #(`XLEN) dmux(Dsaved, D, start, Din); - // outputs - // *** sign extension, handling W instructions assign div0 = (Din == 0); mux2 #(`XLEN) qmux(XQ, {`XLEN{1'b1}}, div0, Q); // Q taken from XQ register, or all 1s when dividing by zero mux2 #(`XLEN) remmux(W, Xsaved, div0, REM); // REM taken from W register, or from X when dividing by zero @@ -124,3 +116,17 @@ module intdiv_restoring ( endmodule // muldiv +module intdivrestoringstep( + input logic [`XLEN-1:0] W, XQ, DAbsB, + output logic [`XLEN-1:0] WOut, XQOut); + + logic [`XLEN-1:0] WShift, WPrime; + logic qi, qib; + + assign {WShift, XQOut} = {W[`XLEN-2:0], XQ, qi}; + assign {qib, WPrime} = {1'b0, WShift} + {1'b1, DAbsB} + 1; // subtractor, carry out determines quotient bit ***replace with add + assign qi = ~qib; + mux2 #(`XLEN) wrestoremux(WShift, WPrime, qi, WOut); +endmodule + +// *** clean up internal signals \ No newline at end of file diff --git a/wally-pipelined/src/muldiv/muldiv.sv b/wally-pipelined/src/muldiv/muldiv.sv index ca9b47b4..43cfba80 100644 --- a/wally-pipelined/src/muldiv/muldiv.sv +++ b/wally-pipelined/src/muldiv/muldiv.sv @@ -47,7 +47,7 @@ module muldiv ( logic [`XLEN-1:0] MulDivResultE, MulDivResultM; logic [`XLEN-1:0] PrelimResultE; logic [`XLEN-1:0] QuotE, RemE; - logic [`XLEN*2-1:0] ProdE; + logic [`XLEN*2-1:0] ProdE, ProdM; logic enable_q; //logic [2:0] Funct3E_Q; @@ -55,19 +55,21 @@ module muldiv ( logic [`XLEN-1:0] X, D; //logic [`XLEN-1:0] Num0, Den0; - logic gclk; + // logic gclk; logic startDivideE, busy; logic signedDivide; // Multiplier mul mul(.*); + flopenrc #(`XLEN*2) ProdMReg(clk, reset, FlushM, ~StallM, ProdE, ProdM); + // Divide - // *** replace this clock gater + /*// *** replace this clock gater always @(negedge clk) begin enable_q <= ~StallM; end - assign gclk = enable_q & clk; + assign gclk = enable_q & clk; */ // Handle sign extension for W-type instructions if (`XLEN == 64) begin // RV64 has W-type instructions @@ -80,7 +82,8 @@ module muldiv ( assign signedDivide = ~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, signedDivide); - intdiv_restoring div(.clk, .reset, .StallM, .signedDivide, .start(startDivideE), .X(X), .D(D), .busy(busy), .done(DivDoneE), .Q(QuotE), .REM(RemE)); +// intdivrestoring div(.clk, .reset, .StallM, .signedDivide, .start(startDivideE), .X(X), .D(D), .busy(busy), .done(DivDoneE), .Q(QuotE), .REM(RemE)); + intdivrestoring div(.clk, .reset, .StallM, .signedDivide, .start(startDivideE), .X(X), .D(D), .busy(busy), .done(DivDoneE), .Q(QuotE), .REM(RemE)); // 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; diff --git a/wally-pipelined/testbench/testbench-arch.sv b/wally-pipelined/testbench/testbench-arch.sv index 7f4233ff..c1ef5a23 100644 --- a/wally-pipelined/testbench/testbench-arch.sv +++ b/wally-pipelined/testbench/testbench-arch.sv @@ -430,7 +430,7 @@ string tests32f[] = '{ // tests = {tests64p,tests64i, tests64periph}; if (`C_SUPPORTED) tests = {tests, tests64ic}; // else tests = {tests, tests64iNOc}; - if (`M_SUPPORTED) tests = {tests, tests64m}; + if (`M_SUPPORTED) tests = {tests64m, tests}; /* if (`F_SUPPORTED) tests = {tests64f, tests}; if (`D_SUPPORTED) tests = {tests64d, tests}; if (`MEM_VIRTMEM) tests = {tests64mmu, tests}; @@ -449,7 +449,7 @@ string tests32f[] = '{ tests = {tests32priv, tests32i}; //tests = {tests32i, tests32priv}; if (`C_SUPPORTED) tests = {tests, tests32ic}; - if (`M_SUPPORTED) tests = {tests, tests32m}; + if (`M_SUPPORTED) tests = {tests32m, tests}; //if (`C_SUPPORTED) tests = {tests32ic, tests}; //if (`M_SUPPORTED) tests = {tests32m, tests}; /* tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment