`timescale 1ns / 1ps

module meggitt_tb;
    reg clk;
    reg rst_n;
    reg start;
    reg [7:0] data_in;
    reg data_valid;
    wire done;
    wire [7:0] data_out;
    wire data_out_valid;
    wire [7:0] error_count;

    // Instantiate Decoder
    meggitt_decoder uut (
        .clk(clk),
        .rst_n(rst_n),
        .start(start),
        .data_in(data_in),
        .data_valid(data_valid),
        .done(done),
        .data_out(data_out),
        .data_out_valid(data_out_valid),
        .error_count(error_count)
    );

    // Clock generation
    initial clk = 0;
    always #5 clk = ~clk;

    // Test Data
    reg [7:0] original_codeword [0:2303];
    reg [7:0] corrupted_codeword [0:2303];
    integer i, j;

    initial begin
        // Reset
        rst_n = 0;
        start = 0;
        data_in = 0;
        data_valid = 0;
        
        // Load original codeword from file
        $readmemh("codeword.mem", original_codeword);
        
        // Create corrupted version with 5 bit errors
        for (i = 0; i < 2304; i = i + 1) corrupted_codeword[i] = original_codeword[i];
        
        // Inject errors at indices 10, 100, 1000, 5000, 15000
        corrupted_codeword[10/8] ^= (1 << (10%8));
        corrupted_codeword[100/8] ^= (1 << (100%8));
        corrupted_codeword[1000/8] ^= (1 << (1000%8));
        corrupted_codeword[5000/8] ^= (1 << (5000%8));
        corrupted_codeword[15000/8] ^= (1 << (15000%8));

        #100;
        rst_n = 1;
        #100;

        // Pulse Start
        start = 1;
        #10;
        start = 0;

        // Phase 1: Stream in corrupted data
        for (i = 0; i < 2304; i = i + 1) begin
            @(posedge clk);
            data_in = corrupted_codeword[i];
            data_valid = 1;
        end
        @(posedge clk);
        data_valid = 0;

        // Phase 2: Wait for decoding
        $display("Decoding started...");
        wait(done);
        $display("Decoding finished. Found %d errors.", error_count);

        // Phase 3: Check output
        $display("Verifying output data...");
        for (i = 0; i < 2304; i = i + 1) begin
            wait(data_out_valid);
            if (data_out !== original_codeword[i]) begin
                $display("ERROR at byte %d: Expected %h, Got %h", i, original_codeword[i], data_out);
            end
            @(posedge clk);
        end
        
        $display("Verification complete.");
        $finish;
    end

endmodule
