/********************************************** _ _ Cook Darwin __

_ descript:

out of order

author : Cook.Darwin Version: VERA.0.0 creaded: 2017/3/30 madified: ***********************************************/ `timescale 1ns/1ps module axi4_merge_rd #(

parameter MAX = 8                   //MUST LARGER THAN 2

)(

axi_inf.slaver_rd slaver,           //Out of Last
axi_inf.master_rd master            //Out of Last

);

logic clock,rst_n;

assign clock = slaver.axi_aclk; assign rst_n = slaver.axi_aresetn;

typedef enum {IDLE,GET_BASE,CHECK_NEXT,MIX,WR_DOMN} STATUS;

STATUS nstate,cstate;

always@(posedge clock,negedge rst_n)

if(~rst_n)  cstate  <= IDLE;
else        cstate  <= nstate;

logic [slaver.ASIZE-1:0] base_addr; logic [master.LSIZE-1:0] base_len;

logic [slaver.ASIZE-1:0] curr_addr; logic [slaver.LSIZE-1:0] curr_len; logic [$clog2(MAX)-1:0] cnt; logic enough_slaver; logic alone_aux; logic aux_fifo_full; logic aux_fifo_empty; logic aux_fifo_wren;

logic next_serial;

assign next_serial = curr_addr+curr_len+1 == slaver.axi_araddr && !enough_slaver;

always_comb begin

case(cstate)
IDLE:
    if(slaver.axi_arvalid && slaver.axi_arready)
            nstate  = GET_BASE;
    else    nstate  = IDLE;
GET_BASE:
    if(alone_aux)
            nstate  = WR_DOMN;
    else if(slaver.axi_arvalid)begin
        if(next_serial)
                nstate  = MIX;
        else    nstate  = WR_DOMN;
    end else    nstate  = GET_BASE;
CHECK_NEXT:
    if(alone_aux)
            nstate  = WR_DOMN;
    else if(slaver.axi_arvalid)begin
        if(next_serial)
                nstate  = MIX;
        else    nstate  = WR_DOMN;
    end else    nstate  = CHECK_NEXT;
MIX:
    if(slaver.axi_arvalid && slaver.axi_arready)
            nstate  = CHECK_NEXT;
    else    nstate  = MIX;
WR_DOMN:
    if(!aux_fifo_full)
            nstate  = IDLE;
    else    nstate  = WR_DOMN;
default:    nstate  = IDLE;
endcase

end

always@(posedge clock,negedge rst_n)

if(~rst_n)  slaver.axi_arready  <= 1'b0;
else
    case(nstate)
    IDLE,MIX:
            slaver.axi_arready  <= 1'b1;
    default:slaver.axi_arready  <= 1'b0;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  base_addr   <= '0;
else
    case(nstate)
    GET_BASE:
            base_addr   <= slaver.axi_araddr;
    default:base_addr   <= base_addr;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  base_len   <= '0;
else
    case(nstate)
    GET_BASE:
            base_len   <= slaver.axi_arlen;
    MIX:
        if(slaver.axi_arvalid)
                base_len    <= slaver.axi_araddr + slaver.axi_arlen;
        else    base_len    <= base_len;

    default:base_len   <= base_len;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  cnt   <= '0;
else
    case(nstate)
    GET_BASE:
            cnt   <= '0;
    MIX:
        if(slaver.axi_arvalid)
                cnt    <= cnt + 1;
        else    cnt    <= cnt;

    default:cnt   <= cnt;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  enough_slaver   <= '0;
else
    case(nstate)
    GET_BASE:
            enough_slaver   <= '0;
    MIX:
        if(slaver.axi_arvalid)
                enough_slaver    <= cnt == MAX-2;
        else    enough_slaver    <= enough_slaver;

    default:enough_slaver   <= enough_slaver;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  curr_addr   <= '0;
else
    case(nstate)
    GET_BASE,CHECK_NEXT:
            curr_addr   <= slaver.axi_araddr;
    default:curr_addr   <= curr_addr;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  curr_len   <= '0;
else
    case(nstate)
    GET_BASE,CHECK_NEXT:
            curr_len   <= slaver.axi_arlen;
    default:curr_len   <= curr_len;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  aux_fifo_wren   <= '0;
else
    case(nstate)
    WR_DOMN:
            aux_fifo_wren   <= 1'b1;
    default:aux_fifo_wren   <= 1'b0;
    endcase

//—>> ALONE <<———————- logic [5:0] alone_cnt;

always@(posedge clock,negedge rst_n)

if(~rst_n)  alone_cnt   <= '0;
else
    case(nstate)
    GET_BASE,CHECK_NEXT:
            alone_cnt   <= alone_cnt + 1'b1;
    default:alone_cnt   <= '0;
    endcase

always@(posedge clock,negedge rst_n)

if(~rst_n)  alone_aux   <= '0;
else        alone_aux   <= &alone_cnt;

//—<< ALONE >>———————- common_fifo #(

.DEPTH      (4      ),
.DSIZE      (master.ASIZE + master.LSIZE)

)aux_common_fifo_inst( /* input */ .clock (clock ), /* input */ .rst_n (rst_n ), /* input [DSIZE-1:0] */ .wdata ({base_addr,base_len}), /* input */ .wr_en (aux_fifo_wren ), /* output logic */ .rdata ({master.axi_araddr,master.axi_arlen}), /* input */ .rd_en (master.axi_arready ), /* output logic */ .count (), /* output logic */ .empty (aux_fifo_empty ), /* output logic */ .full (aux_fifo_full ) );

assign master.axi_arvalid = !aux_fifo_empty; assign master.axi_arid = '0; //——>> READ BEAK AUX <<——————- logic [slaver.ASIZE-1:0] slaver_addr; logic [slaver.LSIZE-1:0] slaver_len; logic [slaver.IDSIZE-1:0] slaver_aid; logic slaver_burst_1; logic slaver_fifo_full; logic slaver_fifo_empty;

common_fifo #(

.DEPTH      (MAX      ),
.DSIZE      (1+slaver.ASIZE + slaver.LSIZE +slaver.IDSIZE)

)slaver_common_fifo_inst( /* input */ .clock (clock ), /* input */ .rst_n (rst_n ), /* input [DSIZE-1:0] */ .wdata ({(slaver.axi_arlen=='0),slaver.axi_araddr,slaver.axi_arlen,slaver.axi_arid} ), /* input */ .wr_en ((slaver.axi_arvalid && slaver.axi_arready) ), /* output logic */ .rdata ({slaver_burst_1,slaver_addr,slaver_len,slaver_aid} ), /* input */ .rd_en ((slaver.axi_rvalid==1'b1 && slaver.axi_rready && slaver.axi_rlast) ), /* output logic */ .count (), /* output logic */ .empty (slaver_fifo_empty ), /* output logic */ .full (slaver_fifo_full ) );

logic [master.LSIZE-1:0] partition_cnt;

always@(posedge clock,negedge rst_n)

if(~rst_n)  partition_cnt   <= '0;
else begin
    if(master.axi_rvalid && master.axi_rready && master.axi_rlast)
            partition_cnt   <= '0;
    else if(master.axi_rvalid && master.axi_rready)begin
        if(partition_cnt==slaver_len)
                partition_cnt   <= '0;
        else    partition_cnt   <= partition_cnt + 1'b1;
    end else
            partition_cnt   <= partition_cnt;
end

// always@(posedge clock,negedge rst_n) // if(~rst_n) slaver.axi_rlast <= 1'b0; // else begin // if(!slaver_fifo_empty && slaver_burst_1) // slaver.axi_rlast <= 1'b1; // else if(slaver.axi_rvalid && slaver.axi_rready && slaver.axi_rlast) // slaver.axi_rlast <= 1'b0; // else if(slaver.axi_rvalid && slaver.axi_rready && (slaver.axi_rcnt == (slaver_len-1))) // slaver.axi_rlast <= 1'b1; // else slaver.axi_rlast <= slaver.axi_rlast; // end

logic cnt_last;

always@(posedge clock,negedge rst_n)

if(~rst_n)  cnt_last    <= 1'b0;
else begin
    if(slaver.axi_rvalid && slaver.axi_rready && slaver.axi_rlast)
            cnt_last    <= 1'b0;
    else if(slaver.axi_rvalid && slaver.axi_rready && (slaver.axi_rcnt == (slaver_len-1)))
            cnt_last    <= 1'b1;
    else    cnt_last    <= cnt_last;
end

assign slaver.axi_rdata = master.axi_rdata; assign slaver.axi_rvalid = master.axi_rvalid; assign slaver.axi_rid = slaver_aid; assign master.axi_rready = slaver.axi_rready;

assign slaver.axi_rlast = cnt_last || slaver_burst_1;

//——<< READ BEAK AUX >>——————-

endmodule