MVB Hash Table Simple
- ENTITY MVB_HASH_TABLE_SIMPLE IS
A hash-based key/value lookup table for the MVB bus. For every valid RX item, the MVB_KEY_WIDTH-bit key is hashed by two independent hash functions (a Toeplitz hash and a simple XOR hash, both keyed by the same SW-configurable HASH_KEY), each indexing its own table implemented in a separate
SDP_MEMXmemory (per MVB item, so 2*MVB_ITEMS memories in total). Three clock cycles later, TX_MVB_DATA/TX_MVB_MATCH report whether either table held a matching entry for that key (the stored key is compared against the original lookup key to reject hash collisions) and, if so, its stored data. TX_MVB_VLD simply follows RX_MVB_VLD (delayed); it does not indicate a match - always check TX_MVB_MATCH for that. When neither table matches, TX_MVB_DATA is undefined (defaults to the XOR table’s read data regardless of validity).Table entries are written through the MI bus (see the WARNING below); MVB lookups are used only for reading. Every MI_WR/MI_RD access, and the whole “clear tables” sweep, stalls RX_MVB_DST_RDY for its duration - do not expect full MVB throughput while configuring the table over MI.
Warning
TABLE_CAPACITY should be a power of two: HASH_WIDTH = log2(TABLE_CAPACITY) is used directly as the address width of the hash functions and of the underlying memories, without any additional range check.
Warning
There is no hash-collision detection on writes. A table address holds exactly one entry, a write to 0x0C unconditionally overwrites whatever is already stored there, and MI_RD never returns the actual table content (only the configuration constants below) - so software has no way to check what currently occupies an address before overwriting it. The two independent tables (Toeplitz/XOR) exist to give software an alternate slot for a colliding key, but choosing between them and tracking which keys occupy which slots is entirely software’s responsibility; the hardware provides no support for it. This only affects writes - a lookup for a key that collides with a different key’s stored entry is still handled safely (the stored-key comparison makes it report TX_MVB_MATCH = ‘0’, never wrong data).
MI register map
Only the low 8 bits of MI_ADDR are decoded. All registers are MI_WIDTH (commonly 32) bits wide.
Address
Write (MI_WR)
Read (MI_RD)
0x00
Command register, see below. Takes effect immediately (1 CLK).
Constant MVB_ITEMS.
0x04
Table write address register (bits HASH_WIDTH-1 downto 0 of MI_DWR).
Constant MVB_KEY_WIDTH.
0x08
Shifts MI_DWR into the entry-data shift register, see the NOTE below.
Constant DATA_OUT_WIDTH.
0x0C
Commits the entry-data shift register to the table selected by the command register, at the address set at 0x04. MI_DWR is ignored; only the write access itself (to this address) matters.
Constant HASH_WIDTH (= log2(TABLE_CAPACITY)).
0x10
Shifts MI_DWR into the hash-key register (shared by both hash functions).
Constant HASH_KEY_WIDTH.
0x14
(no effect)
Constant TABLE_CAPACITY.
Note
An entry only actually changes in the table at the 0x0C commit; the 0x04/0x08 writes before it only prepare the new value and don’t affect the table yet. So an MVB lookup can never see a half-written entry - only the complete old one or the complete new one.
MVB lookups are blocked for the one cycle of every individual MI access (0x04, 0x08, or 0x0C), same as for the table-clearing sweep - not just during the sweep. Between separate MI accesses, though, any gap (a cycle with no MI_WR/MI_RD) lets lookups proceed as normal, so they can still interleave with an in-progress multi-step entry update. That’s fine for the table content itself (as explained above), but if your application additionally needs no lookups to happen at all for the whole duration of an entry update, you need to arrange that yourself; this component only blocks lookups access by access, not for the whole sequence.
Command register (bits of the value written to address 0x00):
bit 0 - select the Toeplitz table for the next 0x0C commit (0 = Toeplitz, 1 = XOR).
bit 1 - start clearing (zeroing) both tables; self-clears when the sweep finishes. While set, MI_ARDY stays deasserted for approximately TABLE_CAPACITY clock cycles (a couple of cycles more in practice) and no new MI request is accepted.
GenericsNote
A stored entry is
MVB_KEY_WIDTH + DATA_OUT_WIDTH + 1bits wide (LSB to MSB: 1 valid bit, then DATA_OUT_WIDTH data bits, then the MVB_KEY_WIDTH key), and is loaded into the entry-data shift register with one or more writes to 0x08 (ceil(entry_width / MI_WIDTH)writes, MI_WIDTH bits each). Each write shifts the new MI_DWR word in at the top, so the first 0x08 write must carry the least-significant MI_WIDTH-bit chunk of the entry (bits 0 and up, i.e. the valid bit and low data bits) and the last write the most-significant chunk (the key). The same shift-in convention (first write = low bits) applies to the multi-word hash-key register at 0x10; there the chunk boundaries only line up cleanly when HASH_KEY_WIDTH is itself a multiple of MI_WIDTH (unlike the entry-data register, which is rounded up to a whole number of MI_WIDTH chunks internally).
PortsGeneric
Type
Default
Description
TABLE_CAPACITY
natural
256
Number of entries in each of the two hash tables. Should be a power of two, see the WARNING above.
MVB_ITEMS
natural
4
Number of MVB items transferred in one word. Determines the number of instantiated SDP_MEMX memories (2*MVB_ITEMS).
MVB_KEY_WIDTH
natural
8
Width of the MVB lookup key, in bits.
DATA_OUT_WIDTH
natural
8
Width of the data value stored per table entry, in bits.
MI_WIDTH
natural
32
Width of the MI bus, in bits (typically 32, i.e. MI32).
HASH_KEY_WIDTH
natural
32
Width of the shared hash-key register (see the MI register map above), in bits.
DEVICE
string
“STRATIX10”
Target FPGA device, passed through to the underlying SDP_MEMX memories. “7SERIES”, “ULTRASCALE”, “VERSAL”, “ARRIA10”, “STRATIX10”, “AGILEX”
Port
Type
Mode
Description
CLK
std_logic
in
RST
std_logic
in
=====
PORTS OF INPUT MVB BUS
=====
=====
RX_MVB_KEY
std_logic_vector(MVB_ITEMS*MVB_KEY_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
Deasserted (regardless of TX_MVB_DST_RDY) while any MI access or table-clear sweep is in progress, see above.
=====
PORTS OF OUTPUT MVB BUS
=====
=====
TX_MVB_DATA
std_logic_vector(MVB_ITEMS*DATA_OUT_WIDTH-1 downto 0)
out
Valid only where TX_MVB_MATCH = ‘1’.
TX_MVB_MATCH
std_logic_vector(MVB_ITEMS-1 downto 0)
out
Set when a valid entry with a matching key was found in either table.
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
=====
PORTS OF MI BUS
=====
Used both to configure the hash key and write table entries, and to read back the component’s configuration constants. See the MI register map above.
MI_ADDR
std_logic_vector(MI_WIDTH-1 downto 0)
in
MI_DWR
std_logic_vector(MI_WIDTH-1 downto 0)
in
MI_BE
std_logic_vector(MI_WIDTH/8-1 downto 0)
in
Not used (present for MI bus interface compatibility only).
MI_WR
std_logic
in
MI_RD
std_logic
in
MI_ARDY
std_logic
out
MI_DRD
std_logic_vector(MI_WIDTH-1 downto 0)
out
MI_DRDY
std_logic
out