# First-in first-out queues

The `amaranth.lib.fifo` module provides building blocks for first-in, first-out queues.

class amaranth.lib.fifo.FIFOInterface(*, width, depth, fwft=True)

  Data written to the input interface (`w_data`, `w_rdy`, `w_en`) is buffered and can be read at the output interface (`r_data`, `r_rdy`, `r_en`). The data entry written first to the input also appears first on the output.

  Parameters:

    - width (int) – Bit width of data entries.

    - depth (int) – Depth of the queue. If zero, the FIFO cannot be read from or written to.

    - fwft (bool) – First-word fallthrough. If set, when `r_rdy` rises, the first entry is already available, i.e. `r_data` is valid. Otherwise, after `r_rdy` rises, it is necessary to strobe `r_en` for `r_data` to become valid.

  Variables:

    - w_data (Signal(width), in) – Input data.

    - w_rdy (Signal(1), out) – Asserted if there is space in the queue, i.e. `w_en` can be asserted to write a new entry.

    - w_en (Signal(1), in) – Write strobe. Latches `w_data` into the queue. Does nothing if `w_rdy` is not asserted.

    - w_level (Signal(range(depth + 1)), out) – Number of unread entries.

    - r_data (Signal(width), out) – Output data. The conditions in which `r_data` is valid depends on the type of the queue.

    - r_rdy (Signal(1), out) – Asserted if there is an entry in the queue, i.e. `r_en` can be asserted to read an existing entry.

    - r_en (Signal(1), in) – Read strobe. Makes the next entry (if any) available on `r_data` at the next cycle. Does nothing if `r_rdy` is not asserted.

    - r_level (Signal(range(depth + 1)), out) – Number of unread entries.

  Note

  The `FIFOInterface` class can be used directly to substitute a FIFO in tests, or inherited from in a custom FIFO implementation.

class amaranth.lib.fifo.SyncFIFO(*, width, depth, fwft=True)

  Synchronous first in, first out queue.

  Read and write interfaces are accessed from the same clock domain. If different clock domains are needed, use `AsyncFIFO`.

  Parameters:

    - width (int) – Bit width of data entries.

    - depth (int) – Depth of the queue. If zero, the FIFO cannot be read from or written to.

    - fwft (bool) – First-word fallthrough. If set, when the queue is empty and an entry is written into it, that entry becomes available on the output on the same clock cycle. Otherwise, it is necessary to assert `r_en` for `r_data` to become valid.

  Variables:

    - level (Signal(range(depth + 1)), out) – Number of unread entries. This level is the same between read and write for synchronous FIFOs.

    - w_data (Signal(width), in) – Input data.

    - w_rdy (Signal(1), out) – Asserted if there is space in the queue, i.e. `w_en` can be asserted to write a new entry.

    - w_en (Signal(1), in) – Write strobe. Latches `w_data` into the queue. Does nothing if `w_rdy` is not asserted.

    - w_level (Signal(range(depth + 1)), out) – Number of unread entries.

    - r_data (Signal(width), out) – Output data. For FWFT queues, valid if `r_rdy` is asserted. For non-FWFT queues, valid on the next cycle after `r_rdy` and `r_en` have been asserted.

    - r_rdy (Signal(1), out) – Asserted if there is an entry in the queue, i.e. `r_en` can be asserted to read an existing entry.

    - r_en (Signal(1), in) – Read strobe. Makes the next entry (if any) available on `r_data` at the next cycle. Does nothing if `r_rdy` is not asserted.

    - r_level (Signal(range(depth + 1)), out) – Number of unread entries.

class amaranth.lib.fifo.SyncFIFOBuffered(*, width, depth)

  Buffered synchronous first in, first out queue.

  This queue’s interface is identical to `SyncFIFO` configured as `fwft=True`, but it does not use asynchronous memory reads, which are incompatible with FPGA block RAMs.

  In exchange, the latency between an entry being written to an empty queue and that entry becoming available on the output is increased by one cycle compared to `SyncFIFO`.

  Parameters:

    - width (int) – Bit width of data entries.

    - depth (int) – Depth of the queue. If zero, the FIFO cannot be read from or written to.

    - fwft (bool) – Always set.

  Variables:

    - level (Signal(range(depth + 1)), out) – Number of unread entries. This level is the same between read and write for synchronous FIFOs.

    - w_data (Signal(width), in) – Input data.

    - w_rdy (Signal(1), out) – Asserted if there is space in the queue, i.e. `w_en` can be asserted to write a new entry.

    - w_en (Signal(1), in) – Write strobe. Latches `w_data` into the queue. Does nothing if `w_rdy` is not asserted.

    - w_level (Signal(range(depth + 1)), out) – Number of unread entries.

    - r_data (Signal(width), out) – Output data. Valid if `r_rdy` is asserted.

    - r_rdy (Signal(1), out) – Asserted if there is an entry in the queue, i.e. `r_en` can be asserted to read an existing entry.

    - r_en (Signal(1), in) – Read strobe. Makes the next entry (if any) available on `r_data` at the next cycle. Does nothing if `r_rdy` is not asserted.

    - r_level (Signal(range(depth + 1)), out) – Number of unread entries.

