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

_ descript: author : Cook.Darwin Version: VERA.0.0 creaded: 2017/2/27 madified: ***********************************************/ `timescale 1ns/1ps (* datainf = “true” *) module common_fifo #(

parameter DEPTH     = 4,
parameter DSIZE     = 8,
//(* show = "false" *)
parameter PSIZE     = $clog2(DEPTH),
parameter CSIZE     = $clog2(DEPTH+1)

)(

input                       clock,
input                       rst_n,
input [DSIZE-1:0]           wdata,
input                       wr_en,
output logic[DSIZE-1:0]     rdata,
input                       rd_en,
output logic[CSIZE-1:0]     count,
output logic                empty,
output logic                full

); import DataInterfacePkg::*;

logic data_array_empty; logic tap_req_rd_en; //—>> WPOINT <<———————— logic [PSIZE-1:0] wpoint;

always@(posedge clock,negedge rst_n)

if(~rst_n)  wpoint  <= '0;
else begin
    if(!full)begin
        if(wr_en)begin
            if(wpoint < (DEPTH-1))
                    wpoint  <= wpoint + 1'b1;
            else    wpoint  <= '0;
        end else    wpoint  <= wpoint;
    end else    wpoint  <= wpoint;
end

//—<< WPOINT >>———————— //—>> RPOINT <<———————— logic [PSIZE-1:0] rpoint;

always@(posedge clock,negedge rst_n)

if(~rst_n) rpoint   <= '0;
else begin
    if(!data_array_empty)begin
        if(tap_req_rd_en)begin
            if(rpoint < (DEPTH-1))
                    rpoint  <= rpoint + 1'b1;
            else    rpoint  <= '0;
        end else    rpoint  <= rpoint;
    end else    rpoint  <= rpoint;
end

//—<< RPOINT >>———————— //—>> FULL <<————————– logic wr_data_array_vld;

assign wr_data_array_vld = wr_en && !full;

always@(posedge clock,negedge rst_n)

if(~rst_n)  full    <= 1'b0;
else begin
    if(wr_data_array_vld && !tap_req_rd_en)begin
        if((wpoint+2==rpoint) && (wpoint+2 <= (DEPTH-1) ))
                full    <= 1'b1;
        else if((wpoint+2-(DEPTH)==rpoint) && (wpoint+2 > (DEPTH-1) ))
                full    <= 1'b1;
        else    full    <= full;
    end else if(!wr_data_array_vld && tap_req_rd_en)begin
        if(full)
                full    <= 1'b0;
        else    full    <= full;
    end else    full    <= full;
end

//—<< FULL >>————————– //—>> data_array_empty <<————————- logic req_data_array_vld;

assign req_data_array_vld = tap_req_rd_en && !data_array_empty;

always@(posedge clock,negedge rst_n)

if(~rst_n)  data_array_empty   <= 1'b1;
else begin
    if(!wr_en && req_data_array_vld)begin
        if((rpoint+1==wpoint) && (rpoint+1 <= (DEPTH-1) ))
                data_array_empty    <= 1'b1;
        else if((rpoint+1-(DEPTH)==wpoint) && (rpoint+1 > (DEPTH-1) ))
                data_array_empty    <= 1'b1;
        else    data_array_empty    <= data_array_empty;
    end else if(wr_en && !req_data_array_vld)begin
        if(data_array_empty)
                data_array_empty   <= 1'b0;
        else    data_array_empty   <= data_array_empty;
    end else    data_array_empty   <= data_array_empty;
end

//—<< data_array_empty >>————————- //—>> COUNTER <<———————– logic rd_data_array_vld;

assign rd_data_array_vld = rd_en && !empty;

always@(posedge clock,negedge rst_n)

if(~rst_n)  count   <= '0;
else begin
    if(wr_data_array_vld && !rd_data_array_vld)begin
        if(count == DEPTH)
                count   <= count;
        else    count   <= count + 1'b1;
    end else if(!wr_data_array_vld && rd_data_array_vld)begin
        if(count == '0)
                count   <= '0;
        else    count   <= count - 1'b1;
    end else if(!wr_data_array_vld && !rd_data_array_vld)
            count   <= count;
    else    count   <= count;
end

//—<< COUNTER >>———————– //—>> DATA ARRAY <<——————– logic [DSIZE-1:0] data_array [DEPTH-1:0];

always@(posedge clock,negedge rst_n)

if(~rst_n)
    foreach(data_array[i])
        data_array[i]   <= '0;
else begin
    if(wr_en && !full)
            data_array[wpoint]  <= wdata;
    else    data_array[wpoint]  <= data_array[wpoint];
end

always@(posedge clock,negedge rst_n)

if(~rst_n)  rdata   <= '0;
else begin
    if(tap_req_rd_en && !data_array_empty)
            rdata   <= data_array[rpoint];
    else    rdata   <= rdata;
end

//—<< DATA ARRAY >>——————– //—>> PIPE TAP <<———————- // logic tap_req_rd_en; logic tap_vld;

always@(posedge clock,negedge rst_n)

if(~rst_n)  tap_vld   <= 1'b0;
else begin
    tap_vld <= pipe_valid_func_force(!data_array_empty,rd_en,tap_vld);
end

assign tap_req_rd_en = !tap_vld || (rd_en && tap_vld); //—<< PIPE TAP >>———————- //—>> EMPTY <<———————- assign empty = !tap_vld; //—<< EMPTY >>———————-

endmodule