This commit is contained in:
Daniel Torres 2022-07-21 20:59:01 -07:00
commit f1578936b8
12 changed files with 219 additions and 90 deletions

View File

@ -165,6 +165,7 @@ module uartPC16550D(
SCR <= #1 8'b0; // not strictly necessary to reset SCR <= #1 8'b0; // not strictly necessary to reset
end else begin end else begin
if (~MEMWb) begin if (~MEMWb) begin
/* verilator lint_off CASEINCOMPLETE */
case (A) case (A)
/* -----\/----- EXCLUDED -----\/----- /* -----\/----- EXCLUDED -----\/-----
3'b000: if (DLAB) DLL <= #1 Din; // else TXHR <= #1 Din; // TX handled in TX register/FIFO section 3'b000: if (DLAB) DLL <= #1 Din; // else TXHR <= #1 Din; // TX handled in TX register/FIFO section
@ -177,34 +178,40 @@ module uartPC16550D(
// freq /baud / 16 = div // freq /baud / 16 = div
//3'b000: if (DLAB) DLL <= #1 8'd38; //else TXHR <= #1 Din; // TX handled in TX register/FIFO section //3'b000: if (DLAB) DLL <= #1 8'd38; //else TXHR <= #1 Din; // TX handled in TX register/FIFO section
//3'b000: if (DLAB) DLL <= #1 8'd11; //else TXHR <= #1 Din; // TX handled in //3'b000: if (DLAB) DLL <= #1 8'd11; //else TXHR <= #1 Din; // TX handled in
3'b000: if (DLAB) DLL <= #1 8'd8; //else TXHR <= #1 Din; // TX handled in 3'b000: if (DLAB) DLL <= #1 8'd8; //else TXHR <= #1 Din; // TX handled in
3'b001: if (DLAB) DLM <= #1 8'b0; else IER <= #1 Din[3:0]; 3'b001: if (DLAB) DLM <= #1 8'b0; else IER <= #1 Din[3:0];
3'b010: FCR <= #1 {Din[7:6], 2'b0, Din[3], 2'b0, Din[0]}; // Write only FIFO Control Register; 4:5 reserved and 2:1 self-clearing 3'b010: FCR <= #1 {Din[7:6], 2'b0, Din[3], 2'b0, Din[0]}; // Write only FIFO Control Register; 4:5 reserved and 2:1 self-clearing
3'b011: LCR <= #1 Din; 3'b011: LCR <= #1 Din;
3'b100: MCR <= #1 Din[4:0]; 3'b100: MCR <= #1 Din[4:0];
3'b101: LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
3'b110: MSR <= #1 Din[3:0];
3'b111: SCR <= #1 Din; 3'b111: SCR <= #1 Din;
endcase endcase
/* verilator lint_on CASEINCOMPLETE */
end end
// Line Status Register (8.6.3) // Line Status Register (8.6.3)
// Ben 6/9/21 I don't like how this is a register. A lot of the individual bits have clocked components, so this just adds unecessary delay. // Ben 6/9/21 I don't like how this is a register. A lot of the individual bits have clocked components, so this just adds unecessary delay.
LSR[0] <= #1 rxdataready; // Data ready if (~MEMWb & (A == 3'b101))
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error else begin
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error LSR[0] <= #1 rxdataready; // Data ready
LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
LSR[5] <= #1 THRE; // THRE LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
LSR[6] <= #1 ~txsrfull & THRE; // TEMT LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing error
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error LSR[4] <= #1 (LSR[4] | rxbreak) & ~squashRXerrIP; // break indicator
LSR[5] <= #1 THRE; // THRE
LSR[6] <= #1 ~txsrfull & THRE; // TEMT
if (rxfifohaserr) LSR[7] <= #1 1; // any bits in FIFO have error
end
// Modem Status Register (8.6.8) // Modem Status Register (8.6.8)
MSR[0] <= #1 MSR[0] | CTSb2 ^ CTSbsync; // Delta Clear to Send if (~MEMWb & (A == 3'b110))
MSR[1] <= #1 MSR[1] | DSRb2 ^ DSRbsync; // Delta Data Set Ready MSR <= #1 Din[3:0];
MSR[2] <= #1 MSR[2] | (~RIb2 & RIbsync); // Trailing Edge of Ring Indicator else begin
MSR[3] <= #1 MSR[3] | DCDb2 ^ DCDbsync; // Delta Data Carrier Detect MSR[0] <= #1 MSR[0] | CTSb2 ^ CTSbsync; // Delta Clear to Send
MSR[1] <= #1 MSR[1] | DSRb2 ^ DSRbsync; // Delta Data Set Ready
MSR[2] <= #1 MSR[2] | (~RIb2 & RIbsync); // Trailing Edge of Ring Indicator
MSR[3] <= #1 MSR[3] | DCDb2 ^ DCDbsync; // Delta Data Carrier Detect
end
end end
always_comb always_comb
if (~MEMRb) if (~MEMRb)
@ -215,7 +222,8 @@ module uartPC16550D(
3'b011: Dout = LCR; 3'b011: Dout = LCR;
3'b100: Dout = {3'b000, MCR}; 3'b100: Dout = {3'b000, MCR};
3'b101: Dout = LSR; 3'b101: Dout = LSR;
3'b110: Dout = {~CTSbsync, ~DSRbsync, ~RIbsync, ~DCDbsync, MSR[3:0]}; // 3'b110: Dout = {~CTSbsync, ~DSRbsync, ~RIbsync, ~DCDbsync, MSR[3:0]};
3'b110: Dout = {~DCDbsync, ~RIbsync, ~DSRbsync, ~CTSbsync, MSR[3:0]};
3'b111: Dout = SCR; 3'b111: Dout = SCR;
endcase endcase
else Dout = 8'b0; else Dout = 8'b0;
@ -304,7 +312,7 @@ module uartPC16550D(
// ERROR CONDITIONS // ERROR CONDITIONS
assign rxparity = ^rxdata; assign rxparity = ^rxdata;
assign rxparityerr = rxparity ^ rxparitybit ^ ~evenparitysel; // Check even/odd parity (*** check if LCR needs to be inverted) assign rxparityerr = (rxparity ^ rxparitybit ^ ~evenparitysel) & LCR[3]; // Check even/odd parity (*** check if LCR needs to be inverted)
assign rxoverrunerr = fifoenabled ? (rxfifoentries == 15) : rxdataready; // overrun if FIFO or receive buffer register full assign rxoverrunerr = fifoenabled ? (rxfifoentries == 15) : rxdataready; // overrun if FIFO or receive buffer register full
assign rxframingerr = ~rxstopbit; // framing error if no stop bit assign rxframingerr = ~rxstopbit; // framing error if no stop bit
assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time assign rxbreak = rxframingerr & (rxdata9 == 9'b0); // break when 0 for start + data + parity + stop time
@ -405,7 +413,7 @@ module uartPC16550D(
txstate <= #1 UART_IDLE; txstate <= #1 UART_IDLE;
end end
assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s) assign txbitsexpected = 4'd1 + (4'd5 + {2'b00, LCR[1:0]}) + {3'b000, LCR[3]} + 4'd1 + {3'b000, LCR[2]} - 4'd1; // start bit + data bits + (parity bit) + stop bit(s) - 1
// *** explain; is this necessary? // *** explain; is this necessary?
if (`QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE if (`QEMU) assign txnextbit = txbaudpulse & (txoversampledcnt[1:0] == 2'b00); // implies txstate = UART_ACTIVE
else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE else assign txnextbit = txbaudpulse & (txoversampledcnt == 4'b0000); // implies txstate = UART_ACTIVE

View File

@ -1,4 +1,4 @@
all: exptestgen testgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen all: exptestgen testgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen modtestgen
sqrttestgen: sqrttestgen.c sqrttestgen: sqrttestgen.c
gcc sqrttestgen.c -o sqrttestgen -lm gcc sqrttestgen.c -o sqrttestgen -lm
@ -28,6 +28,10 @@ inttestgen: inttestgen.c
gcc -lm -o inttestgen inttestgen.c gcc -lm -o inttestgen inttestgen.c
./inttestgen ./inttestgen
modtestgen: modtestgen.c
gcc -lm -o modtestgen modtestgen.c
./modtestgen
clean: clean:
rm -f testgen exptestgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen rm -f testgen exptestgen qslc_r4a2 qslc_r4a2b qslc_sqrt_r4a2 sqrttestgen modtestgen

View File

@ -96,10 +96,6 @@ void output(FILE *fptr, int aSign, int aExp, double aFrac, int bSign, int bExp,
// Print r in standard double format // Print r in standard double format
fprintf(fptr, "%03x", rExp|(rSign<<11)); fprintf(fptr, "%03x", rExp|(rSign<<11));
printhex(fptr, rFrac); printhex(fptr, rFrac);
fprintf(fptr, "_");
// Spacing for testbench, value doesn't matter
fprintf(fptr, "%016x", 0);
fprintf(fptr, "\n"); fprintf(fptr, "\n");
} }

Binary file not shown.

View File

@ -1,9 +1,8 @@
/* testgen.c */ /* testgen.c */
/* Written 10/31/96 by David Harris /* Written 7/21/2022 by Cedar Turek
This program creates test vectors for mantissa component This program creates test vectors for integer divide.
of an IEEE floating point divider.
*/ */
/* #includes */ /* #includes */
@ -19,7 +18,7 @@
/* Prototypes */ /* Prototypes */
void output(FILE *fptr, long a, long b, long r, long rem); void output(FILE *fptr, long a, long b, long r);
void printhex(FILE *fptr, long x); void printhex(FILE *fptr, long x);
double random_input(void); double random_input(void);
@ -28,7 +27,7 @@ double random_input(void);
void main(void) void main(void)
{ {
FILE *fptr; FILE *fptr;
long a, b, r, rem; long a, b, r;
long list[ENTRIES] = {1, 3, 5, 18, 25, 33, 42, 65, 103, 255}; long list[ENTRIES] = {1, 3, 5, 18, 25, 33, 42, 65, 103, 255};
int i, j; int i, j;
@ -42,32 +41,22 @@ void main(void)
for (j=0; j<ENTRIES; j++) { for (j=0; j<ENTRIES; j++) {
a = list[j]; a = list[j];
r = a/b; r = a/b;
rem = a%b; output(fptr, a, b, r);
output(fptr, a, b, r, rem);
} }
} }
// for (i = 0; i< RANDOM_VECS; i++) {
// a = random_input();
// b = random_input();
// r = a/b;
// output(fptr, a, b, r);
// }
fclose(fptr); fclose(fptr);
} }
/* Functions */ /* Functions */
void output(FILE *fptr, long a, long b, long r, long rem) void output(FILE *fptr, long a, long b, long r)
{ {
printhex(fptr, a); printhex(fptr, a);
fprintf(fptr, "_"); fprintf(fptr, "_");
printhex(fptr, b); printhex(fptr, b);
fprintf(fptr, "_"); fprintf(fptr, "_");
printhex(fptr, r); printhex(fptr, r);
fprintf(fptr, "_");
printhex(fptr, rem);
fprintf(fptr, "\n"); fprintf(fptr, "\n");
} }

