SOFA/TESTBENCH/digital_io_hd_test/digital_io_hd_test.v

183 lines
5.2 KiB
Verilog

//-------------------------------------------
// Verilog Testbench for Verifying a digital I/O cell
// Description: This test is applicable to the embedded I/O cell
// used in FPGA fabric. This is a self-testing testbench that
// checks the functionality of
// - The I/O isolation signal, which force the I/O in input mode
// - The input mode,
// - where input from SOC can be propagated to FPGA, when enabled
// - where FPGA input holds high-impedence state ('Z'), when disabled
// - The output mode,
// - where output from FPGA can be propagated to SOC, when enabled
// - where SOC output holds high-impedence state ('Z'), when disabled
//
// Author: Xifan TANG
// Organization: University of Utah
//-------------------------------------------
//----- Time scale -----
`timescale 1ns / 1ps
`define CLOCK_PERIOD 5
`define NUM_TEST_CLOCK_CYCLES 10
module digital_io_hd_test;
// Local clock to
// - synchronize stimulus generation
// - trigger checkout point
reg [0:0] clock;
// Local wires for Design Under Test (DUT)
reg [0:0] IO_ISOL_N;
reg [0:0] FPGA_DIR;
reg [0:0] SOC_IN;
reg [0:0] FPGA_OUT;
wire [0:0] SOC_DIR;
wire [0:0] FPGA_IN;
wire [0:0] SOC_OUT;
// ----- Counters for error checking -----
integer num_clock_cycles = 0;
integer num_errors = 0;
integer num_checked_points = 0;
// Clock pulse generation
initial
begin
clock[0] = 1'b0;
end
always
begin
#`CLOCK_PERIOD clock[0] = ~clock[0];
end
// IO_ISOL_N stimuli:
// - enabled for two clock cycles
// - disabled then
initial
begin
IO_ISOL_N[0] = 1'b0;
#(`CLOCK_PERIOD*4) IO_ISOL_N[0] = 1'b1;
end
// FPGA_DIR stimuli: swing between 0 and 1
// - Test if DIR works when IO_ISOL_N is enabled
// - Test if DIR works when IO_ISOL_N is disabled
initial
begin
FPGA_DIR[0] = 1'b0;
#(`CLOCK_PERIOD) FPGA_DIR[0] = 1'b1;
forever #(`CLOCK_PERIOD*4) FPGA_DIR[0] = ~FPGA_DIR[0];
end
// SOC_IN stimuli: swing in the frequency of double clock period
initial
begin
SOC_IN[0] = 1'b0;
end
always
begin
#(`CLOCK_PERIOD*2) SOC_IN[0] = ~SOC_IN[0];
end
// FPGA_OUTPUT stimuli: swing in the frequency of double clock period
initial
begin
FPGA_OUT[0] = 1'b0;
end
always
begin
#(`CLOCK_PERIOD*2) FPGA_OUT[0] = ~FPGA_OUT[0];
end
// Instanciate the digital I/O cell
EMBEDDED_IO_HD IO_DUT (
.IO_ISOL_N(IO_ISOL_N),
.FPGA_DIR(FPGA_DIR),
.FPGA_IN(FPGA_IN),
.FPGA_OUT(FPGA_OUT),
.SOC_DIR(SOC_DIR),
.SOC_IN(SOC_IN),
.SOC_OUT(SOC_OUT)
);
// Count number of clock cycles
always @(posedge clock[0]) begin
num_clock_cycles = num_clock_cycles + 1;
end
// Check expected values at SOC_DIR port
always @(posedge clock[0]) begin
// SOC DIR should stay at logic '1' when IO_ISOL_N is enabled
if (1'b0 == IO_ISOL_N) begin
if (1'b1 !== SOC_DIR) begin
$display("Error: SOC_DIR = %b (expect =%b)", SOC_DIR, 1'b1);
num_errors = num_errors + 1;
end
end else if (1'b1 == IO_ISOL_N) begin
if (FPGA_DIR !== SOC_DIR) begin
$display("Error: SOC_DIR = %b (expect =%b)", SOC_DIR, FPGA_DIR);
num_errors = num_errors + 1;
end
end
num_checked_points = num_checked_points + 1;
end
// Check expected values at FPGA_IN port
always @(posedge clock[0]) begin
// FPGA_IN should be same as SOC_IN when IO_ISOL_N is enabled
if (1'b0 == IO_ISOL_N) begin
if (SOC_IN !== FPGA_IN) begin
$display("Error: FPGA_IN = %b (expect =%b)", FPGA_IN, SOC_IN);
num_errors = num_errors + 1;
end
end else if (1'b1 == IO_ISOL_N) begin
if (1'b1 == FPGA_DIR) begin
if (SOC_IN !== FPGA_IN) begin
$display("Error: FPGA_IN = %b (expect =%b)", FPGA_IN, SOC_IN);
num_errors = num_errors + 1;
end
end else if (1'b0 == FPGA_DIR) begin
if (1'bz !== FPGA_IN) begin
$display("Error: FPGA_IN = %b (expect =%b)", FPGA_IN, 1'bz);
num_errors = num_errors + 1;
end
end
end
num_checked_points = num_checked_points + 1;
end
// Check expected values at SOC_OUT port
always @(posedge clock[0]) begin
// SOC_OUT should be 'z' when IO_ISOL_N is enabled
if (1'b0 == IO_ISOL_N) begin
if (1'bz !== SOC_OUT) begin
$display("Error: SOC_OUT = %b (expect =%b)", SOC_OUT, 1'bz);
num_errors = num_errors + 1;
end
end else if (1'b1 == IO_ISOL_N) begin
if (1'b1 == FPGA_DIR) begin
if (1'bz !== SOC_OUT) begin
$display("Error: SOC_OUT = %b (expect =%b)", SOC_OUT, 1'bz);
num_errors = num_errors + 1;
end
end else if (1'b0 == FPGA_DIR) begin
if (FPGA_OUT !== SOC_OUT) begin
$display("Error: SOC_OUT = %b (expect =%b)", SOC_OUT, FPGA_OUT);
num_errors = num_errors + 1;
end
end
end
num_checked_points = num_checked_points + 1;
end
// Finish after a number of clock cycles
always @(posedge clock[0]) begin
if (`NUM_TEST_CLOCK_CYCLES < num_clock_cycles) begin
$display("Simulation finish with %d errors / %d checkpoints", num_errors, num_checked_points);
$finish;
end
end
endmodule