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

Generic

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).

Ports

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.