|
|
`define SCAN_DELAY #1
|
`define SCAN_DELAY #1
|
|
|
module tbench();
|
module tbench();
|
|
|
// Scan
|
// Scan
|
reg scan_phi, scan_phi_bar, scan_data_in, scan_load_chip, scan_load_chain;
|
reg scan_phi, scan_phi_bar, scan_data_in, scan_load_chip, scan_load_chain;
|
wire scan_data_out;
|
wire scan_data_out;
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// Scan Chain Registers and Tasks
|
// Scan Chain Registers and Tasks
|
//-----------------------------------------
|
//-----------------------------------------
|
|
|
// Scan Registers and Initializations
|
// Scan Registers and Initializations
|
|
|
PERL begin
|
PERL begin
|
/*
|
/*
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
|
|
print "`define SCAN_CHAIN_LENGTH $scan_chain_length\n\n";
|
print "`define SCAN_CHAIN_LENGTH $scan_chain_length\n\n";
|
|
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
|
|
my $begin = 0;
|
my $begin = 0;
|
my $end = $signal_list[$i]{size} - 1;
|
my $end = $signal_list[$i]{size} - 1;
|
|
|
print " reg [$end:$begin] " . $signal_list[$i]{name} . ";\n";
|
print " reg [$end:$begin] " . $signal_list[$i]{name} . ";\n";
|
print " reg [$end:$begin] " . $signal_list[$i]{name} . "_read;\n";
|
print " reg [$end:$begin] " . $signal_list[$i]{name} . "_read;\n";
|
print " initial " . $signal_list[$i]{name} . " = " .$signal_list[$i]{size} . "'d0;\n";
|
print " initial " . $signal_list[$i]{name} . " = " .$signal_list[$i]{size} . "'d0;\n";
|
print " initial " . $signal_list[$i]{name} . "_read = " .$signal_list[$i]{size} . "'d0;\n";
|
print " initial " . $signal_list[$i]{name} . "_read = " .$signal_list[$i]{size} . "'d0;\n";
|
}
|
}
|
|
|
*/
|
*/
|
end
|
end
|
|
|
// Scan chain tasks
|
// Scan chain tasks
|
|
|
task load_chip;
|
task load_chip;
|
begin
|
begin
|
`SCAN_DELAY scan_load_chip = 1;
|
`SCAN_DELAY scan_load_chip = 1;
|
`SCAN_DELAY scan_load_chip = 0;
|
`SCAN_DELAY scan_load_chip = 0;
|
end
|
end
|
endtask
|
endtask
|
|
|
task load_chain;
|
task load_chain;
|
begin
|
begin
|
`SCAN_DELAY scan_load_chain = 1;
|
`SCAN_DELAY scan_load_chain = 1;
|
`SCAN_DELAY scan_phi = 1;
|
`SCAN_DELAY scan_phi = 1;
|
`SCAN_DELAY scan_phi = 0;
|
`SCAN_DELAY scan_phi = 0;
|
`SCAN_DELAY scan_phi_bar = 1;
|
`SCAN_DELAY scan_phi_bar = 1;
|
`SCAN_DELAY scan_phi_bar = 0;
|
`SCAN_DELAY scan_phi_bar = 0;
|
`SCAN_DELAY scan_load_chain = 0;
|
`SCAN_DELAY scan_load_chain = 0;
|
end
|
end
|
endtask
|
endtask
|
|
|
task rotate_chain;
|
task rotate_chain;
|
|
|
integer i;
|
integer i;
|
|
|
reg [`SCAN_CHAIN_LENGTH-1:0] data_in;
|
reg [`SCAN_CHAIN_LENGTH-1:0] data_in;
|
reg [`SCAN_CHAIN_LENGTH-1:0] data_out;
|
reg [`SCAN_CHAIN_LENGTH-1:0] data_out;
|
|
|
begin
|
begin
|
PERL begin
|
PERL begin
|
/*
|
/*
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
|
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
|
|
my $begin = $signal_list[$i]{start};
|
my $begin = $signal_list[$i]{start};
|
my $end = $signal_list[$i]{start} + $signal_list[$i]{size} - 1;
|
my $end = $signal_list[$i]{start} + $signal_list[$i]{size} - 1;
|
|
|
print " data_in[$end:$begin] = " . $signal_list[$i]{name} . ";\n";
|
print " data_in[$end:$begin] = " . $signal_list[$i]{name} . ";\n";
|
}
|
}
|
|
|
*/
|
*/
|
end
|
end
|
|
|
for (i = 0; i < `SCAN_CHAIN_LENGTH; i=i+1) begin
|
for (i = 0; i < `SCAN_CHAIN_LENGTH; i=i+1) begin
|
scan_data_in = data_in[0];
|
scan_data_in = data_in[0];
|
data_out = {scan_data_out, data_out[`SCAN_CHAIN_LENGTH-1:1]};
|
data_out = {scan_data_out, data_out[`SCAN_CHAIN_LENGTH-1:1]};
|
`SCAN_DELAY scan_phi = 1;
|
`SCAN_DELAY scan_phi = 1;
|
`SCAN_DELAY scan_phi = 0;
|
`SCAN_DELAY scan_phi = 0;
|
`SCAN_DELAY scan_phi_bar = 1;
|
`SCAN_DELAY scan_phi_bar = 1;
|
`SCAN_DELAY scan_phi_bar = 0;
|
`SCAN_DELAY scan_phi_bar = 0;
|
`SCAN_DELAY data_in = data_in >> 1;
|
`SCAN_DELAY data_in = data_in >> 1;
|
end
|
end
|
|
|
PERL begin
|
PERL begin
|
/*
|
/*
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
|
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
|
|
my $begin = $signal_list[$i]{start};
|
my $begin = $signal_list[$i]{start};
|
my $end = $signal_list[$i]{start} + $signal_list[$i]{size} - 1;
|
my $end = $signal_list[$i]{start} + $signal_list[$i]{size} - 1;
|
|
|
print " " . $signal_list[$i]{name} . "_read = data_out[$end:$begin];\n";
|
print " " . $signal_list[$i]{name} . "_read = data_out[$end:$begin];\n";
|
}
|
}
|
|
|
*/
|
*/
|
end
|
end
|
end
|
end
|
|
|
endtask
|
endtask
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// Scan chain DUT
|
// Scan chain DUT
|
//-----------------------------------------
|
//-----------------------------------------
|
|
|
// We're going to use the name chip_iternal_<NAME> for the signals that would
|
// We're going to use the name chip_iternal_<NAME> for the signals that would
|
// normally be inside the chip that we're interacting with. We'll generate them
|
// normally be inside the chip that we're interacting with. We'll generate them
|
// here
|
// here
|
|
|
PERL begin
|
PERL begin
|
/*
|
/*
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
|
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
if ($signal_list[$i]{writable} == 1) {
|
if ($signal_list[$i]{writable} == 1) {
|
print " wire ";
|
print " wire ";
|
} else {
|
} else {
|
print " reg ";
|
print " reg ";
|
}
|
}
|
|
|
print "[$signal_list[$i]{size}-1:0] chip_internal_$signal_list[$i]{name};\n";
|
print "[$signal_list[$i]{size}-1:0] chip_internal_$signal_list[$i]{name};\n";
|
}
|
}
|
|
|
*/
|
*/
|
end
|
end
|
|
|
scan scan_dut ( // Inputs & outputs to the chip
|
scan scan_dut ( // Inputs & outputs to the chip
|
PERL begin
|
PERL begin
|
/*
|
/*
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
DEPERLIFY_INCLUDE(scan_signal_list.pl);
|
|
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
for (my $i = 0; $i < scalar @signal_list; $i++) {
|
print " .$signal_list[$i]{name}(chip_internal_$signal_list[$i]{name}),\n";
|
print " .$signal_list[$i]{name}(chip_internal_$signal_list[$i]{name}),\n";
|
}
|
}
|
|
|
*/
|
*/
|
end
|
end
|
|
|
// To the pads
|
// To the pads
|
.scan_phi (scan_phi),
|
.scan_phi (scan_phi),
|
.scan_phi_bar (scan_phi_bar),
|
.scan_phi_bar (scan_phi_bar),
|
.scan_data_in (scan_data_in),
|
.scan_data_in (scan_data_in),
|
.scan_data_out (scan_data_out),
|
.scan_data_out (scan_data_out),
|
.scan_load_chip (scan_load_chip),
|
.scan_load_chip (scan_load_chip),
|
.scan_load_chain (scan_load_chain)
|
.scan_load_chain (scan_load_chain)
|
);
|
);
|
|
|
|
|
//-----------------------------------------
|
//-----------------------------------------
|
// Testbench
|
// Testbench
|
//-----------------------------------------
|
//-----------------------------------------
|
|
|
initial begin
|
initial begin
|
|
|
$display("Starting scan chain test");
|
$display("Starting scan chain test");
|
|
|
scan_phi = 0;
|
scan_phi = 0;
|
scan_phi_bar = 0;
|
scan_phi_bar = 0;
|
scan_data_in = 0;
|
scan_data_in = 0;
|
scan_load_chip = 0;
|
scan_load_chip = 0;
|
scan_load_chain = 0;
|
scan_load_chain = 0;
|
|
|
rotate_chain();
|
rotate_chain();
|
load_chip();
|
load_chip();
|
|
|
// Write each variable
|
// Write each variable
|
write_data_1 = 1'd1;
|
write_data_1 = 1'd1;
|
write_data_2 = 2'd2;
|
write_data_2 = 2'd2;
|
write_data_3 = 3'd3;
|
write_data_3 = 3'd3;
|
|
|
rotate_chain();
|
rotate_chain();
|
load_chip();
|
load_chip();
|
|
|
// Check that the chip sees the new variables
|
// Check that the chip sees the new variables
|
if (chip_internal_write_data_1 != 1'd1 ||
|
if (chip_internal_write_data_1 != 1'd1 ||
|
chip_internal_write_data_2 != 2'd2 ||
|
chip_internal_write_data_2 != 2'd2 ||
|
chip_internal_write_data_3 != 3'd3 )
|
chip_internal_write_data_3 != 3'd3 )
|
$display("TEST 1 FAILED");
|
$display("TEST 1 FAILED");
|
else
|
else
|
$display("TEST 1 PASSED");
|
$display("TEST 1 PASSED");
|
|
|
// Set internal values to read out
|
// Set internal values to read out
|
chip_internal_read_data_1 = 1'd0; // As if the chip had this value internally
|
chip_internal_read_data_1 = 1'd0; // As if the chip had this value internally
|
chip_internal_read_data_2 = 2'd3;
|
chip_internal_read_data_2 = 2'd3;
|
chip_internal_read_data_3 = 3'd5;
|
chip_internal_read_data_3 = 3'd5;
|
|
|
// Read all of the values for both writable and non-writable variables
|
// Read all of the values for both writable and non-writable variables
|
load_chain();
|
load_chain();
|
rotate_chain();
|
rotate_chain();
|
|
|
// Check to see that we read out all values properly
|
// Check to see that we read out all values properly
|
if (write_data_1_read != 1'd1 ||
|
if (write_data_1_read != 1'd1 ||
|
write_data_2_read != 2'd2 ||
|
write_data_2_read != 2'd2 ||
|
write_data_3_read != 3'd3 ||
|
write_data_3_read != 3'd3 ||
|
read_data_1_read != 1'd0 ||
|
read_data_1_read != 1'd0 ||
|
read_data_2_read != 2'd3 ||
|
read_data_2_read != 2'd3 ||
|
read_data_3_read != 3'd5 ) begin
|
read_data_3_read != 3'd5 ) begin
|
$display("TEST 2 FAILED");
|
$display("TEST 2 FAILED");
|
$display("%d %d %d %d %d %d",
|
$display("%d %d %d %d %d %d",
|
write_data_1_read,
|
write_data_1_read,
|
write_data_2_read,
|
write_data_2_read,
|
write_data_3_read,
|
write_data_3_read,
|
read_data_1_read,
|
read_data_1_read,
|
read_data_2_read,
|
read_data_2_read,
|
read_data_3_read);
|
read_data_3_read);
|
end else
|
end else
|
$display("TEST 2 PASSED");
|
$display("TEST 2 PASSED");
|
|
|
|
|
$finish;
|
$finish;
|
end
|
end
|
|
|
//////////
|
//////////
|
|
|
endmodule // tbench
|
endmodule // tbench
|
|
|
|
|