Starting state | Requests | Conservative result | Occupancy after |
|---|---|---|---|
Partial | Push + pop | Both accepted | Unchanged |
Full | Push + pop | Pop accepted; push rejected |
|
Empty | Push + pop | Push accepted; pop rejected | 1 |
Full | Push only | Rejected |
|
Empty | Pop only | Rejected | 0 |
The conservative rules derive acceptance from the flags visible before the edge. They are easy to verify and portable across memory implementations, but lose one opportunity at full and one at empty.
The telemetry FIFO keeps that policy instead of switching semantics mid-topic. The elastic alternative is shown for comparison, but it is not used by the final module or reference queue.
A throughput-oriented FIFO may accept a push while full when a pop is also accepted. The departing word frees one slot on the same edge, so occupancy stays full.
// snippet: elastic full-boundary policy
assign pop_take = pop_i && !empty_o;
assign push_take = push_i && (!full_o || pop_take);
// At full with both requests, both are accepted and count holds.
// This requires defined read-during-write behavior when pointers select
// the same physical entry.This policy is legal only when the storage implementation returns the old word to the pop while storing the new word for the future. A flop array with nonblocking assignments naturally does that; a memory macro must explicitly support the same read-first collision behavior.
Each slot is one clock cycle, and a request takes effect at the edge that ends its slot. Both FIFOs see words A, B, C and D pushed in slots 0 to 3 and pops in slots 2 to 5.
Slots 0 and 1: two pushes fill both FIFOs. Count is 2, which is full, in slot 2.
Slot 2: push C and pop arrive at full. The conservative FIFO pops A but refuses C, so its count drops to 1. The elastic FIFO accepts both and stays at 2.
Slot 3, the collision: the elastic FIFO wrote C into the slot A was leaving on the same edge, yet elas_dout shows A. The flop array read the old word first.
Slots 4 to 6: the elastic FIFO returns C and D. The conservative FIFO never stored C, so the producer must keep and retry it.
A fall-through FIFO may pair a push and pop while empty by forwarding din_i directly to the consumer. That is a different interface contract: it creates a combinational input-to-output path and makes output timing depend on the producer. The registered baseline instead stores the word and allows it to be popped later.
All entries are occupied and the write pointer names the oldest slot that becomes free next, which is also the slot named by the read pointer. The wrap or count state distinguishes full from empty.
The memory must guarantee old-data/read-first behavior for that same-address collision, and the specification and verification model must expect both operations to be accepted.