blob: 2a7e54102d16deade506a7f1f2abd9d95f3f7869 [file] [log] [blame]
module fifo_flopped(
// Outputs
fifo_outData, fifo_full, fifo_empty, fifo_idle,
// Inputs
clk, rst_n, fifo_inData, single_push, single_pop
);
parameter DWIDTH = 32;
parameter DEPTH = 16;
function integer clogb2;
input [31:0] depth;
begin
depth = depth - 1;
for(clogb2=0; depth>0; clogb2=clogb2+1)
depth = depth >> 1;
end
endfunction
parameter AWIDTH = (DEPTH==1'b1) ? 1'b1 : clogb2(DEPTH);
input clk;
input rst_n;
input [DWIDTH-1:0] fifo_inData;
input single_push;
input single_pop;
output [DWIDTH-1:0] fifo_outData;
output fifo_full;
output fifo_empty;
output fifo_idle;
// Write pointer
wire [AWIDTH-1:0] wrPtr;
wire [AWIDTH-1:0] nxtWrPtr;
assign nxtWrPtr = single_push
? (
((wrPtr==(DEPTH-1)) && (DEPTH != 2**AWIDTH))
? 4'd0
: wrPtr + 1'b1
)
: wrPtr;
edff #(AWIDTH) wrPtrReg (.q(wrPtr), .clk(clk), .rst_n(rst_n), .d(nxtWrPtr), .en(single_push));
// Read pointer
wire [AWIDTH-1:0] rdPtr;
wire [AWIDTH-1:0] rdPtr_p1;
assign rdPtr_p1 = (
((rdPtr==(DEPTH-1)) && (DEPTH != 2**AWIDTH))
? 4'd0
: rdPtr + 1'b1
);
wire [AWIDTH-1:0] nxtRdPtr;
assign nxtRdPtr = single_pop ? rdPtr_p1 : rdPtr;
edff #(AWIDTH) rdPtrReg (.q(rdPtr), .clk(clk), .rst_n(rst_n), .d(nxtRdPtr), .en(single_pop));
// Write enable decodes
wire [DEPTH-1:0] en;
assign en = single_push ? ({{(DEPTH-1){1'b0}},1'b1} << wrPtr) : {DEPTH{1'b0}};
// Data registers
wire [DEPTH*DWIDTH-1:0] d_in;
assign d_in = {DEPTH{fifo_inData}};
wire [DEPTH*DWIDTH-1:0] d_out;
edff_2d #(
.REGISTER_WIDTH(DWIDTH),
.NUM_OF_REGISTERS(DEPTH)
)
dReg (.q(d_out), .clk(clk), .rst_n(rst_n), .en(en), .d(d_in));
// Read output
assign fifo_outData = d_out[DWIDTH*rdPtr+DWIDTH-1 -: DWIDTH];
// fifo_idle.
parameter AWIDTH_PLUS1 = AWIDTH+1;
wire [AWIDTH_PLUS1-1:0] entryCounter;
wire [AWIDTH_PLUS1-1:0] entryCounterN;
wire count;
edff #(AWIDTH_PLUS1,0) entryCounterReg (.q(entryCounter), .clk(clk), .d(entryCounterN), .rst_n(rst_n), .en(count));
assign count = single_push | single_pop;
assign entryCounterN = entryCounter + single_push - single_pop;
assign fifo_empty = (entryCounter == {AWIDTH_PLUS1{1'b0}});
assign fifo_full = (entryCounter == DEPTH);
assign fifo_idle = fifo_empty;
`ifdef ASSERT_ON
`rvv_forbid(single_push&&fifo_full)
else $error("ERROR: Fifo Overflow! \n");
`rvv_forbid(single_pop&&fifo_empty)
else $error("ERROR: Fifo Underflow! \n");
`endif
endmodule