module frame_arbiter(
    input           clk,
    input           rst_n,
    input           wframe_valid,
    input [159:0]   wframe_data,
    output          wframe_ready,
    input           rframe_valid,
    input [159:0]   rframe_data,
    output          rframe_ready,
    output          axi2array_frame_valid,
    output [152:0]  axi2array_frame_data,
    input           axi2array_frame_ready,
    input           mc_work_en,
    input [1:0]     axi_bus_rw_priority
);
    

    reg [1:0] cur_state,next_state;
    localparam [1:0] FARB_IDLE = 2'b00;
    localparam [1:0] FARB_WR   = 2'b01;
    localparam [1:0] FARB_RD   = 2'b10;

    reg rw_round_robin;
    reg [6:0] frame_cnt;
    wire rw_flag;
    wire [151:0] frame;
    wire [7:0] len;


    assign axi2array_frame_valid = (cur_state == FARB_WR) && wframe_valid ||
                                   (cur_state == FARB_RD) && rframe_valid;
    assign axi2array_frame_data  = {rw_frag,frame};
    assign wframe_ready          = (cur_state == FARB_WR) && axi2array_frame_ready;
    assign rframe_ready          = (cur_state == FARB_RD) && axi2array_frame_ready;
    assign rwflag                = (cur_state == FARB_WR);
    assign frame                 = (cur_state == FARB_WR) ? wframe_data[159:8]:
                                                            rframe_data[159:8];
    assign len                   = (cur_state == FARB_WR) ? wframe_data[7:0]:
                                                            rframe_data[7:0];

    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            cur_state <= 'd0;
        end else begin
            cur_state <= next_state;
        end
    end

    always@(*) begin
        case(cur_state)
            FARB_IDLE : begin 
                        if(wframe_valid && rframe_valid) begin
                            case(axi_bus_rw_priority)
                                2'b00: begin
                                    next_state = FARB_RD;
                                end
                                2'b01: begin
                                    next_state = FARB_WR;
                                end
                                2'b10: begin
                                    next_state = rw_round_robin ? FARB_WR : FARB_RD;
                                end
                            endcase
                        end else if (wframe_valid) begin
                            next_state = FARB_WR;
                        end else if (rframe_valid) begin
                            next_state = FARB_RD;
                        end else begin
                            next_state = FARB_IDLE;
                        end
            end
            FARB_WR   : begin if (axi2array_frame_valid && axi2array_frame_ready &&
                                    (frame_cnt == (len>>1))) begin
                                    next_state = FARB_IDLE;
                                end else begin
                                    next_state = FARB_WR;
                                end
            end
            FARB_RD   :begin if (axi2array_frame_valid && axi2array_frame_ready &&
                                    (frame_cnt == (len>>1))) begin
                                    next_state = FARB_IDLE;
                                end else begin
                                    next_state = FARB_RD;
                                end
            end
            default   : begin
                            next_state = FARB_IDLE;
            end
        endcase
    end

    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            rw_round_robin <= 1'b1;
        end else if(wframe_valid && rframe_valid && (cur_state == FARB_IDLE)) begin
            rw_round_robin <= ~rw_round_robin;
        end
    end
    
    always@(posedge clk or negedge rst_n) begin
        if(!rst_n) begin
            frame_cnt <= 'd0;
        end else if (axi2array_frame_valid && axi2array_frame_ready) begin
            if(frame_cnt == (len >> 1)) begin
                frame_cnt <= 'd0;
            end else begin
                frame_cnt <= frame_cnt + 1'b1;
            end
        end
    end

    endmodule


