`timescale 1ns / 1ps

module uart_ctrl_sysreg #(
    parameter BAUD = 115200,
    parameter CLOCK_FREQ = 50_000_000
)(
     input           clk
    ,input           rst_n
    // UART Interface
    ,input           uart_rx
    ,output          uart_tx
    // Register File Interface
    ,output reg [31:0]   o_wrdata        //write data to register file
    ,output reg [24:0]   o_addr          //register file address
    ,output reg          o_wren          //write enable to register file
    ,output reg          o_rden          //read enable to register file
    ,input  [31:0]   i_rddata        //read data from register file
    // Auto-Report Mechanism
    ,input [23:0] i_report_data 
    ,input i_report_vld
);

    // --- uart_top ---
    wire [31:0] uart_rx_data;
    wire        uart_rx_done;
    reg  [31:0] uart_tx_data;
    reg         uart_tx_go;
    wire        uart_tx_done;
    uart_top_32bit #(
        .BAUD(BAUD),
        .CLOCK_FREQ(CLOCK_FREQ)
    ) uart_32bit_inst (
        .Clk(clk), .Reset_n(rst_n),
        .Send_Go32(uart_tx_go), .Tx_Data32(uart_tx_data), .Tx_Done32(uart_tx_done),
        .uart_tx(uart_tx), .uart_rx(uart_rx),
        .Rx_Done32(uart_rx_done), .Rx_Data32(uart_rx_data)
    );


    // Protocol parsing registers
    reg [63:0] cmd_reg;
    reg [31:0] wr_data_buff;
    reg [19:0] data_bytes_len;    

    // State machine definition
    reg [2:0] state;
    localparam S_IDLE      = 3'd0,
               S_RX_CMD_L  = 3'd1,
               S_PARSE     = 3'd2,
               S_WAIT_RD   = 3'd3,
               S_RD_DATA   = 3'd4,
               S_WR_DATA   = 3'd5,
               S_REPORT    = 3'd6; // Auto-report state
               

// Latch auto-report data
    reg [23:0] report_data_latch;
    reg        report_pending;  

    // Capture report pulse: store if busy
    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            report_pending <= 1'b0;
            report_data_latch <= 24'd0;
        end else if(i_report_vld) begin
            report_pending <= 1'b1;
            report_data_latch <= i_report_data;
        end else if(state == S_REPORT) begin
            report_pending <= 1'b0; // Clear flag after entering report state
        end
    end


    always @(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            state <= 0;
            cmd_reg <= 0;
            o_wrdata <= 0;
            o_wren <= 0;
            o_rden <= 0;
            uart_tx_go <= 1'b0;
            uart_tx_data <= 1'b0;
        end
        else begin
            case(state)
            S_IDLE : begin  // IDLE state
                uart_tx_go <= 1'b0;
                if(uart_rx_done) begin
                    cmd_reg[63:32] <= uart_rx_data;
                    state <= S_RX_CMD_L;
                end
                else if(report_pending) begin                                      
                    state <= S_REPORT;           
                end
            end
            S_RX_CMD_L : begin // Receive lower command word
                if(uart_rx_done)begin
                    cmd_reg[31:0] <= uart_rx_data; 
                    state <= S_PARSE;
                end
            end
            S_PARSE : begin // Parse command
                o_addr <= cmd_reg[56:32];
                data_bytes_len <= cmd_reg[19:0];
                if(cmd_reg[63] == 1'b1) begin // Read command
                    o_rden <= 1'b1;
                    state <= S_WAIT_RD;
                end
                else begin // Write command
                    state <= S_WR_DATA;
                end
            end
            S_WAIT_RD : begin // Wait for read data ready
                o_rden <= 1'b0;
                state <= S_RD_DATA;
            end
            S_RD_DATA :begin // Transmit read data
                uart_tx_data <= i_rddata;
                uart_tx_go <= 1'b1;
                state <= S_IDLE;
            end
            S_WR_DATA : begin // Receive and write data
                o_wren <= 1'b0;
                if(data_bytes_len != 0)begin
                    if(uart_rx_done) begin
                    o_wrdata <= uart_rx_data;
                    o_wren <= 1'b1;
                    data_bytes_len <= data_bytes_len - 20'd4;
                    end
                end
                else begin
                    state <= S_IDLE;
                end
            end
            S_REPORT : begin // Auto-report data
                // Construct report packet: [8'hAA (header) + 24bit sensor data]
                uart_tx_data <= {8'hAA, report_data_latch}; 
                uart_tx_go <= 1'b1;
                state <= S_IDLE;
            end

            default: state <= S_IDLE;
            endcase
        end

    end
 

 

endmodule