diff --git a/hdl/combpm_packet_filter.vhd b/hdl/combpm_packet_filter.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..922b7a0dd5e9897386af0647746f1668e8b6e3fc
--- /dev/null
+++ b/hdl/combpm_packet_filter.vhd
@@ -0,0 +1,255 @@
+library ieee;
+use ieee.std_logic_1164.all;
+use ieee.numeric_std.all;
+
+use work.pkg_combpm_stream.all;
+
+entity combpm_packet_filter is
+    port(
+        axis_clk     : in std_logic;
+        axi_clk      : in std_logic;
+        axis_rst_n   : in std_logic;
+        axi_rst_n    : in std_logic;
+
+        -- AXIS SLAVE INTERFACE
+        s_axis_tdest  : in std_logic_vector(C_TDEST_W-1 downto 0);
+        s_axis_tdata  : in std_logic_vector(C_TDATA_W-1 downto 0);
+        s_axis_tlast  : in std_logic;
+        s_axis_tvalid : in std_logic;
+        s_axis_tready : out std_logic;
+
+        -- AXIS SLAVE INTERFACE
+        m_axis_tdest  : out std_logic_vector(C_TDEST_W-1 downto 0);
+        m_axis_tdata  : out std_logic_vector(C_TDATA_W-1 downto 0);
+        m_axis_tlast  : out std_logic;
+        m_axis_tvalid : out std_logic;
+        m_axis_tready : in std_logic;
+
+        -- AXI bus interface
+        s_axi_awaddr : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
+        s_axi_awlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+        s_axi_awsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_awburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_awlock : IN STD_LOGIC;
+        s_axi_awcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
+        s_axi_awprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_awvalid : IN STD_LOGIC;
+        s_axi_awready : OUT STD_LOGIC;
+        s_axi_wdata : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
+        s_axi_wstrb : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
+        s_axi_wlast : IN STD_LOGIC;
+        s_axi_wvalid : IN STD_LOGIC;
+        s_axi_wready : OUT STD_LOGIC;
+        s_axi_bresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_bvalid : OUT STD_LOGIC;
+        s_axi_bready : IN STD_LOGIC;
+        s_axi_araddr : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
+        s_axi_arlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+        s_axi_arsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_arburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_arlock : IN STD_LOGIC;
+        s_axi_arcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
+        s_axi_arprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_arvalid : IN STD_LOGIC;
+        s_axi_arready : OUT STD_LOGIC;
+        s_axi_rdata : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
+        s_axi_rresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_rlast : OUT STD_LOGIC;
+        s_axi_rvalid : OUT STD_LOGIC;
+        s_axi_rready : IN STD_LOGIC
+    );
+end combpm_packet_filter;
+
+
+architecture rtl of combpm_packet_filter is
+
+    ---------------------------
+    -- COMPONENT DECLARATION --
+    ---------------------------
+    COMPONENT combpm_packet_filter_axi_bram_ctrl
+    PORT (
+        s_axi_aclk : IN STD_LOGIC;
+        s_axi_aresetn : IN STD_LOGIC;
+        s_axi_awaddr : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
+        s_axi_awlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+        s_axi_awsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_awburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_awlock : IN STD_LOGIC;
+        s_axi_awcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
+        s_axi_awprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_awvalid : IN STD_LOGIC;
+        s_axi_awready : OUT STD_LOGIC;
+        s_axi_wdata : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
+        s_axi_wstrb : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
+        s_axi_wlast : IN STD_LOGIC;
+        s_axi_wvalid : IN STD_LOGIC;
+        s_axi_wready : OUT STD_LOGIC;
+        s_axi_bresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_bvalid : OUT STD_LOGIC;
+        s_axi_bready : IN STD_LOGIC;
+        s_axi_araddr : IN STD_LOGIC_VECTOR(11 DOWNTO 0);
+        s_axi_arlen : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+        s_axi_arsize : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_arburst : IN STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_arlock : IN STD_LOGIC;
+        s_axi_arcache : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
+        s_axi_arprot : IN STD_LOGIC_VECTOR(2 DOWNTO 0);
+        s_axi_arvalid : IN STD_LOGIC;
+        s_axi_arready : OUT STD_LOGIC;
+        s_axi_rdata : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
+        s_axi_rresp : OUT STD_LOGIC_VECTOR(1 DOWNTO 0);
+        s_axi_rlast : OUT STD_LOGIC;
+        s_axi_rvalid : OUT STD_LOGIC;
+        s_axi_rready : IN STD_LOGIC;
+        bram_rst_a : OUT STD_LOGIC;
+        bram_clk_a : OUT STD_LOGIC;
+        bram_en_a : OUT STD_LOGIC;
+        bram_we_a : OUT STD_LOGIC_VECTOR(3 DOWNTO 0);
+        bram_addr_a : OUT STD_LOGIC_VECTOR(7 DOWNTO 0);
+        bram_wrdata_a : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
+        bram_rddata_a : IN STD_LOGIC_VECTOR(31 DOWNTO 0)
+    );
+    END COMPONENT;
+
+    COMPONENT combpm_packet_filter_blk_mem
+    PORT (
+        clka : IN STD_LOGIC;
+        ena : IN STD_LOGIC;
+        wea : IN STD_LOGIC_VECTOR(3 DOWNTO 0);
+        addra : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+        dina : IN STD_LOGIC_VECTOR(31 DOWNTO 0);
+        douta : OUT STD_LOGIC_VECTOR(31 DOWNTO 0);
+        clkb : IN STD_LOGIC;
+        enb : IN STD_LOGIC;
+        web : IN STD_LOGIC_VECTOR(0 DOWNTO 0);
+        addrb : IN STD_LOGIC_VECTOR(9 DOWNTO 0);
+        dinb : IN STD_LOGIC_VECTOR(7 DOWNTO 0);
+        doutb : OUT STD_LOGIC_VECTOR(7 DOWNTO 0)
+    );
+    END COMPONENT;
+
+    ------------------------
+    -- SIGNAL DECLARATION --
+    ------------------------
+    signal in_packet  : t_combpm_axis_packet;
+    signal out_packet : t_combpm_axis_packet;
+
+    signal bram_clk_a : STD_LOGIC;
+    signal bram_en_a : STD_LOGIC;
+    signal bram_we_a : STD_LOGIC_VECTOR(3 DOWNTO 0);
+    signal bram_addr_a : STD_LOGIC_VECTOR(7 DOWNTO 0);
+    signal bram_wrdata_a : STD_LOGIC_VECTOR(31 DOWNTO 0);
+    signal bram_rddata_a : STD_LOGIC_VECTOR(31 DOWNTO 0);
+
+    signal table_data : std_logic_vector(7 downto 0);
+
+    signal tvalid_r : std_logic_vector(1 downto 0);
+    signal zero_packet : std_logic_vector(C_TDATA_W-1 downto 0);
+
+begin
+
+    zero_packet <= (others => '0');
+
+    -- always ready
+    s_axis_tready <= '1';
+
+    ----------------------
+    -- STREAM REGISTERS --
+    ----------------------
+    p_main: process(axis_clk, axis_rst_n)
+    begin
+        if axis_rst_n = '0' then
+            in_packet   <= slv2combpmpacket(zero_packet);
+            out_packet  <= slv2combpmpacket(zero_packet);
+
+        elsif rising_edge(axis_clk) then
+            -- Register input packet
+            if s_axis_tvalid = '1' then
+                in_packet <= slv2combpmpacket(s_axis_tdata);
+            end if;
+
+            tvalid_r(tvalid_r'left downto 1) <= tvalid_r(tvalid_r'left-1 downto 0);
+            tvalid_r(0) <= s_axis_tvalid;
+
+            out_packet <= in_packet;
+
+        end if;
+    end process;
+
+    -----------------
+    -- AXIS OUTPUT --
+    -----------------
+    m_axis_tdest <= std_logic_vector(risize(unsigned(table_data(6 downto 0)), C_TDEST_W));
+    m_axis_tdata <= combpmpacket2slv(out_packet);
+    m_axis_tlast <= '1';    -- Packet is one tdata only
+    m_axis_tvalid <= tvalid_r(tvalid_r'left) and table_data(7);
+
+    ---------------------
+    -- BRAM CONTROLLER --
+    ---------------------
+    inst_bram_ctrl : combpm_packet_filter_axi_bram_ctrl
+    port map (
+        s_axi_aclk => axi_clk,
+        s_axi_aresetn => axi_rst_n,
+
+        s_axi_awaddr => s_axi_awaddr,
+        s_axi_awlen => s_axi_awlen,
+        s_axi_awsize => s_axi_awsize,
+        s_axi_awburst => s_axi_awburst,
+        s_axi_awlock => s_axi_awlock,
+        s_axi_awcache => s_axi_awcache,
+        s_axi_awprot => s_axi_awprot,
+        s_axi_awvalid => s_axi_awvalid,
+        s_axi_awready => s_axi_awready,
+        s_axi_wdata => s_axi_wdata,
+        s_axi_wstrb => s_axi_wstrb,
+        s_axi_wlast => s_axi_wlast,
+        s_axi_wvalid => s_axi_wvalid,
+        s_axi_wready => s_axi_wready,
+        s_axi_bresp => s_axi_bresp,
+        s_axi_bvalid => s_axi_bvalid,
+        s_axi_bready => s_axi_bready,
+        s_axi_araddr => s_axi_araddr,
+        s_axi_arlen => s_axi_arlen,
+        s_axi_arsize => s_axi_arsize,
+        s_axi_arburst => s_axi_arburst,
+        s_axi_arlock => s_axi_arlock,
+        s_axi_arcache => s_axi_arcache,
+        s_axi_arprot => s_axi_arprot,
+        s_axi_arvalid => s_axi_arvalid,
+        s_axi_arready => s_axi_arready,
+        s_axi_rdata => s_axi_rdata,
+        s_axi_rresp => s_axi_rresp,
+        s_axi_rlast => s_axi_rlast,
+        s_axi_rvalid => s_axi_rvalid,
+        s_axi_rready => s_axi_rready,
+
+        bram_rst_a => open,
+        bram_clk_a => bram_clk_a,
+        bram_en_a => bram_en_a,
+        bram_we_a => bram_we_a,
+        bram_addr_a => bram_addr_a,
+        bram_wrdata_a => bram_wrdata_a,
+        bram_rddata_a => bram_rddata_a
+        );
+
+    -------------------
+    -- BRAM INSTANCE --
+    -------------------
+    inst_bram : combpm_packet_filter_blk_mem
+    port map(
+        clka => bram_clk_a,
+        ena => bram_en_a,
+        wea => bram_we_a,
+        addra => bram_addr_a,
+        dina => bram_wrdata_a,
+        douta => bram_rddata_a,
+        clkb => axis_clk,
+        enb => '1',
+        web => '0',
+        addrb => in_packet.bpm_id(9 downto 0),
+        dinb => (others => '0'),
+        doutb => table_data
+    );
+
+end architecture rtl;
diff --git a/hdl/pkg_combpm_stream.vhd b/hdl/pkg_combpm_stream.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..5d09617ba92d89074c5c480ca76ec50674a7956e
--- /dev/null
+++ b/hdl/pkg_combpm_stream.vhd
@@ -0,0 +1,82 @@
+library ieee;
+use ieee.std_logic_1164.all;
+
+package pkg_combpm_stream is
+
+    -- CONSTANT
+    constant C_TDEST_W : natural := 7;
+    constant C_TDATA_W : natural := 128;
+
+    ---------------------------------
+    -- AXIS MASTER/SLAVE INTERFACE --
+    ---------------------------------
+    type t_combpm_axis_m2s is record
+        tdest  : std_logic_vector(C_TDEST_W-1 downto 0);
+        tdata  : std_logic_vector(C_TDATA_W-1 downto 0);
+        tlast  : std_logic;
+        tvalid : std_logic;
+        ---tid    : std_logic_vector(0 downto 0);
+        --tuser  : std_logic_vector(0 downto 0);
+        --tstrb  : std_logic_vector(15 downto 0);
+        --tkeep  : std_logic_vector(15 downto 0);
+    end record t_combpm_axis_m2s;
+
+    type t_combpm_axis_s2m is record
+        tready : std_logic;
+    end record t_combpm_axis_s2m;
+
+    subtype t_combpm_m_axis_out is t_combpm_axis_m2s;
+    subtype t_combpm_s_axis_in  is t_combpm_axis_m2s;
+    subtype t_combpm_m_axis_in  is t_combpm_axis_s2m;
+    subtype t_combpm_s_axis_out is t_combpm_axis_s2m;
+
+    ------------------------
+    -- AXIS STREAM PACKET --
+    ------------------------
+    type t_combpm_axis_packet is record
+        pos_x                        : std_logic_vector(31 downto 0);
+        pos_y                        : std_logic_vector(31 downto 0);
+        bpm_id                       : std_logic_vector(15 downto 0);
+        mc_timestamp                 : std_logic_vector(39 downto 0);
+        fa_seq                       : std_logic_vector(7 downto 0);
+    end record t_combpm_axis_packet;
+
+    function slv2combpmpacket(
+        signal tdata : std_logic_vector(C_TDATA_W-1 downto 0)
+        )
+        return t_combpm_axis_packet;
+
+    function combpmpacket2slv(
+        signal packet : t_combpm_axis_packet
+        )
+        return std_logic_vector;
+
+
+end package;
+
+package body pkg_combpm_stream is
+
+
+    function slv2combpmpacket(
+        signal tdata : std_logic_vector(C_TDATA_W-1 downto 0)
+        )
+        return t_combpm_axis_packet is
+        variable packet : t_combpm_axis_packet;
+    begin
+        packet.pos_x        := tdata(31 downto 0);
+        packet.pos_y        := tdata(63 downto 32);
+        packet.bpm_id       := tdata(79 downto 64);
+        packet.mc_timestamp := tdata(119 downto 80);
+        packet.fa_seq       := tdata(127 downto 120);
+        return packet;
+    end function;
+
+    function combpmpacket2slv(
+        signal packet : t_combpm_axis_packet
+        )
+        return std_logic_vector is
+    begin
+        return packet.fa_seq & packet.mc_timestamp & packet.bpm_id & packet.pos_y & packet.pos_x;
+    end function;
+
+end package body;
diff --git a/tcl/generate_combpm_packet_filter_ip.tcl b/tcl/generate_combpm_packet_filter_ip.tcl
new file mode 100644
index 0000000000000000000000000000000000000000..12d935a0c92332e962c45e9fecf0791222ad8ef8
--- /dev/null
+++ b/tcl/generate_combpm_packet_filter_ip.tcl
@@ -0,0 +1,36 @@
+set xcipath [create_ip -name axi_bram_ctrl -vendor xilinx.com -library ip -version 4.1 -module_name combpm_packet_filter_axi_bram_ctrl]
+
+set_property -dict [list \
+    CONFIG.PROTOCOL {AXI4} \
+    CONFIG.SUPPORTS_NARROW_BURST {0} \
+    CONFIG.SINGLE_PORT_BRAM {1} \
+    CONFIG.ECC_TYPE {0} \
+    CONFIG.BMG_INSTANCE {EXTERNAL} \
+    CONFIG.MEM_DEPTH {16384} \
+    ] [get_ips combpm_packet_filter_axi_bram_ctrl]
+
+set_property GENERATE_SYNTH_CHECKPOINT 0 [get_files $xcipath]
+
+set xcipath [create_ip -name blk_mem_gen -vendor xilinx.com -library ip -version 8.4 -module_name combpm_packet_filter_blk_mem]
+
+set_property -dict [list \
+    CONFIG.Memory_Type {True_Dual_Port_RAM} \
+    CONFIG.Use_Byte_Write_Enable {true} \
+    CONFIG.Byte_Size {8} \
+    CONFIG.Write_Width_A {32} \
+    CONFIG.Write_Depth_A {16384} \
+    CONFIG.Read_Width_A {32} \
+    CONFIG.Operating_Mode_A {WRITE_FIRST} \
+    CONFIG.Write_Width_B {8} \
+    CONFIG.Read_Width_B {8} \
+    CONFIG.Operating_Mode_B {WRITE_FIRST} \
+    CONFIG.Enable_B {Use_ENB_Pin} \
+    CONFIG.Register_PortA_Output_of_Memory_Primitives {false} \
+    CONFIG.Register_PortA_Output_of_Memory_Core {false} \
+    CONFIG.Register_PortB_Output_of_Memory_Primitives {false} \
+    CONFIG.Port_B_Clock {250} \
+    CONFIG.Port_B_Write_Rate {0} \
+    CONFIG.Port_B_Enable_Rate {100} \
+    ] [get_ips combpm_packet_filter_blk_mem]
+
+set_property GENERATE_SYNTH_CHECKPOINT 0 [get_files $xcipath]