mirror of
https://github.com/openhwgroup/cvw
synced 2025-02-11 06:05:49 +00:00
Merge branch 'main' of https://github.com/davidharrishmc/riscv-wally into main
This commit is contained in:
commit
f1578936b8
@ -165,6 +165,7 @@ module uartPC16550D(
|
||||
SCR <= #1 8'b0; // not strictly necessary to reset
|
||||
end else begin
|
||||
if (~MEMWb) begin
|
||||
/* verilator lint_off CASEINCOMPLETE */
|
||||
case (A)
|
||||
/* -----\/----- EXCLUDED -----\/-----
|
||||
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
|
||||
//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'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'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'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;
|
||||
endcase
|
||||
/* verilator lint_on CASEINCOMPLETE */
|
||||
end
|
||||
|
||||
|
||||
// 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.
|
||||
LSR[0] <= #1 rxdataready; // Data ready
|
||||
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
||||
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
||||
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing 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
|
||||
// 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.
|
||||
if (~MEMWb & (A == 3'b101))
|
||||
LSR[6:1] <= #1 Din[6:1]; // recommended only for test, see 8.6.3
|
||||
else begin
|
||||
LSR[0] <= #1 rxdataready; // Data ready
|
||||
LSR[1] <= #1 (LSR[1] | RXBR[10]) & ~squashRXerrIP;; // overrun error
|
||||
LSR[2] <= #1 (LSR[2] | RXBR[9]) & ~squashRXerrIP; // parity error
|
||||
LSR[3] <= #1 (LSR[3] | RXBR[8]) & ~squashRXerrIP; // framing 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)
|
||||
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
|
||||
if (~MEMWb & (A == 3'b110))
|
||||
MSR <= #1 Din[3:0];
|
||||
else begin
|
||||
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
|
||||
always_comb
|
||||
if (~MEMRb)
|
||||
@ -215,7 +222,8 @@ module uartPC16550D(
|
||||
3'b011: Dout = LCR;
|
||||
3'b100: Dout = {3'b000, MCR};
|
||||
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;
|
||||
endcase
|
||||
else Dout = 8'b0;
|
||||
@ -304,7 +312,7 @@ module uartPC16550D(
|
||||
|
||||
// ERROR CONDITIONS
|
||||
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 rxframingerr = ~rxstopbit; // framing error if no stop bit
|
||||
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;
|
||||
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?
|
||||
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
|
||||
|
@ -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
|
||||
gcc sqrttestgen.c -o sqrttestgen -lm
|
||||
@ -28,6 +28,10 @@ inttestgen: inttestgen.c
|
||||
gcc -lm -o inttestgen inttestgen.c
|
||||
./inttestgen
|
||||
|
||||
modtestgen: modtestgen.c
|
||||
gcc -lm -o modtestgen modtestgen.c
|
||||
./modtestgen
|
||||
|
||||
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
|
||||
|
||||
|
@ -96,10 +96,6 @@ void output(FILE *fptr, int aSign, int aExp, double aFrac, int bSign, int bExp,
|
||||
// Print r in standard double format
|
||||
fprintf(fptr, "%03x", rExp|(rSign<<11));
|
||||
printhex(fptr, rFrac);
|
||||
fprintf(fptr, "_");
|
||||
|
||||
// Spacing for testbench, value doesn't matter
|
||||
fprintf(fptr, "%016x", 0);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
|
Binary file not shown.
@ -1,9 +1,8 @@
|
||||
/* testgen.c */
|
||||
|
||||
/* Written 10/31/96 by David Harris
|
||||
/* Written 7/21/2022 by Cedar Turek
|
||||
|
||||
This program creates test vectors for mantissa component
|
||||
of an IEEE floating point divider.
|
||||
This program creates test vectors for integer divide.
|
||||
*/
|
||||
|
||||
/* #includes */
|
||||
@ -19,7 +18,7 @@
|
||||
|
||||
/* 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);
|
||||
double random_input(void);
|
||||
|
||||
@ -28,7 +27,7 @@ double random_input(void);
|
||||
void main(void)
|
||||
{
|
||||
FILE *fptr;
|
||||
long a, b, r, rem;
|
||||
long a, b, r;
|
||||
long list[ENTRIES] = {1, 3, 5, 18, 25, 33, 42, 65, 103, 255};
|
||||
int i, j;
|
||||
|
||||
@ -42,32 +41,22 @@ void main(void)
|
||||
for (j=0; j<ENTRIES; j++) {
|
||||
a = list[j];
|
||||
r = a/b;
|
||||
rem = a%b;
|
||||
output(fptr, a, b, r, rem);
|
||||
output(fptr, a, b, r);
|
||||
}
|
||||
}
|
||||
|
||||
// for (i = 0; i< RANDOM_VECS; i++) {
|
||||
// a = random_input();
|
||||
// b = random_input();
|
||||
// r = a/b;
|
||||
// output(fptr, a, b, r);
|
||||
// }
|
||||
|
||||
fclose(fptr);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, b);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, r);
|
||||
fprintf(fptr, "_");
|
||||
printhex(fptr, rem);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
|
BIN
pipelined/srt/modtestgen
Executable file
BIN
pipelined/srt/modtestgen
Executable file
Binary file not shown.
73
pipelined/srt/modtestgen.c
Normal file
73
pipelined/srt/modtestgen.c
Normal 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.
@ -86,10 +86,6 @@ void output(FILE *fptr, int aExp, double aFrac, int rExp, double rFrac)
|
||||
// Print r in standard double format
|
||||
fprintf(fptr, "%03x", rExp);
|
||||
printhex(fptr, rFrac);
|
||||
fprintf(fptr, "_");
|
||||
|
||||
// Spacing for testbench, value doesn't matter
|
||||
fprintf(fptr, "%016x", 0);
|
||||
fprintf(fptr, "\n");
|
||||
}
|
||||
|
||||
|
@ -2,4 +2,5 @@ add wave -noupdate /testbench/*
|
||||
add wave -noupdate /testbench/srt/*
|
||||
add wave -noupdate /testbench/srt/sotfc2/*
|
||||
add wave -noupdate /testbench/srt/preproc/*
|
||||
add wave -noupdate /testbench/srt/postproc/*
|
||||
add wave -noupdate /testbench/srt/divcounter/*
|
||||
|
@ -35,33 +35,36 @@ module srt (
|
||||
input logic Start,
|
||||
input logic Stall, // *** multiple pipe stages
|
||||
input logic Flush, // *** multiple pipe stages
|
||||
// Floating Point Inputs
|
||||
// later add exponents, signs, special cases
|
||||
// Floating Point
|
||||
input logic XSign, YSign,
|
||||
input logic [`NE-1:0] XExp, YExp,
|
||||
input logic [`NF-1:0] SrcXFrac, SrcYFrac,
|
||||
// Integer
|
||||
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 W64, // 32-bit ints on XLEN=64
|
||||
// Selection
|
||||
input logic Signed, // Interpret integers as signed 2's complement
|
||||
input logic Int, // Choose integer inputs
|
||||
input logic Mod, // perform remainder calculation (modulo) instead of divide
|
||||
input logic Sqrt, // perform square root, not divide
|
||||
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 [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 calcSign;
|
||||
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 [$clog2(`XLEN+1)-1:0] intExp, dur, calcDur;
|
||||
logic [$clog2(`XLEN+1)-1:0] zeroCntD, intExp, dur, calcDur;
|
||||
logic intSign;
|
||||
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
|
||||
// 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);
|
||||
// otherwise use sotfc
|
||||
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);
|
||||
|
||||
// Adder input selection
|
||||
@ -103,7 +106,7 @@ module srt (
|
||||
|
||||
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
|
||||
|
||||
////////////////
|
||||
@ -121,13 +124,14 @@ module srtpreproc (
|
||||
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 Mod, // perform remainder calculation (modulo) instead of divide
|
||||
input logic Sqrt, // perform square root, not divide
|
||||
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
|
||||
);
|
||||
|
||||
logic [$clog2(`XLEN+1)-1:0] zeroCntA, zeroCntB;
|
||||
logic [$clog2(`XLEN+1)-1:0] zeroCntA;
|
||||
logic [`XLEN-1:0] PosA, PosB;
|
||||
logic [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY, DivX;
|
||||
logic [`NF+4:0] SqrtX;
|
||||
@ -159,7 +163,7 @@ module srtpreproc (
|
||||
assign D = {4'b0001, Int ? PreprocB : PreprocY};
|
||||
|
||||
// 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]);
|
||||
|
||||
// Number of cycles of divider
|
||||
@ -235,7 +239,7 @@ module otfc2 #(parameter N=66) (
|
||||
input logic clk,
|
||||
input logic Start,
|
||||
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
|
||||
// bits to the quotient as they come.
|
||||
@ -261,7 +265,7 @@ module otfc2 #(parameter N=66) (
|
||||
QMNext = {QMR, 1'b0};
|
||||
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
|
||||
|
||||
@ -274,7 +278,6 @@ module sotfc2(
|
||||
input logic sp, sn,
|
||||
input logic Sqrt,
|
||||
input logic [`DIVLEN+3:0] C,
|
||||
output logic [`DIVLEN-2:0] Sq,
|
||||
output logic [`DIVLEN+3:0] S, SM
|
||||
);
|
||||
// The on-the-fly converter transfers the square root
|
||||
@ -298,7 +301,6 @@ module sotfc2(
|
||||
SMNext = SM | (C & ~(C << 1));
|
||||
end
|
||||
end
|
||||
assign Sq = S[`DIVLEN] ? S[`DIVLEN-1:1] : S[`DIVLEN-2:0];
|
||||
endmodule
|
||||
|
||||
//////////////////////////
|
||||
@ -395,14 +397,76 @@ module expcalc(
|
||||
|
||||
endmodule
|
||||
|
||||
//////////////
|
||||
// signcalc //
|
||||
//////////////
|
||||
module signcalc(
|
||||
input logic XSign, YSign,
|
||||
module srtpostproc(
|
||||
input logic [`DIVLEN+3:0] WS, WC, X, D, S, SM,
|
||||
input logic [$clog2(`XLEN+1)-1:0] dur, zeroCntD,
|
||||
input logic XSign, YSign, Signed, Int, Mod,
|
||||
output logic [`DIVLEN-1:0] Result,
|
||||
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;
|
||||
endmodule
|
||||
|
||||
endmodule
|
@ -42,24 +42,23 @@ module testbench;
|
||||
logic clk;
|
||||
logic req;
|
||||
logic done;
|
||||
logic Int;
|
||||
logic Int, Sqrt, Mod;
|
||||
logic [`XLEN-1:0] a, b;
|
||||
logic [`NF-1:0] afrac, bfrac;
|
||||
logic [`NE-1:0] aExp, bExp;
|
||||
logic asign, bsign;
|
||||
logic [`NF-1:0] r;
|
||||
logic [`XLEN-1:0] rInt;
|
||||
logic [`DIVLEN-2:0] Quot;
|
||||
logic [`DIVLEN-1:0] Quot;
|
||||
|
||||
// Test parameters
|
||||
parameter MEM_SIZE = 40000;
|
||||
parameter MEM_WIDTH = 64+64+64+64;
|
||||
|
||||
// Test sizes
|
||||
`define memrem 63:0
|
||||
`define memr 127:64
|
||||
`define memb 191:128
|
||||
`define mema 255:192
|
||||
`define memr 63:0
|
||||
`define memb 127:64
|
||||
`define mema 191:128
|
||||
|
||||
// Test logicisters
|
||||
logic [MEM_WIDTH-1:0] Tests [0:MEM_SIZE]; // Space for input file
|
||||
@ -70,8 +69,9 @@ module testbench;
|
||||
logic rsign;
|
||||
integer testnum, errors;
|
||||
|
||||
// Equip Int test or Sqrt test
|
||||
assign Int = 1'b0;
|
||||
// Equip Int, Sqrt, or IntMod test
|
||||
assign Int = 1'b1;
|
||||
assign Mod = 1'b0;
|
||||
assign Sqrt = 1'b0;
|
||||
|
||||
// Divider
|
||||
@ -81,8 +81,8 @@ module testbench;
|
||||
.XSign(asign), .YSign(bsign), .rsign,
|
||||
.SrcXFrac(afrac), .SrcYFrac(bfrac),
|
||||
.SrcA(a), .SrcB(b), .Fmt(2'b00),
|
||||
.W64(1'b1), .Signed(1'b0), .Int, .Sqrt,
|
||||
.Quot, .Rem(), .Flags(), .done);
|
||||
.W64(1'b1), .Signed(1'b0), .Int, .Mod, .Sqrt,
|
||||
.Result(Quot), .Flags(), .done);
|
||||
|
||||
// Counter
|
||||
// counter counter(clk, req, done);
|
||||
@ -101,7 +101,7 @@ module testbench;
|
||||
begin
|
||||
testnum = 0;
|
||||
errors = 0;
|
||||
$readmemh ("testvectors", Tests);
|
||||
$readmemh ("inttestvectors", Tests);
|
||||
Vec = Tests[testnum];
|
||||
a = Vec[`mema];
|
||||
{asign, aExp, afrac} = a;
|
||||
@ -109,7 +109,7 @@ module testbench;
|
||||
{bsign, bExp, bfrac} = b;
|
||||
nextr = Vec[`memr];
|
||||
r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)];
|
||||
rInt = {1'b1, Quot};
|
||||
rInt = Quot;
|
||||
req <= #5 1;
|
||||
end
|
||||
|
||||
@ -117,9 +117,9 @@ module testbench;
|
||||
|
||||
always @(posedge clk) begin
|
||||
r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)];
|
||||
rInt = {1'b1, Quot};
|
||||
rInt = Quot;
|
||||
if (done) begin
|
||||
if (~Int & ~Sqrt) begin
|
||||
if (~Int & ~Sqrt) begin // This test case checks floating point division
|
||||
req <= #5 1;
|
||||
diffp = correctr[51:0] - r;
|
||||
diffn = r - correctr[51:0];
|
||||
@ -135,23 +135,21 @@ module testbench;
|
||||
$display("%d Tests completed successfully", testnum);
|
||||
$stop;
|
||||
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;
|
||||
diffp = correctr[63:0] - rInt;
|
||||
diffn = rInt - correctr[63:0];
|
||||
if (($signed(diffn) > 1) | ($signed(diffp) > 1) | (diffn === 64'bx) | (diffp === 64'bx)) // check if accurate to 1 ulp
|
||||
if (($signed(diffp) != 0) | (diffp === 64'bx)) // check if accurate to 1 ulp
|
||||
begin
|
||||
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");
|
||||
$stop;
|
||||
end
|
||||
if (afrac === 52'hxxxxxxxxxxxxx)
|
||||
begin
|
||||
$display("%d Tests completed successfully", testnum);
|
||||
$display("%d Tests completed successfully", testnum - errors);
|
||||
$stop;
|
||||
end
|
||||
end else begin
|
||||
end else begin // This test case verifies square root
|
||||
req <= #5 1;
|
||||
diffp = correctr[51:0] - r;
|
||||
diffn = r - correctr[51:0];
|
||||
|
Loading…
Reference in New Issue
Block a user