EECS151 / fpga_labs_fa20 / lab5 / sim / sync_testbench.v
sync_testbench.v
Raw
`timescale 1ns/100ps
`define CLK_PERIOD 10

// This testbench checks that your synchronizer is made up of 2 flip-flops serially connected.
// This testbench cannot model metastability.

module sync_testbench();
    // Generate 100 Mhz clock
    reg clk = 0;
    always #(`CLK_PERIOD/2) clk = ~clk;

    // I/O of synchronizer
    reg async_signal;
    wire sync_signal;

    synchronizer #(.width(1)) DUT (
        .clk(clk),
        .async_signal(async_signal),
        .sync_signal(sync_signal)
    );

    initial begin
        `ifdef IVERILOG
            $dumpfile("sync_testbench.vcd");
            $dumpvars(0,sync_testbench);
        `endif
        `ifndef IVERILOG
            $vcdpluson;
        `endif

        // We use fork-join to create 2 threads that operate in parallel
        fork
            // This first thread will send a test signal into the DUT's async_signal input
            begin
                async_signal = 1'b0;
                #(`CLK_PERIOD * 2) async_signal = 1'b1;
                #(`CLK_PERIOD * 1) async_signal = 1'b0;
                #(`CLK_PERIOD * 3) async_signal = 1'b1;
                #(`CLK_PERIOD * 2) async_signal = 1'b0;
                #(`CLK_PERIOD * 4) async_signal = 1'b1;
            end
            // This second thread will monitor the DUT's sync_signal output for the correct response
            // The #1 is a Verilog oddity that's needed since the sync_signal changes after the rising edge of the clock,
            //   not at the same instant as the rising edge.
            begin
                repeat (4) @(posedge clk); #1 if (sync_signal !== 1'b1) $display("Check 1 failed");
                repeat (1) @(posedge clk); #1 if (sync_signal !== 1'b0) $display("Check 2 failed");
                repeat (3) @(posedge clk); #1 if (sync_signal !== 1'b1) $display("Check 3 failed");
                repeat (2) @(posedge clk); #1 if (sync_signal !== 1'b0) $display("Check 4 failed");
                repeat (4) @(posedge clk); #1 if (sync_signal !== 1'b1) $display("Check 5 failed");
            end
        join

        repeat (3) @(posedge clk);  // Wait for a little time and perform the final check again
        if (sync_signal !== 1'b1) $display("Check 6 failed");
        $display("Test Done! If any failures were printed, fix them! Otherwise this testbench passed.");
        `ifndef IVERILOG
            $vcdplusoff;
        `endif
        $finish();
    end
endmodule