MVB TCAM

ENTITY MVB_TCAM IS

Entity declaration

MVB wrapper around TCAM2: instantiates one full, independent TCAM2 core per MVB item (MVB_ITEMS instances), each holding its own complete, identical copy of the table content. This is what makes it possible to match MVB_ITEMS independent keys against the table in the same clock cycle, but it also means FPGA resource usage scales linearly with MVB_ITEMS - a wide MVB bus with a large or wide TCAM table can become very expensive; consider whether the use case really needs a full MVB_ITEMS-way replicated TCAM.

Warning

Only TCAM2 instance 0 is built with READ_FROM_TCAM enabled; the READ_* interface always reads through that single instance (WRITE_* is broadcast identically to every instance, so all copies stay in sync regardless).

Warning

MATCH_OUT_ADDR is not a binary address like READ_ADDR/WRITE_ADDR. For each MVB item it is an ITEMS-bit one-hot/bitmap vector, one bit per stored TCAM row, since a TCAM can match multiple (or zero) rows at once; MATCH_OUT_HIT for that item is simply the OR of its bits.

Note

A single WRITE_EN request and a match never overlap - the hardware always finishes one before starting the other - so a match always sees that one row’s complete old or complete new content, never a mix. You don’t need to add anything yourself for that.

This only covers a single row, though. Updating several rows is just a sequence of separate writes, and matches can happen in between them - seeing some rows already updated and others not yet. If your application needs the whole table to look consistent during a multi-row update, that’s up to you to arrange (e.g. by holding off match traffic for the duration).

Generics

Generic

Type

Default

Description

MVB_ITEMS

natural

4

Number of MVB items transferred in one word. Directly multiplies FPGA resource usage, see the WARNING above.

DATA_WIDTH

integer

36

Width of one TCAM item (and of WRITE_DATA/WRITE_MASK/MATCH_DATA/READ_DATA/READ_MASK per item), in bits.

ITEMS

integer

16

Number of rows (entries) in the TCAM table. For optimal resource usage should be a multiple of 2*L*(2^RESOURCES_SAVING) on Xilinx (where L is the number of LUTRAMs in one SLICEM), or of 16*(2^RESOURCES_SAVING) on Intel (32*(2^RESOURCES_SAVING) when USE_FRAGMENTED_MEM is set).

RESOURCES_SAVING

integer

0

Trade-off between FPGA resources and matching speed. Possible values are 0-4 on all devices. Higher values save resources and speed up writes, but cost both matching throughput and latency:

  • Throughput (how often a new match can be started): one match every CLK cycle at RESOURCES_SAVING = 0 (MATCH_DST_RDY stays asserted, one result per clock back-to-back); only one match every 2^RESOURCES_SAVING cycles for higher values (MATCH_DST_RDY drops after each accepted match until that many cycles pass).

  • RX-to-TX latency of one result (MATCH_OUT_* after the matching MATCH_DATA is accepted): a fixed 3 + (2^RESOURCES_SAVING - 1) CLK cycles - i.e. 3 cycles at RESOURCES_SAVING = 0, growing by 2^RESOURCES_SAVING - 1 for higher values.

Write speed (time until WRITE_RDY returns after a write) is 2^(5-RESOURCES_SAVING)+1 CLK cycles, the same on all devices.

WRITE_BEFORE_MATCH

boolean

true

When true, a WRITE_EN request presented in the same cycle as a MATCH_EN request is served first (match is delayed); when false, match has priority over write. A read request is only ever deprioritized against a concurrent write (READ_RDY is simply “not WRITE_EN”) - it is not affected by match activity at all, regardless of this generic’s value.

READ_FROM_TCAM

boolean

true

Enables the READ_* interface (through TCAM2 instance 0 only, see the WARNING above) by adding extra internal storage that mirrors WRITE_DATA/WRITE_MASK. Costs extra resources; leave false if the table content never needs to be read back.

OUTPUT_READ_REGS

boolean

true

Adds an output register stage on the READ_DATA/READ_MASK/READ_DATA_VLD path for better timing, at the cost of one extra CLK cycle of read latency. Has no effect unless READ_FROM_TCAM = true (that extra storage is what this register stage sits on).

USE_UNMATCHABLE

boolean

false

Changes the meaning of a masked-out bit (WRITE_MASK bit = ‘0’):

  • false - a masked bit is always don’t-care (matches both ‘0’ and ‘1’).

  • true - a masked bit is don’t-care only if the corresponding WRITE_DATA bit is ‘0’; if that WRITE_DATA bit is ‘1’, the whole row becomes permanently UNMATCHABLE.

USE_FRAGMENTED_MEM

boolean

false

Trade higher memory-primitive utilization for a discontinuous row address space: uses the full Intel MLAB width (20 instead of 16 bits, rows 21-32 unused per block) or the full Xilinx SLICEM width (14 instead of 8 on ULTRASCALE/VERSAL, 6 instead of 4 on 7SERIES, rows 15-16/7-8 unused per block).