class amaranth.lib.fifo.AsyncFIFO(*, width, depth, r_domain='read', w_domain='write', exact_depth=False)

  Asynchronous first in, first out queue.

  Read and write interfaces are accessed from different clock domains, which can be set when constructing the FIFO.

  `AsyncFIFO` can be reset from the write clock domain. When the write domain reset is asserted, the FIFO becomes empty. When the read domain is reset, data remains in the FIFO - the read domain logic should correctly handle this case.

  `AsyncFIFO` only supports power of 2 depths. Unless `exact_depth` is specified, the `depth` parameter is rounded up to the next power of 2.

  Parameters:

    - width (int) – Bit width of data entries.

    - depth (int) – Depth of the queue. If zero, the FIFO cannot be read from or written to.

    - r_domain (str) – Read clock domain.

    - w_domain (str) – Write clock domain.

    - fwft (bool) – Always set.

  Variables:

    - w_data (Signal(width), in) – Input data.

    - w_rdy (Signal(1), out) – Asserted if there is space in the queue, i.e. `w_en` can be asserted to write a new entry.

    - w_en (Signal(1), in) – Write strobe. Latches `w_data` into the queue. Does nothing if `w_rdy` is not asserted.

    - w_level (Signal(range(depth + 1)), out) – Number of unread entries.

    - r_data (Signal(width), out) – Output data. Valid if `r_rdy` is asserted.

    - r_rdy (Signal(1), out) – Asserted if there is an entry in the queue, i.e. `r_en` can be asserted to read an existing entry.

    - r_en (Signal(1), in) – Read strobe. Makes the next entry (if any) available on `r_data` at the next cycle. Does nothing if `r_rdy` is not asserted.

    - r_level (Signal(range(depth + 1)), out) – Number of unread entries.

    - r_rst (Signal(1), out) – Asserted, for at least one read-domain clock cycle, after the FIFO has been reset by the write-domain reset.

class amaranth.lib.fifo.AsyncFIFOBuffered(*, width, depth, r_domain='read', w_domain='write', exact_depth=False)

  Buffered asynchronous first in, first out queue.

  Read and write interfaces are accessed from different clock domains, which can be set when constructing the FIFO.

  `AsyncFIFOBuffered` only supports power of 2 plus one depths. Unless `exact_depth` is specified, the `depth` parameter is rounded up to the next power of 2 plus one. (The output buffer acts as an additional queue element.)

  This queue’s interface is identical to `AsyncFIFO`, but it has an additional register on the output, improving timing in case of block RAM that has large clock-to-output delay.

  In exchange, the latency between an entry being written to an empty queue and that entry becoming available on the output is increased by one cycle compared to `AsyncFIFO`.

  Parameters:

    - width (int) – Bit width of data entries.

    - depth (int) – Depth of the queue. If zero, the FIFO cannot be read from or written to.

    - r_domain (str) – Read clock domain.

    - w_domain (str) – Write clock domain.

    - fwft (bool) – Always set.

  Variables:

    - w_data (Signal(width), in) – Input data.

    - w_rdy (Signal(1), out) – Asserted if there is space in the queue, i.e. `w_en` can be asserted to write a new entry.

    - w_en (Signal(1), in) – Write strobe. Latches `w_data` into the queue. Does nothing if `w_rdy` is not asserted.

    - w_level (Signal(range(depth + 1)), out) – Number of unread entries.

    - r_data (Signal(width), out) – Output data. Valid if `r_rdy` is asserted.

    - r_rdy (Signal(1), out) – Asserted if there is an entry in the queue, i.e. `r_en` can be asserted to read an existing entry.

    - r_en (Signal(1), in) – Read strobe. Makes the next entry (if any) available on `r_data` at the next cycle. Does nothing if `r_rdy` is not asserted.

    - r_level (Signal(range(depth + 1)), out) – Number of unread entries.

    - r_rst (Signal(1), out) – Asserted, for at least one read-domain clock cycle, after the FIFO has been reset by the write-domain reset.