mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Divide performs 2 steps per cycle
This commit is contained in:
parent
e11c565a6f
commit
fbe6e41169
@ -1,10 +1,10 @@
|
|||||||
///////////////////////////////////////////
|
///////////////////////////////////////////
|
||||||
// intdiv_restoring.sv
|
// intdivrestoring.sv
|
||||||
//
|
//
|
||||||
// Written: David_Harris@hmc.edu 12 September 2021
|
// Written: David_Harris@hmc.edu 12 September 2021
|
||||||
// Modified:
|
// 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.
|
// A component of the Wally configurable RISC-V project.
|
||||||
//
|
//
|
||||||
@ -25,7 +25,7 @@
|
|||||||
|
|
||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
|
|
||||||
module intdiv_restoring (
|
module intdivrestoring (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic reset,
|
input logic reset,
|
||||||
input logic StallM,
|
input logic StallM,
|
||||||
@ -36,9 +36,9 @@ module intdiv_restoring (
|
|||||||
output logic [`XLEN-1:0] Q, REM
|
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
|
logic qi, qib; // curent quotient bit
|
||||||
localparam STEPBITS = $clog2(`XLEN);
|
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 negate, init, startd, SignX, SignD, NegW, NegQ;
|
||||||
@ -54,32 +54,24 @@ module intdiv_restoring (
|
|||||||
flopen #(`XLEN) xsavereg(clk, start, X2, Xsaved);
|
flopen #(`XLEN) xsavereg(clk, start, X2, Xsaved);
|
||||||
mux2 #(`XLEN) xfirstmux(Xsaved, X, start, Xinit);
|
mux2 #(`XLEN) xfirstmux(Xsaved, X, start, Xinit);
|
||||||
|
|
||||||
// restoring division
|
|
||||||
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 {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 DAbsB = ~Din;
|
||||||
assign qi = ~qib;
|
|
||||||
mux2 #(`XLEN) wrestoremux(Wshift, Wprime, qi, W2);
|
intdivrestoringstep step1(Win, XQin, DAbsB, W1, XQ1);
|
||||||
|
intdivrestoringstep step2(W1, XQ1, DAbsB, W2, XQshift);
|
||||||
|
|
||||||
// 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);
|
neg #(`XLEN) wneg(W, Wn);
|
||||||
// mux2 #(`XLEN) wnegmux(W, Wn, NegW, Wnn);
|
mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext); //***
|
||||||
// mux2 #(`XLEN) wnextmux(W2, Wnn, negate, Wnext);
|
|
||||||
mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext);
|
|
||||||
neg #(`XLEN) qneg(XQ, XQn);
|
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);
|
mux2 #(`XLEN) qnextmux(XQshift, XQn, NegQ, XQnext);
|
||||||
flopen #(`XLEN) wreg(clk, start | (busy & (~negate | NegW)), Wnext, W);
|
flopen #(`XLEN) wreg(clk, start | (busy & (~negate | NegW)), Wnext, W);
|
||||||
flopen #(`XLEN) xreg(clk, start | (busy & (~negate | NegQ)), XQnext, XQ);
|
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
|
// outputs
|
||||||
// *** sign extension, handling W instructions
|
|
||||||
assign div0 = (Din == 0);
|
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) 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
|
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
|
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
|
@ -47,7 +47,7 @@ module muldiv (
|
|||||||
logic [`XLEN-1:0] MulDivResultE, MulDivResultM;
|
logic [`XLEN-1:0] MulDivResultE, MulDivResultM;
|
||||||
logic [`XLEN-1:0] PrelimResultE;
|
logic [`XLEN-1:0] PrelimResultE;
|
||||||
logic [`XLEN-1:0] QuotE, RemE;
|
logic [`XLEN-1:0] QuotE, RemE;
|
||||||
logic [`XLEN*2-1:0] ProdE;
|
logic [`XLEN*2-1:0] ProdE, ProdM;
|
||||||
|
|
||||||
logic enable_q;
|
logic enable_q;
|
||||||
//logic [2:0] Funct3E_Q;
|
//logic [2:0] Funct3E_Q;
|
||||||
@ -55,19 +55,21 @@ module muldiv (
|
|||||||
logic [`XLEN-1:0] X, D;
|
logic [`XLEN-1:0] X, D;
|
||||||
//logic [`XLEN-1:0] Num0, Den0;
|
//logic [`XLEN-1:0] Num0, Den0;
|
||||||
|
|
||||||
logic gclk;
|
// logic gclk;
|
||||||
logic startDivideE, busy;
|
logic startDivideE, busy;
|
||||||
logic signedDivide;
|
logic signedDivide;
|
||||||
|
|
||||||
// Multiplier
|
// Multiplier
|
||||||
mul mul(.*);
|
mul mul(.*);
|
||||||
|
flopenrc #(`XLEN*2) ProdMReg(clk, reset, FlushM, ~StallM, ProdE, ProdM);
|
||||||
|
|
||||||
// Divide
|
// Divide
|
||||||
|
|
||||||
// *** replace this clock gater
|
/*// *** replace this clock gater
|
||||||
always @(negedge clk) begin
|
always @(negedge clk) begin
|
||||||
enable_q <= ~StallM;
|
enable_q <= ~StallM;
|
||||||
end
|
end
|
||||||
assign gclk = enable_q & clk;
|
assign gclk = enable_q & clk; */
|
||||||
|
|
||||||
// Handle sign extension for W-type instructions
|
// Handle sign extension for W-type instructions
|
||||||
if (`XLEN == 64) begin // RV64 has 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]);
|
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 #(`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
|
// 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;
|
assign startDivideE = MulDivE & Funct3E[2] & ~busy & ~DivDoneE;
|
||||||
|
@ -430,7 +430,7 @@ string tests32f[] = '{
|
|||||||
// tests = {tests64p,tests64i, tests64periph};
|
// tests = {tests64p,tests64i, tests64periph};
|
||||||
if (`C_SUPPORTED) tests = {tests, tests64ic};
|
if (`C_SUPPORTED) tests = {tests, tests64ic};
|
||||||
// else tests = {tests, tests64iNOc};
|
// else tests = {tests, tests64iNOc};
|
||||||
if (`M_SUPPORTED) tests = {tests, tests64m};
|
if (`M_SUPPORTED) tests = {tests64m, tests};
|
||||||
/* if (`F_SUPPORTED) tests = {tests64f, tests};
|
/* if (`F_SUPPORTED) tests = {tests64f, tests};
|
||||||
if (`D_SUPPORTED) tests = {tests64d, tests};
|
if (`D_SUPPORTED) tests = {tests64d, tests};
|
||||||
if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
|
if (`MEM_VIRTMEM) tests = {tests64mmu, tests};
|
||||||
@ -449,7 +449,7 @@ string tests32f[] = '{
|
|||||||
tests = {tests32priv, tests32i};
|
tests = {tests32priv, tests32i};
|
||||||
//tests = {tests32i, tests32priv};
|
//tests = {tests32i, tests32priv};
|
||||||
if (`C_SUPPORTED) tests = {tests, tests32ic};
|
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 (`C_SUPPORTED) tests = {tests32ic, tests};
|
||||||
//if (`M_SUPPORTED) tests = {tests32m, tests};
|
//if (`M_SUPPORTED) tests = {tests32m, tests};
|
||||||
/* tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment
|
/* tests = {tests32i, tests32p};//,tests32periph}; *** broken at the moment
|
||||||
|
Loading…
Reference in New Issue
Block a user