`timescale 1ns / 1ps

module tb_bloom_filter_membership;
    reg clk;
    reg rst;
    reg req_valid;
    reg req_insert;
    reg [15:0] key_in;

    wire maybe_present;

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

    bloom_filter_membership uut (
        .clk(clk),
        .rst(rst),
        .req_valid(req_valid),
        .req_insert(req_insert),
        .key_in(key_in),
        .maybe_present(maybe_present)
    );

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

// Generated by generate_golden.py. Do not edit by hand.
localparam integer NUM_TESTS = 24;
reg test_rst [0:NUM_TESTS-1];
reg test_req_valid [0:NUM_TESTS-1];
reg test_req_insert [0:NUM_TESTS-1];
reg [15:0] test_key [0:NUM_TESTS-1];
reg expected_maybe [0:NUM_TESTS-1];
reg [255:0] test_tag [0:NUM_TESTS-1];

initial begin
    test_rst[0] = 1'b1;
    test_req_valid[0] = 1'b0;
    test_req_insert[0] = 1'b0;
    test_key[0] = 16'h0000;
    expected_maybe[0] = 1'b0;
    test_tag[0] = "startup_reset";
    test_rst[1] = 1'b1;
    test_req_valid[1] = 1'b0;
    test_req_insert[1] = 1'b0;
    test_key[1] = 16'h0000;
    expected_maybe[1] = 1'b0;
    test_tag[1] = "startup_reset";
    test_rst[2] = 1'b0;
    test_req_valid[2] = 1'b0;
    test_req_insert[2] = 1'b0;
    test_key[2] = 16'h0000;
    expected_maybe[2] = 1'b0;
    test_tag[2] = "post_reset_idle";
    test_rst[3] = 1'b0;
    test_req_valid[3] = 1'b1;
    test_req_insert[3] = 1'b0;
    test_key[3] = 16'h1234;
    expected_maybe[3] = 1'b0;
    test_tag[3] = "empty_query";
    test_rst[4] = 1'b0;
    test_req_valid[4] = 1'b0;
    test_req_insert[4] = 1'b0;
    test_key[4] = 16'h0000;
    expected_maybe[4] = 1'b0;
    test_tag[4] = "empty_query_resp";
    test_rst[5] = 1'b0;
    test_req_valid[5] = 1'b1;
    test_req_insert[5] = 1'b1;
    test_key[5] = 16'h1234;
    expected_maybe[5] = 1'b0;
    test_tag[5] = "insert_fresh";
    test_rst[6] = 1'b0;
    test_req_valid[6] = 1'b1;
    test_req_insert[6] = 1'b0;
    test_key[6] = 16'h1234;
    expected_maybe[6] = 1'b0;
    test_tag[6] = "query_same";
    test_rst[7] = 1'b0;
    test_req_valid[7] = 1'b1;
    test_req_insert[7] = 1'b1;
    test_key[7] = 16'h1234;
    expected_maybe[7] = 1'b1;
    test_tag[7] = "reinsert_same";
    test_rst[8] = 1'b0;
    test_req_valid[8] = 1'b0;
    test_req_insert[8] = 1'b0;
    test_key[8] = 16'h0000;
    expected_maybe[8] = 1'b1;
    test_tag[8] = "reinsert_resp_idle";
    test_rst[9] = 1'b1;
    test_req_valid[9] = 1'b0;
    test_req_insert[9] = 1'b0;
    test_key[9] = 16'h0000;
    expected_maybe[9] = 1'b0;
    test_tag[9] = "scenario_reset";
    test_rst[10] = 1'b0;
    test_req_valid[10] = 1'b1;
    test_req_insert[10] = 1'b1;
    test_key[10] = 16'h002f;
    expected_maybe[10] = 1'b0;
    test_tag[10] = "overlap_insert_a";
    test_rst[11] = 1'b0;
    test_req_valid[11] = 1'b1;
    test_req_insert[11] = 1'b0;
    test_key[11] = 16'h0002;
    expected_maybe[11] = 1'b0;
    test_tag[11] = "overlap_query_target";
    test_rst[12] = 1'b0;
    test_req_valid[12] = 1'b1;
    test_req_insert[12] = 1'b1;
    test_key[12] = 16'h0141;
    expected_maybe[12] = 1'b0;
    test_tag[12] = "falsepos_insert_b";
    test_rst[13] = 1'b0;
    test_req_valid[13] = 1'b1;
    test_req_insert[13] = 1'b0;
    test_key[13] = 16'h0002;
    expected_maybe[13] = 1'b0;
    test_tag[13] = "falsepos_query_target";
    test_rst[14] = 1'b0;
    test_req_valid[14] = 1'b1;
    test_req_insert[14] = 1'b0;
    test_key[14] = 16'h002f;
    expected_maybe[14] = 1'b1;
    test_tag[14] = "query_inserted_a";
    test_rst[15] = 1'b0;
    test_req_valid[15] = 1'b1;
    test_req_insert[15] = 1'b1;
    test_key[15] = 16'h003c;
    expected_maybe[15] = 1'b1;
    test_tag[15] = "dup_insert_first";
    test_rst[16] = 1'b0;
    test_req_valid[16] = 1'b1;
    test_req_insert[16] = 1'b0;
    test_key[16] = 16'h003c;
    expected_maybe[16] = 1'b0;
    test_tag[16] = "dup_query";
    test_rst[17] = 1'b0;
    test_req_valid[17] = 1'b1;
    test_req_insert[17] = 1'b1;
    test_key[17] = 16'h003c;
    expected_maybe[17] = 1'b1;
    test_tag[17] = "dup_insert_second";
    test_rst[18] = 1'b0;
    test_req_valid[18] = 1'b0;
    test_req_insert[18] = 1'b0;
    test_key[18] = 16'h0000;
    expected_maybe[18] = 1'b1;
    test_tag[18] = "dup_resp_idle";
    test_rst[19] = 1'b0;
    test_req_valid[19] = 1'b1;
    test_req_insert[19] = 1'b1;
    test_key[19] = 16'h00aa;
    expected_maybe[19] = 1'b0;
    test_tag[19] = "discard_pending_issue";
    test_rst[20] = 1'b1;
    test_req_valid[20] = 1'b0;
    test_req_insert[20] = 1'b0;
    test_key[20] = 16'h0000;
    expected_maybe[20] = 1'b0;
    test_tag[20] = "discard_pending_reset";
    test_rst[21] = 1'b0;
    test_req_valid[21] = 1'b1;
    test_req_insert[21] = 1'b0;
    test_key[21] = 16'h00aa;
    expected_maybe[21] = 1'b0;
    test_tag[21] = "after_reset_query";
    test_rst[22] = 1'b0;
    test_req_valid[22] = 1'b0;
    test_req_insert[22] = 1'b0;
    test_key[22] = 16'h0000;
    expected_maybe[22] = 1'b0;
    test_tag[22] = "after_reset_resp";
    test_rst[23] = 1'b0;
    test_req_valid[23] = 1'b0;
    test_req_insert[23] = 1'b0;
    test_key[23] = 16'h0000;
    expected_maybe[23] = 1'b0;
    test_tag[23] = "final_idle";
end

    task apply_cycle;
        input integer idx;
        begin
            rst = test_rst[idx];
            req_valid = test_req_valid[idx];
            req_insert = test_req_insert[idx];
            key_in = test_key[idx];

            @(posedge clk);
            #1;

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

            if (maybe_present !== expected_maybe[idx]) begin
                $display("ERROR [cycle %0d][%0s]: maybe_present mismatch. Expected %b, got %b (rst=%b req_valid=%b req_insert=%b key=0x%04h)",
                         cycle_count, test_tag[idx], expected_maybe[idx], maybe_present,
                         test_rst[idx], test_req_valid[idx], test_req_insert[idx], test_key[idx]);
                errors = errors + 1;
            end
        end
    endtask

    initial begin
        rst = 1'b0;
        req_valid = 1'b0;
        req_insert = 1'b0;
        key_in = 16'h0000;

        $display("===========================================");
        $display("   Bloom Filter Membership 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