DEVICE

string

“ULTRASCALE”

Target FPGA device. “7SERIES”, “ULTRASCALE”, “VERSAL”, “ARRIA10”, “STRATIX10”, “AGILEX”

IS_XILINX

boolean

(DEVICE = “7SERIES” or DEVICE = “ULTRASCALE” or DEVICE = “VERSAL”)

Manufacturer of the FPGA device, derived from DEVICE by default; only override together with DEVICE.

IS_INTEL

boolean

(DEVICE = “ARRIA10” or DEVICE = “STRATIX10” or DEVICE = “AGILEX”)

INTEL_DATA_WIDTH

integer

tsel(USE_FRAGMENTED_MEM, 20, 16)

The following generics are derived automatically from the generics above and are not meant to be overridden directly.

XILINX_DATA_WIDTH

integer

tsel(DEVICE = “ULTRASCALE” or DEVICE = “VERSAL”, tsel(USE_FRAGMENTED_MEM, 14, 8), tsel(USE_FRAGMENTED_MEM, 6, 4))

MEMORY_DATA_WIDTH

integer

tsel(IS_XILINX, XILINX_DATA_WIDTH, INTEL_DATA_WIDTH)

ALIGNED_DATA_WIDTH

integer

2**log2(MEMORY_DATA_WIDTH)

ITEMS_ALIGNED

natural

tsel(USE_FRAGMENTED_MEM, div_roundup(ITEMS,MEMORY_DATA_WIDTH)*ALIGNED_DATA_WIDTH, ITEMS)

ADDR_WIDTH

natural

max(1, log2(ITEMS_ALIGNED))

Ports

Port

Type

Mode

Description

CLK

std_logic

in

CLOCK AND RESET

RESET

std_logic

in

=====

READ INTERFACE (functional only when READ_FROM_TCAM = true; reads

=====

through TCAM2 instance 0, see the WARNING above)

READ_ADDR

std_logic_vector(ADDR_WIDTH-1 downto 0)

in

Row address to read; any value in 0 to ITEMS_ALIGNED-1.

READ_EN

std_logic

in

READ_RDY

std_logic

out

Equivalent to “not WRITE_EN” (combinational); deasserted only while WRITE_EN is currently asserted, independent of any match activity or of WRITE_BEFORE_MATCH.

READ_DATA

std_logic_vector(DATA_WIDTH-1 downto 0)

out

READ_MASK

std_logic_vector(DATA_WIDTH-1 downto 0)

out

READ_DATA_VLD

std_logic

out

Valid one CLK cycle after a request accepted with READ_RDY = ‘1’ (plus one more CLK cycle when OUTPUT_READ_REGS = true).

=====

WRITE INTERFACE (broadcast identically to every one of the

=====

MVB_ITEMS replicated TCAM2 instances)

WRITE_DATA

std_logic_vector(DATA_WIDTH-1 downto 0)

in

WRITE_MASK

std_logic_vector(DATA_WIDTH-1 downto 0)

in

‘0’ bit = don’t-care (or UNMATCHABLE, see USE_UNMATCHABLE); ‘1’ bit = must match WRITE_DATA.

WRITE_ADDR

std_logic_vector(ADDR_WIDTH-1 downto 0)

in

Row address to write; any value in 0 to ITEMS_ALIGNED-1.

WRITE_EN

std_logic

in

WRITE_RDY

std_logic

out

Asserted only when every one of the MVB_ITEMS replicated instances is ready to accept a write.

=====

MATCH INTERFACE

=====

=====

MATCH_DATA

std_logic_vector(MVB_ITEMS*DATA_WIDTH-1 downto 0)

in

MATCH_VLD

std_logic_vector(MVB_ITEMS-1 downto 0)

in

MATCH_SRC_RDY

std_logic

in

MATCH_DST_RDY

std_logic

out

Asserted only when every one of the MVB_ITEMS replicated instances is ready to match (i.e. the whole MVB word is matched together, or not at all).

=====

MATCH_OUT INTERFACE - result of a MATCH interface request, 3 CLK

=====

cycles later (plus the RESOURCES_SAVING match latency, see above)

MATCH_OUT_HIT

std_logic_vector(MVB_ITEMS-1 downto 0)

out

Per MVB item: ‘1’ if the table held at least one matching row for that item’s MATCH_DATA.

MATCH_OUT_ADDR

std_logic_vector(MVB_ITEMS*ITEMS-1 downto 0)

out

Per MVB item: one-hot/bitmap of matching rows (ITEMS bits), see the WARNING above - not a binary address.

MATCH_OUT_VLD

std_logic_vector(MVB_ITEMS-1 downto 0)

out

MATCH_OUT_SRC_RDY

std_logic

out