MFB Compactor
- ENTITY MFB_COMPACTOR IS
The MFB_COMPACTOR removes empty (unoccupied) regions between frames on the MFB bus and shifts the occupied regions left so they are contiguous in the output word, while preserving frame order and region order within a frame. A region moves as one indivisible unit, so anything short of a whole idle region is left untouched: an internally incomplete region (EOF_POS < max) is not a gap, and neither is a region shared between the tail of one frame and the head of the next (SOF_POS > EOF_POS within it) - only whole idle regions between frames get removed. A small accumulator (up to REGIONS-1 leftover regions) holds regions that did not fill a whole output word yet; it is combined with the next input word every cycle, so throughput is a full word per cycle with no extra write port needed on any downstream memory.
Occupancy (which regions carry frame data, including “the frame continues through this whole word with no SOF/EOF”) is derived with MFB_AUXILIARY_SIGNALS’s region-level in-frame carry. That carry correctly follows a region shared between two frames as well as a fully aligned one, so REGION_SIZE>1 works for arbitrary, non-region-aligned frame lengths too - the only real constraint is plain MFB: a single region carries at most one SOF and one EOF.
RX data falls through into the pipeline by default (see FWFT_MODE), so a stalled TX_DST_RDY does not needlessly stall RX too while the accumulator still has room.
Generics
PortsGeneric
Type
Default
Description
REGIONS
natural
4
Number of regions in a word.
REGION_SIZE
natural
1
Number of blocks in a region.
BLOCK_SIZE
natural
8
Number of items in a block.
ITEM_WIDTH
natural
32
Width of one item, in bits.
META_WIDTH
natural
0
Width of optional per-region user metadata (0 = unused). Travels with its region through compaction.
FLUSH_TIMEOUT
natural
8
Number of consecutive idle (no new occupied region) clock cycles after which a non-empty but not-yet-full accumulator is flushed to TX. 0 = flush as soon as no new data arrived on RX in the previous cycle (lowest latency, lowest density on bursty traffic); a larger value trades tail latency for a higher chance of fully packed output words. A flush only ever happens at a frame boundary: while the accumulator ends inside an unfinished frame it keeps waiting, because the padding of a partial word would read as that frame continuing.
USE_PIPE
boolean
true
Insert a registered input stage ahead of the compaction logic. Useful for timing closure (isolates upstream routing/hard IP from the compaction/accumulator critical path); adds one clock cycle of latency.
FWFT_MODE
boolean
true
First Word Fall Through mode. If FWFT_MODE=True, RX data keeps falling through into the pipeline whenever no valid TX word is waiting to be accepted yet, i.e. RX_DST_RDY=’1’ when TX_DST_RDY=’1’ OR TX_SRC_RDY=’0’, which spends the accumulator’s already provisioned one-word slack instead of stalling RX the instant TX backpressures. If FWFT_MODE=False, RX_DST_RDY is the plain TX_DST_RDY wire; use it when the extra gate on RX_DST_RDY’s wide fan-out does not fit the timing budget of whatever drives this component (e.g. a hard IP ready line).
Port
Type
Mode
Description
=====
CLOCK AND RESET
=====
=====
CLK
std_logic
in
RESET
std_logic
in
=====
RX MFB INTERFACE (uncompacted)
=====
=====
RX_DATA
std_logic_vector(REGIONS*REGION_SIZE*BLOCK_SIZE*ITEM_WIDTH-1 downto 0)
in
RX_META
std_logic_vector(REGIONS*META_WIDTH-1 downto 0)
in
User metadata valid with its region.
RX_SOF_POS
std_logic_vector(REGIONS*max(1,log2(REGION_SIZE))-1 downto 0)
in
RX_EOF_POS
std_logic_vector(REGIONS*max(1,log2(REGION_SIZE*BLOCK_SIZE))-1 downto 0)
in
RX_SOF
std_logic_vector(REGIONS-1 downto 0)
in
RX_EOF
std_logic_vector(REGIONS-1 downto 0)
in
RX_SRC_RDY
std_logic
in
RX_DST_RDY
std_logic
out
=====
TX MFB INTERFACE (compacted: no empty region between two occupied ones)
=====
=====
TX_DATA
std_logic_vector(REGIONS*REGION_SIZE*BLOCK_SIZE*ITEM_WIDTH-1 downto 0)
out
TX_META
std_logic_vector(REGIONS*META_WIDTH-1 downto 0)
out
TX_SOF_POS
std_logic_vector(REGIONS*max(1,log2(REGION_SIZE))-1 downto 0)
out
TX_EOF_POS
std_logic_vector(REGIONS*max(1,log2(REGION_SIZE*BLOCK_SIZE))-1 downto 0)
out
TX_SOF
std_logic_vector(REGIONS-1 downto 0)
out
TX_EOF
std_logic_vector(REGIONS-1 downto 0)
out
TX_SRC_RDY
std_logic
out
TX_DST_RDY
std_logic
in
Component specification
The MFB_COMPACTOR removes empty (unoccupied) regions between frames on the MFB bus and
shifts the occupied regions left so that they are contiguous in the output word, while
preserving frame order and the order of regions within a frame. A region moves as one
indivisible unit, so anything short of a whole idle region is left untouched: the last
region of a frame may still be internally incomplete (EOF_POS less than its maximum
value), and a region may be shared between the tail of one frame and the head of the
next - neither is a gap to be removed, only whole idle regions between frames are.
A small accumulator (up to REGIONS-1 leftover regions) holds regions that did not
fill a whole output word yet; it is combined with the next input word every clock cycle,
so throughput is a full word per cycle with no extra write port needed on any downstream
memory.
Occupancy (which regions carry data of some frame, including a frame continuing through
a whole word with neither SOF nor EOF) is derived with MFB_AUXILIARY_SIGNALS’s
region-level in-frame carry. That carry correctly follows a region shared between two
frames as well as a fully aligned one, so REGION_SIZE>1 works for arbitrary,
non-region-aligned frame lengths too - the only real constraint is plain MFB: a single
region carries at most one SOF and one EOF.
Flow control is a global stall gating every register in the pipeline (no combinational
SRC_RDY/DST_RDY loop). In the default First Word Fall Through mode
(FWFT_MODE=True) RX_DST_RDY = TX_DST_RDY or not TX_SRC_RDY, so RX data keeps
falling through into the accumulator’s one-word slack even while TX_DST_RDY='0', as
long as no TX word is currently waiting to be accepted. Setting FWFT_MODE=False
falls back to the plain RX_DST_RDY <= TX_DST_RDY wire (one gate less on
RX_DST_RDY’s fan-out, at the cost of stalling RX the instant TX backpressures).
A non-empty, non-full accumulator is flushed to TX after FLUSH_TIMEOUT consecutive
clock cycles without new occupied regions arriving, so a leftover partial word does not
wait forever when the input goes idle.