123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158openBasemoduletypeConfig=sigvaldata_width:intvalcapacity:intvalshowahead:boolendmoduleT=structtype'at={q:'a;full:'a;empty:'a;nearly_full:'a;nearly_empty:'a;used:'a}[@@derivingsexp_of,hardcaml]type'acreate_params=?nearly_empty:int(** default is [1] **)->?nearly_full:int(** default is [depth-1] **)->?overflow_check:bool(** default is [true] *)->?reset:Signal.t(** default is [empty] **)->?underflow_check:bool(** default is [true] *)->?ram_attributes:Rtl_attribute.tlist(** default is blockram *)->?scope:Scope.t(* to override naming prefix *)->'atypecreate_fifo=(unit->capacity:int->clock:Signal.t->clear:Signal.t->wr:Signal.t->d:Signal.t->rd:Signal.t->Signal.tt)create_paramsendmoduleKinded_fifo=structtype('a,'b)t=|Classic:'aT.t->('a,[`Classic])t|Showahead:'aT.t->('a,[`Showahead])ttype'apacked=T:('a,'b)t->'apackedtypecreate_classic=capacity:int->write_clock:Signal.t->read_clock:Signal.t->clear:Signal.t->wr:Signal.t->d:Signal.t->rd:Signal.t->(Signal.t,[`Classic])ttypecreate_showahead=capacity:int->write_clock:Signal.t->read_clock:Signal.t->clear:Signal.t->wr:Signal.t->d:Signal.t->rd:Signal.t->(Signal.t,[`Showahead])tendmoduletypeS=sigincludemoduletypeofTwithtype'at='aT.tmoduleKinded_fifo=Kinded_fifo(** {4 Base RTL FIFO} *)(** [create ~clock ~clear ~wr ~d ~rd capacity] builds a FIFO with [capacity] elements
which is written with [d] when [wr] is high and read when [rd] is high.
The default reset configuration is to use a synchronous [clr] signal. An
asynchronous [rst] may be optionally provided. One of [clr] or [rst] must be
non-empty.
Optional overflow and underflow checking may be used. Data will not be
written(/read) when the fifo is [full](/[empty]) regardles or the [wr]/([rd])
signals.
[nearly_emtpy] and [nearly_full] may be programmed to go high when the fifo is
nearing an underflow or overflow state.
The [showahead] mode changes the read behaviour of the FIFO. When showahead is
[false] read data is available 1 cycle after [rd] is high. With showahead [true] the
data is available when the fifo is not [empty] (you can also think of this as data
being available on the same cycle that [rd] is asserted). To support [showahead]
behaviour the timing of the [full]/[empty] flag changes (although they still
correctly indicate when it is safe to read or write to the FIFO). [showahead] mode
has some extra cost in terms of extra logic. The implementation ensures the output
is registered and timing performance is good - nearly as fast as the underlying RAM
allows.
Note; [showahead] is sometimes referred to as "first word fall through". It uses the
write-before-read ram mode which is problematic in synthesis so we include special
logic that performs collision detection.
The [used] output indicates the number of elements currently in the FIFO. *)valcreate:?showahead:bool(** default is [false] *)->T.create_fifo(** {3 Functions to derive fifo architectures from other architecetures.} *)valshowahead_fifo_of_classic_fifo:Kinded_fifo.create_classic->Kinded_fifo.create_showaheadStaged.t(** {3 Derived FIFO architectures.} *)(** Adds an extra output register to the non-showahead fifo. This delays the output, but
ensures there is no logic data on the fifo output. Adds an extra cycle of latency (2
cycles from write to empty low).*)valcreate_classic_with_extra_reg:T.create_fifo(** Constructs a showahead fifo from a non-showahead fifo. Only modifies the control
flags. Has 2 cycles of latency. *)valcreate_showahead_from_classic:create_fifo(** Constructs a fifo similarly to [create_showahead_from_classic] and ensures the output
data is registered. Has 3 cycles of latency, but is slightly faster than [create
~showahead:true] - it seems to only be limited by the underlying RAM frequency. *)valcreate_showahead_with_extra_reg:create_fifomoduletypeConfig=Config(** Create FIFO using interfaces. *)moduleWith_interface(Config:Config):sigmoduleI:sigtype'at={clock:'a;clear:'a;wr:'a;d:'a;rd:'a}[@@derivingsexp_of,hardcaml]endmoduleO:Interface.Swithtype'at='at(** Create a normal or showahead fifo using different read-before-write or
write-before-read (semantically) rams. *)valcreate:Interface.Create_fn(I)(O).tcreate_params(** Create fifo using read-before-write ram only. It may still be used in showahead
mode and include an extra register stage. Latency is slightly higher than the
version built by [create]. *)valclassic:?extra_reg:bool(* default is false *)->Interface.Create_fn(I)(O).tcreate_paramsendend