Initial load of files
This commit is contained in:
281
src_bsc_lib_RTL/SizedFIFO.v
Normal file
281
src_bsc_lib_RTL/SizedFIFO.v
Normal file
@@ -0,0 +1,281 @@
|
||||
|
||||
// Copyright (c) 2000-2012 Bluespec, Inc.
|
||||
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// $Revision$
|
||||
// $Date$
|
||||
|
||||
`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;
|
||||
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
|
||||
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
|
||||
Reference in New Issue
Block a user