forked from Github_Repos/cvw
		
	radix-4 divider passing tests
This commit is contained in:
		
							parent
							
								
									254ebf478e
								
							
						
					
					
						commit
						5d5f79eb8f
					
				
							
								
								
									
										1048
									
								
								pipelined/srt/qsel4.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1048
									
								
								pipelined/srt/qsel4.sv
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										2
									
								
								pipelined/srt/sim-srt4
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										2
									
								
								pipelined/srt/sim-srt4
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1,2 @@ | ||||
| vsim -do "do srt-radix4.do" | ||||
| 
 | ||||
							
								
								
									
										1
									
								
								pipelined/srt/sim-srt4-batch
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										1
									
								
								pipelined/srt/sim-srt4-batch
									
									
									
									
									
										Executable file
									
								
							| @ -0,0 +1 @@ | ||||
| vsim -c -do "do srt-radix4.do" | ||||
							
								
								
									
										31
									
								
								pipelined/srt/srt-radix4.do
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								pipelined/srt/srt-radix4.do
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| # srt.do    | ||||
| # | ||||
| # David_Harris@hmc.edu 19 October 2021 | ||||
| 
 | ||||
| # Use this wally-pipelined.do file to run this example. | ||||
| # Either bring up ModelSim and type the following at the "ModelSim>" prompt: | ||||
| #     do wally-pipelined.do | ||||
| # or, to run from a shell, type the following at the shell prompt: | ||||
| #     vsim -do wally-pipelined.do -c | ||||
| # (omit the "-c" to see the GUI while running from the shell) | ||||
| 
 | ||||
| onbreak {resume} | ||||
| 
 | ||||
| # create library | ||||
| if [file exists work] { | ||||
|     vdel -all | ||||
| } | ||||
| 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 | ||||
| vopt +acc work.testbenchradix4 -o workopt  | ||||
| vsim workopt | ||||
| 
 | ||||
