`timescale 1ns / 1ps

module tb_lpm_router;

    // Inputs
    reg [31:0] ip_addr;
    
    // Outputs
    wire [2:0] next_hop;
    
    // Instantiate DUT
    lpm_router uut (
        .ip_addr(ip_addr),
        .next_hop(next_hop)
    );
    
    // Golden Vectors
    localparam NUM_TESTS = 31;
    reg [31:0] tb_ip [0:30];
    reg [2:0]  exp_hop [0:30];
    
    integer i;
    integer errors = 0;
    
    initial begin
        // Test 0: Example 10.1.1.5
        tb_ip[0] = 32'h0a010105;     exp_hop[0] = 3'd3;

        // Test 1: Example 10.1.2.1
        tb_ip[1] = 32'h0a010201;     exp_hop[1] = 3'd2;

        // Test 2: Example 10.2.0.1
        tb_ip[2] = 32'h0a020001;     exp_hop[2] = 3'd1;

        // Test 3: Example 192.168.1.100
        tb_ip[3] = 32'hc0a80164;     exp_hop[3] = 3'd5;

        // Test 4: Example 172.20.0.1
        tb_ip[4] = 32'hac140001;     exp_hop[4] = 3'd6;

        // Test 5: Example 8.8.8.8
        tb_ip[5] = 32'h08080808;     exp_hop[5] = 3'd7;

        // Test 6: Example 1.2.3.4
        tb_ip[6] = 32'h01020304;     exp_hop[6] = 3'd0;

        // Test 7: Boundary 172.16 low - 1
        tb_ip[7] = 32'hac0fffff;     exp_hop[7] = 3'd0;

        // Test 8: Boundary 172.16 low
        tb_ip[8] = 32'hac100000;     exp_hop[8] = 3'd6;

        // Test 9: Boundary 172.16 high
        tb_ip[9] = 32'hac1fffff;     exp_hop[9] = 3'd6;

        // Test 10: Boundary 172.16 high + 1
        tb_ip[10] = 32'hac200000;     exp_hop[10] = 3'd0;

        // Test 11: Random 0
        tb_ip[11] = 32'ha3b1799d;     exp_hop[11] = 3'd0;

        // Test 12: Random 1
        tb_ip[12] = 32'h46685257;     exp_hop[12] = 3'd0;

        // Test 13: Random 2
        tb_ip[13] = 32'h392456de;     exp_hop[13] = 3'd0;

        // Test 14: Random 3
        tb_ip[14] = 32'hbc8960a9;     exp_hop[14] = 3'd0;

        // Test 15: Random 4
        tb_ip[15] = 32'h6c031199;     exp_hop[15] = 3'd0;

        // Test 16: Random 5
        tb_ip[16] = 32'h07a0ca6e;     exp_hop[16] = 3'd0;

        // Test 17: Random 6
        tb_ip[17] = 32'h37f8a88b;     exp_hop[17] = 3'd0;

        // Test 18: Random 7
        tb_ip[18] = 32'h8b8148f6;     exp_hop[18] = 3'd0;

        // Test 19: Random 8
        tb_ip[19] = 32'h386ecbe0;     exp_hop[19] = 3'd0;

        // Test 20: Random 9
        tb_ip[20] = 32'h96da1dac;     exp_hop[20] = 3'd0;

        // Test 21: Random 10
        tb_ip[21] = 32'hce4a2bbd;     exp_hop[21] = 3'd0;

        // Test 22: Random 11
        tb_ip[22] = 32'hb2b9437a;     exp_hop[22] = 3'd0;

        // Test 23: Random 12
        tb_ip[23] = 32'h571aa876;     exp_hop[23] = 3'd0;

        // Test 24: Random 13
        tb_ip[24] = 32'h27cd8130;     exp_hop[24] = 3'd0;

        // Test 25: Random 14
        tb_ip[25] = 32'h562b0f79;     exp_hop[25] = 3'd0;

        // Test 26: Random 15
        tb_ip[26] = 32'h17be3111;     exp_hop[26] = 3'd0;

        // Test 27: Random 16
        tb_ip[27] = 32'h18c26797;     exp_hop[27] = 3'd0;

        // Test 28: Random 17
        tb_ip[28] = 32'hd8f56413;     exp_hop[28] = 3'd0;

        // Test 29: Random 18
        tb_ip[29] = 32'h9a8dca03;     exp_hop[29] = 3'd0;

        // Test 30: Random 19
        tb_ip[30] = 32'hce9ff57f;     exp_hop[30] = 3'd0;

        // Wait for inputs to settle
        #100;
        
        // Run tests
        for (i = 0; i < NUM_TESTS; i = i + 1) begin
            ip_addr = tb_ip[i];
            
            #10;
            
            if (next_hop !== exp_hop[i]) begin
                $display("ERROR [Test %0d]: IP=%h, Expected Hop=%0d, Got=%0d", 
                         i, ip_addr, exp_hop[i], next_hop);
                errors = errors + 1;
            end
        end
        
        // Final Results
        $display("");
        $display("===========================================");
        $display("  Tests Run: %0d", NUM_TESTS);
        $display("===========================================");
        
        if (errors == 0) begin
            $display("TEST_RESULT: PASS");
        end else begin
            $display("TEST_RESULT: FAIL (%0d errors)", errors);
        end
        
        $finish;
    end

endmodule
