Skip to content

Commit

Permalink
Merge branch 'hak-maint-tcam2_ver' into 'devel'
Browse files Browse the repository at this point in the history
TCAM: [MAINTENANCE] Refactor TCAM2 and MVB_TCAM components

See merge request ndk/ndk-fpga!75
  • Loading branch information
jakubcabal committed Oct 17, 2024
2 parents 823d869 + f5be7db commit 18a701a
Show file tree
Hide file tree
Showing 29 changed files with 243 additions and 818 deletions.
143 changes: 51 additions & 92 deletions comp/base/mem/tcam2/tcam2.vhd
Original file line number Diff line number Diff line change
Expand Up @@ -54,15 +54,28 @@ entity TCAM2 is

-- FPGA device
-- available are "7SERIES", "ULTRASCALE", "ARRIA10", "STRATIX10", "AGILEX"
DEVICE : string := "ULTRASCALE"
DEVICE : string := "ULTRASCALE";

-- Manufacturer of FPGA device
IS_XILINX : boolean := (DEVICE = "7SERIES" or DEVICE = "ULTRASCALE");
IS_INTEL : boolean := (DEVICE = "ARRIA10" or DEVICE = "STRATIX10" or DEVICE = "AGILEX");

-- Optimal parameters by FPGA device
INTEL_DATA_WIDTH : integer := tsel(USE_FRAGMENTED_MEM, 20, 16);
XILINX_DATA_WIDTH : integer := tsel(DEVICE = "ULTRASCALE", tsel(USE_FRAGMENTED_MEM, 14, 8), tsel(USE_FRAGMENTED_MEM, 6, 4));
MEMORY_ADDR_WIDTH : integer := 5;
MEMORY_DATA_WIDTH : integer := tsel(IS_XILINX, XILINX_DATA_WIDTH, INTEL_DATA_WIDTH);
ALIGNED_DATA_WIDTH : integer := 2**log2(MEMORY_DATA_WIDTH);
ITEMS_ALIGNED : integer := tsel(USE_FRAGMENTED_MEM, div_roundup(ITEMS,MEMORY_DATA_WIDTH)*ALIGNED_DATA_WIDTH, ITEMS);
ADDR_WIDTH : integer := max(1, log2(ITEMS_ALIGNED))
);
Port (
-- CLOCK AND RESET
CLK : in std_logic;
RST : in std_logic;

-- READ INTERFACE (READ_FROM_TCAM must be set as true)
READ_ADDR : in std_logic_vector(max(1,log2(ITEMS))-1 downto 0);
READ_ADDR : in std_logic_vector(ADDR_WIDTH-1 downto 0);
READ_EN : in std_logic;
READ_RDY : out std_logic;
READ_DATA : out std_logic_vector(DATA_WIDTH-1 downto 0);
Expand All @@ -72,7 +85,7 @@ entity TCAM2 is
-- WRITE INTERFACE
WRITE_DATA : in std_logic_vector(DATA_WIDTH-1 downto 0);
WRITE_MASK : in std_logic_vector(DATA_WIDTH-1 downto 0);
WRITE_ADDR : in std_logic_vector(max(1,log2(ITEMS))-1 downto 0);
WRITE_ADDR : in std_logic_vector(ADDR_WIDTH-1 downto 0);
WRITE_EN : in std_logic;
WRITE_RDY : out std_logic;

Expand All @@ -92,24 +105,13 @@ end entity;
-- =====================================================================
architecture FULL of TCAM2 is

-- Manufacturer of FPGA device
constant IS_XILINX : boolean := (DEVICE = "7SERIES" or DEVICE = "ULTRASCALE");
constant IS_INTEL : boolean := (DEVICE = "ARRIA10" or DEVICE = "STRATIX10" or DEVICE = "AGILEX");

-- Optimal parameters by FPGA device
constant INTEL_DATA_WIDTH : integer := tsel(USE_FRAGMENTED_MEM, 20, 16);
constant XILINX_DATA_WIDTH : integer := tsel(DEVICE = "ULTRASCALE", tsel(USE_FRAGMENTED_MEM, 14, 8), tsel(USE_FRAGMENTED_MEM, 6, 4));
constant MEMORY_ADDR_WIDTH : integer := 5;
constant MEMORY_DATA_WIDTH : integer := tsel(IS_XILINX, XILINX_DATA_WIDTH, INTEL_DATA_WIDTH);
constant ALIGNED_DATA_WIDTH : integer := 2**log2(MEMORY_DATA_WIDTH);

-- Setting TCAM2 resources parameters
constant CELL_WIDTH : integer := MEMORY_ADDR_WIDTH - RESOURCES_SAVING;
constant CELL_HEIGHT : integer := MEMORY_DATA_WIDTH * (2**RESOURCES_SAVING);
constant ALIGNED_CELL_HEIGHT : integer := ALIGNED_DATA_WIDTH * (2**RESOURCES_SAVING);
constant CELL_HEIGHT_RATIO : integer := CELL_HEIGHT/MEMORY_DATA_WIDTH;
constant COLUMNS : integer := div_roundup(DATA_WIDTH, CELL_WIDTH);
constant ROWS : integer := div_roundup(ITEMS, ALIGNED_CELL_HEIGHT);
constant ROWS : integer := div_roundup(ITEMS_ALIGNED, ALIGNED_CELL_HEIGHT);

-- --------------------------------------------------------------------------
-- I/O data signals
Expand All @@ -125,7 +127,6 @@ architecture FULL of TCAM2 is
signal input_m_data_reg_aug : std_logic_vector(COLUMNS*CELL_WIDTH-1 downto 0);
signal input_wr_data_reg_aug : std_logic_vector(COLUMNS*CELL_WIDTH-1 downto 0) := (others => '0');
signal input_wr_mask_reg_aug : std_logic_vector(COLUMNS*CELL_WIDTH-1 downto 0) := (others => '0');
signal input_wr_addr_reg_aug : std_logic_vector(log2(ROWS*ALIGNED_CELL_HEIGHT)-1 downto 0) := (others => '0');

-- Input registers augmented arrays
signal input_m_data_reg_aug_arr : slv_array_t(COLUMNS-1 downto 0)(CELL_WIDTH-1 downto 0);
Expand Down Expand Up @@ -218,14 +219,9 @@ architecture FULL of TCAM2 is
signal sf_cnt_en : std_logic;
signal sf_cnt_en_reg : std_logic;

-- output match register write enable
signal m_aug_reg_we : std_logic_vector(CELL_HEIGHT_RATIO-1 downto 0);

-- output match vector register
signal m_aug_reg : slv_array_2d_t(ROWS-1 downto 0)(CELL_HEIGHT_RATIO-1 downto 0)(ALIGNED_DATA_WIDTH-1 downto 0);

-- fit output match
signal m_aug : std_logic_vector(ROWS*ALIGNED_CELL_HEIGHT-1 downto 0);
-- output match register
signal m_reg_we : std_logic_vector(CELL_HEIGHT_RATIO-1 downto 0);
signal m_reg : slv_array_2d_t(ROWS-1 downto 0)(CELL_HEIGHT_RATIO-1 downto 0)(MEMORY_DATA_WIDTH-1 downto 0);

begin

Expand Down Expand Up @@ -289,60 +285,27 @@ begin
-- memory element generate
mem_rows_g : for r in 0 to ROWS-1 generate
mem_colums_g : for c in 0 to COLUMNS-1 generate

memory_xilinx_g : if IS_XILINX generate
-- write data block (backup other records and add new)
mem_wr_data_block(c)(r) <= (mem_match_vector(c)(r) and not mem_wr_bit_en_reg) or ((MEMORY_DATA_WIDTH-1 downto 0 => mem_wr_data_reg(c)) and mem_wr_bit_en_reg);

-- Xilinx Single Port RAM
sp_distmem_i : entity work.GEN_LUTRAM
generic map (
DATA_WIDTH => MEMORY_DATA_WIDTH,
ITEMS => 2**MEMORY_ADDR_WIDTH,
RD_PORTS => 1,
RD_LATENCY => 1,
WRITE_USE_RD_ADDR0 => False,
MLAB_CONSTR_RDW_DC => False,
DEVICE => DEVICE
)
port map (
CLK => CLK,
WR_EN => mem_wr_en_reg(r),
WR_ADDR => mem_wr_addr_reg,
WR_DATA => mem_wr_data_block(c)(r),
RD_ADDR => mem_addr_arr(c),
RD_DATA => mem_match_vector(c)(r)
);
end generate;

storage_intel_g : if IS_INTEL generate
-- write data block (backup other records and add new)
mem_wr_data_block(c)(r) <= (mem_match_vector(c)(r) and not mem_wr_bit_en_reg) or ((MEMORY_DATA_WIDTH-1 downto 0 => mem_wr_data_reg(c)) and mem_wr_bit_en_reg);

-- INTEL MLAB simple dual port RAM
sdp_mlab_ram_i : entity work.GEN_LUTRAM
generic map (
DATA_WIDTH => MEMORY_DATA_WIDTH,
ITEMS => 2**MEMORY_ADDR_WIDTH,
RD_PORTS => 1,
RD_LATENCY => 1,
WRITE_USE_RD_ADDR0 => False,
MLAB_CONSTR_RDW_DC => True,
DEVICE => DEVICE
)
port map (
CLK => CLK,
WR_EN => mem_wr_en_reg(r),
WR_ADDR => mem_wr_addr_reg,
WR_DATA => mem_wr_data_block(c)(r),
RD_ADDR => mem_addr_arr(c),
RD_DATA => mem_match_vector(c)(r)
);
end generate;

-- propagating match
-- write data block (backup other records and add new)
mem_wr_data_block(c)(r) <= (mem_match_vector(c)(r) and not mem_wr_bit_en_reg) or ((MEMORY_DATA_WIDTH-1 downto 0 => mem_wr_data_reg(c)) and mem_wr_bit_en_reg);
sp_distmem_i : entity work.GEN_LUTRAM
generic map (
DATA_WIDTH => MEMORY_DATA_WIDTH,
ITEMS => 2**MEMORY_ADDR_WIDTH,
RD_PORTS => 1,
RD_LATENCY => 1,
WRITE_USE_RD_ADDR0 => False,
MLAB_CONSTR_RDW_DC => IS_INTEL,
DEVICE => DEVICE
)
port map (
CLK => CLK,
WR_EN => mem_wr_en_reg(r),
WR_ADDR => mem_wr_addr_reg,
WR_DATA => mem_wr_data_block(c)(r),
RD_ADDR => mem_addr_arr(c),
RD_DATA => mem_match_vector(c)(r)
);
mem_match_carry(c+1)(r) <= mem_match_carry(c)(r) and mem_match_vector(c)(r);

end generate;
end generate;

Expand All @@ -359,7 +322,7 @@ begin
write_data_storage_i : entity work.SDP_BRAM_BEHAV
generic map (
DATA_WIDTH => DATA_WIDTH,
ITEMS => ITEMS,
ITEMS => ITEMS_ALIGNED,
OUTPUT_REG => OUTPUT_READ_REGS
)
port map (
Expand All @@ -382,7 +345,7 @@ begin
write_mask_storage_i : entity work.SDP_BRAM_BEHAV
generic map (
DATA_WIDTH => DATA_WIDTH,
ITEMS => ITEMS,
ITEMS => ITEMS_ALIGNED,
OUTPUT_REG => OUTPUT_READ_REGS
)
port map (
Expand Down Expand Up @@ -434,7 +397,6 @@ begin
-- write signals registers padding
input_wr_data_reg_aug(input_wr_data_reg'range) <= input_wr_data_reg;
input_wr_mask_reg_aug(input_wr_mask_reg'range) <= input_wr_mask_reg;
input_wr_addr_reg_aug(input_wr_addr_reg'range) <= input_wr_addr_reg;
-- write data and mask registers arrays
input_wr_data_reg_aug_arr <= slv_array_deser(input_wr_data_reg_aug,COLUMNS);
input_wr_mask_reg_aug_arr <= slv_array_deser(input_wr_mask_reg_aug,COLUMNS);
Expand Down Expand Up @@ -469,7 +431,7 @@ begin
ITEMS => ROWS
)
port map (
ADDR => input_wr_addr_reg_aug(input_wr_addr_reg_aug'high downto log2(ALIGNED_CELL_HEIGHT)),
ADDR => input_wr_addr_reg(input_wr_addr_reg'high downto log2(ALIGNED_CELL_HEIGHT)),
ENABLE => wr_cnt_en,
DO => mem_wr_en
);
Expand All @@ -480,7 +442,7 @@ begin

-- cell height address
mem_sf_addr_g : if CELL_HEIGHT_RATIO > 1 generate
mem_sf_addr <= input_wr_addr_reg_aug(log2(ALIGNED_CELL_HEIGHT)-1 downto log2(ALIGNED_DATA_WIDTH));
mem_sf_addr <= input_wr_addr_reg(log2(ALIGNED_CELL_HEIGHT)-1 downto log2(ALIGNED_DATA_WIDTH));
end generate;
fake_mem_sf_addr_g : if CELL_HEIGHT_RATIO = 1 generate
mem_sf_addr(0) <= '0';
Expand All @@ -493,7 +455,7 @@ begin
ITEMS => ALIGNED_DATA_WIDTH
)
port map (
ADDR => input_wr_addr_reg_aug(log2(ALIGNED_DATA_WIDTH)-1 downto 0),
ADDR => input_wr_addr_reg(log2(ALIGNED_DATA_WIDTH)-1 downto 0),
DO => mem_wr_bit_en
);
end generate;
Expand Down Expand Up @@ -603,35 +565,32 @@ begin
mem_match_en <= sf_cnt_en;

-- output match register write enable decoder
m_aug_reg_we_dec_i : entity work.dec1fn_enable
m_reg_we_dec_i : entity work.dec1fn_enable
generic map (
ITEMS => CELL_HEIGHT_RATIO
)
port map (
ADDR => sf_cnt_reg,
ENABLE => sf_cnt_en_reg,
DO => m_aug_reg_we
DO => m_reg_we
);

-- output match vector register
match_bits_reg_g : for i in 0 to ROWS-1 generate
match_words_reg_g : for j in 0 to CELL_HEIGHT_RATIO-1 generate
m_aug_reg_p : process (CLK)
m_reg_p : process (CLK)
begin
if rising_edge(CLK) then
if (m_aug_reg_we(j) = '1') then
m_aug_reg(i)(j) <= (others=>'0');
m_aug_reg(i)(j)(mem_match_out(i)'range) <= mem_match_out(i);
if (m_reg_we(j) = '1') then
m_reg(i)(j) <= mem_match_out(i);
end if;
end if;
end process;
end generate;
end generate;
-- array conversion
m_aug <= slv_array_2d_ser(m_aug_reg);

-- output length fit
MATCH_OUT_ADDR <= m_aug(MATCH_OUT_ADDR'range);
MATCH_OUT_ADDR <= slv_array_2d_ser(m_reg)(MATCH_OUT_ADDR'range);

-- match hit
MATCH_OUT_HIT <= or MATCH_OUT_ADDR;
Expand Down
20 changes: 9 additions & 11 deletions comp/base/mem/tcam2/ver/Modules.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,14 @@
#
# SPDX-License-Identifier: BSD-3-Clause

# set paths
set SV_MVB_BASE "$OFM_PATH/comp/mvb_tools/ver"
set SV_WB_BASE "$ENTITY_BASE/tbench/write_bus"
set SV_RB_BASE "$ENTITY_BASE/tbench/read_bus"

set SV_MVB_BASE "$OFM_PATH/comp/mvb_tools/ver"
set SV_WB_BASE "$ENTITY_BASE/tbench/write_bus"
lappend COMPONENTS [ list "SV_MVB" $SV_MVB_BASE "FULL" ]
lappend COMPONENTS [ list "SV_WB" $SV_WB_BASE "FULL" ]
lappend COMPONENTS [ list "SV_RB" $SV_RB_BASE "FULL" ]

set COMPONENTS [list \
[ list "SV_MVB" $SV_MVB_BASE "FULL"] \
[ list "SV_WB" $SV_WB_BASE "FULL"] \
]

set MOD "$MOD $ENTITY_BASE/tbench/test_pkg.sv"
set MOD "$MOD $ENTITY_BASE/tbench/dut.sv"
set MOD "$MOD $ENTITY_BASE/tbench/test.sv"
lappend MOD "$ENTITY_BASE/tbench/test_pkg.sv"
lappend MOD "$ENTITY_BASE/tbench/dut.sv"
lappend MOD "$ENTITY_BASE/tbench/test.sv"
13 changes: 13 additions & 0 deletions comp/base/mem/tcam2/ver/tbench/read_bus/Modules.tcl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
# Modules.tcl: Local include tcl script
# Copyright (C) 2024 CESNET z. s. p. o.
# Author: Tomas Hak <[email protected]>
#
# SPDX-License-Identifier: BSD-3-Clause

set SV_COMMON_BASE "$OFM_PATH/comp/ver"
set SV_MVB_BASE "$OFM_PATH/comp/mvb_tools/ver"

lappend COMPONENTS [ list "SV_COMMON" $SV_COMMON_BASE "FULL" ]
lappend COMPONENTS [ list "SV_MVB" $SV_MVB_BASE "FULL" ]

lappend MOD "$ENTITY_BASE/sv_rb_pkg.sv"
21 changes: 21 additions & 0 deletions comp/base/mem/tcam2/ver/tbench/read_bus/rb_transaction.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// rb_transaction.sv: Read Bus transaction
// Copyright (C) 2024 CESNET z. s. p. o.
// Author: Tomas Hak <[email protected]>
//
// SPDX-License-Identifier: BSD-3-Clause

class RbTransaction #(ADDR_WIDTH = 8, FRAGMENTED_MEM = FALSE, ITEMS = 2**ADDR_WIDTH, BLOCK_ITEMS = 20) extends MvbTransaction#(.ITEM_WIDTH(ADDR_WIDTH));
constraint mem_items_constr { data < ITEMS; }
// in fragmented mode top BLOCK addresses are not used
constraint frag_mem_constr { !FRAGMENTED_MEM || data[$clog2(BLOCK_ITEMS)-1 : 0] < BLOCK_ITEMS; }

virtual function Transaction copy(Transaction to = null);
RbTransaction #(ADDR_WIDTH, FRAGMENTED_MEM, ITEMS, BLOCK_ITEMS) tr;
if (to == null)
tr = new();
else
$cast(tr, to);
copy = super.copy(tr);
endfunction

endclass
14 changes: 14 additions & 0 deletions comp/base/mem/tcam2/ver/tbench/read_bus/sv_rb_pkg.sv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// sv_rb_pkg.sv: SystemVerilog package with Read Bus
// Copyright (C) 2024 CESNET z. s. p. o.
// Author: Tomas Hak <[email protected]>
//
// SPDX-License-Identifier: BSD-3-Clause

package sv_rb_pkg;

import sv_common_pkg::*;
import sv_mvb_pkg::*;

`include "rb_transaction.sv"

endpackage
Loading

0 comments on commit 18a701a

Please sign in to comment.