`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: yangshenbo
// 
// Create Date: 2026/03/31 10:53:24
// Design Name: 
// Module Name: uart_top_32bit
// 
//////////////////////////////////////////////////////////////////////////////////
module uart_top_32bit #(
    parameter BAUD = 9600,
    parameter CLOCK_FREQ = 50_000_000
)
(
    input           Clk,
    input           Reset_n,
    
    // 32-bit Transmit Interface
    input           Send_Go32,    // 32-bit transmit start pulse
    input  [31:0]   Tx_Data32,    // 32-bit data to transmit
    output          Tx_Done32,    // 32-bit transmit done flag
    output          uart_tx,      // Physical TX pin
    
    // 32-bit Receive Interface
    input           uart_rx,      // Physical RX pin
    output reg         Rx_Done32,    // 32-bit receive done flag
    output reg [31:0]   Rx_Data32     // 32-bit received data
);

    // --- Internal Wires ---
    wire        byte_tx_go;
    wire [7:0]  byte_tx_data;
    wire        byte_tx_done;
    
    wire        byte_rx_done;
    wire [7:0]  byte_rx_data;

    // ============================================================
    // 1. Transmit Control Logic (32-bit to 4x8-bit)
    // ============================================================
    reg [3:0] tx_state;
    reg [31:0] tx_data_buffer;
    reg byte_tx_go_reg;
    reg [7:0] byte_tx_data_reg;

    assign byte_tx_go = byte_tx_go_reg;
    assign byte_tx_data = byte_tx_data_reg;

    always @(posedge Clk or negedge Reset_n) begin
        if (!Reset_n) begin
            tx_state <= 0;
            byte_tx_go_reg <= 0;
            tx_data_buffer <= 0;
        end else begin
            case (tx_state)
                0: begin // Wait for transmit trigger
                    if (Send_Go32) begin
                        tx_data_buffer <= Tx_Data32;
                        tx_state <= 1;
                    end
                end
                
                1, 2, 3, 4: begin // Send byte 0, 1, 2, 3 sequentially
                    byte_tx_data_reg <= tx_data_buffer[31:24]; // Send high byte first (Big-endian)
                    byte_tx_go_reg <= 1;
                    tx_state <= tx_state + 4; // Jump to wait state
                end

                // States 5, 6, 7, 8: Wait for byte_tx_done
                5, 6, 7, 8: begin
                    byte_tx_go_reg <= 0;
                    if (byte_tx_done) begin
                        tx_data_buffer <= tx_data_buffer << 8; // Shift for next byte
                        if (tx_state == 8) tx_state <= 0; // 4 bytes sent
                        else tx_state <= tx_state - 3; // Return to next send state
                    end
                end
            endcase
        end
    end
    
    assign Tx_Done32 = (tx_state == 8 && byte_tx_done);

    // ============================================================
    // 2. Receive Control Logic (4x8-bit to 32-bit)
    // ============================================================
    reg [1:0] rx_cnt;
    reg [31:0] rx_data_buffer;
    reg rx_done32_reg;

    always @(posedge Clk or negedge Reset_n) begin
        if (!Reset_n) begin
            rx_cnt <= 0;
            rx_data_buffer <= 0;
            rx_done32_reg <= 0;
        end else begin
            rx_done32_reg <= 0;
            if (byte_rx_done) begin
                // Concatenate data (Big-endian mode)
                case(rx_cnt)
                    0: rx_data_buffer[31:24]   <= byte_rx_data;
                    1: rx_data_buffer[23:16]  <= byte_rx_data;
                    2: rx_data_buffer[15:8] <= byte_rx_data;
                    3: rx_data_buffer[7:0] <= byte_rx_data;
                endcase
                
                if (rx_cnt == 3) begin
                    rx_cnt <= 0;
                    rx_done32_reg <= 1;
                end else begin
                    rx_cnt <= rx_cnt + 1;
                end
            end
        end
    end


    always @(posedge Clk or negedge Reset_n) begin
        if(!Reset_n) begin
            Rx_Data32 <= 1'b0;
            Rx_Done32 <= 1'b0;
        end
        else if(rx_done32_reg)begin
            Rx_Data32 <= rx_data_buffer;
            Rx_Done32 <= rx_done32_reg;
        end
        else begin
            Rx_Data32 <= Rx_Data32;
            Rx_Done32 <= 0;
        end
    end

    // ============================================================
    // 3. Module Instantiation
    // ============================================================
    
    // Instantiate byte transmit module
    uart_byte_tx #(
        .BAUD(BAUD),
        .CLOCK_FREQ(CLOCK_FREQ)
    ) u_uart_byte_tx (
        .Clk(Clk),
        .Reset_n(Reset_n),
        .Send_Go(byte_tx_go),
        .Data(byte_tx_data),
        .uart_tx(uart_tx),
        .Tx_Done(byte_tx_done)
    );

    // Instantiate byte receive module
    uart_byte_rx #(
        .BAUD(BAUD),
        .CLOCK_FREQ(CLOCK_FREQ)
    ) u_uart_byte_rx (
        .Clk(Clk),
        .Reset_n(Reset_n),
        .uart_rx(uart_rx),
        .Rx_Done(byte_rx_done),
        .Rx_Data(byte_rx_data)
    );

endmodule