mirror of
				https://github.com/openhwgroup/cvw
				synced 2025-02-11 06:05:49 +00:00 
			
		
		
		
	using memread for quotent select
This commit is contained in:
		
							parent
							
								
									03b9878005
								
							
						
					
					
						commit
						6001956bd8
					
				@ -17,7 +17,7 @@ if [file exists work] {
 | 
			
		||||
}
 | 
			
		||||
vlib work
 | 
			
		||||
 | 
			
		||||
vlog +incdir+../config/rv64gc +incdir+../config/shared srt-radix4.sv testbench-radix4.sv qsel4.sv ../src/generic/flop/flop*.sv ../src/generic/mux.sv ../src/generic/lzc.sv
 | 
			
		||||
vlog +incdir+../config/rv64gc +incdir+../config/shared srt-radix4.sv testbench-radix4.sv ../src/generic/flop/flop*.sv ../src/generic/mux.sv ../src/generic/lzc.sv
 | 
			
		||||
vopt +acc work.testbenchradix4 -o workopt 
 | 
			
		||||
vsim workopt
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -34,29 +34,24 @@
 | 
			
		||||
 | 
			
		||||
module srtradix4 (
 | 
			
		||||
  input  logic clk,
 | 
			
		||||
  input  logic Start, 
 | 
			
		||||
  input  logic Stall, // *** multiple pipe stages
 | 
			
		||||
  input  logic Flush, // *** multiple pipe stages
 | 
			
		||||
  // Floating Point Inputs
 | 
			
		||||
  // later add exponents, signs, special cases
 | 
			
		||||
  input  logic       XSign, YSign,
 | 
			
		||||
  input  logic [`NE-1:0] XExp, YExp,
 | 
			
		||||
  input  logic DivStart, 
 | 
			
		||||
  input  logic       XSgnE, YSgnE,
 | 
			
		||||
  input  logic [`NE-1:0] XExpE, YExpE,
 | 
			
		||||
  input  logic [`NF-1:0] XFrac, YFrac,
 | 
			
		||||
  input  logic [`XLEN-1:0] SrcA, SrcB,
 | 
			
		||||
  input  logic [1:0] Fmt, // Floats: 00 = 16 bit, 01 = 32 bit, 10 = 64 bit, 11 = 128 bit
 | 
			
		||||
  input  logic       W64, // 32-bit ints on XLEN=64
 | 
			
		||||
  input  logic       Signed, // Interpret integers as signed 2's complement
 | 
			
		||||
  input  logic       Int, // Choose integer inputs
 | 
			
		||||
  input  logic       Sqrt, // perform square root, not divide
 | 
			
		||||
  output logic       rsign,
 | 
			
		||||
  output logic       DivDone,
 | 
			
		||||
  output logic       DivSgn,
 | 
			
		||||
  output logic [`DIVLEN-1:0] Quot, Rem, // *** later handle integers
 | 
			
		||||
  output logic [`NE-1:0] rExp,
 | 
			
		||||
  output logic [3:0] Flags
 | 
			
		||||
  output logic [`NE-1:0] DivExp
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
  // logic           qp, qz, qm; // quotient is +1, 0, or -1
 | 
			
		||||
  logic [3:0]     q;
 | 
			
		||||
  logic [`NE-1:0] calcExp;
 | 
			
		||||
  logic [`NE-1:0] DivCalcExp;
 | 
			
		||||
  logic           calcSign;
 | 
			
		||||
  logic [`DIVLEN-1:0]  X, Dpreproc;
 | 
			
		||||
  logic [`DIVLEN+3:0]  WS, WSA, WSN;
 | 
			
		||||
@ -65,7 +60,7 @@ module srtradix4 (
 | 
			
		||||
  logic [$clog2(`XLEN+1)-1:0] intExp;
 | 
			
		||||
  logic           intSign;
 | 
			
		||||
 
 | 
			
		||||
  srtpreproc preproc(SrcA, SrcB, XFrac, YFrac, Fmt, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, intSign);
 | 
			
		||||
  srtpreproc preproc(SrcA, SrcB, XFrac, YFrac, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, intSign);
 | 
			
		||||
 | 
			
		||||
  // Top Muxes and Registers
 | 
			
		||||
  // When start is asserted, the inputs are loaded into the divider.
 | 
			
		||||
