module verilog6502_apb_adapter(
    input                   i_clk,
    input                   i_rst,

    input  logic [15:0]     i_addr,
    input  logic [7:0]      i_data,
    output logic [7:0]      o_data,
    input  logic            i_rd,
    input  logic            i_we,
    output logic            o_rdy,

    taxi_apb_if.mst         m_apb
);

enum logic {IDLE, ENABLE} state, state_next;

logic [15:0] latched_addr, latched_addr_next;
logic [15:0] second_addr, second_addr_next;
logic second_we, second_rd, second_we_next, second_rd_next;
logic [7:0] latched_data, latched_data_next;
logic [7:0] second_data, second_data_next;
logic latched_pwrite, latched_pwrite_next;

always_ff @(posedge i_clk) begin
    if (i_rst) begin
        state <= IDLE;
        latched_addr <= '0;
        second_addr <= '0;
        second_we <= '0;
        second_rd <= '0;
        latched_data <= '0;
        latched_pwrite <= '0;
        second_data <= '0;
    end else begin
        state <= state_next;
        latched_addr <= latched_addr_next;
        second_addr <= second_addr_next;
        second_we <= second_we_next;
        second_rd <= second_rd_next;
        latched_data <= latched_data_next;
        latched_pwrite <= latched_pwrite_next;
        second_data <= second_data_next;
    end
end


always_comb begin


    case (state)
        IDLE: begin
            if (i_rd | i_we) begin
                m_apb.pprot = '0;
                m_apb.paddr = {16'b0, i_addr} & 32'hfffc;    // 32 bit address
                m_apb.psel = '1;
                m_apb.pwrite = i_we;
                m_apb.pstrb = 4'h1 << i_addr[1:0];  // shift based on lower 2 bits
                m_apb.pwdata = {24'b0, i_data} << i_addr[1:0];
                o_rdy = '0;

                m_apb.penable = '0;
                state_next = ENABLE;
                latched_addr_next = i_addr;
                latched_data_next = i_data;
                latched_pwrite_next = i_we;
            end else if (second_rd | second_we) begin
                m_apb.pprot = '0;
                m_apb.paddr = {16'b0, second_addr} & 32'hfffc;    // 32 bit address
                m_apb.psel = '1;
                m_apb.pwrite = second_we;
                m_apb.pstrb = 4'h1 << second_addr[1:0];  // shift based on lower 2 bits
                m_apb.pwdata = {24'b0, second_data} << second_addr[1:0];
                o_rdy = '0;

                m_apb.penable = '0;
                state_next = ENABLE;
                latched_addr_next = second_addr;
                latched_data_next = second_data;
                latched_pwrite_next = second_we;
            end else begin
                m_apb.pprot = '0;
                m_apb.paddr = '0;
                m_apb.psel = '0;
                m_apb.pwrite = '0;
                m_apb.pstrb = '0;
                m_apb.pwdata = '0;
                o_rdy = '0;
            end
        end

        ENABLE: begin
            m_apb.penable = '1;

            second_we_next = i_we;
            second_rd_next = i_rd;
            second_addr_next = i_addr;
            second_data_next = i_data;

            m_apb.pprot = '0;
            m_apb.paddr = {16'b0, latched_addr} & 32'hfffc;    // 32 bit address
            m_apb.psel = '1;
            m_apb.pwrite = latched_pwrite;
            m_apb.pstrb = 4'h1 << latched_addr[1:0];  // shift based on lower 2 bits
            m_apb.pwdata = {24'b0, latched_data} << latched_addr[1:0];

            if (m_apb.pready) begin
                state_next = IDLE;
                o_data = m_apb.prdata[8 * latched_addr[1:0] +: 8];
                o_rdy = '1;
            end
        end

    endcase
end

endmodule