BIN
pipelined/srt/modtestgen Executable file

Binary file not shown.

View File

@ -0,0 +1,73 @@
/* testgen.c */
/* Written 7/21/2022 by Cedar Turek
This program creates test vectors for modulo
calculation from integer divide.
*/
/* #includes */
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
/* Constants */
#define ENTRIES 10
#define RANDOM_VECS 500
/* Prototypes */
void output(FILE *fptr, long a, long b, long rem);
void printhex(FILE *fptr, long x);
double random_input(void);
/* Main */
void main(void)
{
FILE *fptr;
long a, b, rem;
long list[ENTRIES] = {1, 3, 5, 18, 25, 33, 42, 65, 103, 255};
int i, j;
if ((fptr = fopen("modtestvectors","w")) == NULL) {
fprintf(stderr, "Couldn't write testvectors file\n");
exit(1);
}
for (i=0; i<ENTRIES; i++) {
b = list[i];
for (j=0; j<ENTRIES; j++) {
a = list[j];
rem = a%b;
output(fptr, a, b, rem);
}
}
fclose(fptr);
}
/* Functions */
void output(FILE *fptr, long a, long b, long rem)
{
printhex(fptr, a);
fprintf(fptr, "_");
printhex(fptr, b);
fprintf(fptr, "_");
printhex(fptr, rem);
fprintf(fptr, "\n");
}
void printhex(FILE *fptr, long m)
{
fprintf(fptr, "%016llx", m);
}
double random_input(void)
{
return 1.0 + rand()/32767.0;
}

