`timescale 1ns / 1ps

module tb_median7_denoiser;
    reg clk;
    reg rst;
    reg signed [11:0] sample_in;

    wire out_valid;
    wire signed [11:0] sample_out;

    integer errors = 0;
    integer tests_run = 0;
    integer cycle_count = 0;
    integer i;

// Generated by generate_golden.py. Do not edit by hand.
localparam integer NUM_TESTS = 72;
reg test_rst [0:NUM_TESTS-1];
reg signed [11:0] test_sample [0:NUM_TESTS-1];
reg expected_valid [0:NUM_TESTS-1];
reg signed [11:0] expected_sample [0:NUM_TESTS-1];
reg [255:0] test_tag [0:NUM_TESTS-1];

initial begin
    test_rst[0] = 1'b1;
    test_sample[0] = 12'sh000;
    expected_valid[0] = 1'b0;
    expected_sample[0] = 12'sh000;
    test_tag[0] = "startup_reset";
    test_rst[1] = 1'b1;
    test_sample[1] = 12'sh000;
    expected_valid[1] = 1'b0;
    expected_sample[1] = 12'sh000;
    test_tag[1] = "startup_reset";
    test_rst[2] = 1'b0;
    test_sample[2] = 12'shff7;
    expected_valid[2] = 1'b0;
    expected_sample[2] = 12'sh000;
    test_tag[2] = "startup_monotonic";
    test_rst[3] = 1'b0;
    test_sample[3] = 12'shffc;
    expected_valid[3] = 1'b0;
    expected_sample[3] = 12'sh000;
    test_tag[3] = "startup_monotonic";
    test_rst[4] = 1'b0;
    test_sample[4] = 12'sh000;
    expected_valid[4] = 1'b0;
    expected_sample[4] = 12'sh000;
    test_tag[4] = "startup_monotonic";
    test_rst[5] = 1'b0;
    test_sample[5] = 12'sh003;
    expected_valid[5] = 1'b0;
    expected_sample[5] = 12'sh000;
    test_tag[5] = "startup_monotonic";
    test_rst[6] = 1'b0;
    test_sample[6] = 12'sh008;
    expected_valid[6] = 1'b0;
    expected_sample[6] = 12'sh000;
    test_tag[6] = "startup_monotonic";
    test_rst[7] = 1'b0;
    test_sample[7] = 12'sh00c;
    expected_valid[7] = 1'b0;
    expected_sample[7] = 12'sh000;
    test_tag[7] = "startup_monotonic";
    test_rst[8] = 1'b0;
    test_sample[8] = 12'sh014;
    expected_valid[8] = 1'b0;
    expected_sample[8] = 12'sh000;
    test_tag[8] = "startup_monotonic";
    test_rst[9] = 1'b0;
    test_sample[9] = 12'sh019;
    expected_valid[9] = 1'b1;
    expected_sample[9] = 12'sh003;
    test_tag[9] = "startup_monotonic";
    test_rst[10] = 1'b0;
    test_sample[10] = 12'sh01e;
    expected_valid[10] = 1'b1;
    expected_sample[10] = 12'sh008;
    test_tag[10] = "startup_monotonic";
    test_rst[11] = 1'b1;
    test_sample[11] = 12'sh000;
    expected_valid[11] = 1'b0;
    expected_sample[11] = 12'sh000;
    test_tag[11] = "pos_impulse_reset";
    test_rst[12] = 1'b0;
    test_sample[12] = 12'sh00a;
    expected_valid[12] = 1'b0;
    expected_sample[12] = 12'sh000;
    test_tag[12] = "pos_impulse";
    test_rst[13] = 1'b0;
    test_sample[13] = 12'sh00b;
    expected_valid[13] = 1'b0;
    expected_sample[13] = 12'sh000;
    test_tag[13] = "pos_impulse";
    test_rst[14] = 1'b0;
    test_sample[14] = 12'sh00c;
    expected_valid[14] = 1'b0;
    expected_sample[14] = 12'sh000;
    test_tag[14] = "pos_impulse";
    test_rst[15] = 1'b0;
    test_sample[15] = 12'sh12c;
    expected_valid[15] = 1'b0;
    expected_sample[15] = 12'sh000;
    test_tag[15] = "pos_impulse";
    test_rst[16] = 1'b0;
    test_sample[16] = 12'sh00d;
    expected_valid[16] = 1'b0;
    expected_sample[16] = 12'sh000;
    test_tag[16] = "pos_impulse";
    test_rst[17] = 1'b0;
    test_sample[17] = 12'sh00b;
    expected_valid[17] = 1'b0;
    expected_sample[17] = 12'sh000;
    test_tag[17] = "pos_impulse";
    test_rst[18] = 1'b0;
    test_sample[18] = 12'sh00a;
    expected_valid[18] = 1'b0;
    expected_sample[18] = 12'sh000;
    test_tag[18] = "pos_impulse";
    test_rst[19] = 1'b0;
    test_sample[19] = 12'sh00a;
    expected_valid[19] = 1'b1;
    expected_sample[19] = 12'sh00b;
    test_tag[19] = "pos_impulse";
    test_rst[20] = 1'b0;
    test_sample[20] = 12'sh009;
    expected_valid[20] = 1'b1;
    expected_sample[20] = 12'sh00b;
    test_tag[20] = "pos_impulse";
    test_rst[21] = 1'b1;
    test_sample[21] = 12'sh000;
    expected_valid[21] = 1'b0;
    expected_sample[21] = 12'sh000;
    test_tag[21] = "neg_impulse_reset";
    test_rst[22] = 1'b0;
    test_sample[22] = 12'shff8;
    expected_valid[22] = 1'b0;
    expected_sample[22] = 12'sh000;
    test_tag[22] = "neg_impulse";
    test_rst[23] = 1'b0;
    test_sample[23] = 12'shff9;
    expected_valid[23] = 1'b0;
    expected_sample[23] = 12'sh000;
    test_tag[23] = "neg_impulse";
    test_rst[24] = 1'b0;
    test_sample[24] = 12'shffa;
    expected_valid[24] = 1'b0;
    expected_sample[24] = 12'sh000;
    test_tag[24] = "neg_impulse";
    test_rst[25] = 1'b0;
    test_sample[25] = 12'shf38;
    expected_valid[25] = 1'b0;
    expected_sample[25] = 12'sh000;
    test_tag[25] = "neg_impulse";
    test_rst[26] = 1'b0;
    test_sample[26] = 12'shffb;
    expected_valid[26] = 1'b0;
    expected_sample[26] = 12'sh000;
    test_tag[26] = "neg_impulse";
    test_rst[27] = 1'b0;
    test_sample[27] = 12'shff9;
    expected_valid[27] = 1'b0;
    expected_sample[27] = 12'sh000;
    test_tag[27] = "neg_impulse";
    test_rst[28] = 1'b0;
    test_sample[28] = 12'shffa;
    expected_valid[28] = 1'b0;
    expected_sample[28] = 12'sh000;
    test_tag[28] = "neg_impulse";
    test_rst[29] = 1'b0;
    test_sample[29] = 12'shffa;
    expected_valid[29] = 1'b1;
    expected_sample[29] = 12'shff9;
    test_tag[29] = "neg_impulse";
    test_rst[30] = 1'b0;
    test_sample[30] = 12'shffb;
    expected_valid[30] = 1'b1;
    expected_sample[30] = 12'shffa;
    test_tag[30] = "neg_impulse";
    test_rst[31] = 1'b1;
    test_sample[31] = 12'sh000;
    expected_valid[31] = 1'b0;
    expected_sample[31] = 12'sh000;
    test_tag[31] = "signed_dup_reset";
    test_rst[32] = 1'b0;
    test_sample[32] = 12'sh7ff;
    expected_valid[32] = 1'b0;
    expected_sample[32] = 12'sh000;
    test_tag[32] = "signed_dup";
    test_rst[33] = 1'b0;
    test_sample[33] = 12'sh800;
    expected_valid[33] = 1'b0;
    expected_sample[33] = 12'sh000;
    test_tag[33] = "signed_dup";
    test_rst[34] = 1'b0;
    test_sample[34] = 12'sh004;
    expected_valid[34] = 1'b0;
    expected_sample[34] = 12'sh000;
    test_tag[34] = "signed_dup";
    test_rst[35] = 1'b0;
    test_sample[35] = 12'sh004;
    expected_valid[35] = 1'b0;
    expected_sample[35] = 12'sh000;
    test_tag[35] = "signed_dup";
    test_rst[36] = 1'b0;
    test_sample[36] = 12'shffe;
    expected_valid[36] = 1'b0;
    expected_sample[36] = 12'sh000;
    test_tag[36] = "signed_dup";
    test_rst[37] = 1'b0;
    test_sample[37] = 12'sh004;
    expected_valid[37] = 1'b0;
    expected_sample[37] = 12'sh000;
    test_tag[37] = "signed_dup";
    test_rst[38] = 1'b0;
    test_sample[38] = 12'sh009;
    expected_valid[38] = 1'b0;
    expected_sample[38] = 12'sh000;
    test_tag[38] = "signed_dup";
    test_rst[39] = 1'b0;
    test_sample[39] = 12'sh007;
    expected_valid[39] = 1'b1;
    expected_sample[39] = 12'sh004;
    test_tag[39] = "signed_dup";
    test_rst[40] = 1'b0;
    test_sample[40] = 12'shfe2;
    expected_valid[40] = 1'b1;
    expected_sample[40] = 12'sh004;
    test_tag[40] = "signed_dup";
    test_rst[41] = 1'b1;
    test_sample[41] = 12'sh000;
    expected_valid[41] = 1'b0;
    expected_sample[41] = 12'sh000;
    test_tag[41] = "sliding_reset";
    test_rst[42] = 1'b0;
    test_sample[42] = 12'sh005;
    expected_valid[42] = 1'b0;
    expected_sample[42] = 12'sh000;
    test_tag[42] = "sliding_windows";
    test_rst[43] = 1'b0;
    test_sample[43] = 12'sh001;
    expected_valid[43] = 1'b0;
    expected_sample[43] = 12'sh000;
    test_tag[43] = "sliding_windows";
    test_rst[44] = 1'b0;
    test_sample[44] = 12'sh009;
    expected_valid[44] = 1'b0;
    expected_sample[44] = 12'sh000;
    test_tag[44] = "sliding_windows";
    test_rst[45] = 1'b0;
    test_sample[45] = 12'sh003;
    expected_valid[45] = 1'b0;
    expected_sample[45] = 12'sh000;
    test_tag[45] = "sliding_windows";
    test_rst[46] = 1'b0;
    test_sample[46] = 12'sh007;
    expected_valid[46] = 1'b0;
    expected_sample[46] = 12'sh000;
    test_tag[46] = "sliding_windows";
    test_rst[47] = 1'b0;
    test_sample[47] = 12'sh00b;
    expected_valid[47] = 1'b0;
    expected_sample[47] = 12'sh000;
    test_tag[47] = "sliding_windows";
    test_rst[48] = 1'b0;
    test_sample[48] = 12'sh00d;
    expected_valid[48] = 1'b0;
    expected_sample[48] = 12'sh000;
    test_tag[48] = "sliding_windows";
    test_rst[49] = 1'b0;
    test_sample[49] = 12'sh00f;
    expected_valid[49] = 1'b1;
    expected_sample[49] = 12'sh007;
    test_tag[49] = "sliding_windows";
    test_rst[50] = 1'b0;
    test_sample[50] = 12'shffb;
    expected_valid[50] = 1'b1;
    expected_sample[50] = 12'sh009;
    test_tag[50] = "sliding_windows";
    test_rst[51] = 1'b0;
    test_sample[51] = 12'sh004;
    expected_valid[51] = 1'b1;
    expected_sample[51] = 12'sh009;
    test_tag[51] = "sliding_windows";
    test_rst[52] = 1'b0;
    test_sample[52] = 12'sh006;
    expected_valid[52] = 1'b1;
    expected_sample[52] = 12'sh007;
    test_tag[52] = "sliding_windows";
    test_rst[53] = 1'b0;
    test_sample[53] = 12'sh008;
    expected_valid[53] = 1'b1;
    expected_sample[53] = 12'sh007;
    test_tag[53] = "sliding_windows";
    test_rst[54] = 1'b1;
    test_sample[54] = 12'sh000;
    expected_valid[54] = 1'b0;
    expected_sample[54] = 12'sh000;
    test_tag[54] = "midstream_reset_begin";
    test_rst[55] = 1'b0;
    test_sample[55] = 12'sh014;
    expected_valid[55] = 1'b0;
    expected_sample[55] = 12'sh000;
    test_tag[55] = "midstream_before_reset";
    test_rst[56] = 1'b0;
    test_sample[56] = 12'sh015;
    expected_valid[56] = 1'b0;
    expected_sample[56] = 12'sh000;
    test_tag[56] = "midstream_before_reset";
    test_rst[57] = 1'b0;
    test_sample[57] = 12'sh016;
    expected_valid[57] = 1'b0;
    expected_sample[57] = 12'sh000;
    test_tag[57] = "midstream_before_reset";
    test_rst[58] = 1'b0;
    test_sample[58] = 12'sh017;
    expected_valid[58] = 1'b0;
    expected_sample[58] = 12'sh000;
    test_tag[58] = "midstream_before_reset";
    test_rst[59] = 1'b0;
    test_sample[59] = 12'sh018;
    expected_valid[59] = 1'b0;
    expected_sample[59] = 12'sh000;
    test_tag[59] = "midstream_before_reset";
    test_rst[60] = 1'b0;
    test_sample[60] = 12'sh019;
    expected_valid[60] = 1'b0;
    expected_sample[60] = 12'sh000;
    test_tag[60] = "midstream_before_reset";
    test_rst[61] = 1'b0;
    test_sample[61] = 12'sh01a;
    expected_valid[61] = 1'b0;
    expected_sample[61] = 12'sh000;
    test_tag[61] = "midstream_before_reset";
    test_rst[62] = 1'b0;
    test_sample[62] = 12'sh01b;
    expected_valid[62] = 1'b1;
    expected_sample[62] = 12'sh017;
    test_tag[62] = "midstream_before_reset";
    test_rst[63] = 1'b1;
    test_sample[63] = 12'sh000;
    expected_valid[63] = 1'b0;
    expected_sample[63] = 12'sh000;
    test_tag[63] = "midstream_reset_assert";
    test_rst[64] = 1'b0;
    test_sample[64] = 12'shfff;
    expected_valid[64] = 1'b0;
    expected_sample[64] = 12'sh000;
    test_tag[64] = "midstream_after_reset";
    test_rst[65] = 1'b0;
    test_sample[65] = 12'shffe;
    expected_valid[65] = 1'b0;
    expected_sample[65] = 12'sh000;
    test_tag[65] = "midstream_after_reset";
    test_rst[66] = 1'b0;
    test_sample[66] = 12'shffd;
    expected_valid[66] = 1'b0;
    expected_sample[66] = 12'sh000;
    test_tag[66] = "midstream_after_reset";
    test_rst[67] = 1'b0;
    test_sample[67] = 12'shffc;
    expected_valid[67] = 1'b0;
    expected_sample[67] = 12'sh000;
    test_tag[67] = "midstream_after_reset";
    test_rst[68] = 1'b0;
    test_sample[68] = 12'shffb;
    expected_valid[68] = 1'b0;
    expected_sample[68] = 12'sh000;
    test_tag[68] = "midstream_after_reset";
    test_rst[69] = 1'b0;
    test_sample[69] = 12'shffa;
    expected_valid[69] = 1'b0;
    expected_sample[69] = 12'sh000;
    test_tag[69] = "midstream_after_reset";
    test_rst[70] = 1'b0;
    test_sample[70] = 12'shff9;
    expected_valid[70] = 1'b0;
    expected_sample[70] = 12'sh000;
    test_tag[70] = "midstream_after_reset";
    test_rst[71] = 1'b0;
    test_sample[71] = 12'shff8;
    expected_valid[71] = 1'b1;
    expected_sample[71] = 12'shffc;
    test_tag[71] = "midstream_after_reset";
end

    median7_denoiser uut (
        .clk(clk),
        .rst(rst),
        .sample_in(sample_in),
        .out_valid(out_valid),
        .sample_out(sample_out)
    );

    initial begin
        clk = 1'b0;
        forever #5 clk = ~clk;
    end

    task apply_cycle;
        input integer cycle_idx;
        begin
            rst = test_rst[cycle_idx];
            sample_in = test_sample[cycle_idx];

            @(posedge clk);
            #1;

            cycle_count = cycle_count + 1;
            tests_run = tests_run + 1;

            if (out_valid !== expected_valid[cycle_idx]) begin
                $display("ERROR [%s cycle %0d]: out_valid mismatch. expected=%b got=%b",
                         test_tag[cycle_idx], cycle_count, expected_valid[cycle_idx], out_valid);
                errors = errors + 1;
            end

            if ((test_rst[cycle_idx] || expected_valid[cycle_idx]) &&
                (sample_out !== expected_sample[cycle_idx])) begin
                $display("ERROR [%s cycle %0d]: sample_out mismatch. expected=%0d got=%0d",
                         test_tag[cycle_idx], cycle_count,
                         $signed(expected_sample[cycle_idx]), $signed(sample_out));
                errors = errors + 1;
            end
        end
    endtask

    initial begin
        rst = 1'b0;
        sample_in = 12'sh000;

        $display("===========================================");
        $display("        Median7 Signal Denoiser Testbench");
        $display("===========================================");

        for (i = 0; i < NUM_TESTS; i = i + 1) begin
            apply_cycle(i);
        end

        $display("");
        $display("===========================================");
        $display("  Tests Run: %0d", tests_run);
        $display("===========================================");

        if (errors == 0) begin
            $display("TEST_RESULT: PASS");
        end else begin
            $display("TEST_RESULT: FAIL (%0d errors)", errors);
        end

        $finish;
    end
endmodule
