`timescale 1ns / 1ps

module tb_uart_top_32bit();

    // --- 参数定义 ---
    parameter CLK_PERIOD = 20; 
    parameter BAUD = 115200;       // 提高波特率可以加快仿真速度
    parameter CLOCK_FREQ = 50_000_000;

    // --- 信号声明 ---
    reg         Clk;
    reg         Reset_n;
    reg         Send_Go32;
    reg  [31:0] Tx_Data32;
    
    wire        uart_tx;
    wire        uart_rx; 
    wire        Tx_Done32;
    wire        Rx_Done32;
    wire [31:0] Rx_Data32;

    // --- 实例化 DUT ---
    uart_top_32bit #(
        .BAUD(BAUD),
        .CLOCK_FREQ(CLOCK_FREQ)
    ) dut (
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Send_Go32(Send_Go32),
        .Tx_Data32(Tx_Data32),
        .Tx_Done32(Tx_Done32),
        .uart_tx(uart_tx),
        .uart_rx(uart_rx),      
        .Rx_Done32(Rx_Done32),
        .Rx_Data32(Rx_Data32)
    );

    // 构造回环
    assign uart_rx = uart_tx;

    // 时钟产生
    initial Clk = 0;
    always #(CLK_PERIOD/2) Clk = ~Clk;

    // ============================================================
    // 发送并校验的任务 (Task)
    // ============================================================
    task send_and_check;
        input [31:0] data;
        begin
            Tx_Data32 = data;
            Send_Go32 = 1;
            #(CLK_PERIOD);
            Send_Go32 = 0;
            
            // 等待发送和接收全部完成
            fork
                wait(Rx_Done32);
                wait(Tx_Done32);
            join
            
            #(CLK_PERIOD * 10); // 留一点余量
            
            if (Rx_Data32 === data)
                $display("[PASS] 发送: 0x%h | 接收: 0x%h", data, Rx_Data32);
            else
                $display("[FAIL] 发送: 0x%h | 接收: 0x%h !!! 错误 !!!", data, Rx_Data32);
            
            #(CLK_PERIOD * 100); // 两次发送间的间隔
        end
    endtask

    // ============================================================
    // 测试流程
    // ============================================================
    integer i;
    initial begin
        // 初始化
        Reset_n = 0;
        Send_Go32 = 0;
        Tx_Data32 = 0;
        
        // 复位
        #(CLK_PERIOD * 10);
        Reset_n = 1;
        #(CLK_PERIOD * 10);

        $display("======= 开始 32位串口回环测试 =======");

        // 1. 基础边界测试
        send_and_check(32'h0000_0000);
        send_and_check(32'hFFFF_FFFF);
        
        // 2. 经典交替位测试 (检查串扰和采样)
        send_and_check(32'hAAAA_AAAA);
        send_and_check(32'h5555_5555);

        // 3. 随机/特殊数据测试
        send_and_check(32'h1234_5678);
        send_and_check(32'h8765_4321);
        send_and_check(32'hDEAD_BEEF);

        // 4. 循环自动测试 (测试 5 组递增数据)
        for (i = 0; i < 5; i = i + 1) begin
            send_and_check(32'h2024_0000 + i);
        end

        $display("======= 所有测试用例执行完毕 =======");
        #(CLK_PERIOD * 200);
        $stop;
    end

endmodule