| -- display input and output signals as hexidecimal values | ||||
| add wave /testbenchradix4/* | ||||
| add wave /testbenchradix4/srtradix4/* | ||||
| add wave /testbenchradix4/srtradix4/qsel4/* | ||||
| add wave /testbenchradix4/srtradix4/otfc4/* | ||||
| 
 | ||||
| -- Run the Simulation  | ||||
| run -all | ||||
							
								
								
									
										323
									
								
								pipelined/srt/srt-radix4.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										323
									
								
								pipelined/srt/srt-radix4.sv
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,323 @@ | ||||
| ///////////////////////////////////////////
 | ||||
| // srt.sv
 | ||||
| //
 | ||||
| // Written: David_Harris@hmc.edu 13 January 2022
 | ||||
| // Modified: 
 | ||||
| //
 | ||||
| // Purpose: Combined Divide and Square Root Floating Point and Integer Unit
 | ||||
| // 
 | ||||
| // A component of the Wally configurable RISC-V project.
 | ||||
| // 
 | ||||
| // Copyright (C) 2021 Harvey Mudd College & Oklahoma State University
 | ||||
| //
 | ||||
| // MIT LICENSE
 | ||||
| // Permission is hereby granted, free of charge, to any person obtaining a copy of this 
 | ||||
| // software and associated documentation files (the "Software"), to deal in the Software 
 | ||||
| // without restriction, including without limitation the rights to use, copy, modify, merge, 
 | ||||
| // publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons 
 | ||||
| // to whom the Software is furnished to do so, subject to the following conditions:
 | ||||
| //
 | ||||
| //   The above copyright notice and this permission notice shall be included in all copies or 
 | ||||
| //   substantial portions of the Software.
 | ||||
| //
 | ||||
| //   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, 
 | ||||
| //   INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR 
 | ||||
| //   PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 
 | ||||
| //   BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 
 | ||||
| //   TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE 
 | ||||
| //   OR OTHER DEALINGS IN THE SOFTWARE.
 | ||||
| ////////////////////////////////////////////////////////////////////////////////////////////////
 | ||||
| 
 | ||||
| `include "wally-config.vh" | ||||
| 
 | ||||
| `define DIVLEN ((`NF<(`XLEN)) ? (`XLEN) : `NF) | ||||
| 
 | ||||
| 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 [`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 [`DIVLEN-1:0] Quot, Rem, // *** later handle integers
 | ||||
|   output logic [`NE-1:0] rExp, | ||||
|   output logic [3:0] Flags | ||||
| ); | ||||
| 
 | ||||
|   // logic           qp, qz, qm; // quotient is +1, 0, or -1
 | ||||
|   logic [3:0]     q; | ||||
|   logic [`NE-1:0] calcExp; | ||||
|   logic           calcSign; | ||||
|   logic [`DIVLEN-1:0]  X, Dpreproc; | ||||
|   logic [`DIVLEN+3:0]  WS, WSA, WSN; | ||||
|   logic [`DIVLEN+3:0]  WC, WCA, WCN; | ||||
|   logic [`DIVLEN+3:0]  D, DBar, D2, DBar2, Dsel; | ||||
|   logic [$clog2(`XLEN+1)-1:0] intExp; | ||||
|   logic           intSign; | ||||
|   | ||||
|   srtpreproc preproc(SrcA, SrcB, XFrac, YFrac, Fmt, W64, Signed, Int, Sqrt, X, Dpreproc, intExp, intSign); | ||||
| 
 | ||||
|   // Top Muxes and Registers
 | ||||
|   // When start is asserted, the inputs are loaded into the divider.
 | ||||
|   // Otherwise, the divisor is retained and the partial remainder
 | ||||
|   // is fed back for the next iteration.
 | ||||
|   //  - assumed one is added here since all numbers are normlaized
 | ||||
|   //    *** wait what about zero? is that specal case? can the divider handle it?
 | ||||
|   //  - when the start signal is asserted X and 0 are loaded into WS and WC
 | ||||
|   //  - 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); | ||||
|   flop   #(`DIVLEN+4) wsflop(clk, WSN, WS); | ||||
|   mux2   #(`DIVLEN+4) wcmux({WCA[`DIVLEN+1:0], 2'b0}, {`DIVLEN+4{1'b0}}, Start, WCN); | ||||
|   flop   #(`DIVLEN+4) wcflop(clk, WCN, WC); | ||||
|   flopen #(`DIVLEN+4) dflop(clk, Start, {4'b0001, Dpreproc}, D); | ||||
| 
 | ||||
|   // Quotient Selection logic
 | ||||
|   // Given partial remainder, select quotient of +1, 0, or -1 (qp, qz, pm)
 | ||||
|   // *** change this for radix 4 - generate w/ stine code
 | ||||
|   // q encoding:
 | ||||
| 	// 1000 = +2
 | ||||
| 	// 0100 = +1
 | ||||
| 	// 0000 =  0
 | ||||
| 	// 0010 = -1
 | ||||
| 	// 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); | ||||
| 
 | ||||
|   // Divisor Selection logic
 | ||||
|   // *** radix 4 change to choose -2 to 2
 | ||||
|   // - choose the negitive version of what's being selected
 | ||||
|   assign DBar = ~D; | ||||
|   assign DBar2 = {~D[`DIVLEN+2:0], 1'b1}; | ||||
|   assign D2 = {D[`DIVLEN+2:0], 1'b0}; | ||||
| 
 | ||||
|   always_comb | ||||
|     case (q) | ||||
|       4'b1000: Dsel = DBar2; | ||||
|       4'b0100: Dsel = DBar; | ||||
|       4'b0000: Dsel = {(`DIVLEN+4){1'b0}}; | ||||
|       4'b0010: Dsel = D; | ||||
|       4'b0001: Dsel = D2; | ||||
|       default: Dsel = {`DIVLEN+4{1'bx}}; | ||||
|     endcase | ||||
| 
 | ||||
|   // Partial Product Generation
 | ||||
|   //  WSA, WCA = WS + WC - qD
 | ||||
|   csa    #(`DIVLEN+4) csa(WS, WC, Dsel, |q[3:2], WSA, WCA); | ||||
|    | ||||
|   //*** change for radix 4
 | ||||
|   otfc4  #(`DIVLEN) otfc4(clk, Start, q, Quot); | ||||
| 
 | ||||
|   expcalc expcalc(.XExp, .YExp, .calcExp); | ||||
| 
 | ||||
|   signcalc signcalc(.XSign, .YSign, .calcSign); | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| ////////////////
 | ||||
| // Submodules //
 | ||||
| ////////////////
 | ||||
| 
 | ||||
| ///////////////////
 | ||||
| // 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
 | ||||
|   input  logic       Sqrt, // perform square root, not divide
 | ||||
|   output logic [`DIVLEN-1:0] X, D, | ||||
|   output logic [$clog2(`XLEN+1)-1:0] intExp, // Quotient integer exponent
 | ||||
|   output logic       intSign // Quotient integer sign
 | ||||
| ); | ||||
| 
 | ||||
|   logic  [$clog2(`XLEN+1)-1:0] zeroCntA, zeroCntB; | ||||
|   logic  [`XLEN-1:0] PosA, PosB; | ||||
|   logic  [`DIVLEN-1:0] ExtraA, ExtraB, PreprocA, PreprocB, PreprocX, PreprocY; | ||||
| 
 | ||||
|   assign PosA = (Signed & SrcA[`XLEN - 1]) ? -SrcA : SrcA; | ||||
|   assign PosB = (Signed & SrcB[`XLEN - 1]) ? -SrcB : SrcB; | ||||
| 
 | ||||
|   lzc #(`XLEN) lzcA (PosA, zeroCntA); | ||||
|   lzc #(`XLEN) lzcB (PosB, zeroCntB); | ||||
| 
 | ||||
|   assign ExtraA = {PosA, {`DIVLEN-`XLEN{1'b0}}}; | ||||
|   assign ExtraB = {PosB, {`DIVLEN-`XLEN{1'b0}}}; | ||||
| 
 | ||||
|   assign PreprocA = ExtraA << zeroCntA; | ||||
|   assign PreprocB = ExtraB << (zeroCntB + 1); | ||||
|   assign PreprocX = {XFrac, {`DIVLEN-`NF{1'b0}}}; | ||||
|   assign PreprocY = {YFrac, {`DIVLEN-`NF{1'b0}}}; | ||||
| 
 | ||||
|    | ||||
|   assign X = Int ? PreprocA : PreprocX; | ||||
|   assign D = Int ? PreprocB : PreprocY; | ||||
|   assign intExp = zeroCntB - zeroCntA + 1; | ||||
|   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 [3:0]   q, | ||||
|   output logic [N-1:0] r | ||||
| ); | ||||
| 
 | ||||
|   //  The on-the-fly converter transfers the quotient 
 | ||||
|   //  bits to the quotient as they come. 
 | ||||
|   //
 | ||||
|   //  This code follows the psuedocode presented in the 
 | ||||
|   //  floating point chapter of the book. Right now, 
 | ||||
|   //  it is written for Radix-2 division.
 | ||||
|   //
 | ||||
|   //  QM is Q-1. It allows us to write negative bits 
 | ||||
|   //  without using a costly CPA. 
 | ||||
|   logic [N+2:0] Q, QM, QNext, QMNext, QMux, QMMux; | ||||
|   //  QR and QMR are the shifted versions of Q and QM.
 | ||||
|   //  They are treated as [N-1:r] size signals, and 
 | ||||
|   //  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); | ||||
|   flop #(N+3) Qreg(clk, QMux, Q); | ||||
|   flop #(N+3) QMreg(clk, QMMux, QM); | ||||
| 
 | ||||
|   // shift Q (quotent) and QM (quotent-1)
 | ||||
| 		// if 	q = 2  	    Q = {Q, 10} 	QM = {Q, 01}		
 | ||||
| 		// else if 	q = 1   Q = {Q, 01} 	QM = {Q, 00}	
 | ||||
| 		// else if 	q = 0   Q = {Q, 00} 	QM = {QM, 11}	
 | ||||
| 		// else if 	q = -1	Q = {QM, 11} 	QM = {QM, 10}
 | ||||
| 		// else if 	q = -2	Q = {QM, 10} 	QM = {QM, 01}
 | ||||
|     // *** how does the 0 concatination numbers work?
 | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|   always_comb begin | ||||
|     QR  = Q[N:0]; | ||||
|     QMR = QM[N:0];     // Shift Q and QM
 | ||||
|     if (q[3]) begin // +2
 | ||||
|       QNext  = {QR,  2'b10}; | ||||
|       QMNext = {QR,  2'b01}; | ||||
|     end else if (q[2]) begin // +1
 | ||||
|       QNext  = {QR,  2'b01}; | ||||
|       QMNext = {QR,  2'b00}; | ||||
|     end else if (q[1]) begin // -1
 | ||||
|       QNext  = {QMR,  2'b11}; | ||||
|       QMNext = {QMR,  2'b10}; | ||||
|     end else if (q[0]) begin // -2
 | ||||
|       QNext  = {QMR,  2'b10}; | ||||
|       QMNext = {QMR,  2'b01}; | ||||
|     end else begin           // 0
 | ||||
|       QNext  = {QR,  2'b00}; | ||||
|       QMNext = {QMR, 2'b11}; | ||||
|     end  | ||||
|   end | ||||
|   assign r = Q[N+2] ? Q[N+1:2] : Q[N:1]; | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| /////////
 | ||||
| // csa //
 | ||||
| /////////
 | ||||
| module csa #(parameter N=69) ( | ||||
|   input  logic [N-1:0] in1, in2, in3,  | ||||
|   input  logic         cin,  | ||||
|   output logic [N-1:0] out1, out2 | ||||
| ); | ||||
| 
 | ||||
|   // 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.
 | ||||
|   // Fortunately, the carry (out2) is shifted left by one
 | ||||
|   // bit, leaving room in the least significant bit to 
 | ||||
|   // insert cin.
 | ||||
| 
 | ||||
|   assign #1 out1 = in1 ^ in2 ^ in3; | ||||
|   assign #1 out2 = {in1[N-2:0] & (in2[N-2:0] | in3[N-2:0]) |  | ||||
| 		    (in2[N-2:0] & in3[N-2:0]), cin}; | ||||
| endmodule | ||||
| 
 | ||||
| 
 | ||||
| //////////////
 | ||||
| // expcalc  //
 | ||||
| //////////////
 | ||||
| module expcalc( | ||||
|   input logic  [`NE-1:0] XExp, YExp, | ||||
|   output logic [`NE-1:0] calcExp | ||||
| ); | ||||
| 
 | ||||
|   assign calcExp = XExp - YExp + (`NE)'(`BIAS); | ||||
| 
 | ||||
| endmodule | ||||
| 
 | ||||
| //////////////
 | ||||
| // signcalc //
 | ||||
| //////////////
 | ||||
| module signcalc( | ||||
|   input logic  XSign, YSign, | ||||
|   output logic calcSign | ||||
| ); | ||||
| 
 | ||||
|   assign calcSign = XSign ^ YSign; | ||||
| 
 | ||||
| endmodule | ||||
							
								
								
									
										148
									
								
								pipelined/srt/testbench-radix4.sv
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										148
									
								
								pipelined/srt/testbench-radix4.sv
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,148 @@ | ||||
| 
 | ||||
| `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 //
 | ||||
| ///////////
 | ||||
| module clock(clk); | ||||
|   output clk; | ||||
|   | ||||
|   // Internal clk signal
 | ||||
|   logic clk; | ||||
|   | ||||
| endmodule | ||||
| 
 | ||||
| //////////
 | ||||
| // testbench //
 | ||||
| //////////
 | ||||
| module testbenchradix4; | ||||
|   logic              clk; | ||||
|   logic              req; | ||||
|   logic              done; | ||||
|   logic [63:0]       a, b; | ||||
|   logic [51:0]       afrac, bfrac; | ||||
|   logic [10:0]       aExp, bExp; | ||||
|   logic              asign, bsign; | ||||
|   logic [51:0]       r, rOTFC; | ||||
|   logic [`DIVLEN-1:0]  Quot, QuotOTFC; | ||||
|   logic [54:0]       rp, rm;   // positive quotient digits
 | ||||
|   | ||||
|   // Test parameters
 | ||||
|   parameter MEM_SIZE = 40000; | ||||
|   parameter MEM_WIDTH = 64+64+64; | ||||
|   | ||||
|   `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
 | ||||
|   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; | ||||
|   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, | ||||
|                 .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()); | ||||
| 
 | ||||
|   // Counter
 | ||||
|   counter counter(clk, req, done); | ||||
| 
 | ||||
| 
 | ||||
|     initial | ||||
|     forever | ||||
|       begin | ||||
|         clk = 1; #17; | ||||
|         clk = 0; #17; | ||||
|       end | ||||
| 
 | ||||
| 
 | ||||
|   // Read test vectors from disk
 | ||||
|   initial | ||||
|     begin | ||||
|       testnum = 0;  | ||||
|       errors = 0; | ||||
|       $readmemh ("testvectors", Tests); | ||||
|       Vec = Tests[testnum]; | ||||
|       a = Vec[`mema]; | ||||
|       {asign, aExp, afrac} = a; | ||||
|       b = Vec[`memb]; | ||||
|       {bsign, bExp, bfrac} = b; | ||||
|       nextr = Vec[`memr]; | ||||
|       r = Quot[`DIVLEN-1:`DIVLEN - 52]; | ||||
|       req <= 1; | ||||
|     end | ||||
|    | ||||
|   // Apply directed test vectors read from file.
 | ||||
| 
 | ||||
|   always @(posedge clk) | ||||
|     begin | ||||
|       r = Quot[`DIVLEN-1:`DIVLEN - 52]; | ||||
|       if (done) 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
 | ||||
|           begin | ||||
|             errors = errors+1; | ||||
|             $display("result was %h_%h, should be %h %h %h\n", rExp, r, correctr, diffn, diffp); | ||||
|             $display("failed\n"); | ||||
|             $stop; | ||||
|           end | ||||
|         if (afrac === 52'hxxxxxxxxxxxxx) | ||||
|           begin | ||||
|             $display("%d Tests completed successfully", testnum); | ||||
|             $stop; | ||||
|           end | ||||
| 	end | ||||
|       if (req)  | ||||
| 	begin | ||||
| 	  req <= 0; | ||||
| 	  correctr = nextr; | ||||
| 	  testnum = testnum+1; | ||||
| 	  Vec = Tests[testnum]; | ||||
| 	  $display("a = %h  b = %h",a,b); | ||||
|     a = Vec[`mema]; | ||||
|     {asign, aExp, afrac} = a; | ||||
|     b = Vec[`memb]; | ||||
|     {bsign, bExp, bfrac} = b; | ||||
|     nextr = Vec[`memr]; | ||||
| 	end | ||||
|     end | ||||
|   | ||||
| endmodule | ||||
|   | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user