From abe1ff906eb9d7ba7bcc67a2b4171d94a2930569 Mon Sep 17 00:00:00 2001 From: cturek Date: Thu, 21 Jul 2022 20:45:08 +0000 Subject: [PATCH 1/3] Renamed variables, moved output handling to postprocessor, added remainder handling --- pipelined/srt/sqrttestgen | Bin 22792 -> 22792 bytes pipelined/srt/srt.sv | 100 +++++++++++++++++++++++++++++-------- pipelined/srt/testbench.sv | 10 ++-- 3 files changed, 85 insertions(+), 25 deletions(-) diff --git a/pipelined/srt/sqrttestgen b/pipelined/srt/sqrttestgen index 06615165395cb6abb37c9d60152d5fe70f15e11a..d2cb80d445718cfa8efc5daa24fefc6b5d462149 100755 GIT binary patch delta 695 zcmXxiO=uHA6ae6PsoR()?atZ;R#1#kNU;Y?6~!LxR$N>x6e;8qJj5P~^8llk64tG4?8ZfL&qtv#acVY(I2f8`~B(tn-8&JVB^% zLv8Hs>7 zZo0!)K%q3#VTtNPnpg^0EzqcJH-al(U&QYCp+v(e(*50h`-IMcWAT14@lJdYhTV_x zS%6{8wr4@O&)OwKzBjPkaU>cP3sJ|YK8;uPk)hllrHb?=Rafc)P0_QC=V$eJPOpa(G7U#@UhaWGd`dBa z?w9-@{Yv3#VQdkGFkP@FH8_nI?P>7bbvv)a aS)9o1k8M?W_#ksQW=gABWV&B6>6T65Z3JZi delta 715 zcmXw%L1+^}6o%(DjY&w8oduP8uw6xMwP1rvN=3~IUEPx+nj*a^9-sd^$XE8 z%=wj`)&Wn)BW^HXVD^~LF|RS7VgACLXWn2w%G_c;#N6rWN_gN9FZi6Wn_1}SLRsb{ z^A2Xo+~WrfGXG_^n13^mGXG@G=_^_{9bdfQR-KOf=zd4s9d#ea z7j{{~t$uuefO@(LB=rYD;!8@b2iTgYS<~4HTHbzxRyv>jG3NMPk2NOma_G8&7p1r!Mb&bjm`dZJDyX14^J@N+m zFrBzTKJZU#L3daux5$&!L!0~_X5`r6S5#%3vcyzEO0pb{541)N3?q2Z6pa0u{$5Y!oJbYc8NLkVjH(Ba?aU}L1h0y`7 diff --git a/pipelined/srt/srt.sv b/pipelined/srt/srt.sv index a7216b9ff..7cbcd0daa 100644 --- a/pipelined/srt/srt.sv +++ b/pipelined/srt/srt.sv @@ -35,33 +35,35 @@ 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 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] Rem, 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, Sqrt, X, Dpreproc, zeroCntD, intExp, calcDur, intSign); // Top Muxes and Registers // When start is asserted, the inputs are loaded into the divider. @@ -91,7 +93,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 +105,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, .Result, .Rem, .calcSign); endmodule //////////////// @@ -123,11 +125,11 @@ module srtpreproc ( input logic Int, // Choose integer inputs 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; @@ -235,7 +237,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 +263,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 +276,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 +299,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 +395,74 @@ 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, + output logic [`DIVLEN-1:0] Result, Rem, 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 Result = Int ? intRes : floatRes; assign calcSign = XSign ^ YSign; + assign shiftRem = intRem >>> dur; + assign Rem = shiftRem[`DIVLEN-1:0]; +endmodule -endmodule \ No newline at end of file diff --git a/pipelined/srt/testbench.sv b/pipelined/srt/testbench.sv index 7a4e1897b..b72ffb42e 100644 --- a/pipelined/srt/testbench.sv +++ b/pipelined/srt/testbench.sv @@ -49,7 +49,7 @@ module testbench; logic asign, bsign; logic [`NF-1:0] r; logic [`XLEN-1:0] rInt; - logic [`DIVLEN-2:0] Quot; + logic [`DIVLEN-1:0] Quot, Rem; // Test parameters parameter MEM_SIZE = 40000; @@ -72,7 +72,7 @@ module testbench; // Equip Int test or Sqrt test assign Int = 1'b0; - assign Sqrt = 1'b0; + assign Sqrt = 1'b1; // Divider srt srt(.clk, .Start(req), @@ -82,7 +82,7 @@ module testbench; .SrcXFrac(afrac), .SrcYFrac(bfrac), .SrcA(a), .SrcB(b), .Fmt(2'b00), .W64(1'b1), .Signed(1'b0), .Int, .Sqrt, - .Quot, .Rem(), .Flags(), .done); + .Result(Quot), .Rem, .Flags(), .done); // Counter // counter counter(clk, req, done); @@ -101,7 +101,7 @@ module testbench; begin testnum = 0; errors = 0; - $readmemh ("testvectors", Tests); + $readmemh ("sqrttestvectors", Tests); Vec = Tests[testnum]; a = Vec[`mema]; {asign, aExp, afrac} = a; @@ -117,7 +117,7 @@ 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 req <= #5 1; From c170a8d9b6f7506dfa805333b76e936bb95b3dd8 Mon Sep 17 00:00:00 2001 From: cturek Date: Fri, 22 Jul 2022 01:27:08 +0000 Subject: [PATCH 2/3] Changed testbench to operate on two inputs and one output, changed all test generators, changed srt module to return only one output and take in Mod as a signal to compute integer remainder --- pipelined/srt/Makefile | 8 +++- pipelined/srt/exptestgen.c | 4 -- pipelined/srt/inttestgen | Bin 18496 -> 18496 bytes pipelined/srt/inttestgen.c | 23 +++--------- pipelined/srt/modtestgen | Bin 0 -> 18496 bytes pipelined/srt/modtestgen.c | 73 ++++++++++++++++++++++++++++++++++++ pipelined/srt/sqrttestgen | Bin 22792 -> 22792 bytes pipelined/srt/sqrttestgen.c | 4 -- pipelined/srt/srt-waves.do | 1 + pipelined/srt/srt.sv | 22 ++++++----- pipelined/srt/testbench.sv | 40 ++++++++++---------- 11 files changed, 118 insertions(+), 57 deletions(-) create mode 100755 pipelined/srt/modtestgen create mode 100644 pipelined/srt/modtestgen.c diff --git a/pipelined/srt/Makefile b/pipelined/srt/Makefile index 5d7898b17..ee249139d 100644 --- a/pipelined/srt/Makefile +++ b/pipelined/srt/Makefile @@ -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 diff --git a/pipelined/srt/exptestgen.c b/pipelined/srt/exptestgen.c index d6bebb774..61fe74aa4 100644 --- a/pipelined/srt/exptestgen.c +++ b/pipelined/srt/exptestgen.c @@ -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"); } diff --git a/pipelined/srt/inttestgen b/pipelined/srt/inttestgen index 2f7e6819945a6b827154fdc1c264eb7d77a29312..9e65cf4a031da28d084759b76e92bd9fd7e4bfc3 100755 GIT binary patch delta 1043 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 +#include +#include + +/* 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; iS@dfGW*6;)pR$3B;vl1Fb|V94`HlJm(ND)e8+rKp=J)G)=H#`G zo$YJs~8&&+{Z~M0Ng7L0i#%Qq~qfYzlY>gQ41$-}chVq=T zq|&7q(!bnZkC(0&@FDL6RSvFy(8XB#MqXbPE8b4py~X3OOK#$W@QmC!IP>3()tGTy zU#%K{W3~JEhcj2NB#fzB#e?=fI_AZy60TQLhH^9R#6{1(0h!4S(+T8No zKbDmfz5D9aw_JU4wd+gC>tk#)hCUZ@xT-eubLNWbl_3=f!<|NhN6np0(?Nd}uSb*^ zEOqz!=VV8%X5*vZ@-+tG&mEmor89_AV61af9bOeOe?fFl#2=&n9k8_b0Vwc#^YuNuIgcWPZiV$?9oks=4%yl0;bs9=R!o<+&CTav zdtZpR!v4NxY`4Ti4VBGQX7DO(xnvfEr{Xx$9Ep25-wiM8X`X=CJ%!ea2~t>#*{4*V;Wt gp(WAd@1DC%W^pcCgdNmOX4+bBa z^Pvh2ZG|+3GoKplgIZ0)A5A3P2OCMaBQ?D?P1D0PrP`QY+BCU}B*;roq+P$+{lGfO z&g}1-Z)SF9Cp&ze51;4pv?uCiR*8P{Yr>mUY$TPSb(4fie!FDvM_+cGY5Z<$-^8uW zFD?FZbn4yJo5q;qkgFhA9AtWGE)9>}3j=ptjIAi%lR?uoR}|H?K-S6E$(`gBIYLg5 zqvRjSN60^r`^n?v_igvNzOn<_pjiD3VOZcZLR=tD7!x>6_*&o;VM5?IVOroA;etR6 zW<7y{*X_{B>#V;Rhqz0ULjYK{~%YB?~-?+Q(Df;^!|#O8 zi;nVhAW7wX9BQQsJ_QG)n(lMrkc^}*h!d4vTD5jd%jl=I97eO^pxO7A5^su(8O#uY zpAc+z>dC>=)TNJHN)(FRQTRrx+c(1*>rooCOzhs`Q}}_j3|4ZzL+sa~IXse9K+9l` z%ZJg}?Uc4AW?$^Fva?;F$QAq`?3C*cPCvQeZ-1NSkhbO=`e3c`!%yQ^E{64y``Li? z4z)?K3ZqqelR;-?Kw9EO9tmH0WY%7Mo$4i1qbsL{C zuBdJqmdkan8_!gXmU?vD4pBN`zOmhtmThT9`QEF1gH7;PQ=PQl*@Q!2ux?8+ZVh8X zqG(pmhD1*P(>ILn<`elIZ6jyCam)V&)hz)}C-sM6zI8KXc!_bW<$2C^WNDtlBG~$P z5_quG>1BS^a0GYe@igpi_i+slv@hU&RmfMizPR-~SaCey%ptQTcqN3HMsLW?c{jYL z#c;9*S_2P4S;xzK33@wPak0scL|K%cWPOV5`HXp)c!cBoeYngQ`$x-eNI|RnIwi$0 yXA_gzw?>;jF7dbF!D|g0`>I1#xY-k-X(MnL_21w3Y`D45uiDe$d)*Ch&-)idgXL=g diff --git a/pipelined/srt/sqrttestgen.c b/pipelined/srt/sqrttestgen.c index 76c6a6649..7a45449fd 100644 --- a/pipelined/srt/sqrttestgen.c +++ b/pipelined/srt/sqrttestgen.c @@ -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"); } diff --git a/pipelined/srt/srt-waves.do b/pipelined/srt/srt-waves.do index 1e0c3f281..2fbf40c18 100644 --- a/pipelined/srt/srt-waves.do +++ b/pipelined/srt/srt-waves.do @@ -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/* diff --git a/pipelined/srt/srt.sv b/pipelined/srt/srt.sv index 7cbcd0daa..1b61bc14f 100644 --- a/pipelined/srt/srt.sv +++ b/pipelined/srt/srt.sv @@ -47,9 +47,10 @@ module srt ( // 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-1:0] Rem, Result, + output logic [`DIVLEN-1:0] Result, output logic [`NE-1:0] rExp, output logic [3:0] Flags ); @@ -63,7 +64,7 @@ module srt ( logic intSign; logic cin; - srtpreproc preproc(SrcA, SrcB, SrcXFrac, SrcYFrac, XExp, Fmt, W64, Signed, Int, Sqrt, X, Dpreproc, zeroCntD, 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. @@ -105,7 +106,7 @@ module srt ( expcalc expcalc(.XExp, .YExp, .calcExp, .Sqrt); - srtpostproc postproc(.WS, .WC, .X, .D, .S, .SM, .dur, .zeroCntD, .XSign, .YSign, .Signed, .Int, .Result, .Rem, .calcSign); + srtpostproc postproc(.WS, .WC, .X, .D, .S, .SM, .dur, .zeroCntD, .XSign, .YSign, .Signed, .Int, .Mod, .Result, .calcSign); endmodule //////////////// @@ -123,6 +124,7 @@ 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] zeroCntB, intExp, dur, // Quotient integer exponent @@ -161,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 @@ -398,8 +400,8 @@ endmodule 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, - output logic [`DIVLEN-1:0] Result, Rem, + input logic XSign, YSign, Signed, Int, Mod, + output logic [`DIVLEN-1:0] Result, output logic calcSign ); logic [`DIVLEN+3:0] W, shiftRem, intRem, intS; @@ -460,9 +462,11 @@ module srtpostproc( end assign floatRes = S[`DIVLEN] ? S[`DIVLEN:1] : S[`DIVLEN-1:0]; assign intRes = intS[`DIVLEN] ? intS[`DIVLEN:1] : intS[`DIVLEN-1:0]; - assign Result = Int ? intRes : floatRes; + 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 shiftRem = intRem >>> dur; - assign Rem = shiftRem[`DIVLEN-1:0]; endmodule diff --git a/pipelined/srt/testbench.sv b/pipelined/srt/testbench.sv index b72ffb42e..513305b26 100644 --- a/pipelined/srt/testbench.sv +++ b/pipelined/srt/testbench.sv @@ -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-1:0] Quot, Rem; + 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,9 +69,10 @@ module testbench; logic rsign; integer testnum, errors; - // Equip Int test or Sqrt test - assign Int = 1'b0; - assign Sqrt = 1'b1; + // Equip Int, Sqrt, or IntMod test + assign Int = 1'b1; + assign Mod = 1'b0; + assign Sqrt = 1'b0; // Divider srt srt(.clk, .Start(req), @@ -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, - .Result(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 ("sqrttestvectors", 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 @@ -119,7 +119,7 @@ module testbench; r = Quot[(`DIVLEN - 2):(`DIVLEN - `NF - 1)]; 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]; From bfa500234d9041dd52b872b8d53fcf324f48eb3b Mon Sep 17 00:00:00 2001 From: slmnemo Date: Thu, 21 Jul 2022 20:35:46 -0700 Subject: [PATCH 3/3] Fixed UART bug related to parity and MSR/LSR --- pipelined/src/uncore/uartPC16550D.sv | 50 ++++++++++++++++------------ 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/pipelined/src/uncore/uartPC16550D.sv b/pipelined/src/uncore/uartPC16550D.sv index 524a63454..89bdc837d 100644 --- a/pipelined/src/uncore/uartPC16550D.sv +++ b/pipelined/src/uncore/uartPC16550D.sv @@ -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