`ifdef BSV_ASSIGNMENT_DELAY `else `define BSV_ASSIGNMENT_DELAY `endif `ifdef BSV_POSITIVE_RESET `define BSV_RESET_VALUE 1'b1 `define BSV_RESET_EDGE posedge `else `define BSV_RESET_VALUE 1'b0 `define BSV_RESET_EDGE negedge `endif `ifdef BSV_ASYNC_RESET `define BSV_ARESET_EDGE_META or `BSV_RESET_EDGE RST `else `define BSV_ARESET_EDGE_META `endif `ifdef BSV_RESET_FIFO_HEAD `define BSV_ARESET_EDGE_HEAD `BSV_ARESET_EDGE_META `else `define BSV_ARESET_EDGE_HEAD `endif `ifdef BSV_RESET_FIFO_ARRAY `define BSV_ARESET_EDGE_ARRAY `BSV_ARESET_EDGE_META `else `define BSV_ARESET_EDGE_ARRAY `endif // Sized fifo. Model has output register which improves timing module SizedFIFO(CLK, RST, D_IN, ENQ, FULL_N, D_OUT, DEQ, EMPTY_N, CLR); parameter p1width = 1; // data width parameter p2depth = 3; parameter p3cntr_width = 1; // log(p2depth-1) // The -1 is allowed since this model has a fast output register parameter guarded = 1'b1; localparam p2depth2 = (p2depth >= 2) ? (p2depth -2) : 0 ; input CLK; input RST; input CLR; input [p1width - 1 : 0] D_IN; input ENQ; input DEQ; output FULL_N; output EMPTY_N; output [p1width - 1 : 0] D_OUT; reg not_ring_full; reg ring_empty; reg [p3cntr_width-1 : 0] head; wire [p3cntr_width-1 : 0] next_head; reg [p3cntr_width-1 : 0] tail; wire [p3cntr_width-1 : 0] next_tail; // if the depth is too small, don't create an ill-sized array; // instead, make a 1-sized array and let the initial block report an error (* RAM_STYLE = "DISTRIBUTED" *) reg [p1width - 1 : 0] arr[0: p2depth2]; reg [p1width - 1 : 0] D_OUT; reg hasodata; wire [p3cntr_width-1:0] depthLess2 = p2depth2[p3cntr_width-1:0] ; wire [p3cntr_width-1 : 0] incr_tail; wire [p3cntr_width-1 : 0] incr_head; assign incr_tail = tail + 1'b1 ; assign incr_head = head + 1'b1 ; assign next_head = (head == depthLess2 ) ? {p3cntr_width{1'b0}} : incr_head ; assign next_tail = (tail == depthLess2 ) ? {p3cntr_width{1'b0}} : incr_tail ; assign EMPTY_N = hasodata; assign FULL_N = not_ring_full; `ifdef BSV_NO_INITIAL_BLOCKS `else // not BSV_NO_INITIAL_BLOCKS // synopsys translate_off initial begin : initial_block integer i; D_OUT = {((p1width + 1)/2){2'b10}} ; ring_empty = 1'b1; not_ring_full = 1'b1; hasodata = 1'b0; head = {p3cntr_width {1'b0}} ; tail = {p3cntr_width {1'b0}} ; for (i = 0; i <= p2depth2; i = i + 1) begin arr[i] = D_OUT ; end end // synopsys translate_on `endif // BSV_NO_INITIAL_BLOCKS always @(posedge CLK `BSV_ARESET_EDGE_META) begin if (RST == `BSV_RESET_VALUE) begin head <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ; tail <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ; ring_empty <= `BSV_ASSIGNMENT_DELAY 1'b1; not_ring_full <= `BSV_ASSIGNMENT_DELAY 1'b1; hasodata <= `BSV_ASSIGNMENT_DELAY 1'b0; end // if (RST == `BSV_RESET_VALUE) else begin casez ({CLR, DEQ, ENQ, hasodata, ring_empty}) // Clear operation 5'b1????: begin head <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ; tail <= `BSV_ASSIGNMENT_DELAY {p3cntr_width {1'b0}} ; ring_empty <= `BSV_ASSIGNMENT_DELAY 1'b1; not_ring_full <= `BSV_ASSIGNMENT_DELAY 1'b1; hasodata <= `BSV_ASSIGNMENT_DELAY 1'b0; end // ----------------------- // DEQ && ENQ case -- change head and tail if added to ring 5'b011?0: begin tail <= `BSV_ASSIGNMENT_DELAY next_tail; head <= `BSV_ASSIGNMENT_DELAY next_head; end // ----------------------- // DEQ only and NO data is in ring 5'b010?1: begin hasodata <= `BSV_ASSIGNMENT_DELAY 1'b0; end // DEQ only and data is in ring (move the head pointer) 5'b010?0: begin head <= `BSV_ASSIGNMENT_DELAY next_head; not_ring_full <= `BSV_ASSIGNMENT_DELAY 1'b1; ring_empty <= `BSV_ASSIGNMENT_DELAY next_head == tail ; end // ----------------------- // ENQ only when empty 5'b0010?: begin hasodata <= `BSV_ASSIGNMENT_DELAY 1'b1; end // ENQ only when not empty 5'b0011?: begin if ( not_ring_full ) // Drop this test to save redundant test // but be warnned that with test fifo overflow causes loss of new data // while without test fifo drops all but head entry! (pointer overflow) begin tail <= `BSV_ASSIGNMENT_DELAY next_tail; ring_empty <= `BSV_ASSIGNMENT_DELAY 1'b0; not_ring_full <= `BSV_ASSIGNMENT_DELAY ! (next_tail == head) ; end end endcase end // else: !if(RST == `BSV_RESET_VALUE) end // always @ (posedge CLK) // Update the fast data out register always @(posedge CLK `BSV_ARESET_EDGE_HEAD) begin `ifdef BSV_RESET_FIFO_HEAD if (RST == `BSV_RESET_VALUE) begin D_OUT <= `BSV_ASSIGNMENT_DELAY {p1width {1'b0}} ; end // if (RST == `BSV_RESET_VALUE) else `endif begin casez ({CLR, DEQ, ENQ, hasodata, ring_empty}) // DEQ && ENQ cases 5'b011?0: begin D_OUT <= `BSV_ASSIGNMENT_DELAY arr[head]; end 5'b011?1: begin D_OUT <= `BSV_ASSIGNMENT_DELAY D_IN; end // DEQ only and data is in ring 5'b010?0: begin D_OUT <= `BSV_ASSIGNMENT_DELAY arr[head]; end // ENQ only when empty 5'b0010?: begin D_OUT <= `BSV_ASSIGNMENT_DELAY D_IN; end endcase end // else: !if(RST == `BSV_RESET_VALUE) end // always @ (posedge CLK) // Update the memory array reset is OFF always @(posedge CLK `BSV_ARESET_EDGE_ARRAY) begin: array `ifdef BSV_RESET_FIFO_ARRAY if (RST == `BSV_RESET_VALUE) begin: rst_array integer i; for (i = 0; i <= p2depth2 && p2depth > 2; i = i + 1) begin arr[i] <= `BSV_ASSIGNMENT_DELAY {p1width {1'b0}} ; end end // if (RST == `BSV_RESET_VALUE) else `endif begin if (!CLR && ENQ && ((DEQ && !ring_empty) || (!DEQ && hasodata && not_ring_full))) begin arr[tail] <= `BSV_ASSIGNMENT_DELAY D_IN; end end // else: !if(RST == `BSV_RESET_VALUE) end // always @ (posedge CLK) // synopsys translate_off always@(posedge CLK) begin: error_checks reg deqerror, enqerror ; deqerror = 0; enqerror = 0; if (RST == ! `BSV_RESET_VALUE) begin if ( ! EMPTY_N && DEQ ) begin deqerror = 1 ; $display( "Warning: SizedFIFO: %m -- Dequeuing from empty fifo" ) ; end if ( ! FULL_N && ENQ && (!DEQ || guarded) ) begin enqerror = 1 ; $display( "Warning: SizedFIFO: %m -- Enqueuing to a full fifo" ) ; end end end // block: error_checks // synopsys translate_on // synopsys translate_off // Some assertions about parameter values initial begin : parameter_assertions integer ok ; ok = 1 ; if ( p2depth <= 1) begin ok = 0; $display ( "Warning SizedFIFO: %m -- depth parameter increased from %0d to 2", p2depth); end if ( p3cntr_width <= 0 ) begin ok = 0; $display ( "ERROR SizedFIFO: %m -- width parameter must be greater than 0" ) ; end if ( ok == 0 ) $finish ; end // initial begin // synopsys translate_on endmodule