MVB Lookup Table
- ENTITY MVB_LOOKUP_TABLE IS
MVB Lookup Table: for every valid MVB item on the RX side, looks up the table entry addressed by RX_MVB_LUT_ADDR and presents it on the corresponding TX_MVB_LUT_DATA item, together with the (registered) RX_MVB_LUT_ADDR and RX_MVB_METADATA of that item. This is the top-level (recommended) entity: it picks one of the three available implementations (a single register,
MVB_LOOKUP_TABLE_LUTRAM, orMVB_LOOKUP_TABLE_BRAM) based on LUT_ARCH/LUT_DEPTH. RX-to-TX latency depends on which of these is selected and on OUTPUT_REG, see the OUTPUT_REG generic below for the exact cycle counts.The table content is configured through a synchronous SW_* register-file style port (address + byte-enabled data, not the CESNET MI bus) - see the port descriptions below. This component does not reset or initialize the table content on RESET; all LUT_DEPTH entries must be written through the SW_* interface before the first RX lookup that relies on them, otherwise reads of not-yet-written entries return undefined data.
Note
SW_WRITE never stalls or backpressures RX_MVB lookups - RX_MVB_DST_RDY only follows TX_MVB_DST_RDY, regardless of SW_* activity. Unlike some sibling components, there is also no atomicity guarantee here, not even for a single entry: each SW_WRITE goes straight into the table as soon as it happens, with no staging step that only commits a complete entry at once. So if LUT_WIDTH > SW_WIDTH, an entry needs several SW_WRITEs (one per slice, see above) to fully update, and an RX_MVB lookup running in between can see that one entry half-written - part old slices, part new.
The same applies, entry by entry, when updating several entries in a row. If your application needs lookups to only ever see a fully consistent entry (or a consistent snapshot across several entries), you need to arrange that yourself, e.g. by pausing RX_MVB lookups for the duration of an update; this component does not do it for you.
GenericsWarning
LUT_WIDTH must be an integer multiple of SW_WIDTH. Any other ratio is not correctly supported: depending on LUT_DEPTH/LUT_ARCH it causes the topmost bits of an entry to be silently unreachable through SW_DOUT (single register and
MVB_LOOKUP_TABLE_BRAM), aliased writes (single register), or an elaboration-time width mismatch (MVB_LOOKUP_TABLE_BRAM).MVB_LOOKUP_TABLE_LUTRAMhandles the entry width itself correctly, but the shared SW_SLICE port is always sized for the exact-multiple case, so higher slices can still be unreachable there too.
PortsGeneric
Type
Default
Description
MVB_ITEMS
natural
4
Number of MVB items transferred in one word.
LUT_DEPTH
natural
128
Number of entries in the lookup table. Any positive value; LUT_DEPTH = 1 is implemented directly as a single shared register regardless of LUT_ARCH.
LUT_WIDTH
natural
32
Width of one lookup table entry in bits. Should be a multiple of SW_WIDTH, see the WARNING above.
LUT_ARCH
string
“AUTO”
Select the memory implementation used when LUT_DEPTH > 1:
“LUT” -
MVB_LOOKUP_TABLE_LUTRAM, effective for a shallow table (approx. LUT_DEPTH <= 64).“BRAM” -
MVB_LOOKUP_TABLE_BRAM, effective for a deep table (approx. LUT_DEPTH > 64); consumes MVB_ITEMS+1 block RAMs.“AUTO” - chosen automatically from LUT_DEPTH using the same approx. 64-entry threshold as above.
SW_WIDTH
natural
32
Data width of the SW_* configuration port in bits. Must be a multiple of 8: SW_BE has one bit per byte of SW_DIN (SW_WIDTH/8, integer division), so a non-multiple silently loses byte-enable coverage over the trailing, incomplete byte.
META_WIDTH
natural
1
Width of the RX_MVB_METADATA/TX_MVB_METADATA side-channel in bits. Any non-negative value; the metadata is only delayed together with the MVB transaction, it does not influence the lookup itself.
OUTPUT_REG
boolean
True
Adds an output register stage on the TX_MVB_* path (and, for the BRAM implementation, also on the internal RAM output). Improves timing at the cost of extra registers and one additional CLK cycle of RX-to-TX latency:
Single register (LUT_DEPTH = 1) or LUT_ARCH = “LUT”: 0 CLK cycles when false, 1 CLK cycle when true.
LUT_ARCH = “BRAM”: 1 CLK cycle when false, 2 CLK cycles when true.
DEVICE
string
“AGILEX”
Target FPGA device, passed through to the underlying memory implementation.
Port
Type
Mode
Description
CLK
std_logic
in
RESET
std_logic
in
=====
RX MVB INTERFACE
=====
Lookup request: RX_MVB_LUT_ADDR addresses the entry to look up.
RX_MVB_LUT_ADDR
slv_array_t(MVB_ITEMS-1 downto 0)(max(log2(LUT_DEPTH),1)-1 downto 0)
in
RX_MVB_METADATA
slv_array_t(MVB_ITEMS-1 downto 0)(META_WIDTH-1 downto 0)
in
RX_MVB_VLD
std_logic_vector(MVB_ITEMS-1 downto 0)
in
RX_MVB_SRC_RDY
std_logic
in
RX_MVB_DST_RDY
std_logic
out
=====
TX MVB INTERFACE
=====
Lookup result, RX-to-TX latency cycles later (see OUTPUT_REG above).
TX_MVB_LUT_DATA
slv_array_t(MVB_ITEMS-1 downto 0)(LUT_WIDTH-1 downto 0)
out
Lookup table entry addressed by the corresponding (registered) TX_MVB_LUT_ADDR.
TX_MVB_LUT_ADDR
slv_array_t(MVB_ITEMS-1 downto 0)(max(log2(LUT_DEPTH),1)-1 downto 0)
out
TX_MVB_METADATA
slv_array_t(MVB_ITEMS-1 downto 0)(META_WIDTH-1 downto 0)
out
TX_MVB_VLD
std_logic_vector(MVB_ITEMS-1 downto 0)
out
TX_MVB_SRC_RDY
std_logic
out
TX_MVB_DST_RDY
std_logic
in
=====
SW CONFIGURATION INTERFACE
=====
Synchronous register-file style port used to read/write the lookup table content. Not the CESNET MI bus; intended to be driven through an external MI (or other software-accessible bus) adapter. One access addresses a single LUT entry (SW_ADDR). If LUT_WIDTH is wider than SW_WIDTH, each access only reaches one SW_WIDTH-wide slice of that entry, chosen by SW_SLICE. Writing a whole entry therefore means repeating SW_WRITE at the same SW_ADDR once per slice, SW_SLICE = 0 to LUT_WIDTH/SW_WIDTH-1.
SW_ADDR
std_logic_vector(max(log2(LUT_DEPTH),1)-1 downto 0)
in
Address of the accessed lookup table entry.
SW_SLICE
std_logic_vector(max(log2(LUT_WIDTH/SW_WIDTH),1)-1 downto 0)
in
Selects which SW_WIDTH-wide slice of the addressed entry is accessed, when LUT_WIDTH > SW_WIDTH. Unused (any value valid) when LUT_WIDTH = SW_WIDTH (the only other case the WARNING above allows).
SW_DIN
std_logic_vector(SW_WIDTH-1 downto 0)
in
Data to write; valid when SW_WRITE = ‘1’.
SW_BE
std_logic_vector(SW_WIDTH/8-1 downto 0)
in
Byte-enable for SW_DIN; only enabled bytes are written.
SW_WRITE
std_logic
in
Write request for the (SW_ADDR, SW_SLICE) location, takes effect immediately (1 CLK).
SW_READ
std_logic
in
Read request for the (SW_ADDR, SW_SLICE) location; the result appears on SW_DOUT one CLK later.
SW_DOUT
std_logic_vector(SW_WIDTH-1 downto 0)
out
Read data, valid when SW_DOUT_VLD = ‘1’ (registered, one CLK after SW_READ).
SW_DOUT_VLD
std_logic
out