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

_ descript: author : Cook.Darwin Version: VERA.0.0 creaded: 2016/11/3 madified: ***********************************************/ `timescale 1ns/1ps module axi4_error_chk #(

parameter   DELAY = 24'hFFF_000

)(

axi_inf.mirror inf

);

typedef enum {WIDLE,WS_CMD,WW_DATA,WB_RESP,W_ERROR,W_JUDGE} W_STATUS; W_STATUS wcstate,wnstate;

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        wcstate <= WIDLE;
else    wcstate <= wnstate;

logic wtimeout,wrong_wnum; always@(*)

case(wcstate)
WIDLE:
    if(inf.axi_awvalid && inf.axi_awready)
            wnstate = WS_CMD;
    else    wnstate = WIDLE;
WS_CMD:
    if(wtimeout)
            wnstate = W_ERROR;
    else if(inf.axi_awvalid && inf.axi_awready)
            wnstate = W_ERROR;
    else if(inf.axi_wvalid)begin
        if(inf.axi_wready && inf.axi_wlast)
                wnstate = WB_RESP;
        else    wnstate = WW_DATA;
    end else
            wnstate = WS_CMD;
WW_DATA:
    if(wtimeout)
            wnstate = W_ERROR;
    else if(inf.axi_wlast && inf.axi_wready && inf.axi_wvalid)
            wnstate = WB_RESP;
    else    wnstate = WW_DATA;
WB_RESP:
    if(wtimeout || wrong_wnum)
            wnstate = W_ERROR;
    else if(inf.axi_bready && inf.axi_bvalid)
            wnstate = WIDLE;
    else    wnstate = WB_RESP;
W_JUDGE:    wnstate = WIDLE;
default:    wnstate = WIDLE;
endcase

// logic enable_wcnt; // // always@(posedge inf.axi_aclk) // if(~inf.axi_aresetn) // enable_wcnt <= 1'b0; // else // case(wnstate) // WIDLE: enable_wcnt <= 1'b0; // default:enable_wcnt <= 1'b1; // endcase //—>> write timeout <<————— logic [23:0] wdcnt; // logic wtimeout always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        wdcnt    <= 24'd0;
else
    case(wnstate)
    WIDLE:  wdcnt    <= 24'd0;
    default:begin
        if(inf.axi_wvalid && inf.axi_wready)
                wdcnt   <= wdcnt;
        else    wdcnt   <= wdcnt + 1'b1;
    end
    endcase

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        wtimeout    <= 1'b0;
else
    case(wnstate)
    WIDLE:
        wtimeout    <= 1'b0;
    default:begin
        if(wdcnt > DELAY)
                wtimeout    <= 1'b1;
        else    wtimeout    <= 1'b0;
    end
    endcase

//—<< write timeout >>————— //—<< write chk >>————— always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        inf.axi_weresp  <= 4'd0;
else begin
    case(wnstate)
    WS_CMD:     inf.axi_weresp  <= 4'd1;
    WW_DATA:    inf.axi_weresp  <= 4'd2;
    WB_RESP,W_ERROR:begin
        if(wtimeout)
                inf.axi_weresp  <= 4'd3;
        else    inf.axi_weresp  <= 4'd4;
    end
    default:;
    endcase
end

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        inf.axi_wevld   <= 1'b0;
else
    case(wnstate)
    W_ERROR:
        inf.axi_wevld   <= 1'b1;
    default:
        inf.axi_wevld   <= 1'b0;
    endcase

//—<< write chk >>————— //—>> WRITE DATA CNT <<———- logic [9:0] wcnt; // logic wrong_wnum; logic [9:0] wr_need;

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        wr_need <= 10'd0;
else begin
    if(inf.axi_awvalid && inf.axi_awready)
            wr_need <= inf.axi_awlen;
    else    wr_need <= wr_need;
end

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        wcnt    <= 10'd0;
else begin
    if(inf.axi_awvalid && inf.axi_awready)
        wcnt    <= 10'd0;
    else if(inf.axi_wvalid && inf.axi_wready)
        wcnt    <= wcnt + 1'b1;
    else
        wcnt    <= wcnt;
end

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        wrong_wnum  <= 1'b0;
else begin
    if(inf.axi_awvalid && inf.axi_awready)
            wrong_wnum  <= 1'b0;
    else if(inf.axi_wvalid && inf.axi_wready && inf.axi_wlast)
            wrong_wnum  <= wcnt != wr_need;
    else    wrong_wnum  <= wrong_wnum;
end

//—<< WRITE DATA CNT >>———-

typedef enum {RIDLE,RS_CMD,RR_DATA,R_LAST,R_ERROR} R_STATUS; R_STATUS rcstate,rnstate;

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        rcstate = RIDLE;
else    rcstate = rnstate;

logic rtimeout,wrong_rnum;

always@(*)

case(rcstate)
RIDLE:
    if(inf.axi_arvalid && inf.axi_arready)
            rnstate = RS_CMD;
    else    rnstate = RIDLE;
RS_CMD:
    if(rtimeout)
            rnstate = R_ERROR;
    else if(inf.axi_arvalid && inf.axi_arready)
            rnstate = R_ERROR;
    else if(inf.axi_rvalid)begin
        if(inf.axi_rready && inf.axi_rlast)
                rnstate = R_LAST;
        else    rnstate = RR_DATA;
    end else    rnstate = RS_CMD;
RR_DATA:
    if(rtimeout)
            rnstate = R_ERROR;
    else if(inf.axi_rready && inf.axi_rlast && inf.axi_rvalid)
            rnstate = R_LAST;
    else    rnstate = RR_DATA;
R_LAST:
    if(wrong_rnum)
            rnstate = R_ERROR;
    else    rnstate = RIDLE;
default:    rnstate = RIDLE;
endcase

//—>> read timeout <<————— logic [23:0] rdcnt; // logic wtimeout always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        rdcnt    <= 24'd0;
else
    case(rnstate)
    RIDLE:  rdcnt    <= 24'd0;
    default:begin
        if(inf.axi_rvalid && inf.axi_rready)
                rdcnt   <= rdcnt;
        else    rdcnt   <= rdcnt + 1'b1;
    end
    endcase

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        rtimeout    <= 1'b0;
else
    case(rnstate)
    RIDLE,R_ERROR:
        rtimeout    <= 1'b0;
    default:begin
        if(rdcnt > DELAY)
                rtimeout    <= 1'b1;
        else    rtimeout    <= 1'b0;
    end
    endcase

//—<< read timeout >>————— //—>> READ DATA CNT <<———- logic [9:0] rcnt; // logic wrong_rnum; logic [9:0] rd_need;

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        rd_need <= 10'd0;
else begin
    if(inf.axi_arvalid && inf.axi_arready)
            rd_need <= inf.axi_arlen;
    else    rd_need <= rd_need;
end

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        rcnt    <= 10'd0;
else begin
    if(inf.axi_arvalid && inf.axi_arready)
        rcnt    <= 10'd0;
    else if(inf.axi_rvalid && inf.axi_rready)
        rcnt    <= rcnt + 1'b1;
    else
        rcnt    <= rcnt;
end

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        wrong_rnum  <= 1'b0;
else begin
    if(inf.axi_rvalid && inf.axi_rready && inf.axi_rlast)
            wrong_rnum  <= rcnt != rd_need;
    else    wrong_rnum  <= 1'b0;
end

//—<< READ DATA CNT >>———- //—<< read chk >>————— always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        inf.axi_reresp  <= 4'd0;
else begin
    case(rnstate)
    RS_CMD:     inf.axi_reresp  <= 4'd1;
    RR_DATA:    inf.axi_reresp  <= 4'd2;
    R_LAST:begin
        if(rtimeout)
                inf.axi_reresp  <= 4'd3;
        else    inf.axi_reresp  <= 4'd4;
    end
    default:;
    endcase
end

always@(posedge inf.axi_aclk)

if(~inf.axi_aresetn)
        inf.axi_revld   <= 1'b0;
else
    case(rnstate)
    R_ERROR:
        inf.axi_revld   <= 1'b1;
    default:
        inf.axi_revld   <= 1'b0;
    endcase

//—<< read chk >>————— endmodule