`timescale 1ns / 1ps
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2025/03/20 20:49:32
// Design Name: 
// Module Name: axi_fifo_ctrl
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module axi_fifo_ctrl(
    input                             sys_clk_i,
    input                             sys_rst_i,

    input [1:0]                       rw_req_i,
    input [32:0]                      rw_addr_i,
    input [4:0]                       rd_len_i,
    input [511:0]                     wr_data_i,
    input [63:0]                      wr_mask_i,
    input [4:0]                       rw_info_i,

    output                            rw_ack_o,
    output [4:0]                      rw_info_o,

    output [511:0]                    rd_data_o,
    output                            rd_data_v_o,
    output [4:0]                      rd_info_o,

    input                             wr_fifo_almost_full_i,
    input                             wr_fifo_full_i,
    output                            wr_fifo_we_o,
    output [32:0]                     wr_fifo_addr_o,
    output [511:0]                    wr_fifo_data_o,
    output [63:0]                     wr_fifo_mask_o,

    input                             rd_fifo_almost_full_i,
    input                             rd_fifo_full_i,
    output [32:0]                     rd_fifo_addr_o,
    output [7:0]                      rd_fifo_len_o,
    output [4:0]                      rd_fifo_info_o,
    output                            rd_fifo_we_o,
    input                             rd_fifo_empty_i,
    output                            rd_fifo_re_o,
    input [511:0]                     rd_fifo_data_o,
    input                             rd_fifo_data_v_o,
    input [4:0]                       rd_fifo_info_i,

    output [1:0]                      rw_fifo_busy_o
    );

    localparam
        S_IDLE       = 3'b000,
        S_WR_START   = 3'b001,
        S_WR_RESP    = 3'b010,
        S_RD_START   = 3'b011,
        S_RD_RESP    = 3'b100;


    reg [2:0] c_state;
    reg [2:0] n_state;

    reg         rd_req;
    reg         wr_req;
    reg         rw_ack;
    reg [4:0]   rd_info;
    reg [511:0] rd_data;
    reg         rd_data_v;
    reg [4:0]   rw_info;

    reg         wr_fifo_we;
    reg [32:0]  wr_fifo_addr;
    reg [511:0] wr_fifo_data;
    reg [63:0]  wr_fifo_mask;
    reg [32:0]  rd_fifo_addr;
    reg [7:0]   rd_fifo_len;
    reg         rd_fifo_we;
    reg         rd_fifo_re;

    assign rw_ack_o = rw_ack;
    assign rd_info_o = rd_info;
    assign rd_data_o = rd_data;
    assign rd_data_v_o = rd_data_v;
    assign rw_info_o = rw_info;
    assign wr_fifo_we_o = wr_fifo_we;
    assign wr_fifo_addr_o = wr_fifo_addr;
    assign wr_fifo_data_o = wr_fifo_data;
    assign wr_fifo_mask_o = wr_fifo_mask;
    assign rd_fifo_addr_o = rd_fifo_addr;
    assign rd_fifo_len_o = rd_fifo_len;
    assign rd_fifo_we_o = rd_fifo_we;
    assign rd_fifo_re_o = rd_fifo_re;
    assign rd_fifo_info_o = rw_info;
    assign rw_fifo_busy_o = 2'b11;  // !

    always @(posedge sys_clk_i or posedge sys_rst_i) begin
        if (sys_rst_i) begin
            c_state <= S_IDLE;
        end else begin
            c_state <= n_state;
        end
    end

    always @(*) begin
        rd_req          = 1'b0;
        wr_req          = 1'b0;
        rw_ack          = 1'b0;
        rw_info         = 5'b0;
        wr_fifo_we      = 1'b0;
        wr_fifo_addr    = 33'b0;
        wr_fifo_data    = 512'b0;
        wr_fifo_mask    = 64'b0;
        rd_fifo_addr    = 33'b0;
        rd_fifo_len     = 8'b0;
        rd_fifo_we      = 1'b0;
        rd_fifo_re      = 1'b0;
        n_state = S_IDLE;
        case (c_state)
            S_IDLE: begin
                rw_info         = rw_info_i;
                if(rw_req_i == 2'b01) begin
                    rd_fifo_addr    = rw_addr_i;
                    rd_fifo_len     = rd_len_i;
                    rd_req          = 1'b1;
                    n_state         = S_WR_START;
                end else if(rw_req_i == 2'b10) begin
                    wr_fifo_addr    = rw_addr_i;
                    wr_fifo_data    = wr_data_i;
                    wr_fifo_mask    = wr_mask_i;
                    wr_req          = 1'b1;
                    n_state         = S_RD_START;
                end
                else begin
                    n_state = S_IDLE;
                end
            end
            S_RD_START: begin
                rw_info         = rw_info;
                rd_fifo_addr    = rd_fifo_addr;
                rd_fifo_len     = rd_fifo_len;
                rd_req          = rd_req;
                if(rd_fifo_full_i == 1'b0) begin
                    rd_fifo_we  = 1'b1;
                    n_state     = S_RD_RESP;
                end
                else begin
                    n_state = S_RD_START;
                end
            end
            S_RD_RESP: begin
                rw_info     = rw_info;
                rw_ack      = 1'b1;
                n_state     = S_IDLE;
            end
            S_WR_START: begin
                rw_info         = rw_info;
                wr_fifo_addr    = wr_fifo_addr;
                wr_fifo_data    = wr_fifo_data;
                wr_fifo_mask    = wr_fifo_mask;
                wr_req          = wr_req;
                if(wr_fifo_full_i == 1'b0) begin
                    wr_fifo_we  = 1'b1;
                    n_state     = S_WR_RESP;
                end
                else begin
                    n_state = S_WR_START;
                end
            end
            S_WR_RESP: begin
                rw_info     = rw_info;
                rw_ack      = 1'b1;
                n_state     = S_IDLE;
            end
            default: begin
                n_state = S_IDLE;
            end
        endcase
    end

    always @(posedge sys_clk_i or posedge sys_rst_i) begin
        if (sys_rst_i) begin
            rd_data <= 512'b0;
            rd_data_v <= 1'b0;
            rd_info <= 5'b0;
        end
        else begin
            if () begin

            end
        end
    end
    
endmodule
