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:
		
							parent
							
								
									735132191c
								
							
						
					
					
						commit
						0e0e204d3d
					
				@ -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/ALUResultE
 | 
			
		||||
#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 -hex /testbench/dut/hart/ifu/PCM
 | 
			
		||||
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 -divider
 | 
			
		||||
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 /testbench/InstrWName
 | 
			
		||||
#add wave /testbench/InstrWName
 | 
			
		||||
add wave -hex /testbench/dut/hart/ReadDataW
 | 
			
		||||
add wave -hex /testbench/dut/hart/ieu/dp/ResultW
 | 
			
		||||
add wave -hex /testbench/dut/hart/ieu/dp/RegWriteW
 | 
			
		||||
 | 
			
		||||
@ -28,9 +28,9 @@
 | 
			
		||||
module intdivrestoring (
 | 
			
		||||
  input  logic clk,
 | 
			
		||||
  input  logic reset,
 | 
			
		||||
  input  logic StallM,
 | 
			
		||||
  input  logic signedDivide,
 | 
			
		||||
  input  logic start,
 | 
			
		||||
  input  logic StallM, FlushM,
 | 
			
		||||
  input  logic SignedDivideE,
 | 
			
		||||
  input  logic StartDivideE,
 | 
			
		||||
  input  logic [`XLEN-1:0] X, D,
 | 
			
		||||
  output logic busy, done,
 | 
			
		||||
  output logic [`XLEN-1:0] Q, REM
 | 
			
		||||
@ -41,78 +41,84 @@ module intdivrestoring (
 | 
			
		||||
  localparam STEPBITS = $clog2(`XLEN)-1;
 | 
			
		||||
  logic [STEPBITS:0] step;
 | 
			
		||||
  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
 | 
			
		||||
  abs #(`XLEN) absd(D, Dabs);
 | 
			
		||||
  mux2 #(`XLEN) dabsmux(D, Dabs, signedDivide, D2);
 | 
			
		||||
  flopen #(`XLEN) dsavereg(clk, start, D2, Dsaved);
 | 
			
		||||
  mux2 #(`XLEN) dfirstmux(Dsaved, D, start, Din); 
 | 
			
		||||
  mux2 #(`XLEN) dabsmux(D, Dabs, SignedDivideE, D2);
 | 
			
		||||
  flopen #(`XLEN) dsavereg(clk, StartDivideE, D2, Dsaved);
 | 
			
		||||
  mux2 #(`XLEN) dfirstmux(Dsaved, D, StartDivideE, Din); 
 | 
			
		||||
 | 
			
		||||
  abs #(`XLEN) absx(X, Xabs);
 | 
			
		||||
  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); 
 | 
			
		||||
  mux2 #(`XLEN) xabsmux(X, Xabs, SignedDivideE & ~div0, X2);  // need original X as remainder if doing divide by 0
 | 
			
		||||
  flopen #(`XLEN) xsavereg(clk, StartDivideE, X2, Xsaved);
 | 
			
		||||
  mux2 #(`XLEN) xfirstmux(Xsaved, X, StartDivideE, Xinit); 
 | 
			
		||||
 | 
			
		||||
  mux2 #(`XLEN) wmux(W, {`XLEN{1'b0}}, init, Win);
 | 
			
		||||
  mux2 #(`XLEN) xmux(XQ, Xinit, init, XQin);
 | 
			
		||||
 | 
			
		||||
  assign DAbsB = ~Din;
 | 
			
		||||
  assign div0 = (Din == 0); // *** eventually replace with just the negedge saved D
 | 
			
		||||
 | 
			
		||||
  // *** parameterize steps per cycle
 | 
			
		||||
  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
 | 
			
		||||
  // *** move into M stage
 | 
			
		||||
  neg #(`XLEN) wneg(W, Wn);
 | 
			
		||||
  mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext); //***
 | 
			
		||||
  neg #(`XLEN) qneg(XQ, XQn);
 | 
			
		||||
  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);
 | 
			
		||||
 | 
			
		||||
//  flopen #(`XLEN) wreg(clk, StartDivideE | (busy & (~negate | NegW)), Wnext, W);
 | 
			
		||||
//  flopen #(`XLEN) xreg(clk, StartDivideE | (busy & (~negate | NegQ)), XQnext, XQ);
 | 
			
		||||
  flopen #(`XLEN) wreg(clk, StartDivideE | busy, Wnext, W); // *** could become just busy once start moves to its own cycle
 | 
			
		||||
  flopen #(`XLEN) xreg(clk, StartDivideE | busy, XQnext, XQ);
 | 
			
		||||
 | 
			
		||||
  // outputs
 | 
			
		||||
  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
 | 
			
		||||
  neg #(`XLEN) wneg(W, Wn);
 | 
			
		||||
