blob: f981e7760a2d3162957dcf93e2a8ad7004141535 [file] [log] [blame]
module openFifo4_flopped_ptr(/*AUTOARG*/
// Outputs
fifo_outData, fifo_full, fifo_empty, d0, d1, d2, d3, dValid, dPtr,
// Inputs
clk, rst_n, fifo_inData, single_push, single_pop
);
parameter DWIDTH = 32,
AWIDTH = 2;
localparam ZERO = {DWIDTH{1'b0}};
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 [DWIDTH-1:0] d0;
output [DWIDTH-1:0] d1;
output [DWIDTH-1:0] d2;
output [DWIDTH-1:0] d3;
output [3:0] dValid;
output [AWIDTH-1:0] dPtr;
// Write pointer
wire [AWIDTH-1:0] wrPtr;
wire [AWIDTH-1:0] nxtWrPtr = single_push ? wrPtr + 1'b1 : wrPtr;
edff #(AWIDTH) wrPtrReg (.q(wrPtr), .clk(clk), .rst_n(rst_n), .d(nxtWrPtr), .en(single_push) `ifdef TB_SUPPORT , .init_data('0)`endif);
// Read pointer
wire [AWIDTH-1:0] rdPtr;
wire [AWIDTH-1:0] nxtRdPtr = single_pop ? rdPtr + 1'b1 : rdPtr;
edff #(AWIDTH) rdPtrReg (.q(rdPtr), .clk(clk), .rst_n(rst_n), .d(nxtRdPtr), .en(single_pop) `ifdef TB_SUPPORT , .init_data('0)`endif);
assign dPtr = nxtRdPtr;
// Flag generation
reg nxtLempty;
always @(*)
if ((nxtWrPtr == nxtRdPtr) & single_pop)
nxtLempty = 1'b1;
else if (nxtWrPtr != nxtRdPtr)
nxtLempty = 1'b0;
else
nxtLempty = fifo_empty;
dff #(1) emptyReg (.q(fifo_empty), .clk(clk), .rst_n(rst_n), .d(nxtLempty));
reg nxtLfull;
always @(*)
if ((nxtWrPtr == nxtRdPtr) & single_push)
nxtLfull = 1'b1;
else if (nxtWrPtr != nxtRdPtr)
nxtLfull = 1'b0;
else
nxtLfull = fifo_full;
dff #(1) fullReg (.q(fifo_full), .clk(clk), .rst_n(rst_n), .d(nxtLfull));
// Write enable decodes
wire en0 = single_push & (wrPtr == 2'd0);
wire en1 = single_push & (wrPtr == 2'd1);
wire en2 = single_push & (wrPtr == 2'd2);
wire en3 = single_push & (wrPtr == 2'd3);
// Data registers
wire [DWIDTH-1:0] d0;
wire [DWIDTH-1:0] d1;
wire [DWIDTH-1:0] d2;
wire [DWIDTH-1:0] d3;
edff #(DWIDTH) d0Reg (.q(d0), .clk(clk), .rst_n(rst_n), .en(en0), .d(fifo_inData) `ifdef TB_SUPPORT , .init_data('0)`endif);
edff #(DWIDTH) d1Reg (.q(d1), .clk(clk), .rst_n(rst_n), .en(en1), .d(fifo_inData) `ifdef TB_SUPPORT , .init_data('0)`endif);
edff #(DWIDTH) d2Reg (.q(d2), .clk(clk), .rst_n(rst_n), .en(en2), .d(fifo_inData) `ifdef TB_SUPPORT , .init_data('0)`endif);
edff #(DWIDTH) d3Reg (.q(d3), .clk(clk), .rst_n(rst_n), .en(en3), .d(fifo_inData) `ifdef TB_SUPPORT , .init_data('0)`endif);
// Read output
reg [DWIDTH-1:0] fifo_outData;
always @(*)
case (rdPtr)
2'd0 : fifo_outData = d0;
2'd1 : fifo_outData = d1;
2'd2 : fifo_outData = d2;
2'd3 : fifo_outData = d3;
default : fifo_outData = ZERO;
endcase
// Valid signal per data
reg [4-1:0] dValidN;
wire updateDValid;
edff #(4) dValidReg (.q(dValid), .clk(clk), .d(dValidN), .rst_n(rst_n), .en(updateDValid) `ifdef TB_SUPPORT , .init_data('0)`endif);
assign updateDValid = single_push | single_pop;
always @(*) begin
dValidN = dValid;
if (single_push) dValidN[wrPtr] = 1'b1;
if (single_pop) dValidN[rdPtr] = 1'b0;
end
`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