Binary file not shown.

View File

@ -86,10 +86,6 @@ void output(FILE *fptr, int aExp, double aFrac, int rExp, double rFrac)
// Print r in standard double format // Print r in standard double format
fprintf(fptr, "%03x", rExp); fprintf(fptr, "%03x", rExp);
printhex(fptr, rFrac); printhex(fptr, rFrac);
fprintf(fptr, "_");
// Spacing for testbench, value doesn't matter
fprintf(fptr, "%016x", 0);
fprintf(fptr, "\n"); fprintf(fptr, "\n");
} }

View File

@ -2,4 +2,5 @@ add wave -noupdate /testbench/*
add wave -noupdate /testbench/srt/* add wave -noupdate /testbench/srt/*
add wave -noupdate /testbench/srt/sotfc2/* add wave -noupdate /testbench/srt/sotfc2/*
add wave -noupdate /testbench/srt/preproc/* add wave -noupdate /testbench/srt/preproc/*
add wave -noupdate /testbench/srt/postproc/*
add wave -noupdate /testbench/srt/divcounter/* add wave -noupdate /testbench/srt/divcounter/*

View File

@ -35,33 +35,36 @@ module srt (
input logic Start, input logic Start,
input logic Stall, // *** multiple pipe stages input logic Stall, // *** multiple pipe stages
input logic Flush, // *** multiple pipe stages input logic Flush, // *** multiple pipe stages
// Floating Point Inputs // Floating Point
// later add exponents, signs, special cases
input logic XSign, YSign, input logic XSign, YSign,
input logic [`NE-1:0] XExp, YExp, input logic [`NE-1:0] XExp, YExp,
input logic [`NF-1:0] SrcXFrac, SrcYFrac, input logic [`NF-1:0] SrcXFrac, SrcYFrac,
// Integer
input logic [`XLEN-1:0] SrcA, SrcB, input logic [`XLEN-1:0] SrcA, SrcB,
// Customization
input logic [1:0] Fmt, // Floats: 00 = 16 bit, 01 = 32 bit, 10 = 64 bit, 11 = 128 bit 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
// Selection
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 Mod, // perform remainder calculation (modulo) instead of divide
input logic Sqrt, // perform square root, not divide input logic Sqrt, // perform square root, not divide
output logic rsign, done, output logic rsign, done,
output logic [`DIVLEN-2:0] Rem, Quot, // *** later handle integers output logic [`DIVLEN-1:0] Result,
output logic [`NE-1:0] rExp, output logic [`NE-1:0] rExp,
output logic [3:0] Flags output logic [3:0] Flags
); );
logic qp, qz, qn; // quotient is +1, 0, or -1 logic qp, qz, qn; // result bits are +1, 0, or -1
logic [`NE-1:0] calcExp; logic [`NE-1:0] calcExp;
logic calcSign; logic calcSign;
logic [`DIVLEN+3:0] X, Dpreproc, C, F, S, SM, AddIn; logic [`DIVLEN+3:0] X, Dpreproc, C, F, S, SM, AddIn;
logic [`DIVLEN+3:0] WS, WSA, WSN, WC, WCA, WCN, D, Db, Dsel; logic [`DIVLEN+3:0] WS, WSA, WSN, WC, WCA, WCN, D, Db, Dsel;
logic [$clog2(`XLEN+1)-1:0] intExp, dur, calcDur; logic [$clog2(`XLEN+1)-1:0] zeroCntD, intExp, dur, calcDur;
logic intSign; logic intSign;
logic cin; logic cin;
srtpreproc preproc(SrcA, SrcB, SrcXFrac, SrcYFrac, XExp, Fmt, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, calcDur, intSign); srtpreproc preproc(SrcA, SrcB, SrcXFrac, SrcYFrac, XExp, Fmt, W64, Signed, Int, Mod, Sqrt, X, Dpreproc, zeroCntD, intExp, calcDur, 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.
@ -91,7 +94,7 @@ module srt (
// otfc2 #(`DIVLEN) otfc2(clk, Start, qp, qz, qn, Quot); // otfc2 #(`DIVLEN) otfc2(clk, Start, qp, qz, qn, Quot);
// otherwise use sotfc // otherwise use sotfc
creg sotfcC(clk, Start, Sqrt, C); creg sotfcC(clk, Start, Sqrt, C);
sotfc2 sotfc2(clk, Start, qp, qn, Sqrt, C, Quot, S, SM); sotfc2 sotfc2(clk, Start, qp, qn, Sqrt, C, S, SM);
fsel2 fsel(qp, qn, C, S, SM, F); fsel2 fsel(qp, qn, C, S, SM, F);
// Adder input selection // Adder input selection
@ -103,7 +106,7 @@ module srt (
expcalc expcalc(.XExp, .YExp, .calcExp, .Sqrt); expcalc expcalc(.XExp, .YExp, .calcExp, .Sqrt);
signcalc signcalc(.XSign, .YSign, .calcSign); srtpostproc postproc(.WS, .WC, .X, .D, .S, .SM, .dur, .zeroCntD, .XSign, .YSign, .Signed, .Int, .Mod, .Result, .calcSign);
endmodule endmodule
//////////////// ////////////////
@ -121,13 +124,14 @@ module srtpreproc (
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 Mod, // perform remainder calculation (modulo) instead of divide
input logic Sqrt, // perform square root, not divide input logic Sqrt, // perform square root, not divide
output logic [`DIVLEN+3:0] X, D, output logic [`DIVLEN+3:0] X, D,
output logic [$clog2(`XLEN+1)-1:0] intExp, dur, // Quotient integer exponent output logic [$clog2(`XLEN+1)-1:0] zeroCntB, intExp, dur, // Quotient integer exponent
output logic intSign // Quotient integer sign output logic intSign // Quotient integer sign
); );
logic [$clog2(`XLEN+1)-1:0] zeroCntA, zeroCntB; logic [$clog2(`XLEN+1)-1:0] zeroCntA;
logic [`XLEN-1:0] PosA, PosB; logic [`XLEN-1:0] PosA, PosB;
logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY, DivX; logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY, DivX;
logic [`NF+4:0] SqrtX; logic [`NF+4:0] SqrtX;
@ -159,7 +163,7 @@ module srtpreproc (
assign D = {4'b0001, Int ? PreprocB : PreprocY}; assign D = {4'b0001, Int ? PreprocB : PreprocY};
// Integer exponent and sign calculations // Integer exponent and sign calculations
assign intExp = zeroCntB - zeroCntA + 1; assign intExp = zeroCntB - zeroCntA - Mod + (PreprocA >= PreprocB);
assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]); assign intSign = Signed & (SrcA[`XLEN - 1] ^ SrcB[`XLEN - 1]);
// Number of cycles of divider // Number of cycles of divider
@ -235,7 +239,7 @@ module otfc2 #(parameter N=66) (
input logic clk, input logic clk,
input logic Start, input logic Start,
input logic qp, qz, qn, input logic qp, qz, qn,
output logic [N-3:0] r output logic [N-3:0] Result
); );
// The on-the-fly converter transfers the quotient // The on-the-fly converter transfers the quotient
// bits to the quotient as they come. // bits to the quotient as they come.
@ -261,7 +265,7 @@ module otfc2 #(parameter N=66) (
QMNext = {QMR, 1'b0}; QMNext = {QMR, 1'b0};
end end
end end
assign r = Q[N] ? Q[N-1:2] : Q[N-2:1]; assign Result = Q[N] ? Q[N-1:2] : Q[N-2:1];
endmodule endmodule
@ -274,7 +278,6 @@ module sotfc2(
input logic sp, sn, input logic sp, sn,
input logic Sqrt, input logic Sqrt,
input logic [`DIVLEN+3:0] C, input logic [`DIVLEN+3:0] C,
output logic [`DIVLEN-2:0] Sq,
output logic [`DIVLEN+3:0] S, SM output logic [`DIVLEN+3:0] S, SM
); );
// The on-the-fly converter transfers the square root // The on-the-fly converter transfers the square root
@ -298,7 +301,6 @@ module sotfc2(
SMNext = SM | (C & ~(C << 1)); SMNext = SM | (C & ~(C << 1));
end end
end end
assign Sq = S[`DIVLEN] ? S[`DIVLEN-1:1] : S[`DIVLEN-2:0];
endmodule endmodule
////////////////////////// //////////////////////////
@ -395,14 +397,76 @@ module expcalc(
endmodule endmodule
////////////// module srtpostproc(
// signcalc // input logic [`DIVLEN+3:0] WS, WC, X, D, S, SM,
////////////// input logic [$clog2(`XLEN+1)-1:0] dur, zeroCntD,
module signcalc( input logic XSign, YSign, Signed, Int, Mod,
input logic XSign, YSign, output logic [`DIVLEN-1:0] Result,
output logic calcSign output logic calcSign
); );
logic [`DIVLEN+3:0] W, shiftRem, intRem, intS;
logic [`DIVLEN-1:0] floatRes, intRes;
logic WSign;
assign W = WS + WC;
assign WSign = W[`DIVLEN+3];
// Remainder handling
always_comb begin
if (zeroCntD == ($clog2(`XLEN+1))'(`XLEN)) begin
intRem = X;
intS = -1;
end
else if (~Signed) begin
if (WSign) begin
intRem = W + D;
intS = SM;
end else begin
intRem = W;
intS = S;
end
end
else case ({YSign, XSign, WSign})
3'b000: begin
intRem = W;
intS = S;
end
3'b001: begin
intRem = W + D;
intS = SM;
end
3'b010: begin
intRem = W - D;
intS = ~S;
end
3'b011: begin
intRem = W;
intS = ~SM;
end
3'b100: begin
intRem = W;
intS = ~SM;
end
3'b101: begin
intRem = W + D;
intS = ~SM + 1;
end
3'b110: begin
intRem = W - D;
intS = S + 1;
end
3'b111: begin
intRem = W;
intS = S;
end
endcase
end
assign floatRes = S[`DIVLEN] ? S[`DIVLEN:1] : S[`DIVLEN-1:0];
assign intRes = intS[`DIVLEN] ? intS[`DIVLEN:1] : intS[`DIVLEN-1:0];
assign shiftRem = (intRem >>> (`DIVLEN - dur + 2));
always_comb
if (Int) Result = intRes >> (`DIVLEN - dur);
else if (Mod) Result = shiftRem[`DIVLEN-1:0];
else Result = floatRes;
assign calcSign = XSign ^ YSign; assign calcSign = XSign ^ YSign;
endmodule
endmodule

View File

@ -42,24 +42,23 @@ module testbench;
logic clk; logic clk;
logic req; logic req;
logic done; logic done;
logic Int; logic Int, Sqrt, Mod;
logic [`XLEN-1:0] a, b; logic [`XLEN-1:0] a, b;
logic [`NF-1:0] afrac, bfrac; logic [`NF-1:0] afrac, bfrac;
logic [`NE-1:0] aExp, bExp; logic [`NE-1:0] aExp, bExp;
logic asign, bsign; logic asign, bsign;
logic [`NF-1:0] r; logic [`NF-1:0] r;
logic [`XLEN-1:0] rInt; logic [`XLEN-1:0] rInt;
logic [`DIVLEN-2:0] Quot; logic [`DIVLEN-1:0] Quot;
// Test parameters // Test parameters
parameter MEM_SIZE = 40000; parameter MEM_SIZE = 40000;
parameter MEM_WIDTH = 64+64+64+64; parameter MEM_WIDTH = 64+64+64+64;
// Test sizes // Test sizes
`define memrem 63:0 `define memr 63:0
`define memr 127:64 `define memb 127:64
`define memb 191:128 `define mema 191:128
`define mema 255:192
// Test logicisters // Test logicisters
logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file
@ -70,8 +69,9 @@ module testbench;
logic rsign; logic rsign;
integer testnum, errors; integer testnum, errors;
// Equip Int test or Sqrt test // Equip Int, Sqrt, or IntMod test
assign Int = 1'b0; assign Int = 1'b1;
assign Mod = 1'b0;
assign Sqrt = 1'b0; assign Sqrt = 1'b0;
// Divider // Divider
@ -81,8 +81,8 @@ module testbench;
.XSign(asign), .YSign(bsign), .rsign, .XSign(asign), .YSign(bsign), .rsign,
.SrcXFrac(afrac), .SrcYFrac(bfrac), .SrcXFrac(afrac), .SrcYFrac(bfrac),
.SrcA(a), .SrcB(b), .Fmt(2'b00), .SrcA(a), .SrcB(b), .Fmt(2'b00),
.W64(1'b1), .Signed(1'b0), .Int, .Sqrt, .W64(1'b1), .Signed(1'b0), .Int, .Mod, .Sqrt,
.Quot, .Rem(), .Flags(), .done); .Result(Quot), .Flags(), .done);
// Counter // Counter
// counter counter(clk, req, done); // counter counter(clk, req, done);
@ -101,7 +101,7 @@ module testbench;
begin begin
testnum = 0; testnum = 0;
errors = 0; errors = 0;
$readmemh ("testvectors", Tests); $readmemh ("inttestvectors", Tests);
Vec = Tests[testnum]; Vec = Tests[testnum];
a = Vec[`mema]; a = Vec[`mema];
{asign, aExp, afrac} = a; {asign, aExp, afrac} = a;
@ -109,7 +109,7 @@ module testbench;
{bsign, bExp, bfrac} = b; {bsign, bExp, bfrac} = b;
nextr = Vec[`memr]; nextr = Vec[`memr];
r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)]; r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)];
rInt = {1'b1, Quot}; rInt = Quot;
req <= #5 1; req <= #5 1;
end end
@ -117,9 +117,9 @@ module testbench;
always @(posedge clk) begin always @(posedge clk) begin
r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)]; r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)];
rInt = {1'b1, Quot}; rInt = Quot;
if (done) begin if (done) begin
if (~Int & ~Sqrt) begin if (~Int & ~Sqrt) begin // This test case checks floating point division
req <= #5 1; req <= #5 1;
diffp = correctr[51:0] - r; diffp = correctr[51:0] - r;
diffn = r - correctr[51:0]; diffn = r - correctr[51:0];
@ -135,23 +135,21 @@ module testbench;
$display("%d Tests completed successfully", testnum); $display("%d Tests completed successfully", testnum);
$stop; $stop;
end end
end else if (~Sqrt) begin end else if (~Sqrt) begin // This test case works for both integer divide and integer modulo
req <= #5 1; req <= #5 1;
diffp = correctr[63:0] - rInt; diffp = correctr[63:0] - rInt;
diffn = rInt - correctr[63:0]; if (($signed(diffp) != 0) | (diffp === 64'bx)) // check if accurate to 1 ulp
if (($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, should be %h %h %h\n", rInt, correctr, diffn, diffp); $display("result was %h, should be %h %h\n", rInt, correctr, diffp);
$display("failed\n"); $display("failed\n");
$stop;
end end
if (afrac === 52'hxxxxxxxxxxxxx) if (afrac === 52'hxxxxxxxxxxxxx)
begin begin
$display("%d Tests completed successfully", testnum); $display("%d Tests completed successfully", testnum - errors);
$stop; $stop;
end end
end else begin end else begin // This test case verifies square root
req <= #5 1; req <= #5 1;
diffp = correctr[51:0] - r; diffp = correctr[51:0] - r;
diffn = r - correctr[51:0]; diffn = r - correctr[51:0];