/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// FPU ////
|
//// FPU ////
|
//// Floating Point Unit (Single precision) ////
|
//// Floating Point Unit (Single precision) ////
|
//// ////
|
//// ////
|
//// TEST BENCH ////
|
//// TEST BENCH ////
|
//// ////
|
//// ////
|
//// Author: Rudolf Usselmann ////
|
//// Author: Rudolf Usselmann ////
|
//// rudi@asics.ws ////
|
//// rudi@asics.ws ////
|
//// ////
|
//// ////
|
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
//// ////
|
//// ////
|
//// Copyright (C) 2000 Rudolf Usselmann ////
|
//// Copyright (C) 2000 Rudolf Usselmann ////
|
//// rudi@asics.ws ////
|
//// rudi@asics.ws ////
|
//// ////
|
//// ////
|
//// This source file may be used and distributed without ////
|
//// This source file may be used and distributed without ////
|
//// restriction provided that this copyright statement is not ////
|
//// restriction provided that this copyright statement is not ////
|
//// removed from the file and that any derivative work contains ////
|
//// removed from the file and that any derivative work contains ////
|
//// the original copyright notice and the associated disclaimer.////
|
//// the original copyright notice and the associated disclaimer.////
|
//// ////
|
//// ////
|
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
//// THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY ////
|
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
//// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED ////
|
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
//// TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS ////
|
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
//// FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL THE AUTHOR ////
|
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
//// OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, ////
|
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
//// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ////
|
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
//// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE ////
|
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
//// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR ////
|
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
//// BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF ////
|
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
//// LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT ////
|
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
//// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT ////
|
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
//// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ////
|
//// POSSIBILITY OF SUCH DAMAGE. ////
|
//// POSSIBILITY OF SUCH DAMAGE. ////
|
//// ////
|
//// ////
|
/////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////
|
|
|
|
|
`timescale 1ns / 100ps
|
`timescale 1ns / 100ps
|
|
|
module test;
|
module test;
|
|
|
reg clk;
|
reg clk;
|
reg [31:0] opa;
|
reg [31:0] opa;
|
reg [31:0] opb;
|
reg [31:0] opb;
|
wire [3:0] sum;
|
wire [3:0] sum;
|
wire inf, snan, qnan;
|
wire inf, snan, qnan;
|
wire div_by_zero;
|
wire div_by_zero;
|
wire altb, blta, aeqb;
|
wire altb, blta, aeqb;
|
wire unordered;
|
wire unordered;
|
|
|
reg [3:0] exp;
|
reg [3:0] exp;
|
reg [31:0] opa1;
|
reg [31:0] opa1;
|
reg [31:0] opb1;
|
reg [31:0] opb1;
|
reg [2:0] fpu_op;
|
reg [2:0] fpu_op;
|
reg [3:0] rmode;
|
reg [3:0] rmode;
|
reg start;
|
reg start;
|
reg [75:0] tmem[0:500000];
|
reg [75:0] tmem[0:500000];
|
reg [75:0] tmp;
|
reg [75:0] tmp;
|
reg [7:0] oper;
|
reg [7:0] oper;
|
reg [7:0] exc;
|
reg [7:0] exc;
|
integer i;
|
integer i;
|
wire ine;
|
wire ine;
|
reg match;
|
reg match;
|
wire overflow, underflow;
|
wire overflow, underflow;
|
wire zero;
|
wire zero;
|
reg exc_err;
|
reg exc_err;
|
reg m0, m1, m2;
|
reg m0, m1, m2;
|
reg [1:0] fpu_rmode;
|
reg [1:0] fpu_rmode;
|
reg [3:0] test_rmode;
|
reg [3:0] test_rmode;
|
reg [4:0] test_sel;
|
reg [4:0] test_sel;
|
reg fp_fasu;
|
reg fp_fasu;
|
reg fp_mul;
|
reg fp_mul;
|
reg fp_div;
|
reg fp_div;
|
reg fp_combo;
|
reg fp_combo;
|
reg fp_i2f;
|
reg fp_i2f;
|
reg fp_0fcmp;
|
reg fp_0fcmp;
|
reg test_exc;
|
reg test_exc;
|
reg show_prog;
|
reg show_prog;
|
event error_event;
|
event error_event;
|
|
|
integer error, vcount;
|
integer error, vcount;
|
|
|
always #50 clk = ~clk;
|
always #50 clk = ~clk;
|
|
|
initial
|
initial
|
begin
|
begin
|
$display ("\n\nFloating Point Compare Version 1.0\n\n");
|
$display ("\n\nFloating Point Compare Version 1.0\n\n");
|
clk = 0;
|
clk = 0;
|
start = 0;
|
start = 0;
|
|
|
error = 0;
|
error = 0;
|
vcount = 0;
|
vcount = 0;
|
|
|
show_prog = 0;
|
show_prog = 0;
|
|
|
test_exc = 1;
|
test_exc = 1;
|
test_sel = 5'b11111;
|
test_sel = 5'b11111;
|
|
|
@(posedge clk);
|
@(posedge clk);
|
|
|
$display("\n\nTesting FP CMP Unit\n");
|
$display("\n\nTesting FP CMP Unit\n");
|
|
|
if(test_sel[0])
|
if(test_sel[0])
|
begin
|
begin
|
$display("\nRunning Pat 0 Test ...\n");
|
$display("\nRunning Pat 0 Test ...\n");
|
$readmemh ("../test_vectors/fcmp/fcmp_pat0.hex", tmem);
|
$readmemh ("../test_vectors/fcmp/fcmp_pat0.hex", tmem);
|
run_test;
|
run_test;
|
end
|
end
|
|
|
if(test_sel[1])
|
if(test_sel[1])
|
begin
|
begin
|
$display("\nRunning Pat 1 Test ...\n");
|
$display("\nRunning Pat 1 Test ...\n");
|
$readmemh ("../test_vectors/fcmp/fcmp_pat1.hex", tmem);
|
$readmemh ("../test_vectors/fcmp/fcmp_pat1.hex", tmem);
|
run_test;
|
run_test;
|
end
|
end
|
|
|
if(test_sel[2])
|
if(test_sel[2])
|
begin
|
begin
|
$display("\nRunning Pat 2 Test ...\n");
|
$display("\nRunning Pat 2 Test ...\n");
|
$readmemh ("../test_vectors/fcmp/fcmp_pat2.hex", tmem);
|
$readmemh ("../test_vectors/fcmp/fcmp_pat2.hex", tmem);
|
run_test;
|
run_test;
|
end
|
end
|
|
|
if(test_sel[3])
|
if(test_sel[3])
|
begin
|
begin
|
$display("\nRunning Random Lg. Num Test ...\n");
|
$display("\nRunning Random Lg. Num Test ...\n");
|
$readmemh ("../test_vectors/fcmp/fcmp_lg.hex", tmem);
|
$readmemh ("../test_vectors/fcmp/fcmp_lg.hex", tmem);
|
run_test;
|
run_test;
|
end
|
end
|
|
|
if(test_sel[4])
|
if(test_sel[4])
|
begin
|
begin
|
$display("\nRunning Random Sm. Num Test ...\n");
|
$display("\nRunning Random Sm. Num Test ...\n");
|
$readmemh ("../test_vectors/fcmp/fcmp_sm.hex", tmem);
|
$readmemh ("../test_vectors/fcmp/fcmp_sm.hex", tmem);
|
run_test;
|
run_test;
|
end
|
end
|
|
|
repeat (4) @(posedge clk);
|
repeat (4) @(posedge clk);
|
$display("\n\n");
|
$display("\n\n");
|
|
|
$display("\n\nAll test Done !\n\n");
|
$display("\n\nAll test Done !\n\n");
|
$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
|
$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
|
|
|
$finish;
|
$finish;
|
end
|
end
|
|
|
|
|
task run_test;
|
task run_test;
|
begin
|
begin
|
@(posedge clk);
|
@(posedge clk);
|
#1;
|
#1;
|
opa = 32'h0;
|
opa = 32'h0;
|
opb = 32'hx;
|
opb = 32'hx;
|
|
|
@(posedge clk);
|
@(posedge clk);
|
#1;
|
#1;
|
|
|
i=0;
|
i=0;
|
while( |opa !== 1'bx )
|
while( |opa !== 1'bx )
|
begin
|
begin
|
|
|
@(posedge clk);
|
@(posedge clk);
|
#1;
|
#1;
|
start = 1;
|
start = 1;
|
tmp = tmem[i];
|
tmp = tmem[i];
|
|
|
exc = tmp[75:68];
|
exc = tmp[75:68];
|
opa = tmp[67:36];
|
opa = tmp[67:36];
|
opb = tmp[35:04];
|
opb = tmp[35:04];
|
|
|
exp = exc==0 ? tmp[03:00] : 0;
|
exp = exc==0 ? tmp[03:00] : 0;
|
|
|
if(show_prog) $write("Vector: %d\015",i);
|
if(show_prog) $write("Vector: %d\015",i);
|
|
|
i= i+1;
|
i= i+1;
|
end
|
end
|
start = 0;
|
start = 0;
|
|
|
@(posedge clk);
|
@(posedge clk);
|
#1;
|
#1;
|
opa = 32'hx;
|
opa = 32'hx;
|
opb = 32'hx;
|
opb = 32'hx;
|
fpu_rmode = 2'hx;
|
fpu_rmode = 2'hx;
|
|
|
@(posedge clk);
|
@(posedge clk);
|
#1;
|
#1;
|
|
|
for(i=0;i<500000;i=i+1) // Clear Memory
|
for(i=0;i<500000;i=i+1) // Clear Memory
|
tmem[i] = 76'hxxxxxxxxxxxxxxxxx;
|
tmem[i] = 76'hxxxxxxxxxxxxxxxxx;
|
|
|
end
|
end
|
endtask
|
endtask
|
|
|
always @(posedge clk)
|
always @(posedge clk)
|
begin
|
begin
|
|
|
#3;
|
#3;
|
|
|
// Floating Point Exceptions ( exc4 )
|
// Floating Point Exceptions ( exc4 )
|
// -------------------------
|
// -------------------------
|
// float_flag_invalid = 1,
|
// float_flag_invalid = 1,
|
// float_flag_divbyzero = 4,
|
// float_flag_divbyzero = 4,
|
// float_flag_overflow = 8,
|
// float_flag_overflow = 8,
|
// float_flag_underflow = 16,
|
// float_flag_underflow = 16,
|
// float_flag_inexact = 32
|
// float_flag_inexact = 32
|
|
|
exc_err=0;
|
exc_err=0;
|
|
|
if(test_exc)
|
if(test_exc)
|
begin
|
begin
|
|
|
if(exc[5])
|
if(exc[5])
|
begin
|
begin
|
exc_err=1;
|
exc_err=1;
|
$display("\nERROR: INE Exception: Expected: 0, Got 1\n");
|
$display("\nERROR: INE Exception: Expected: 0, Got 1\n");
|
end
|
end
|
|
|
if(exc[3])
|
if(exc[3])
|
begin
|
begin
|
exc_err=1;
|
exc_err=1;
|
$display("\nERROR: Overflow Exception: Expected: 0, Got 1\n");
|
$display("\nERROR: Overflow Exception: Expected: 0, Got 1\n");
|
end
|
end
|
|
|
if(exc[4])
|
if(exc[4])
|
begin
|
begin
|
exc_err=1;
|
exc_err=1;
|
$display("\nERROR: Underflow Exception: Expected: 0, Got 1\n");
|
$display("\nERROR: Underflow Exception: Expected: 0, Got 1\n");
|
end
|
end
|
|
|
if(zero !== !(|opa[30:0]))
|
if(zero !== !(|opa[30:0]))
|
begin
|
begin
|
exc_err=1;
|
exc_err=1;
|
$display("\nERROR: Zero Detection Failed. ZERO: %h, Sum: %h\n", zero, opa);
|
$display("\nERROR: Zero Detection Failed. ZERO: %h, Sum: %h\n", zero, opa);
|
end
|
end
|
|
|
|
|
if(inf !== (((opa[30:23] == 8'hff) & ((|opa[22:0]) == 1'b0)) | ((opb[30:23] == 8'hff) & ((|opb[22:0]) == 1'b0))) )
|
if(inf !== (((opa[30:23] == 8'hff) & ((|opa[22:0]) == 1'b0)) | ((opb[30:23] == 8'hff) & ((|opb[22:0]) == 1'b0))) )
|
begin
|
begin
|
exc_err=1;
|
exc_err=1;
|
$display("\nERROR: INF Detection Failed. INF: %h, Sum: %h\n", inf, sum);
|
$display("\nERROR: INF Detection Failed. INF: %h, Sum: %h\n", inf, sum);
|
end
|
end
|
|
|
if(unordered !== ( ( &opa[30:23] & |opa[22:0]) | ( &opb[30:23] & |opb[22:0]) ) )
|
if(unordered !== ( ( &opa[30:23] & |opa[22:0]) | ( &opb[30:23] & |opb[22:0]) ) )
|
begin
|
begin
|
exc_err=1;
|
exc_err=1;
|
$display("\nERROR: UNORDERED Detection Failed. SNAN: %h, OpA: %h, OpB: %h\n", snan, opa, opb);
|
$display("\nERROR: UNORDERED Detection Failed. SNAN: %h, OpA: %h, OpB: %h\n", snan, opa, opb);
|
end
|
end
|
|
|
end
|
end
|
|
|
m0 = ( (|sum) !== 1'b1) & ( (|sum) !== 1'b0); // result unknown (ERROR)
|
m0 = ( (|sum) !== 1'b1) & ( (|sum) !== 1'b0); // result unknown (ERROR)
|
m1 = (exp === sum) ; // results are equal
|
m1 = (exp === sum) ; // results are equal
|
|
|
match = m1;
|
match = m1;
|
|
|
if( (exc_err | !match | m0) & start )
|
if( (exc_err | !match | m0) & start )
|
begin
|
begin
|
$display("\n%t: ERROR: output mismatch. Expected %h, Got %h (%h)", $time, exp, sum, {opa, opb, exp} );
|
$display("\n%t: ERROR: output mismatch. Expected %h, Got %h (%h)", $time, exp, sum, {opa, opb, exp} );
|
$write("opa:\t"); disp_fp(opa);
|
$write("opa:\t"); disp_fp(opa);
|
$write("opb:\t"); disp_fp(opb);
|
$write("opb:\t"); disp_fp(opb);
|
$display("EXP:\t%b",exp);
|
$display("EXP:\t%b",exp);
|
$display("GOT:\t%b",sum);
|
$display("GOT:\t%b",sum);
|
$display("\n");
|
$display("\n");
|
|
|
error = error + 1;
|
error = error + 1;
|
end
|
end
|
|
|
if(start) vcount = vcount + 1;
|
if(start) vcount = vcount + 1;
|
|
|
if(error > 10)
|
if(error > 10)
|
begin
|
begin
|
@(posedge clk);
|
@(posedge clk);
|
$display("\n\nFound to many errors, aborting ...\n\n");
|
$display("\n\nFound to many errors, aborting ...\n\n");
|
$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
|
$display("Run %0d vecors, found %0d errors.\n\n",vcount, error);
|
$finish;
|
$finish;
|
end
|
end
|
end
|
end
|
|
|
assign sum = {1'b0, altb, blta, aeqb};
|
assign sum = {1'b0, altb, blta, aeqb};
|
|
|
fcmp u0(opa, opb, unordered, altb, blta, aeqb, inf, zero );
|
fcmp u0(opa, opb, unordered, altb, blta, aeqb, inf, zero );
|
|
|
task disp_fp;
|
task disp_fp;
|
input [31:0] fp;
|
input [31:0] fp;
|
|
|
reg [63:0] x;
|
reg [63:0] x;
|
reg [7:0] exp;
|
reg [7:0] exp;
|
|
|
begin
|
begin
|
|
|
exp = fp[30:23];
|
exp = fp[30:23];
|
if(exp==8'h7f) $write("(%h %h ( 00 ) %h) ",fp[31], exp, fp[22:0]);
|
if(exp==8'h7f) $write("(%h %h ( 00 ) %h) ",fp[31], exp, fp[22:0]);
|
else
|
else
|
if(exp>8'h7f) $write("(%h %h (+%d ) %h) ",fp[31], exp, exp-8'h7f, fp[22:0]);
|
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]);
|
else $write("(%h %h (-%d ) %h) ",fp[31], exp, 8'h7f-exp, fp[22:0]);
|
|
|
|
|
x[51:0] = {fp[22:0], 29'h0};
|
x[51:0] = {fp[22:0], 29'h0};
|
x[63] = fp[31];
|
x[63] = fp[31];
|
x[62] = fp[30];
|
x[62] = fp[30];
|
x[61:59] = {fp[29], fp[29], fp[29]};
|
x[61:59] = {fp[29], fp[29], fp[29]};
|
x[58:52] = fp[29:23];
|
x[58:52] = fp[29:23];
|
|
|
$display("\t%f",$bitstoreal(x));
|
$display("\t%f",$bitstoreal(x));
|
end
|
end
|
|
|
endtask
|
endtask
|
|
|
endmodule
|
endmodule
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|