Line 1... |
Line 1... |
`define HALF_CYCLE 1000
|
|
`timescale 1ns / 1ps
|
`timescale 1ns / 1ps
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
// Company:
|
// Company:
|
// Engineer: Yihua Liu
|
// Engineer: Yihua Liu
|
//
|
//
|
// Create Date: 2022/06/08 16:51:12
|
// Create Date: 2022/10/14 01:01:28
|
// Design Name:
|
// Design Name:
|
// Module Name: testbench
|
// Module Name: testbench
|
// Project Name: lab_3_b
|
// Project Name: lab_3_b
|
// Target Devices: xczu7eg-ffvf1517-2-i
|
// Target Devices: xczu7eg-ffvf1517-2-i
|
// Tool Versions:
|
// Tool Versions:
|
Line 14... |
Line 13... |
//
|
//
|
// Dependencies:
|
// Dependencies:
|
//
|
//
|
// Revision:
|
// Revision:
|
// Revision 0.01 - File Created
|
// Revision 0.01 - File Created
|
|
// Revision 0.02 - Update Testbench
|
// Additional Comments:
|
// Additional Comments:
|
//
|
//
|
//////////////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
module testbench();
|
module testbench();
|
|
|
logic [63:0] value;
|
logic [63:0] test_input;
|
logic clock, reset;
|
logic clock, reset, quit;
|
|
|
logic [31:0] result;
|
logic [31:0] result;
|
logic done;
|
logic done;
|
|
|
logic [31:0] cres;
|
integer i;
|
|
|
wire correct = (cres===result)|~done|reset;
|
ISR UUT(
|
|
|
integer value_test, j;
|
|
time start_time = $time, finish_time;
|
|
|
|
task ISR_test;
|
|
input [63:0] value;
|
|
output [31:0] cres;
|
|
cres = 0;
|
|
for (integer i = 31; i >= 0; i--) begin
|
|
cres[i] = 1;
|
|
if (cres * cres > value)
|
|
cres[i] = 0;
|
|
end
|
|
endtask
|
|
|
|
ISR isr(
|
|
.reset(reset),
|
.reset(reset),
|
.value(value),
|
.value(test_input),
|
.clock(clock),
|
.clock(clock),
|
.result(result),
|
.result(result),
|
.done(done)
|
.done(done)
|
);
|
);
|
|
|
always @(posedge clock)
|
task compare_correct_result;
|
#2 if(!correct) begin
|
input [63:0] value;
|
$display("Incorrect at time %4.0f",$time);
|
input [31:0] result;
|
$display("cres = %h result = %h",cres,result);
|
|
|
logic [31:0] guess;
|
|
logic [63:0] multi;
|
|
begin
|
|
// First, calculate the correct result
|
|
guess = 32'h8000_0000;
|
|
for (i = 0; i <= 31; i = i + 1) begin
|
|
guess[31 - i] = 1'b1;
|
|
multi = {32'b0, guess};
|
|
if ((multi * multi) > value) begin
|
|
guess[31 - i] = 1'b0;
|
|
end
|
|
end
|
|
// Then, compare the result with the correct one
|
|
if (result == guess) begin
|
|
end
|
|
else begin
|
$display("@@@Failed");
|
$display("@@@Failed");
|
|
$display("Incorrect at time %4.0f",$time);
|
|
$display("corrent_result = %h result = %h", guess, result);
|
$finish;
|
$finish;
|
end
|
end
|
|
end
|
|
endtask
|
|
|
|
|
always begin
|
always begin
|
#`HALF_CYCLE;
|
#250;
|
clock=~clock;
|
clock=~clock;
|
end
|
end
|
|
|
|
// Some users have had problems just using "@(posedge done)" because their
|
|
// "done" signals glitch (even though they are the output of a register). This
|
|
// prevents that by making sure "done" is high at the clock edge.
|
task wait_until_done;
|
task wait_until_done;
|
forever begin : wait_loop
|
forever begin : wait_loop
|
@(posedge done);
|
@(posedge done);
|
@(negedge clock);
|
@(negedge clock);
|
if(done) begin
|
if (done) disable wait_until_done;
|
finish_time = $time;
|
|
$display("Done one calculation of ISR");
|
|
// Calculate the total number of cycles you need to do one calculation of ISR
|
|
// Note that in this way the additional cycles added during simulation will be counted
|
|
// So the displayed value may be 1 to 3 cycles more than 600 cycles
|
|
$display("Number of cycles needed: %d", (finish_time - start_time) / (2 * `HALF_CYCLE));
|
|
start_time = finish_time;
|
|
disable wait_until_done;
|
|
end
|
|
end
|
end
|
endtask
|
endtask
|
|
|
|
|
initial begin
|
initial begin
|
$monitor("Time:%4.0f done:%b cres:%h result:%h reset:%h",$time,done,cres,result,reset);
|
$dumpvars;
|
// Test 1
|
$monitor("Time:%4.0f done:%b input:%h result:%h ",$time, done, test_input, result);
|
value = 0; // square number
|
|
reset = 1;
|
|
clock = 0;
|
|
ISR_test(value, cres);
|
|
#2000;
|
|
@(negedge clock);
|
|
reset = 0;
|
reset = 0;
|
wait_until_done();
|
clock = 0;
|
@(negedge clock);
|
|
// Test 2
|
// First some special cases
|
reset = 1;
|
test_input = 64'h0000_0000_0000_03E9;
|
value = 4; // square number
|
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
|
reset = 0;
|
|
wait_until_done();
|
|
@(negedge clock);
|
@(negedge clock);
|
// Test 3
|
|
reset = 1;
|
reset = 1;
|
value = 121; // square number
|
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
@(negedge clock);
|
reset = 0;
|
reset = 0;
|
wait_until_done();
|
wait_until_done();
|
|
$display("Calculate done!");
|
|
compare_correct_result(test_input, result);
|
@(negedge clock);
|
@(negedge clock);
|
// Test 4
|
|
reset = 1;
|
|
value = 1000000; // square number
|
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
|
reset = 0;
|
|
wait_until_done();
|
|
// Test 5
|
|
reset = 1;
|
reset = 1;
|
value = 130; // non square number
|
test_input = 64'hFFFF_FFFF_FFFF_FFFF;
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
@(negedge clock);
|
reset = 0;
|
reset = 0;
|
wait_until_done();
|
wait_until_done();
|
// Test 6
|
compare_correct_result(test_input, result);
|
@(negedge clock);
|
@(negedge clock);
|
reset = 1;
|
reset = 1;
|
value = 2; // non square number (value to be discarded)
|
test_input = 64'h0000_0000_0000_0000;
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
|
reset = 0;
|
|
@(negedge clock);
|
|
@(negedge clock);
|
|
@(negedge clock);
|
|
reset = 1; // reset is asserted part way through a computation
|
|
value = 3; // non square number (new value to be latched into)
|
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
@(negedge clock);
|
reset = 0;
|
reset = 0;
|
wait_until_done();
|
wait_until_done();
|
|
compare_correct_result(test_input, result);
|
|
|
|
// Then some random tests
|
@(negedge clock);
|
@(negedge clock);
|
@(negedge clock);
|
|
// Test 7
|
|
reset = 1;
|
reset = 1;
|
value = 64'h7FFF_FFFF_FFFF_FFFF;
|
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
@(negedge clock);
|
reset = 0;
|
quit = 0;
|
wait_until_done();
|
quit <= #100000 1;
|
@(negedge clock);
|
while (~quit) begin
|
value_test = 64'hFFFF_FFFF_FFFF_FFFF;
|
|
// Short loops
|
|
for (j = 0; j < 100; j++) begin
|
|
reset = 1;
|
reset = 1;
|
value = value_test;
|
test_input = {$random, $random};
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
@(negedge clock);
|
reset = 0;
|
reset = 0;
|
wait_until_done();
|
wait_until_done();
|
value_test = value_test - 64'h0000_0000_7FFF_FFFF;
|
compare_correct_result(test_input, result);
|
end
|
end
|
// Random testing
|
@(negedge clock);
|
for (j = 0; j < 1000; j++) begin
|
|
reset = 1;
|
reset = 1;
|
value = {$random, $random};
|
|
ISR_test(value, cres);
|
|
@(negedge clock);
|
@(negedge clock);
|
reset = 0;
|
|
wait_until_done();
|
|
end
|
|
$display("@@@Passed");
|
$display("@@@Passed");
|
$finish;
|
$finish;
|
end
|
end
|
|
|
endmodule
|
endmodule
|