//  mux2 #(`XLEN) wnextmux(W2, Wn, NegW, Wnext); //***
 | 
			
		||||
  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
 | 
			
		||||
  always_ff @(posedge clk) 
 | 
			
		||||
    if (reset) begin
 | 
			
		||||
        busy = 0; done = 0; step = 0; negate = 0;
 | 
			
		||||
    end else if (start & ~StallM) begin 
 | 
			
		||||
        busy = 0; done = 0; step = 0; //negate = 0;
 | 
			
		||||
    end else if (StartDivideE & ~StallM) begin 
 | 
			
		||||
        if (div0) done = 1;
 | 
			
		||||
        else begin
 | 
			
		||||
            busy = 1; step = 1;
 | 
			
		||||
        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;
 | 
			
		||||
        if (step[STEPBITS]) begin // *** early terminate on division by 0
 | 
			
		||||
          if (signedDivide & ~negate) begin
 | 
			
		||||
/*          if (SignedDivideE & ~negate) begin
 | 
			
		||||
            negate = 1;
 | 
			
		||||
          end else begin
 | 
			
		||||
          end else begin*/
 | 
			
		||||
            step = 0;
 | 
			
		||||
            busy = 0;
 | 
			
		||||
            negate = 0;
 | 
			
		||||
            //negate = 0;
 | 
			
		||||
            done = 1;
 | 
			
		||||
          end
 | 
			
		||||
          //end
 | 
			
		||||
        end
 | 
			
		||||
    end else if (done) begin
 | 
			
		||||
        done = 0;
 | 
			
		||||
        busy = 0;
 | 
			
		||||
        negate = 0;
 | 
			
		||||
        //negate = 0;
 | 
			
		||||
    end
 | 
			
		||||
 
 | 
			
		||||
  // 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);
 | 
			
		||||
  mux2 #(1) initmux(start, startd, signedDivide, init);
 | 
			
		||||
  flop #(1) initflop(clk, StartDivideE, startd);
 | 
			
		||||
  mux2 #(1) initmux(StartDivideE, startd, SignedDivideE, init);
 | 
			
		||||
 | 
			
		||||
  // 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
 | 
			
		||||
  assign NegW = SignX & negate;
 | 
			
		||||
  assign NegQ = (SignX ^ SignD) & negate;
 | 
			
		||||
  assign NegW = SignedDivideM & SignX; // & negate;
 | 
			
		||||
  assign NegQ = SignedDivideM & (SignX ^ SignD); // & negate;
 | 
			
		||||
 | 
			
		||||
endmodule // muldiv
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -56,7 +56,7 @@ module muldiv (
 | 
			
		||||
	 //logic [`XLEN-1:0]   Num0, Den0;	 
 | 
			
		||||
 | 
			
		||||
	// logic 		     gclk;
 | 
			
		||||
	 logic 		     startDivideE, busy;
 | 
			
		||||
	 logic 		     StartDivideE, busy;
 | 
			
		||||
	 logic 		     SignedDivideE;	
 | 
			
		||||
	 logic           W64M; 
 | 
			
		||||
	 
 | 
			
		||||
@ -77,12 +77,13 @@ module muldiv (
 | 
			
		||||
	 end	    
 | 
			
		||||
 | 
			
		||||
	 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);
 | 
			
		||||
	 intdivrestoring div(.clk, .reset, .StallM, .signedDivide(SignedDivideE), .start(startDivideE), .X(X), .D(D), .busy(busy), .done(DivDoneE), .Q(QuotM), .REM(RemM));
 | 
			
		||||
	 //intdiv #(`XLEN) div (QuotE, RemE, DivDoneE, DivBusyE, div0error, N, D, gclk, reset, StartDivideE, SignedDivideE);
 | 
			
		||||
	 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
 | 
			
		||||
	 assign startDivideE = MulDivE & Funct3E[2] & ~busy & ~DivDoneE; // *** mabye DivDone should be M stage
 | 
			
		||||
	 assign DivBusyE = startDivideE | busy;
 | 
			
		||||
	 assign StartDivideE = MulDivE & Funct3E[2] & ~busy & ~DivDoneE; // *** mabye DivDone should be M stage
 | 
			
		||||
	 assign DivBusyE = StartDivideE | busy;
 | 
			
		||||
	 	 
 | 
			
		||||
	 // Select result
 | 
			
		||||
	 always_comb
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user