@ -77,11 +72,11 @@ module srtradix4 (
 | 
			
		||||
  //  - otherwise load WSA into the flipflop
 | 
			
		||||
  //  *** what does N and A stand for?
 | 
			
		||||
  //  *** change shift amount for radix4
 | 
			
		||||
  mux2   #(`DIVLEN+4) wsmux({WSA[`DIVLEN+1:0], 2'b0}, {4'b0001, X}, Start, WSN);
 | 
			
		||||
  mux2   #(`DIVLEN+4) wsmux({WSA[`DIVLEN+1:0], 2'b0}, {4'b0001, X}, DivStart, WSN);
 | 
			
		||||
  flop   #(`DIVLEN+4) wsflop(clk, WSN, WS);
 | 
			
		||||
  mux2   #(`DIVLEN+4) wcmux({WCA[`DIVLEN+1:0], 2'b0}, {`DIVLEN+4{1'b0}}, Start, WCN);
 | 
			
		||||
  mux2   #(`DIVLEN+4) wcmux({WCA[`DIVLEN+1:0], 2'b0}, {`DIVLEN+4{1'b0}}, DivStart, WCN);
 | 
			
		||||
  flop   #(`DIVLEN+4) wcflop(clk, WCN, WC);
 | 
			
		||||
  flopen #(`DIVLEN+4) dflop(clk, Start, {4'b0001, Dpreproc}, D);
 | 
			
		||||
  flopen #(`DIVLEN+4) dflop(clk, DivStart, {4'b0001, Dpreproc}, D);
 | 
			
		||||
 | 
			
		||||
  // Quotient Selection logic
 | 
			
		||||
  // Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
 | 
			
		||||
@ -94,9 +89,9 @@ module srtradix4 (
 | 
			
		||||
	// 0001 = -2
 | 
			
		||||
  qsel4 qsel4(.D, .WS, .WC, .q);
 | 
			
		||||
 | 
			
		||||
  // Store the expoenent and sign until division is done
 | 
			
		||||
  flopen #(`NE) expflop(clk, Start, calcExp, rExp);
 | 
			
		||||
  flopen #(1) signflop(clk, Start, calcSign, rsign);
 | 
			
		||||
  // Store the expoenent and sign until division is DivDone
 | 
			
		||||
  flopen #(`NE) expflop(clk, DivStart, DivCalcExp, DivExp);
 | 
			
		||||
  flopen #(1) signflop(clk, DivStart, calcSign, DivSgn);
 | 
			
		||||
 | 
			
		||||
  // Divisor Selection logic
 | 
			
		||||
  // *** radix 4 change to choose -2 to 2
 | 
			
		||||
@ -120,11 +115,13 @@ module srtradix4 (
 | 
			
		||||
  csa    #(`DIVLEN+4) csa(WS, WC, Dsel, |q[3:2], WSA, WCA);
 | 
			
		||||
  
 | 
			
		||||
  //*** change for radix 4
 | 
			
		||||
  otfc4  #(`DIVLEN) otfc4(clk, Start, q, Quot);
 | 
			
		||||
  otfc4  #(`DIVLEN) otfc4(clk, DivStart, q, Quot);
 | 
			
		||||
 | 
			
		||||
  expcalc expcalc(.XExp, .YExp, .calcExp);
 | 
			
		||||
  expcalc expcalc(.XExpE, .YExpE, .DivCalcExp);
 | 
			
		||||
 | 
			
		||||
  signcalc signcalc(.XSign, .YSign, .calcSign);
 | 
			
		||||
  signcalc signcalc(.XSgnE, .YSgnE, .calcSign);
 | 
			
		||||
 | 
			
		||||
  counter counter(clk, DivStart, DivDone);
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
@ -132,13 +129,58 @@ endmodule
 | 
			
		||||
// Submodules //
 | 
			
		||||
////////////////
 | 
			
		||||
 | 
			
		||||
/////////////
 | 
			
		||||
// counter //
 | 
			
		||||
/////////////
 | 
			
		||||
module counter(input  logic clk, 
 | 
			
		||||
               input  logic DivStart, 
 | 
			
		||||
               output logic DivDone);
 | 
			
		||||
 
 | 
			
		||||
   logic    [5:0]  count;
 | 
			
		||||
 | 
			
		||||
  // This block of control logic sequences the divider
 | 
			
		||||
  // through its iterations.  You may modify it if you
 | 
			
		||||
  // build a divider which completes in fewer iterations.
 | 
			
		||||
  // You are not responsible for the (trivial) circuit
 | 
			
		||||
  // design of the block.
 | 
			
		||||
 | 
			
		||||
  always @(posedge clk)
 | 
			
		||||
    begin
 | 
			
		||||
      if      (count == `DIVLEN/2+1) DivDone <= #1 1;
 | 
			
		||||
      else if (DivDone | DivStart) DivDone <= #1 0;	
 | 
			
		||||
      if (DivStart) count <= #1 0;
 | 
			
		||||
      else     count <= #1 count+1;
 | 
			
		||||
    end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
module qsel4 (
 | 
			
		||||
	input logic [`DIVLEN+3:0] D,
 | 
			
		||||
	input logic [`DIVLEN+3:0] WS, WC,
 | 
			
		||||
	output logic [3:0] q
 | 
			
		||||
);
 | 
			
		||||
	logic [6:0] Wmsbs;
 | 
			
		||||
	logic [7:0] PreWmsbs;
 | 
			
		||||
	logic [2:0] Dmsbs;
 | 
			
		||||
	assign PreWmsbs = WC[`DIVLEN+3:`DIVLEN-4] + WS[`DIVLEN+3:`DIVLEN-4];
 | 
			
		||||
	assign Wmsbs = PreWmsbs[7:1];
 | 
			
		||||
	assign Dmsbs = D[`DIVLEN-1:`DIVLEN-3];
 | 
			
		||||
	// D = 0001.xxx...
 | 
			
		||||
	// Dmsbs = |   |
 | 
			
		||||
  // W =      xxxx.xxx...
 | 
			
		||||
	// Wmsbs = |        |
 | 
			
		||||
 | 
			
		||||
	logic [3:0] QSel4[1023:0];
 | 
			
		||||
	initial $readmemh("qslc_r4a2b.tv", QSel4);
 | 
			
		||||
	assign q = QSel4[{Dmsbs,Wmsbs}];
 | 
			
		||||
	
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
///////////////////
 | 
			
		||||
// Preprocessing //
 | 
			
		||||
///////////////////
 | 
			
		||||
module srtpreproc (
 | 
			
		||||
  input  logic [`XLEN-1:0] SrcA, SrcB,
 | 
			
		||||
  input  logic [`NF-1:0] XFrac, YFrac,
 | 
			
		||||
  input  logic [1:0] Fmt, // Floats: 00 = 16 bit, 01 = 32 bit, 10 = 64 bit, 11 = 128 bit
 | 
			
		||||
  input  logic       W64, // 32-bit ints on XLEN=64
 | 
			
		||||
  input  logic       Signed, // Interpret integers as signed 2's complement
 | 
			
		||||
  input  logic       Int, // Choose integer inputs
 | 
			
		||||
@ -173,48 +215,12 @@ module srtpreproc (
 | 
			
		||||
  assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
/////////////////////////////////
 | 
			
		||||
// Quotient Selection, Radix 2 //
 | 
			
		||||
/////////////////////////////////
 | 
			
		||||
module qsel2 ( // *** eventually just change to 4 bits
 | 
			
		||||
  input  logic [`DIVLEN+3:`DIVLEN] ps, pc, 
 | 
			
		||||
  output logic         qp, qz, qm
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
  logic [`DIVLEN+3:`DIVLEN]  p, g;
 | 
			
		||||
  logic          magnitude, sign, cout;
 | 
			
		||||
 | 
			
		||||
  // The quotient selection logic is presented for simplicity, not
 | 
			
		||||
  // for efficiency.  You can probably optimize your logic to
 | 
			
		||||
  // select the proper divisor with less delay.
 | 
			
		||||
 | 
			
		||||
  // Quotient equations from EE371 lecture notes 13-20
 | 
			
		||||
  assign p = ps ^ pc;
 | 
			
		||||
  assign g = ps & pc;
 | 
			
		||||
 | 
			
		||||
  assign #1 magnitude = ~(&p[`DIVLEN+2:`DIVLEN]);
 | 
			
		||||
  assign #1 cout = g[`DIVLEN+2] | (p[`DIVLEN+2] & (g[`DIVLEN+1] | p[`DIVLEN+1] & g[`DIVLEN]));
 | 
			
		||||
  assign #1 sign = p[`DIVLEN+3] ^ cout;
 | 
			
		||||
/*  assign #1 magnitude = ~((ps[54]^pc[54]) & (ps[53]^pc[53]) & 
 | 
			
		||||
			  (ps[52]^pc[52]));
 | 
			
		||||
  assign #1 sign = (ps[55]^pc[55])^
 | 
			
		||||
      (ps[54] & pc[54] | ((ps[54]^pc[54]) &
 | 
			
		||||
			    (ps[53]&pc[53] | ((ps[53]^pc[53]) &
 | 
			
		||||
						(ps[52]&pc[52]))))); */
 | 
			
		||||
 | 
			
		||||
  // Produce quotient = +1, 0, or -1
 | 
			
		||||
  assign #1 qp = magnitude & ~sign;
 | 
			
		||||
  assign #1 qz = ~magnitude;
 | 
			
		||||
  assign #1 qm = magnitude & sign;
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
///////////////////////////////////
 | 
			
		||||
// On-The-Fly Converter, Radix 2 //
 | 
			
		||||
///////////////////////////////////
 | 
			
		||||
module otfc4 #(parameter N=65) (
 | 
			
		||||
  input  logic         clk,
 | 
			
		||||
  input  logic         Start,
 | 
			
		||||
  input  logic         DivStart,
 | 
			
		||||
  input  logic [3:0]   q,
 | 
			
		||||
  output logic [N-1:0] r
 | 
			
		||||
);
 | 
			
		||||
@ -234,8 +240,8 @@ module otfc4 #(parameter N=65) (
 | 
			
		||||
  //  discard the r most significant bits of Q and QM. 
 | 
			
		||||
  logic [N:0] QR, QMR;
 | 
			
		||||
  // if starting a new divison set Q to 0 and QM to -1
 | 
			
		||||
  mux2 #(N+3) Qmux(QNext, {N+3{1'b0}}, Start, QMux);
 | 
			
		||||
  mux2 #(N+3) QMmux(QMNext, {N+3{1'b1}}, Start, QMMux);
 | 
			
		||||
  mux2 #(N+3) Qmux(QNext, {N+3{1'b0}}, DivStart, QMux);
 | 
			
		||||
  mux2 #(N+3) QMmux(QMNext, {N+3{1'b1}}, DivStart, QMMux);
 | 
			
		||||
  flop #(N+3) Qreg(clk, QMux, Q);
 | 
			
		||||
  flop #(N+3) QMreg(clk, QMMux, QM);
 | 
			
		||||
 | 
			
		||||
@ -287,7 +293,7 @@ module csa #(parameter N=69) (
 | 
			
		||||
  // This block adds in1, in2, in3, and cin to produce 
 | 
			
		||||
  // a result out1 / out2 in carry-save redundant form.
 | 
			
		||||
  // cin is just added to the least significant bit and
 | 
			
		||||
  // is required to handle adding a negative divisor.
 | 
			
		||||
  // is Startuired to handle adding a negative divisor.
 | 
			
		||||
  // Fortunately, the carry (out2) is shifted left by one
 | 
			
		||||
  // bit, leaving room in the least significant bit to 
 | 
			
		||||
  // insert cin.
 | 
			
		||||
@ -302,11 +308,11 @@ endmodule
 | 
			
		||||
// expcalc  //
 | 
			
		||||
//////////////
 | 
			
		||||
module expcalc(
 | 
			
		||||
  input logic  [`NE-1:0] XExp, YExp,
 | 
			
		||||
  output logic [`NE-1:0] calcExp
 | 
			
		||||
  input logic  [`NE-1:0] XExpE, YExpE,
 | 
			
		||||
  output logic [`NE-1:0] DivCalcExp
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
  assign calcExp = XExp - YExp + (`NE)'(`BIAS);
 | 
			
		||||
  assign DivCalcExp = XExpE - YExpE + (`NE)'(`BIAS);
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
@ -314,10 +320,10 @@ endmodule
 | 
			
		||||
// signcalc //
 | 
			
		||||
//////////////
 | 
			
		||||
module signcalc(
 | 
			
		||||
  input logic  XSign, YSign,
 | 
			
		||||
  input logic  XSgnE, YSgnE,
 | 
			
		||||
  output logic calcSign
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
  assign calcSign = XSign ^ YSign;
 | 
			
		||||
  assign calcSign = XSgnE ^ YSgnE;
 | 
			
		||||
 | 
			
		||||
endmodule
 | 
			
		||||
@ -2,30 +2,6 @@
 | 
			
		||||
`include "wally-config.vh"
 | 
			
		||||
`define DIVLEN ((`NF<`XLEN) ? `XLEN : `NF)
 | 
			
		||||
 | 
			
		||||
/////////////
 | 
			
		||||
// counter //
 | 
			
		||||
/////////////
 | 
			
		||||
module counter(input  logic clk, 
 | 
			
		||||
               input  logic req, 
 | 
			
		||||
               output logic done);
 | 
			
		||||
 
 | 
			
		||||
   logic    [5:0]  count;
 | 
			
		||||
 | 
			
		||||
  // This block of control logic sequences the divider
 | 
			
		||||
  // through its iterations.  You may modify it if you
 | 
			
		||||
  // build a divider which completes in fewer iterations.
 | 
			
		||||
  // You are not responsible for the (trivial) circuit
 | 
			
		||||
  // design of the block.
 | 
			
		||||
 | 
			
		||||
  always @(posedge clk)
 | 
			
		||||
    begin
 | 
			
		||||
      if      (count == `DIVLEN/2+1) done <= #1 1;
 | 
			
		||||
      else if (done | req) done <= #1 0;	
 | 
			
		||||
      if (req) count <= #1 0;
 | 
			
		||||
      else     count <= #1 count+1;
 | 
			
		||||
    end
 | 
			
		||||
endmodule
 | 
			
		||||
 | 
			
		||||
///////////
 | 
			
		||||
// clock //
 | 
			
		||||
///////////
 | 
			
		||||
@ -43,7 +19,7 @@ endmodule
 | 
			
		||||
module testbenchradix4;
 | 
			
		||||
  logic              clk;
 | 
			
		||||
  logic              req;
 | 
			
		||||
  logic              done;
 | 
			
		||||
  logic              DivDone;
 | 
			
		||||
  logic [63:0]       a, b;
 | 
			
		||||
  logic [51:0]       afrac, bfrac;
 | 
			
		||||
  logic [10:0]       aExp, bExp;
 | 
			
		||||
@ -65,22 +41,20 @@ module testbenchradix4;
 | 
			
		||||
  logic [MEM_WIDTH-1:0] Vec;  // Verilog doesn't allow direct access to a
 | 
			
		||||
                            // bit field of an array 
 | 
			
		||||
  logic [63:0] correctr, nextr, diffn, diffp;
 | 
			
		||||
  logic [10:0] rExp;
 | 
			
		||||
  logic        rsign;
 | 
			
		||||
  logic [10:0] DivExp;
 | 
			
		||||
  logic        DivSgn;
 | 
			
		||||
  integer testnum, errors;
 | 
			
		||||
 | 
			
		||||
  // Divider
 | 
			
		||||
  srtradix4 srtradix4(.clk, .Start(req), 
 | 
			
		||||
                .Stall(1'b0), .Flush(1'b0), 
 | 
			
		||||
                .XExp(aExp), .YExp(bExp), .rExp,
 | 
			
		||||
                .XSign(asign), .YSign(bsign), .rsign,
 | 
			
		||||
  srtradix4 srtradix4(.clk, .DivStart(req), 
 | 
			
		||||
                .XExpE(aExp), .YExpE(bExp), .DivExp,
 | 
			
		||||
                .XSgnE(asign), .YSgnE(bsign), .DivSgn,
 | 
			
		||||
                .XFrac(afrac), .YFrac(bfrac), 
 | 
			
		||||
                .SrcA('0), .SrcB('0), .Fmt(2'b00), 
 | 
			
		||||
                .W64(1'b0), .Signed(1'b0), .Int(1'b0), .Sqrt(1'b0), 
 | 
			
		||||
                .Quot, .Rem(), .Flags());
 | 
			
		||||
                .W64(1'b0), .Signed(1'b0), .Int(1'b0), .Sqrt(1'b0), .DivDone,
 | 
			
		||||
                .Quot, .Rem());
 | 
			
		||||
 | 
			
		||||
  // Counter
 | 
			
		||||
  counter counter(clk, req, done);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    initial
 | 
			
		||||
@ -112,14 +86,14 @@ module testbenchradix4;
 | 
			
		||||
  always @(posedge clk)
 | 
			
		||||
    begin
 | 
			
		||||
      r = Quot[`DIVLEN-1:`DIVLEN - 52];
 | 
			
		||||
      if (done) begin
 | 
			
		||||
      if (DivDone) begin
 | 
			
		||||
        req <= 1;
 | 
			
		||||
        diffp = correctr[51:0] - r;
 | 
			
		||||
        diffn = r - correctr[51:0];
 | 
			
		||||
        if ((rsign !== correctr[63]) | (rExp !== correctr[62:52]) | ($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
 | 
			
		||||
        if ((DivSgn !== correctr[63]) | (DivExp !== correctr[62:52]) | ($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
 | 
			
		||||
          begin
 | 
			
		||||
            errors = errors+1;
 | 
			
		||||
            $display("result was %h_%h, should be %h %h %h\n", rExp, r, correctr, diffn, diffp);
 | 
			
		||||
            $display("result was %h_%h, should be %h %h %h\n", DivExp, r, correctr, diffn, diffp);
 | 
			
		||||
            $display("failed\n");
 | 
			
		||||
            $stop;
 | 
			
		||||
          end
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user