`timescale 1ns / 1ps

`ifdef VERILATOR
    `include "assertion_error.sv"
`endif
import assertion_error::errors;
module debouncer_tb;

parameter TESTCYCLES=1000;

logic clk,reset,source;
wire out;

debouncer Dut (.*);
bind debouncer debouncer_assertions AssertDut (.*);

initial begin
    clk = 0;
    forever #10 clk = ~clk;
end

initial begin
    // Turn assertions off during reset
    $assertoff;
    $display("Testing debouncer");
    reset = 1;
    source = 0;
    @(posedge clk);
    @(posedge clk);
    reset = 0;
    $asserton;
    @(posedge clk);
    source = 1;
    #1;
    assert (out == 1) else begin
        $error("Output not brought high during first press");
        errors++;
    end
    @(posedge clk);
    #1;
    assert (out == 0) else begin
        $error("Output not brought low after first press");
        errors++;
    end
    @(posedge clk);
    source = 0;
    @(posedge clk);
    source = 1;
    #1;
    assert (out == 1) else begin
        $error("Output not brought high during second press");
        errors++;
    end
    @(posedge clk);
    source = 0;
    @(posedge clk);
    #1;
    assert (out == 0) else begin
        $error("Output not brought low after second press");
        errors++;
    end

    $display("Generating random input to test assertions");
    for (int i=0; i<TESTCYCLES; i++) begin
        source = $urandom;
        @(posedge clk);
    end

    if (errors == 0)
        $display("Found no errors while testing debouncer");
    else
        $display("ERROR: Found %0d errors while testing debouncer", errors);

    $finish;

end
endmodule
