OpenCores
URL https://opencores.org/ocsvn/fpu/fpu/trunk

Subversion Repositories fpu

[/] [fpu/] [trunk/] [test_bench/] [test_top.v] - Rev 11

Compare with Previous | Blame | View Log

/////////////////////////////////////////////////////////////////////
////                                                             ////
////  FPU                                                        ////
////  Floating Point Unit (Single precision)                     ////
////                                                             ////
////  TEST BENCH                                                 ////
////                                                             ////
////  Author: Rudolf Usselmann                                   ////
////          rudi@asics.ws                                      ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
////                                                             ////
//// Copyright (C) 2000 Rudolf Usselmann                         ////
////                    rudi@asics.ws                            ////
////                                                             ////
//// This source file may be used and distributed without        ////
//// restriction provided that this copyright statement is not   ////
//// removed from the file and that any derivative work contains ////
//// the original copyright notice and the associated disclaimer.////
////                                                             ////
////     THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY     ////
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED   ////
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS   ////
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR      ////
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,         ////
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    ////
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE   ////
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR        ////
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF  ////
//// LIABILITY, WHETHER IN  CONTRACT, STRICT LIABILITY, OR TORT  ////
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT  ////
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE         ////
//// POSSIBILITY OF SUCH DAMAGE.                                 ////
////                                                             ////
/////////////////////////////////////////////////////////////////////
 
 
`timescale 1ns / 100ps
 
module test;
 
reg		clk;
reg	[31:0]	opa;
reg	[31:0]	opb;
wire	[31:0]	sum;
wire		inf, snan, qnan;
wire		div_by_zero;
 
reg	[31:0]	exp, exp1, exp2, exp3, exp4;
reg	[31:0]	opa1, opa2, opa3, opa4;
reg	[31:0]	opb1, opb2, opb3, opb4;
reg	[2:0]	fpu_op, fpu_op1, fpu_op2, fpu_op3, fpu_op4, fpu_op5;
reg	[3:0]	rmode, rmode1, rmode2, rmode3, rmode4, rmode5;
reg		start, s1, s2, s3, s4;
reg	[115:0]	tmem[0:500000];
reg	[115:0]	tmp;
reg	[7:0]	oper;
reg	[7:0]	exc, exc1, exc2, exc3, exc4;
integer		i;
wire		ine;
reg		match;
wire		overflow, underflow;
wire		zero;
reg		exc_err;
reg		m0, m1, m2;
reg	[1:0]	fpu_rmode;
reg	[3:0]	test_rmode;
reg	[4:0]	test_sel;
reg		fp_fasu;
reg		fp_mul;
reg		fp_div;
reg		fp_combo;
reg		fp_i2f;
reg		fp_f2i;
reg		test_exc;
reg		show_prog;
event		error_event;
 
integer		error, vcount;
 
always #50 clk = ~clk;
 
initial
   begin
	$display ("\n\nFloating Point Unit Version 1.5\n\n");
	clk = 0;
	start = 0;
	s1 = 0;
	s2 = 0;
	s3 = 0;
	s4 = 0;
	error = 0;
	vcount = 0;
 
	show_prog = 0;
 
	fp_combo = 0;
	fp_fasu  = 0;
	fp_mul   = 0;
	fp_div   = 0;
	fp_i2f   = 1;
	fp_f2i   = 1;
 
	test_exc = 1;
	test_sel   = 5'b01111;
	test_rmode = 4'b1111;
 
	//test_sel   = 5'b00110;
	//test_rmode = 4'b01110;
 
	fp_combo = 1;
	fp_fasu  = 1;
	fp_mul   = 1;
	fp_div   = 1;
	fp_i2f   = 1;
	fp_f2i   = 1;
 
	test_sel   = 5'b11111;
	test_rmode = 4'b1111;
 
	@(posedge clk);
 
`include "test_bench/sel_test.vh"
 
	repeat (4)	@(posedge clk);
	$display("\n\n");
 
	$display("\n\nAll test Done !\n\n");
	$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
 
	$finish;
   end
 
 
