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
c41391e228
commit
e9f5778e2a
@ -17,7 +17,7 @@ if [file exists work] {
|
|||||||
}
|
}
|
||||||
vlib 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
|
vopt +acc work.testbenchradix4 -o workopt
|
||||||
vsim workopt
|
vsim workopt
|
||||||
|
|
||||||
|
@ -34,29 +34,24 @@
|
|||||||
|
|
||||||
module srtradix4 (
|
module srtradix4 (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic Start,
|
input logic DivStart,
|
||||||
input logic Stall, // *** multiple pipe stages
|
input logic XSgnE, YSgnE,
|
||||||
input logic Flush, // *** multiple pipe stages
|
input logic [`NE-1:0] XExpE, YExpE,
|
||||||
// Floating Point Inputs
|
|
||||||
// later add exponents, signs, special cases
|
|
||||||
input logic XSign, YSign,
|
|
||||||
input logic [`NE-1:0] XExp, YExp,
|
|
||||||
input logic [`NF-1:0] XFrac, YFrac,
|
input logic [`NF-1:0] XFrac, YFrac,
|
||||||
input logic [`XLEN-1:0] SrcA, SrcB,
|
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 W64, // 32-bit ints on XLEN=64
|
||||||
input logic Signed, // Interpret integers as signed 2's complement
|
input logic Signed, // Interpret integers as signed 2's complement
|
||||||
input logic Int, // Choose integer inputs
|
input logic Int, // Choose integer inputs
|
||||||
input logic Sqrt, // perform square root, not divide
|
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 [`DIVLEN-1:0] Quot, Rem, // *** later handle integers
|
||||||
output logic [`NE-1:0] rExp,
|
output logic [`NE-1:0] DivExp
|
||||||
output logic [3:0] Flags
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// logic qp, qz, qm; // quotient is +1, 0, or -1
|
// logic qp, qz, qm; // quotient is +1, 0, or -1
|
||||||
logic [3:0] q;
|
logic [3:0] q;
|
||||||
logic [`NE-1:0] calcExp;
|
logic [`NE-1:0] DivCalcExp;
|
||||||
logic calcSign;
|
logic calcSign;
|
||||||
logic [`DIVLEN-1:0] X, Dpreproc;
|
logic [`DIVLEN-1:0] X, Dpreproc;
|
||||||
logic [`DIVLEN+3:0] WS, WSA, WSN;
|
logic [`DIVLEN+3:0] WS, WSA, WSN;
|
||||||
@ -65,7 +60,7 @@ module srtradix4 (
|
|||||||
logic [$clog2(`XLEN+1)-1:0] intExp;
|
logic [$clog2(`XLEN+1)-1:0] intExp;
|
||||||
logic intSign;
|
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
|
// Top Muxes and Registers
|
||||||
// When start is asserted, the inputs are loaded into the divider.
|
// When start is asserted, the inputs are loaded into the divider.
|
||||||
@ -77,11 +72,11 @@ module srtradix4 (
|
|||||||
// - otherwise load WSA into the flipflop
|
// - otherwise load WSA into the flipflop
|
||||||
// *** what does N and A stand for?
|
// *** what does N and A stand for?
|
||||||
// *** change shift amount for radix4
|
// *** 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);
|
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);
|
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
|
// Quotient Selection logic
|
||||||
// Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
|
// Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
|
||||||
@ -94,9 +89,9 @@ module srtradix4 (
|
|||||||
// 0001 = -2
|
// 0001 = -2
|
||||||
qsel4 qsel4(.D, .WS, .WC, .q);
|
qsel4 qsel4(.D, .WS, .WC, .q);
|
||||||
|
|
||||||
// Store the expoenent and sign until division is done
|
// Store the expoenent and sign until division is DivDone
|
||||||
flopen #(`NE) expflop(clk, Start, calcExp, rExp);
|
flopen #(`NE) expflop(clk, DivStart, DivCalcExp, DivExp);
|
||||||
flopen #(1) signflop(clk, Start, calcSign, rsign);
|
flopen #(1) signflop(clk, DivStart, calcSign, DivSgn);
|
||||||
|
|
||||||
// Divisor Selection logic
|
// Divisor Selection logic
|
||||||
// *** radix 4 change to choose -2 to 2
|
// *** 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);
|
csa #(`DIVLEN+4) csa(WS, WC, Dsel, |q[3:2], WSA, WCA);
|
||||||
|
|
||||||
//*** change for radix 4
|
//*** 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
|
endmodule
|
||||||
|
|
||||||
@ -132,13 +129,58 @@ endmodule
|
|||||||
// Submodules //
|
// 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 //
|
// Preprocessing //
|
||||||
///////////////////
|
///////////////////
|
||||||
module srtpreproc (
|
module srtpreproc (
|
||||||
input logic [`XLEN-1:0] SrcA, SrcB,
|
input logic [`XLEN-1:0] SrcA, SrcB,
|
||||||
input logic [`NF-1:0] XFrac, YFrac,
|
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 W64, // 32-bit ints on XLEN=64
|
||||||
input logic Signed, // Interpret integers as signed 2's complement
|
input logic Signed, // Interpret integers as signed 2's complement
|
||||||
input logic Int, // Choose integer inputs
|
input logic Int, // Choose integer inputs
|
||||||
@ -173,48 +215,12 @@ module srtpreproc (
|
|||||||
assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
|
assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
|
||||||
endmodule
|
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 //
|
// On-The-Fly Converter, Radix 2 //
|
||||||
///////////////////////////////////
|
///////////////////////////////////
|
||||||
module otfc4 #(parameter N=65) (
|
module otfc4 #(parameter N=65) (
|
||||||
input logic clk,
|
input logic clk,
|
||||||
input logic Start,
|
input logic DivStart,
|
||||||
input logic [3:0] q,
|
input logic [3:0] q,
|
||||||
output logic [N-1:0] r
|
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.
|
// discard the r most significant bits of Q and QM.
|
||||||
logic [N:0] QR, QMR;
|
logic [N:0] QR, QMR;
|
||||||
// if starting a new divison set Q to 0 and QM to -1
|
// 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) Qmux(QNext, {N+3{1'b0}}, DivStart, QMux);
|
||||||
mux2 #(N+3) QMmux(QMNext, {N+3{1'b1}}, Start, QMMux);
|
mux2 #(N+3) QMmux(QMNext, {N+3{1'b1}}, DivStart, QMMux);
|
||||||
flop #(N+3) Qreg(clk, QMux, Q);
|
flop #(N+3) Qreg(clk, QMux, Q);
|
||||||
flop #(N+3) QMreg(clk, QMMux, QM);
|
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
|
// This block adds in1, in2, in3, and cin to produce
|
||||||
// a result out1 / out2 in carry-save redundant form.
|
// a result out1 / out2 in carry-save redundant form.
|
||||||
// cin is just added to the least significant bit and
|
// 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
|
// Fortunately, the carry (out2) is shifted left by one
|
||||||
// bit, leaving room in the least significant bit to
|
// bit, leaving room in the least significant bit to
|
||||||
// insert cin.
|
// insert cin.
|
||||||
@ -302,11 +308,11 @@ endmodule
|
|||||||
// expcalc //
|
// expcalc //
|
||||||
//////////////
|
//////////////
|
||||||
module expcalc(
|
module expcalc(
|
||||||
input logic [`NE-1:0] XExp, YExp,
|
input logic [`NE-1:0] XExpE, YExpE,
|
||||||
output logic [`NE-1:0] calcExp
|
output logic [`NE-1:0] DivCalcExp
|
||||||
);
|
);
|
||||||
|
|
||||||
assign calcExp = XExp - YExp + (`NE)'(`BIAS);
|
assign DivCalcExp = XExpE - YExpE + (`NE)'(`BIAS);
|
||||||
|
|
||||||
endmodule
|
endmodule
|
||||||
|
|
||||||
@ -314,10 +320,10 @@ endmodule
|
|||||||
// signcalc //
|
// signcalc //
|
||||||
//////////////
|
//////////////
|
||||||
module signcalc(
|
module signcalc(
|
||||||
input logic XSign, YSign,
|
input logic XSgnE, YSgnE,
|
||||||
output logic calcSign
|
output logic calcSign
|
||||||
);
|
);
|
||||||
|
|
||||||
assign calcSign = XSign ^ YSign;
|
assign calcSign = XSgnE ^ YSgnE;
|
||||||
|
|
||||||
endmodule
|
endmodule
|
@ -2,30 +2,6 @@
|
|||||||
`include "wally-config.vh"
|
`include "wally-config.vh"
|
||||||
`define DIVLEN ((`NF<`XLEN) ? `XLEN : `NF)
|
`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 //
|
// clock //
|
||||||
///////////
|
///////////
|
||||||
@ -43,7 +19,7 @@ endmodule
|
|||||||
module testbenchradix4;
|
module testbenchradix4;
|
||||||
logic clk;
|
logic clk;
|
||||||
logic req;
|
logic req;
|
||||||
logic done;
|
logic DivDone;
|
||||||
logic [63:0] a, b;
|
logic [63:0] a, b;
|
||||||
logic [51:0] afrac, bfrac;
|
logic [51:0] afrac, bfrac;
|
||||||
logic [10:0] aExp, bExp;
|
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
|
logic [MEM_WIDTH-1:0] Vec; // Verilog doesn't allow direct access to a
|
||||||
// bit field of an array
|
// bit field of an array
|
||||||
logic [63:0] correctr, nextr, diffn, diffp;
|
logic [63:0] correctr, nextr, diffn, diffp;
|
||||||
logic [10:0] rExp;
|
logic [10:0] DivExp;
|
||||||
logic rsign;
|
logic DivSgn;
|
||||||
integer testnum, errors;
|
integer testnum, errors;
|
||||||
|
|
||||||
// Divider
|
// Divider
|
||||||
srtradix4 srtradix4(.clk, .Start(req),
|
srtradix4 srtradix4(.clk, .DivStart(req),
|
||||||
.Stall(1'b0), .Flush(1'b0),
|
.XExpE(aExp), .YExpE(bExp), .DivExp,
|
||||||
.XExp(aExp), .YExp(bExp), .rExp,
|
.XSgnE(asign), .YSgnE(bsign), .DivSgn,
|
||||||
.XSign(asign), .YSign(bsign), .rsign,
|
|
||||||
.XFrac(afrac), .YFrac(bfrac),
|
.XFrac(afrac), .YFrac(bfrac),
|
||||||
.SrcA('0), .SrcB('0), .Fmt(2'b00),
|
.SrcA('0), .SrcB('0), .Fmt(2'b00),
|
||||||
.W64(1'b0), .Signed(1'b0), .Int(1'b0), .Sqrt(1'b0),
|
.W64(1'b0), .Signed(1'b0), .Int(1'b0), .Sqrt(1'b0), .DivDone,
|
||||||
.Quot, .Rem(), .Flags());
|
.Quot, .Rem());
|
||||||
|
|
||||||
// Counter
|
// Counter
|
||||||
counter counter(clk, req, done);
|
|
||||||
|
|
||||||
|
|
||||||
initial
|
initial
|
||||||
@ -112,14 +86,14 @@ module testbenchradix4;
|
|||||||
always @(posedge clk)
|
always @(posedge clk)
|
||||||
begin
|
begin
|
||||||
r = Quot[`DIVLEN-1:`DIVLEN - 52];
|
r = Quot[`DIVLEN-1:`DIVLEN - 52];
|
||||||
if (done) begin
|
if (DivDone) begin
|
||||||
req <= 1;
|
req <= 1;
|
||||||
diffp = correctr[51:0] - r;
|
diffp = correctr[51:0] - r;
|
||||||
diffn = r - correctr[51:0];
|
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
|
begin
|
||||||
errors = errors+1;
|
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");
|
$display("failed\n");
|
||||||
$stop;
|
$stop;
|
||||||
end
|
end
|
||||||
|
Loading…
Reference in New Issue
Block a user