`timescale 1ns / 1ps

module tb_sort8_ranker;
    reg clk;
    reg rst;
    reg in_valid;
    reg [127:0] in_data;

    wire out_valid;
    wire [127:0] out_data;
    wire [23:0] out_index;

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

    sort8_ranker uut (
        .clk(clk),
        .rst(rst),
        .in_valid(in_valid),
        .in_data(in_data),
        .out_valid(out_valid),
        .out_data(out_data),
        .out_index(out_index)
    );

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

// Generated by generate_golden.py and copied here. Do not edit by hand.
localparam integer NUM_TESTS = 40;
reg test_rst [0:NUM_TESTS-1];
reg test_in_valid [0:NUM_TESTS-1];
reg [127:0] test_in_data [0:NUM_TESTS-1];
reg expected_out_valid [0:NUM_TESTS-1];
reg [127:0] expected_out_data [0:NUM_TESTS-1];
reg [23:0] expected_out_index [0:NUM_TESTS-1];
reg [255:0] test_tag [0:NUM_TESTS-1];

initial begin
    test_rst[0] = 1'b1;
    test_in_valid[0] = 1'b0;
    test_in_data[0] = 128'h00000000000000000000000000000000;
    expected_out_valid[0] = 1'b0;
    expected_out_data[0] = 128'h00000000000000000000000000000000;
    expected_out_index[0] = 24'h000000;
    test_tag[0] = "startup_reset";
    test_rst[1] = 1'b1;
    test_in_valid[1] = 1'b1;
    test_in_data[1] = 128'h00080007000600050004000300020001;
    expected_out_valid[1] = 1'b0;
    expected_out_data[1] = 128'h00000000000000000000000000000000;
    expected_out_index[1] = 24'h000000;
    test_tag[1] = "reset_ign_valid";
    test_rst[2] = 1'b0;
    test_in_valid[2] = 1'b0;
    test_in_data[2] = 128'h00000000000000000000000000000000;
    expected_out_valid[2] = 1'b0;
    expected_out_data[2] = 128'h00000000000000000000000000000000;
    expected_out_index[2] = 24'h000000;
    test_tag[2] = "post_reset_idle";
    test_rst[3] = 1'b0;
    test_in_valid[3] = 1'b1;
    test_in_data[3] = 128'h001e000c000900070000fffffffbffec;
    expected_out_valid[3] = 1'b0;
    expected_out_data[3] = 128'h00000000000000000000000000000000;
    expected_out_index[3] = 24'h000000;
    test_tag[3] = "ascending";
    test_rst[4] = 1'b0;
    test_in_valid[4] = 1'b1;
    test_in_data[4] = 128'hffecfffbffff000000070009000c001e;
    expected_out_valid[4] = 1'b0;
    expected_out_data[4] = 128'h00000000000000000000000000000000;
    expected_out_index[4] = 24'h000000;
    test_tag[4] = "descending";
    test_rst[5] = 1'b0;
    test_in_valid[5] = 1'b1;
    test_in_data[5] = 128'h00040004000400040004000400040004;
    expected_out_valid[5] = 1'b0;
    expected_out_data[5] = 128'h00000000000000000000000000000000;
    expected_out_index[5] = 24'h000000;
    test_tag[5] = "all_equal";
    test_rst[6] = 1'b0;
    test_in_valid[6] = 1'b1;
    test_in_data[6] = 128'h7fff80007fff80007fff80007fff8000;
    expected_out_valid[6] = 1'b0;
    expected_out_data[6] = 128'h00000000000000000000000000000000;
    expected_out_index[6] = 24'h000000;
    test_tag[6] = "alt_extreme";
    test_rst[7] = 1'b0;
    test_in_valid[7] = 1'b0;
    test_in_data[7] = 128'h00000000000000000000000000000000;
    expected_out_valid[7] = 1'b0;
    expected_out_data[7] = 128'h00000000000000000000000000000000;
    expected_out_index[7] = 24'h000000;
    test_tag[7] = "input_bubble";
    test_rst[8] = 1'b0;
    test_in_valid[8] = 1'b1;
    test_in_data[8] = 128'h000000030008ffff00030005ffff0005;
    expected_out_valid[8] = 1'b0;
    expected_out_data[8] = 128'h00000000000000000000000000000000;
    expected_out_index[8] = 24'h000000;
    test_tag[8] = "dup_mix";
    test_rst[9] = 1'b0;
    test_in_valid[9] = 1'b1;
    test_in_data[9] = 128'h7fff0000cfc73039ffff000180007fff;
    expected_out_valid[9] = 1'b1;
    expected_out_data[9] = 128'h001e000c000900070000fffffffbffec;
    expected_out_index[9] = 24'hfac688;
    test_tag[9] = "signed_mix";
    test_rst[10] = 1'b0;
    test_in_valid[10] = 1'b1;
    test_in_data[10] = 128'hfffdfff9fffffff7fffefffbfffefff8;
    expected_out_valid[10] = 1'b1;
    expected_out_data[10] = 128'h001e000c000900070000fffffffbffec;
    expected_out_index[10] = 24'h053977;
    test_tag[10] = "negative_mix";
    test_rst[11] = 1'b0;
    test_in_valid[11] = 1'b1;
    test_in_data[11] = 128'hff9c0000000ffffc0063fffc000f000f;
    expected_out_valid[11] = 1'b1;
    expected_out_data[11] = 128'h00040004000400040004000400040004;
    expected_out_index[11] = 24'hfac688;
    test_tag[11] = "late_burst0";
    test_rst[12] = 1'b1;
    test_in_valid[12] = 1'b0;
    test_in_data[12] = 128'h00000000000000000000000000000000;
    expected_out_valid[12] = 1'b0;
    expected_out_data[12] = 128'h00000000000000000000000000000000;
    expected_out_index[12] = 24'h000000;
    test_tag[12] = "flush_reset1";
    test_rst[13] = 1'b0;
    test_in_valid[13] = 1'b0;
    test_in_data[13] = 128'h00000000000000000000000000000000;
    expected_out_valid[13] = 1'b0;
    expected_out_data[13] = 128'h00000000000000000000000000000000;
    expected_out_index[13] = 24'h000000;
    test_tag[13] = "idle_after_r1";
    test_rst[14] = 1'b0;
    test_in_valid[14] = 1'b1;
    test_in_data[14] = 128'h00060008000200030001000700040009;
    expected_out_valid[14] = 1'b0;
    expected_out_data[14] = 128'h00000000000000000000000000000000;
    expected_out_index[14] = 24'h000000;
    test_tag[14] = "burst2_0";
    test_rst[15] = 1'b0;
    test_in_valid[15] = 1'b1;
    test_in_data[15] = 128'h000000000005fff00005fff00005fff0;
    expected_out_valid[15] = 1'b0;
    expected_out_data[15] = 128'h00000000000000000000000000000000;
    expected_out_index[15] = 24'h000000;
    test_tag[15] = "burst2_1";
    test_rst[16] = 1'b0;
    test_in_valid[16] = 1'b1;
    test_in_data[16] = 128'h004b0000ffe70019ffce0032ff9c0064;
    expected_out_valid[16] = 1'b0;
    expected_out_data[16] = 128'h00000000000000000000000000000000;
    expected_out_index[16] = 24'h000000;
    test_tag[16] = "burst2_2";
    test_rst[17] = 1'b0;
    test_in_valid[17] = 1'b1;
    test_in_data[17] = 128'h000400050006000700080009000a000b;
    expected_out_valid[17] = 1'b0;
    expected_out_data[17] = 128'h00000000000000000000000000000000;
    expected_out_index[17] = 24'h000000;
    test_tag[17] = "burst2_3";
    test_rst[18] = 1'b0;
    test_in_valid[18] = 1'b1;
    test_in_data[18] = 128'h80010004800000037ffe00027fff0001;
    expected_out_valid[18] = 1'b0;
    expected_out_data[18] = 128'h00000000000000000000000000000000;
    expected_out_index[18] = 24'h000000;
    test_tag[18] = "burst2_4";
    test_rst[19] = 1'b0;
    test_in_valid[19] = 1'b1;
    test_in_data[19] = 128'h002700270028002800290029002a002a;
    expected_out_valid[19] = 1'b0;
    expected_out_data[19] = 128'h00000000000000000000000000000000;
    expected_out_index[19] = 24'h000000;
    test_tag[19] = "burst2_5";
    test_rst[20] = 1'b0;
    test_in_valid[20] = 1'b1;
    test_in_data[20] = 128'h7ffff93d442400055b1d85b076b97fff;
    expected_out_valid[20] = 1'b1;
    expected_out_data[20] = 128'h00090008000700060004000300020001;
    expected_out_index[20] = 24'h19732b;
    test_tag[20] = "discard_rand0";
    test_rst[21] = 1'b0;
    test_in_valid[21] = 1'b1;
    test_in_data[21] = 128'h0001ff01000126227fffffff800071f8;
    expected_out_valid[21] = 1'b1;
    expected_out_data[21] = 128'h00050005000500000000fff0fff0fff0;
    expected_out_index[21] = 24'hacfd10;
    test_tag[21] = "discard_rand1";
    test_rst[22] = 1'b0;
    test_in_valid[22] = 1'b1;
    test_in_data[22] = 128'h002a006300018000a21439840005ff01;
    expected_out_valid[22] = 1'b1;
    expected_out_data[22] = 128'h0064004b003200190000ffe7ffceff9c;
    expected_out_index[22] = 24'h1d4d59;
    test_tag[22] = "discard_rand2";
    test_rst[23] = 1'b0;
    test_in_valid[23] = 1'b1;
    test_in_data[23] = 128'h0063fff912cc00000001ffffb0880001;
    expected_out_valid[23] = 1'b1;
    expected_out_data[23] = 128'h000b000a000900080007000600050004;
    expected_out_index[23] = 24'h053977;
    test_tag[23] = "discard_rand3";
    test_rst[24] = 1'b1;
    test_in_valid[24] = 1'b1;
    test_in_data[24] = 128'h5f199135448f88288a3793fd1c555cdf;
    expected_out_valid[24] = 1'b0;
    expected_out_data[24] = 128'h00000000000000000000000000000000;
    expected_out_index[24] = 24'h000000;
    test_tag[24] = "reset_during_out";
    test_rst[25] = 1'b0;
    test_in_valid[25] = 1'b0;
    test_in_data[25] = 128'h00000000000000000000000000000000;
    expected_out_valid[25] = 1'b0;
    expected_out_data[25] = 128'h00000000000000000000000000000000;
    expected_out_index[25] = 24'h000000;
    test_tag[25] = "idle_after_r2";
    test_rst[26] = 1'b0;
    test_in_valid[26] = 1'b1;
    test_in_data[26] = 128'h00010006000100060001000600010006;
    expected_out_valid[26] = 1'b0;
    expected_out_data[26] = 128'h00000000000000000000000000000000;
    expected_out_index[26] = 24'h000000;
    test_tag[26] = "post3_dup";
    test_rst[27] = 1'b0;
    test_in_valid[27] = 1'b1;
    test_in_data[27] = 128'h0032fed400c800640000ff9c00c8fed4;
    expected_out_valid[27] = 1'b0;
    expected_out_data[27] = 128'h00000000000000000000000000000000;
    expected_out_index[27] = 24'h000000;
    test_tag[27] = "post3_mix";
    test_rst[28] = 1'b0;
    test_in_valid[28] = 1'b1;
    test_in_data[28] = 128'h243a8000bd55aabc8000883f7fff5d8c;
    expected_out_valid[28] = 1'b0;
    expected_out_data[28] = 128'h00000000000000000000000000000000;
    expected_out_index[28] = 24'h000000;
    test_tag[28] = "keep_rand0";
    test_rst[29] = 1'b0;
    test_in_valid[29] = 1'b1;
    test_in_data[29] = 128'h50203abdd3b9b2043541dd533c3cd1a4;
    expected_out_valid[29] = 1'b0;
    expected_out_data[29] = 128'h00000000000000000000000000000000;
    expected_out_index[29] = 24'h000000;
    test_tag[29] = "keep_rand1";
    test_rst[30] = 1'b0;
    test_in_valid[30] = 1'b1;
    test_in_data[30] = 128'hfff98000ffff0000fff97811ff018000;
    expected_out_valid[30] = 1'b0;
    expected_out_data[30] = 128'h00000000000000000000000000000000;
    expected_out_index[30] = 24'h000000;
    test_tag[30] = "keep_rand2";
    test_rst[31] = 1'b0;
    test_in_valid[31] = 1'b1;
    test_in_data[31] = 128'hfbffc7d426e00ca1f7d390d3a38d6ce9;
    expected_out_valid[31] = 1'b0;
    expected_out_data[31] = 128'h00000000000000000000000000000000;
    expected_out_index[31] = 24'h000000;
    test_tag[31] = "keep_rand3";
    test_rst[32] = 1'b0;
    test_in_valid[32] = 1'b0;
    test_in_data[32] = 128'h00000000000000000000000000000000;
    expected_out_valid[32] = 1'b1;
    expected_out_data[32] = 128'h00060006000600060001000100010001;
    expected_out_index[32] = 24'hd10f59;
    test_tag[32] = "flush_idle0";
    test_rst[33] = 1'b0;
    test_in_valid[33] = 1'b0;
    test_in_data[33] = 128'h00000000000000000000000000000000;
    expected_out_valid[33] = 1'b1;
    expected_out_data[33] = 128'h00c800c8006400320000ff9cfed4fed4;
    expected_out_index[33] = 24'ha676b0;
    test_tag[33] = "flush_idle1";
    test_rst[34] = 1'b0;
    test_in_valid[34] = 1'b0;
    test_in_data[34] = 128'h00000000000000000000000000000000;
    expected_out_valid[34] = 1'b1;
    expected_out_data[34] = 128'h7fff5d8c243abd55aabc883f80008000;
    expected_out_index[34] = 24'h23d8b3;
    test_tag[34] = "flush_idle2";
    test_rst[35] = 1'b0;
    test_in_valid[35] = 1'b0;
    test_in_data[35] = 128'h00000000000000000000000000000000;
    expected_out_valid[35] = 1'b1;
    expected_out_data[35] = 128'h50203c3c3abd3541dd53d3b9d1a4b204;
    expected_out_index[35] = 24'he73544;
    test_tag[35] = "flush_idle3";
    test_rst[36] = 1'b0;
    test_in_valid[36] = 1'b0;
    test_in_data[36] = 128'h00000000000000000000000000000000;
    expected_out_valid[36] = 1'b1;
    expected_out_data[36] = 128'h78110000fffffff9fff9ff0180008000;
    expected_out_index[36] = 24'h52f670;
    test_tag[36] = "flush_idle4";
    test_rst[37] = 1'b0;
    test_in_valid[37] = 1'b0;
    test_in_data[37] = 128'h00000000000000000000000000000000;
    expected_out_valid[37] = 1'b1;
    expected_out_data[37] = 128'h6ce926e00ca1fbfff7d3c7d4a38d90d3;
    expected_out_index[37] = 24'h16778a;
    test_tag[37] = "flush_idle5";
    test_rst[38] = 1'b0;
    test_in_valid[38] = 1'b0;
    test_in_data[38] = 128'h00000000000000000000000000000000;
    expected_out_valid[38] = 1'b0;
    expected_out_data[38] = 128'h00000000000000000000000000000000;
    expected_out_index[38] = 24'h000000;
    test_tag[38] = "flush_idle6";
    test_rst[39] = 1'b0;
    test_in_valid[39] = 1'b0;
    test_in_data[39] = 128'h00000000000000000000000000000000;
    expected_out_valid[39] = 1'b0;
    expected_out_data[39] = 128'h00000000000000000000000000000000;
    expected_out_index[39] = 24'h000000;
    test_tag[39] = "flush_idle7";
end

    task apply_cycle;
        input integer idx;
        begin
            rst = test_rst[idx];
            in_valid = test_in_valid[idx];
            in_data = test_in_data[idx];

            @(posedge clk);
            #1;

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

            if (out_valid !== expected_out_valid[idx]) begin
                $display("ERROR [cycle %0d][%0s]: out_valid mismatch. Expected %b, got %b (rst=%b in_valid=%b in_data=0x%032h)",
                         cycle_count, test_tag[idx], expected_out_valid[idx], out_valid,
                         test_rst[idx], test_in_valid[idx], test_in_data[idx]);
                errors = errors + 1;
            end

            if (out_data !== expected_out_data[idx]) begin
                $display("ERROR [cycle %0d][%0s]: out_data mismatch. Expected 0x%032h, got 0x%032h (rst=%b in_valid=%b in_data=0x%032h)",
                         cycle_count, test_tag[idx], expected_out_data[idx], out_data,
                         test_rst[idx], test_in_valid[idx], test_in_data[idx]);
                errors = errors + 1;
            end

            if (out_index !== expected_out_index[idx]) begin
                $display("ERROR [cycle %0d][%0s]: out_index mismatch. Expected 0x%06h, got 0x%06h (rst=%b in_valid=%b in_data=0x%032h)",
                         cycle_count, test_tag[idx], expected_out_index[idx], out_index,
                         test_rst[idx], test_in_valid[idx], test_in_data[idx]);
                errors = errors + 1;
            end
        end
    endtask

    initial begin
        rst = 1'b0;
        in_valid = 1'b0;
        in_data = 128'h00000000000000000000000000000000;

        $display("===========================================");
        $display("   8-Lane Sorting Accelerator 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