task run_test;
begin
	@(posedge clk);
	#1;
	opa = 32'hx;
	opb = 32'hx;
	fpu_rmode = 2'hx;
	fpu_op = 3'hx;
 
	repeat(4) @(posedge clk);
	#1;
 
	oper = 1;
	i=0;
	while( |oper == 1'b1 )
	   begin
 
		@(posedge clk);
		#1;
		start = 1;
		tmp   = tmem[i];
		rmode = tmp[115:112];
		exc   = tmp[111:104];
		oper  = tmp[103:96];
		opa   = tmp[95:64];
		opb   = tmp[63:32];
		exp   = tmp[31:00];
 
		// FPU rounding mode
		//  0:	float_round_nearest_even
		//  1:	float_round_down
		//  2:	float_round_up
		//  3:	float_round_to_zero
 
		case(rmode)
		  0: fpu_rmode = 0;
		  1: fpu_rmode = 3;
		  2: fpu_rmode = 2;
		  3: fpu_rmode = 1;
		  default: fpu_rmode=2'hx;
		endcase
 
		// oper	fpu operation
		//   1   add
		//   2   sub
		//   4   mul
		//   8   div
		//   ...
 
		case(oper)
		   8'b00000001:	fpu_op=3'b000;	// Add
		   8'b00000010:	fpu_op=3'b001;	// Sub
		   8'b00000100:	fpu_op=3'b010;	// Mul
		   8'b00001000:	fpu_op=3'b011;	// Div
		   8'b00010000:	fpu_op=3'b100;	// i2f
		   8'b00100000:	fpu_op=3'b101;	// f2i
		   8'b01000000:	fpu_op=3'b110;	// rem
		   default: fpu_op=3'bx;
		endcase
 
		if(show_prog)	$write("Vector: %d\015",i);
 
		//if(oper==1)	$write("+");
		//else
		//if(oper==2)	$write("-");
		//else
		//if(oper==4)	$write("*");
		//else
		//if(oper==8)	$write("/");
		//else		$write("Unknown Operation (%d)",oper);
 
		i= i+1;
	   end
	start = 0;
 
   	@(posedge clk);
	#1;
	opa = 32'hx;
	opb = 32'hx;
	fpu_rmode = 2'hx;
	fpu_op = 2'hx;
 
	repeat(4) @(posedge clk);
	#1;
 
	for(i=0;i<500000;i=i+1)		// Clear Memory
	   tmem[i] = 112'hxxxxxxxxxxxxxxxxx;
 
   end
endtask
 
always @(posedge clk)
   begin
   	s1 <= #1 start;
   	s2 <= #1 s1;
   	s3 <= #1 s2;
   	s4 <= #1 s3;
	exp1 <= #1 exp;
	exp2 <= #1 exp1;
	exp3 <= #1 exp2;
	exp4 <= #1 exp3;
	opa1 <= #1 opa;
	opa2 <= #1 opa1;
	opa3 <= #1 opa2;
	opa4 <= #1 opa3;
	opb1 <= #1 opb;
	opb2 <= #1 opb1;
	opb3 <= #1 opb2;
	opb4 <= #1 opb3;
	fpu_op1 <= #1 fpu_op;
	fpu_op2 <= #1 fpu_op1;
	fpu_op3 <= #1 fpu_op2;
	fpu_op4 <= #1 fpu_op3;
	fpu_op5 <= #1 fpu_op4;
	rmode1 <= #1 rmode;
	rmode2 <= #1 rmode1;
	rmode3 <= #1 rmode2;
	rmode4 <= #1 rmode3;
	rmode5 <= #1 rmode4;
	exc1 <= #1 exc;
	exc2 <= #1 exc1;
	exc3 <= #1 exc2;
	exc4 <= #1 exc3;
 
	#3;
 
	//	Floating Point Exceptions ( exc4 )
	//	-------------------------
	//	float_flag_invalid   =  1,
	//	float_flag_divbyzero =  4,
	//	float_flag_overflow  =  8,
	//	float_flag_underflow = 16,
	//	float_flag_inexact   = 32
 
   	exc_err=0;
 
	if(test_exc)
	   begin
 
		if(div_by_zero !== exc4[2])
		   begin
		   	exc_err=1;
			$display("\nERROR: DIV_BY_ZERO Exception: Expected: %h, Got %h\n",exc4[2],div_by_zero);
		   end
 
 
		if(ine !== exc4[5])
		   begin
		   	exc_err=1;
			$display("\nERROR: INE Exception: Expected: %h, Got %h\n",exc4[5],ine);
		   end
 
		if(overflow !== exc4[3])
		   begin
		   	exc_err=1;
			$display("\nERROR: Overflow Exception Expected: %h, Got %h\n",exc4[3],overflow);
		   end
 
 
		if(underflow !== exc4[4])
		   begin
		   	exc_err=1;
			$display("\nERROR: Underflow Exception Expected: %h, Got %h\n",exc4[4],underflow);
		   end
 
 
		if(zero !== !(|sum[30:0]))
		   begin
		   	exc_err=1;
			$display("\nERROR: Zero Detection Failed. ZERO: %h, Sum: %h\n", zero, sum);
		   end
 
		if(inf !== ( (sum[30:23] == 8'hff) & ((|sum[22:0]) == 1'b0) ) )
		   begin
		   	exc_err=1;
			$display("\nERROR: INF Detection Failed. INF: %h, Sum: %h\n", inf, sum);
		   end
 
 
		if(qnan !== ( &sum[30:23]  & |sum[22:0] )  & !(fpu_op4==5)   )
		   begin
		   	exc_err=1;
			$display("\nERROR: QNAN Detection Failed. QNAN: %h, Sum: %h\n", qnan, sum);
		   end
 
 
		if(snan !== ( ( &opa4[30:23] & !opa4[22] & |opa4[21:0]) | ( &opb4[30:23] & !opb4[22] & |opb4[21:0]) ) )
		   begin
		   	exc_err=1;
			$display("\nERROR: SNAN Detection Failed. SNAN: %h, OpA: %h, OpB: %h\n", snan, opa4, opb4);
		   end
 
	   end
 
 
	m0 = ( (|sum) !== 1'b1) & ( (|sum) !== 1'b0);		// result unknown (ERROR)
	//m0 = ( (|sum) === 1'bx) & 0;
	m1 = (exp4 === sum);					// results are equal
 
	// NAN   *** Ignore Fraction Detail ***
	m2 =    (sum[31] == exp4[31]) &
		(sum[30:23] == 8'hff)  & (exp4[30:23] == 8'hff) &
		(sum[22] == exp4[22]) &
		( (|sum[22:0]) == 1'b1) & ((|exp4[22:0]) == 1'b1);
 
	match = m1 | m2;
 
	if( (exc_err | !match | m0) & s4 )
	   begin
		-> error_event;
		#0.6;
		$display("\n%t: ERROR: output mismatch. Expected %h, Got %h (%h)", $time, exp4, sum, {opa4, opb4, exp4} );
		$write("opa:\t");	disp_fp(opa4);
		$display("opa:\t%h",opa4[30:0]);
		case(fpu_op4)
		   0: $display("\t+");
		   1: $display("\t-");
		   2: $display("\t*");
		   3: $display("\t/");
		   default: $display("\t Unknown Operation ");
		endcase
		$write("opb:\t");	disp_fp(opb4);
		$write("EXP:\t");	disp_fp(exp4);
		$write("GOT:\t");	disp_fp(sum);
 
$display("\nThis rmode: %h fpop: %h; Previous: rmode: %h fpop: %h; Next: rmode: %h fpop: %h\n",
rmode4, fpu_op4, rmode5, fpu_op5, rmode3, fpu_op3);
 
		$display("\n");
		error = error + 1;
	   end
 
	if(s4)	vcount = vcount + 1;
 
	if(error > 10)
	   begin
		@(posedge clk);
	   	$display("\n\nFound to many errors, aborting ...\n\n");
		$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
		$finish;
	   end
   end
 
 
fpu u0(clk, fpu_rmode, fpu_op, opa, opb, sum, inf, snan, qnan, ine, overflow, underflow, zero, div_by_zero);
 
 
task disp_fp;
input [31:0]	fp;
 
reg 	[63:0]	x;
reg	[7:0]	exp;
 
   begin
 
	exp = fp[30:23];
	if(exp==8'h7f)	$write("(%h %h ( 00 ) %h) ",fp[31], exp, fp[22:0]);
	else
	if(exp>8'h7f)	$write("(%h %h (+%d ) %h) ",fp[31], exp, exp-8'h7f, fp[22:0]);
	else		$write("(%h %h (-%d ) %h) ",fp[31], exp, 8'h7f-exp, fp[22:0]);
 
 
	x[51:0] = {fp[22:0], 29'h0};
	x[63] = fp[31];
	x[62] = fp[30];
	x[61:59] = {fp[29], fp[29], fp[29]};
	x[58:52] = fp[29:23];
 
	$display("\t%f",$bitstoreal(x));
   end
 
endtask
 
endmodule
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.