diff --git a/pipelined/srt/srt-radix4.do b/pipelined/srt/srt-radix4.do index b213aa994..07dedfbfe 100644 --- a/pipelined/srt/srt-radix4.do +++ b/pipelined/srt/srt-radix4.do @@ -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 diff --git a/pipelined/srt/srt-radix4.sv b/pipelined/srt/srt-radix4.sv index ccb6453c0..6c9cd0fa7 100644 --- a/pipelined/srt/srt-radix4.sv +++ b/pipelined/srt/srt-radix4.sv @@ -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 \ No newline at end of file diff --git a/pipelined/srt/testbench-radix4.sv b/pipelined/srt/testbench-radix4.sv index 6ac616ed6..0cea8059c 100644 --- a/pipelined/srt/testbench-radix4.sv +++ b/pipelined/srt/testbench-radix4.sv @@ -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