diff --git a/libraries/base/axi4/src/vhdl/axi4_lite_mm_bridge.vhd b/libraries/base/axi4/src/vhdl/axi4_lite_mm_bridge.vhd
index 73799be8cb2a80c009c3ece03b64bb4eac2632c2..8522aa997fe49c57ddf233c89489a28db29be2b8 100644
--- a/libraries/base/axi4/src/vhdl/axi4_lite_mm_bridge.vhd
+++ b/libraries/base/axi4/src/vhdl/axi4_lite_mm_bridge.vhd
@@ -31,6 +31,8 @@
 --   . The read latency is not adapted. Ensure that the Controller and Peripheral use the same 
 --     read-latency.
 --   . Both AXI4-lite and MM use ready latency = 0 for waitrequest/ready.
+--   . AXI4-lite is assumed to use byte addressed registers while MM uses word addressed 
+--     registers.
 
 LIBRARY IEEE, common_lib;
 USE IEEE.STD_LOGIC_1164.ALL;
diff --git a/libraries/base/axi4/src/vhdl/axi4_lite_pkg.vhd b/libraries/base/axi4/src/vhdl/axi4_lite_pkg.vhd
index 7214af9bff71ee6de5b12ce5df43dea3ac98f1b4..35c121f370427ab13abd94befef596bd5eb4b514 100644
--- a/libraries/base/axi4/src/vhdl/axi4_lite_pkg.vhd
+++ b/libraries/base/axi4/src/vhdl/axi4_lite_pkg.vhd
@@ -109,9 +109,9 @@ PACKAGE BODY axi4_lite_pkg IS
     VARIABLE v_mm_copi : t_mem_copi := c_mem_copi_rst;
   BEGIN
     IF axi4_copi.awvalid = '1' THEN
-      v_mm_copi.address := axi4_copi.awaddr;
+      v_mm_copi.address := "00" & axi4_copi.awaddr(c_axi4_lite_address_w-1 DOWNTO 2); -- convert byte addressed to word addressed.
     ELSE
-      v_mm_copi.address := axi4_copi.araddr;
+      v_mm_copi.address := "00" & axi4_copi.araddr(c_axi4_lite_address_w-1 DOWNTO 2); -- convert byte addressed to word addressed.
     END IF;
     v_mm_copi.wrdata(c_axi4_lite_data_w-1 DOWNTO 0) := axi4_copi.wdata;
     v_mm_copi.wr                                    := axi4_copi.awvalid;
@@ -131,14 +131,14 @@ PACKAGE BODY axi4_lite_pkg IS
   FUNCTION func_axi4_lite_from_mm_copi(mm_copi : t_mem_copi) RETURN t_axi4_lite_copi IS
     VARIABLE v_axi4_copi : t_axi4_lite_copi := c_axi4_lite_copi_rst;
   BEGIN
-    v_axi4_copi.awaddr  := mm_copi.address;  
+    v_axi4_copi.awaddr  := mm_copi.address(c_axi4_lite_address_w-3 DOWNTO 0) & "00"; -- convert word addressed to byte addressed.
     v_axi4_copi.awprot  := (OTHERS => '0');  
     v_axi4_copi.awvalid := mm_copi.wr;  
     v_axi4_copi.wdata   := mm_copi.wrdata(c_axi4_lite_data_w-1 DOWNTO 0);  
     v_axi4_copi.wstrb   := (OTHERS => '1'); -- Either ignored or all bytes selected.  
     v_axi4_copi.wvalid  := mm_copi.wr;  
     v_axi4_copi.bready  := '1'; -- Unsupported by MM, assuming always ready.  
-    v_axi4_copi.araddr  := mm_copi.address;  
+    v_axi4_copi.araddr  := mm_copi.address(c_axi4_lite_address_w-3 DOWNTO 0) & "00"; -- convert word addressed to byte addressed.  
     v_axi4_copi.arprot  := (OTHERS => '0');  
     v_axi4_copi.arvalid := mm_copi.rd;  
     v_axi4_copi.rready  := '1'; -- Unsupported by MM, assuming always ready.  
diff --git a/libraries/io/eth/hdllib.cfg b/libraries/io/eth/hdllib.cfg
index ef29caf98d50561a9867acc8475e4682deb03264..94292b2cb6c0999278e4667266c83e16f143cb24 100644
--- a/libraries/io/eth/hdllib.cfg
+++ b/libraries/io/eth/hdllib.cfg
@@ -1,6 +1,6 @@
 hdl_lib_name = eth
 hdl_library_clause_name = eth_lib
-hdl_lib_uses_synth = dp common diag tech_tse
+hdl_lib_uses_synth = dp common diag tech_tse axi4
 hdl_lib_uses_sim = 
 hdl_lib_technology = 
 
@@ -28,6 +28,7 @@ synth_files =
     src/vhdl/eth_tester_tx.vhd
     src/vhdl/eth_tester_rx.vhd
     src/vhdl/eth_tester.vhd
+    src/vhdl/eth_tester_axi4_wrapper.vhd
 
 test_bench_files = 
     src/vhdl/eth_statistics.vhd
diff --git a/libraries/io/eth/src/vhdl/eth_tester_axi4_wrapper.vhd b/libraries/io/eth/src/vhdl/eth_tester_axi4_wrapper.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..1dc6ba295c786292a12cff7c58eccecd0d88cb55
--- /dev/null
+++ b/libraries/io/eth/src/vhdl/eth_tester_axi4_wrapper.vhd
@@ -0,0 +1,612 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+-- Author: R. van der Walle
+-- Purpose: Provide AXI4-Stream and AXI4-Lite interface for eth_tester.vhd such
+--          that it can be used to create a Vivado IP block.
+-- Description: 
+-- . The eth_tester_axi4_wrapper uses axi4_stream_dp_bridge to convert the dp
+--   sosi/siso interfaces of the eth_tester into AXI4-Stream interfaces.
+--   Similarly, axi4_lite_mm_bridge is used to convert the mem copi/cipo 
+--   interfaces into AXI4_Lite interfaces.
+-- . In order for this component to be suitable as a Vivado IP, the ports are
+--   exclusively STD_LOGIC(_VECTOR) where the widths are hard-coded as demanded
+--   by the Vivado IP creator (only supports VHDL-93).
+
+LIBRARY IEEE, common_lib, dp_lib, diag_lib, axi4_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.common_network_layers_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE dp_lib.dp_components_pkg.ALL;
+USE diag_lib.diag_pkg.ALL;
+USE axi4_lib.axi4_stream_pkg.ALL;
+USE axi4_lib.axi4_lite_pkg.ALL;
+USE work.eth_pkg.ALL;
+USE work.eth_tester_pkg.ALL;
+
+ENTITY eth_tester_axi4_wrapper IS  
+  PORT (
+    -- Clocks and reset
+    mm_clk             : IN  STD_LOGIC;
+    st_clk             : IN  STD_LOGIC;
+    st_pps             : IN  STD_LOGIC;
+    aresetn            : IN  STD_LOGIC;
+    -- UDP transmit interface
+    eth_src_mac        : IN  STD_LOGIC_VECTOR(6*8-1 DOWNTO 0);
+    ip_src_addr        : IN  STD_LOGIC_VECTOR(4*8-1 DOWNTO 0);
+    udp_src_port       : IN  STD_LOGIC_VECTOR(2*8-1 DOWNTO 0);
+
+    tx_fifo_rd_emp_arr : OUT STD_LOGIC_VECTOR(0 DOWNTO 0);
+
+    -- tx_udp
+    -- Source In and Sink Out
+    tx_udp_tready    : IN STD_LOGIC;
+
+    -- Source Out and Sink In
+    tx_udp_tvalid    : OUT STD_LOGIC;
+    tx_udp_tdata     : OUT STD_LOGIC_VECTOR(512-1 DOWNTO 0);
+    tx_udp_tstrb     : OUT STD_LOGIC_VECTOR(512/8-1 DOWNTO 0);
+    tx_udp_tkeep     : OUT STD_LOGIC_VECTOR(512/8-1 DOWNTO 0);
+    tx_udp_tlast     : OUT STD_LOGIC;
+    tx_udp_tid       : OUT STD_LOGIC_VECTOR(4-1 DOWNTO 0);
+    tx_udp_tdest     : OUT STD_LOGIC_VECTOR(32-1 DOWNTO 0);
+    tx_udp_tuser     : OUT STD_LOGIC_VECTOR(70-1 DOWNTO 0);
+
+    -- rx_udp
+    -- Source In and Sink Out
+    rx_udp_tready    : OUT STD_LOGIC;
+
+    -- Source Out and Sink In
+    rx_udp_tvalid    : IN STD_LOGIC;
+    rx_udp_tdata     : IN STD_LOGIC_VECTOR(512-1 DOWNTO 0);
+    rx_udp_tstrb     : IN STD_LOGIC_VECTOR(512/8-1 DOWNTO 0);
+    rx_udp_tkeep     : IN STD_LOGIC_VECTOR(512/8-1 DOWNTO 0);
+    rx_udp_tlast     : IN STD_LOGIC;
+    rx_udp_tid       : IN STD_LOGIC_VECTOR(4-1 DOWNTO 0);
+    rx_udp_tdest     : IN STD_LOGIC_VECTOR(32-1 DOWNTO 0);
+    rx_udp_tuser     : IN STD_LOGIC_VECTOR(70-1 DOWNTO 0);
+
+    -- reg_bg_ctrl
+    -- copi
+    reg_bg_ctrl_awaddr                : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bg_ctrl_awprot                : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_bg_ctrl_awvalid               : IN STD_LOGIC;
+    reg_bg_ctrl_wdata                 : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bg_ctrl_wstrb                 : IN STD_LOGIC_VECTOR((32/8)-1 downto 0);
+    reg_bg_ctrl_wvalid                : IN STD_LOGIC;
+    reg_bg_ctrl_bready                : IN STD_LOGIC;
+    reg_bg_ctrl_araddr                : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bg_ctrl_arprot                : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_bg_ctrl_arvalid               : IN STD_LOGIC;
+    reg_bg_ctrl_rready                : IN STD_LOGIC;
+    -- cipo
+    reg_bg_ctrl_awready               : OUT STD_LOGIC;
+    reg_bg_ctrl_wready                : OUT STD_LOGIC;
+    reg_bg_ctrl_bresp                 : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_bg_ctrl_bvalid                : OUT STD_LOGIC;
+    reg_bg_ctrl_arready               : OUT STD_LOGIC;
+    reg_bg_ctrl_rdata                 : OUT STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bg_ctrl_rresp                 : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_bg_ctrl_rvalid                : OUT STD_LOGIC;
+
+    -- reg_hdr_dat
+    -- copi
+    reg_hdr_dat_awaddr                : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_hdr_dat_awprot                : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_hdr_dat_awvalid               : IN STD_LOGIC;
+    reg_hdr_dat_wdata                 : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_hdr_dat_wstrb                 : IN STD_LOGIC_VECTOR((32/8)-1 downto 0);
+    reg_hdr_dat_wvalid                : IN STD_LOGIC;
+    reg_hdr_dat_bready                : IN STD_LOGIC;
+    reg_hdr_dat_araddr                : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_hdr_dat_arprot                : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_hdr_dat_arvalid               : IN STD_LOGIC;
+    reg_hdr_dat_rready                : IN STD_LOGIC;
+    -- cipo
+    reg_hdr_dat_awready               : OUT STD_LOGIC;
+    reg_hdr_dat_wready                : OUT STD_LOGIC;
+    reg_hdr_dat_bresp                 : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_hdr_dat_bvalid                : OUT STD_LOGIC;
+    reg_hdr_dat_arready               : OUT STD_LOGIC;
+    reg_hdr_dat_rdata                 : OUT STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_hdr_dat_rresp                 : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_hdr_dat_rvalid                : OUT STD_LOGIC;
+
+    -- reg_bsn_monitor_v2_tx
+    -- copi
+    reg_bsn_monitor_v2_tx_awaddr      : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_tx_awprot      : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_bsn_monitor_v2_tx_awvalid     : IN STD_LOGIC;
+    reg_bsn_monitor_v2_tx_wdata       : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_tx_wstrb       : IN STD_LOGIC_VECTOR((32/8)-1 downto 0);
+    reg_bsn_monitor_v2_tx_wvalid      : IN STD_LOGIC;
+    reg_bsn_monitor_v2_tx_bready      : IN STD_LOGIC;
+    reg_bsn_monitor_v2_tx_araddr      : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_tx_arprot      : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_bsn_monitor_v2_tx_arvalid     : IN STD_LOGIC;
+    reg_bsn_monitor_v2_tx_rready      : IN STD_LOGIC;
+    -- cipo
+    reg_bsn_monitor_v2_tx_awready     : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_tx_wready      : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_tx_bresp       : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_bsn_monitor_v2_tx_bvalid      : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_tx_arready     : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_tx_rdata       : OUT STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_tx_rresp       : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_bsn_monitor_v2_tx_rvalid      : OUT STD_LOGIC;
+
+    -- reg_strobe_total_count_tx
+    -- copi
+    reg_strobe_total_count_tx_awaddr  : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_tx_awprot  : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_strobe_total_count_tx_awvalid : IN STD_LOGIC;
+    reg_strobe_total_count_tx_wdata   : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_tx_wstrb   : IN STD_LOGIC_VECTOR((32/8)-1 downto 0);
+    reg_strobe_total_count_tx_wvalid  : IN STD_LOGIC;
+    reg_strobe_total_count_tx_bready  : IN STD_LOGIC;
+    reg_strobe_total_count_tx_araddr  : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_tx_arprot  : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_strobe_total_count_tx_arvalid : IN STD_LOGIC;
+    reg_strobe_total_count_tx_rready  : IN STD_LOGIC;
+    -- cipo
+    reg_strobe_total_count_tx_awready : OUT STD_LOGIC;
+    reg_strobe_total_count_tx_wready  : OUT STD_LOGIC;
+    reg_strobe_total_count_tx_bresp   : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_strobe_total_count_tx_bvalid  : OUT STD_LOGIC;
+    reg_strobe_total_count_tx_arready : OUT STD_LOGIC;
+    reg_strobe_total_count_tx_rdata   : OUT STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_tx_rresp   : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_strobe_total_count_tx_rvalid  : OUT STD_LOGIC;
+
+    -- reg_bsn_monitor_v2_rx
+    -- copi
+    reg_bsn_monitor_v2_rx_awaddr      : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_rx_awprot      : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_bsn_monitor_v2_rx_awvalid     : IN STD_LOGIC;
+    reg_bsn_monitor_v2_rx_wdata       : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_rx_wstrb       : IN STD_LOGIC_VECTOR((32/8)-1 downto 0);
+    reg_bsn_monitor_v2_rx_wvalid      : IN STD_LOGIC;
+    reg_bsn_monitor_v2_rx_bready      : IN STD_LOGIC;
+    reg_bsn_monitor_v2_rx_araddr      : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_rx_arprot      : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_bsn_monitor_v2_rx_arvalid     : IN STD_LOGIC;
+    reg_bsn_monitor_v2_rx_rready      : IN STD_LOGIC;
+    -- cipo
+    reg_bsn_monitor_v2_rx_awready     : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_rx_wready      : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_rx_bresp       : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_bsn_monitor_v2_rx_bvalid      : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_rx_arready     : OUT STD_LOGIC;
+    reg_bsn_monitor_v2_rx_rdata       : OUT STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_bsn_monitor_v2_rx_rresp       : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_bsn_monitor_v2_rx_rvalid      : OUT STD_LOGIC;
+
+    -- reg_strobe_total_count_rx
+    -- copi
+    reg_strobe_total_count_rx_awaddr  : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_rx_awprot  : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_strobe_total_count_rx_awvalid : IN STD_LOGIC;
+    reg_strobe_total_count_rx_wdata   : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_rx_wstrb   : IN STD_LOGIC_VECTOR((32/8)-1 downto 0);
+    reg_strobe_total_count_rx_wvalid  : IN STD_LOGIC;
+    reg_strobe_total_count_rx_bready  : IN STD_LOGIC;
+    reg_strobe_total_count_rx_araddr  : IN STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_rx_arprot  : IN STD_LOGIC_VECTOR(3-1 downto 0);
+    reg_strobe_total_count_rx_arvalid : IN STD_LOGIC;
+    reg_strobe_total_count_rx_rready  : IN STD_LOGIC;
+    -- cipo
+    reg_strobe_total_count_rx_awready : OUT STD_LOGIC;
+    reg_strobe_total_count_rx_wready  : OUT STD_LOGIC;
+    reg_strobe_total_count_rx_bresp   : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_strobe_total_count_rx_bvalid  : OUT STD_LOGIC;
+    reg_strobe_total_count_rx_arready : OUT STD_LOGIC;
+    reg_strobe_total_count_rx_rdata   : OUT STD_LOGIC_VECTOR(32-1 downto 0);
+    reg_strobe_total_count_rx_rresp   : OUT STD_LOGIC_VECTOR(2-1 downto 0);
+    reg_strobe_total_count_rx_rvalid  : OUT STD_LOGIC
+
+  );
+END eth_tester_axi4_wrapper;
+
+
+ARCHITECTURE str OF eth_tester_axi4_wrapper IS
+  SIGNAL rx_udp_sosi_arr                : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL rx_udp_siso_arr                : t_dp_siso_arr(0 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
+  SIGNAL tx_udp_sosi_arr                : t_dp_sosi_arr(0 DOWNTO 0) := (OTHERS => c_dp_sosi_rst);
+  SIGNAL tx_udp_siso_arr                : t_dp_siso_arr(0 DOWNTO 0) := (OTHERS => c_dp_siso_rdy);
+
+  SIGNAL rx_udp_axi4_sosi               : t_axi4_sosi := c_axi4_sosi_rst;
+  SIGNAL rx_udp_axi4_siso               : t_axi4_siso := c_axi4_siso_rst;
+  SIGNAL tx_udp_axi4_sosi               : t_axi4_sosi := c_axi4_sosi_rst;
+  SIGNAL tx_udp_axi4_siso               : t_axi4_siso := c_axi4_siso_rst;
+
+  SIGNAL reg_bg_ctrl_copi               : t_mem_copi := c_mem_copi_rst;
+  SIGNAL reg_bg_ctrl_cipo               : t_mem_cipo;
+  SIGNAL reg_hdr_dat_copi               : t_mem_copi := c_mem_copi_rst;
+  SIGNAL reg_hdr_dat_cipo               : t_mem_cipo;
+  SIGNAL reg_bsn_monitor_v2_tx_copi     : t_mem_copi := c_mem_copi_rst;
+  SIGNAL reg_bsn_monitor_v2_tx_cipo     : t_mem_cipo;
+  SIGNAL reg_strobe_total_count_tx_copi : t_mem_copi := c_mem_copi_rst;
+  SIGNAL reg_strobe_total_count_tx_cipo : t_mem_cipo;
+
+  SIGNAL reg_bsn_monitor_v2_rx_copi     : t_mem_copi := c_mem_copi_rst;
+  SIGNAL reg_bsn_monitor_v2_rx_cipo     : t_mem_cipo;
+  SIGNAL reg_strobe_total_count_rx_copi : t_mem_copi := c_mem_copi_rst;
+  SIGNAL reg_strobe_total_count_rx_cipo : t_mem_cipo;
+
+
+  SIGNAL reg_bg_ctrl_axi4_copi               : t_axi4_lite_copi := c_axi4_lite_copi_rst;
+  SIGNAL reg_bg_ctrl_axi4_cipo               : t_axi4_lite_cipo;
+  SIGNAL reg_hdr_dat_axi4_copi               : t_axi4_lite_copi := c_axi4_lite_copi_rst;
+  SIGNAL reg_hdr_dat_axi4_cipo               : t_axi4_lite_cipo;
+  SIGNAL reg_bsn_monitor_v2_tx_axi4_copi     : t_axi4_lite_copi := c_axi4_lite_copi_rst;
+  SIGNAL reg_bsn_monitor_v2_tx_axi4_cipo     : t_axi4_lite_cipo;
+  SIGNAL reg_strobe_total_count_tx_axi4_copi : t_axi4_lite_copi := c_axi4_lite_copi_rst;
+  SIGNAL reg_strobe_total_count_tx_axi4_cipo : t_axi4_lite_cipo;
+
+  SIGNAL reg_bsn_monitor_v2_rx_axi4_copi     : t_axi4_lite_copi := c_axi4_lite_copi_rst;
+  SIGNAL reg_bsn_monitor_v2_rx_axi4_cipo     : t_axi4_lite_cipo;
+  SIGNAL reg_strobe_total_count_rx_axi4_copi : t_axi4_lite_copi := c_axi4_lite_copi_rst;
+  SIGNAL reg_strobe_total_count_rx_axi4_cipo : t_axi4_lite_cipo;
+
+  SIGNAL mm_rst : STD_LOGIC := '0';
+  SIGNAL st_rst : STD_LOGIC := '0';
+
+BEGIN
+
+  u_eth_tester : ENTITY work.eth_tester
+  GENERIC MAP (
+    g_remove_crc => FALSE
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst             => mm_rst,
+    mm_clk             => mm_clk,
+    st_rst             => st_rst,
+    st_clk             => st_clk,
+    st_pps             => st_pps,
+
+    -- UDP transmit interface
+    eth_src_mac        => eth_src_mac,
+    ip_src_addr        => ip_src_addr,
+    udp_src_port       => udp_src_port,
+
+    tx_fifo_rd_emp_arr => tx_fifo_rd_emp_arr,
+
+    tx_udp_sosi_arr    => tx_udp_sosi_arr,
+    tx_udp_siso_arr    => tx_udp_siso_arr,
+
+    -- UDP receive interface
+    rx_udp_sosi_arr    => rx_udp_sosi_arr,
+
+    -- Memory Mapped Slaves (one per stream)
+    reg_bg_ctrl_copi               => reg_bg_ctrl_copi,
+    reg_bg_ctrl_cipo               => reg_bg_ctrl_cipo,
+    reg_hdr_dat_copi               => reg_hdr_dat_copi,
+    reg_hdr_dat_cipo               => reg_hdr_dat_cipo,
+    reg_bsn_monitor_v2_tx_copi     => reg_bsn_monitor_v2_tx_copi,
+    reg_bsn_monitor_v2_tx_cipo     => reg_bsn_monitor_v2_tx_cipo,
+    reg_strobe_total_count_tx_copi => reg_strobe_total_count_tx_copi,
+    reg_strobe_total_count_tx_cipo => reg_strobe_total_count_tx_cipo,
+
+    reg_bsn_monitor_v2_rx_copi     => reg_bsn_monitor_v2_rx_copi,
+    reg_bsn_monitor_v2_rx_cipo     => reg_bsn_monitor_v2_rx_cipo,
+    reg_strobe_total_count_rx_copi => reg_strobe_total_count_rx_copi,
+    reg_strobe_total_count_rx_cipo => reg_strobe_total_count_rx_cipo
+  );
+
+  -- DP to AXI4
+  u_axi4_tx_udp : ENTITY axi4_lib.axi4_stream_dp_bridge
+  GENERIC MAP (
+    g_axi4_rl => 0,
+    g_dp_rl   => 1,
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => st_clk,
+    in_rst => aresetn,
+
+    dp_rst => st_rst,
+
+    dp_in_sosi => tx_udp_sosi_arr(0),
+    dp_in_siso => tx_udp_siso_arr(0),
+
+    axi4_out_sosi => tx_udp_axi4_sosi,
+    axi4_out_siso => tx_udp_axi4_siso
+  );
+
+  u_axi4_rx_udp : ENTITY axi4_lib.axi4_stream_dp_bridge
+  GENERIC MAP (
+    g_axi4_rl => 0,
+    g_dp_rl   => 1,
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => st_clk,
+    in_rst => aresetn,
+
+    axi4_in_sosi => rx_udp_axi4_sosi,
+    axi4_in_siso => rx_udp_axi4_siso,
+
+    dp_out_sosi => rx_udp_sosi_arr(0),
+    dp_out_siso => rx_udp_siso_arr(0)
+  );
+
+  -- AXI4 to MM
+  u_axi4_reg_bg_ctrl : ENTITY axi4_lib.axi4_lite_mm_bridge
+  GENERIC MAP (
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => mm_clk,
+    in_rst => aresetn,
+
+    mm_rst => mm_rst,
+
+    axi4_in_copi => reg_bg_ctrl_axi4_copi,
+    axi4_in_cipo => reg_bg_ctrl_axi4_cipo,
+
+    mm_out_copi  => reg_bg_ctrl_copi,
+    mm_out_cipo  => reg_bg_ctrl_cipo
+  );
+
+  u_axi4_reg_hdr_dat : ENTITY axi4_lib.axi4_lite_mm_bridge
+  GENERIC MAP (
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => mm_clk,
+    in_rst => aresetn,
+
+    axi4_in_copi => reg_hdr_dat_axi4_copi,
+    axi4_in_cipo => reg_hdr_dat_axi4_cipo,
+
+    mm_out_copi  => reg_hdr_dat_copi,
+    mm_out_cipo  => reg_hdr_dat_cipo
+  );
+
+
+  u_axi4_reg_bsn_monitor_v2_tx : ENTITY axi4_lib.axi4_lite_mm_bridge
+  GENERIC MAP (
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => mm_clk,
+    in_rst => aresetn,
+
+    axi4_in_copi => reg_bsn_monitor_v2_tx_axi4_copi,
+    axi4_in_cipo => reg_bsn_monitor_v2_tx_axi4_cipo,
+
+    mm_out_copi  => reg_bsn_monitor_v2_tx_copi,
+    mm_out_cipo  => reg_bsn_monitor_v2_tx_cipo
+  );
+
+
+  u_axi4_reg_strobe_total_count_tx : ENTITY axi4_lib.axi4_lite_mm_bridge
+  GENERIC MAP (
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => mm_clk,
+    in_rst => aresetn,
+
+    axi4_in_copi => reg_strobe_total_count_tx_axi4_copi,
+    axi4_in_cipo => reg_strobe_total_count_tx_axi4_cipo,
+
+    mm_out_copi  => reg_strobe_total_count_tx_copi,
+    mm_out_cipo  => reg_strobe_total_count_tx_cipo
+  );
+
+
+  u_axi4_reg_bsn_monitor_v2_rx : ENTITY axi4_lib.axi4_lite_mm_bridge
+  GENERIC MAP (
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => mm_clk,
+    in_rst => aresetn,
+
+    axi4_in_copi => reg_bsn_monitor_v2_rx_axi4_copi,
+    axi4_in_cipo => reg_bsn_monitor_v2_rx_axi4_cipo,
+
+    mm_out_copi  => reg_bsn_monitor_v2_rx_copi,
+    mm_out_cipo  => reg_bsn_monitor_v2_rx_cipo
+  );
+
+  u_axi4_reg_strobe_total_count_rx : ENTITY axi4_lib.axi4_lite_mm_bridge
+  GENERIC MAP (
+    g_active_low_rst => TRUE
+  )
+  PORT MAP (
+    in_clk => mm_clk,
+    in_rst => aresetn,
+
+    axi4_in_copi => reg_strobe_total_count_rx_axi4_copi,
+    axi4_in_cipo => reg_strobe_total_count_rx_axi4_cipo,
+
+    mm_out_copi  => reg_strobe_total_count_rx_copi,
+    mm_out_cipo  => reg_strobe_total_count_rx_cipo
+  );
+
+  -- Wire Records to IN/OUT ports.
+
+  -- tx_udp
+  tx_udp_axi4_siso.tready <= tx_udp_tready;
+
+  tx_udp_tvalid <= tx_udp_axi4_sosi.tvalid;
+  tx_udp_tdata  <= tx_udp_axi4_sosi.tdata;
+  tx_udp_tstrb  <= tx_udp_axi4_sosi.tstrb;
+  tx_udp_tkeep  <= tx_udp_axi4_sosi.tkeep;
+  tx_udp_tlast  <= tx_udp_axi4_sosi.tlast;
+  tx_udp_tid    <= tx_udp_axi4_sosi.tid;
+  tx_udp_tdest  <= tx_udp_axi4_sosi.tdest;
+  tx_udp_tuser  <= tx_udp_axi4_sosi.tuser;
+
+  -- rx_udp
+  rx_udp_tready <= rx_udp_axi4_siso.tready;
+
+  rx_udp_axi4_sosi.tvalid <= rx_udp_tvalid;
+  rx_udp_axi4_sosi.tdata  <= rx_udp_tdata;
+  rx_udp_axi4_sosi.tstrb  <= rx_udp_tstrb;
+  rx_udp_axi4_sosi.tkeep  <= rx_udp_tkeep;
+  rx_udp_axi4_sosi.tlast  <= rx_udp_tlast;
+  rx_udp_axi4_sosi.tid    <= rx_udp_tid;
+  rx_udp_axi4_sosi.tdest  <= rx_udp_tdest;
+  rx_udp_axi4_sosi.tuser  <= rx_udp_tuser;
+
+  -- reg_bg_ctrl
+  -- copi
+  reg_bg_ctrl_axi4_copi.awaddr  <= reg_bg_ctrl_awaddr;
+  reg_bg_ctrl_axi4_copi.awprot  <= reg_bg_ctrl_awprot;
+  reg_bg_ctrl_axi4_copi.awvalid <= reg_bg_ctrl_awvalid;
+  reg_bg_ctrl_axi4_copi.wdata   <= reg_bg_ctrl_wdata;
+  reg_bg_ctrl_axi4_copi.wstrb   <= reg_bg_ctrl_wstrb;
+  reg_bg_ctrl_axi4_copi.wvalid  <= reg_bg_ctrl_wvalid;
+  reg_bg_ctrl_axi4_copi.bready  <= reg_bg_ctrl_bready;
+  reg_bg_ctrl_axi4_copi.araddr  <= reg_bg_ctrl_araddr;
+  reg_bg_ctrl_axi4_copi.arprot  <= reg_bg_ctrl_arprot;
+  reg_bg_ctrl_axi4_copi.arvalid <= reg_bg_ctrl_arvalid;
+  reg_bg_ctrl_axi4_copi.rready  <= reg_bg_ctrl_rready;
+  -- cipo
+  reg_bg_ctrl_awready <=  reg_bg_ctrl_axi4_cipo.awready;
+  reg_bg_ctrl_wready  <=  reg_bg_ctrl_axi4_cipo.wready;
+  reg_bg_ctrl_bresp   <=  reg_bg_ctrl_axi4_cipo.bresp;
+  reg_bg_ctrl_bvalid  <=  reg_bg_ctrl_axi4_cipo.bvalid;
+  reg_bg_ctrl_arready <=  reg_bg_ctrl_axi4_cipo.arready;
+  reg_bg_ctrl_rdata   <=  reg_bg_ctrl_axi4_cipo.rdata;
+  reg_bg_ctrl_rresp   <=  reg_bg_ctrl_axi4_cipo.rresp;
+  reg_bg_ctrl_rvalid  <=  reg_bg_ctrl_axi4_cipo.rvalid;
+
+  -- reg_hdr_dat
+  -- copi
+  reg_hdr_dat_axi4_copi.awaddr  <= reg_hdr_dat_awaddr;
+  reg_hdr_dat_axi4_copi.awprot  <= reg_hdr_dat_awprot;
+  reg_hdr_dat_axi4_copi.awvalid <= reg_hdr_dat_awvalid;
+  reg_hdr_dat_axi4_copi.wdata   <= reg_hdr_dat_wdata;
+  reg_hdr_dat_axi4_copi.wstrb   <= reg_hdr_dat_wstrb;
+  reg_hdr_dat_axi4_copi.wvalid  <= reg_hdr_dat_wvalid;
+  reg_hdr_dat_axi4_copi.bready  <= reg_hdr_dat_bready;
+  reg_hdr_dat_axi4_copi.araddr  <= reg_hdr_dat_araddr;
+  reg_hdr_dat_axi4_copi.arprot  <= reg_hdr_dat_arprot;
+  reg_hdr_dat_axi4_copi.arvalid <= reg_hdr_dat_arvalid;
+  reg_hdr_dat_axi4_copi.rready  <= reg_hdr_dat_rready;
+  -- cipo
+  reg_hdr_dat_awready <=  reg_hdr_dat_axi4_cipo.awready;
+  reg_hdr_dat_wready  <=  reg_hdr_dat_axi4_cipo.wready;
+  reg_hdr_dat_bresp   <=  reg_hdr_dat_axi4_cipo.bresp;
+  reg_hdr_dat_bvalid  <=  reg_hdr_dat_axi4_cipo.bvalid;
+  reg_hdr_dat_arready <=  reg_hdr_dat_axi4_cipo.arready;
+  reg_hdr_dat_rdata   <=  reg_hdr_dat_axi4_cipo.rdata;
+  reg_hdr_dat_rresp   <=  reg_hdr_dat_axi4_cipo.rresp;
+  reg_hdr_dat_rvalid  <=  reg_hdr_dat_axi4_cipo.rvalid;
+
+  -- reg_bsn_monitor_v2_tx
+  -- copi
+  reg_bsn_monitor_v2_tx_axi4_copi.awaddr  <= reg_bsn_monitor_v2_tx_awaddr;
+  reg_bsn_monitor_v2_tx_axi4_copi.awprot  <= reg_bsn_monitor_v2_tx_awprot;
+  reg_bsn_monitor_v2_tx_axi4_copi.awvalid <= reg_bsn_monitor_v2_tx_awvalid;
+  reg_bsn_monitor_v2_tx_axi4_copi.wdata   <= reg_bsn_monitor_v2_tx_wdata;
+  reg_bsn_monitor_v2_tx_axi4_copi.wstrb   <= reg_bsn_monitor_v2_tx_wstrb;
+  reg_bsn_monitor_v2_tx_axi4_copi.wvalid  <= reg_bsn_monitor_v2_tx_wvalid;
+  reg_bsn_monitor_v2_tx_axi4_copi.bready  <= reg_bsn_monitor_v2_tx_bready;
+  reg_bsn_monitor_v2_tx_axi4_copi.araddr  <= reg_bsn_monitor_v2_tx_araddr;
+  reg_bsn_monitor_v2_tx_axi4_copi.arprot  <= reg_bsn_monitor_v2_tx_arprot;
+  reg_bsn_monitor_v2_tx_axi4_copi.arvalid <= reg_bsn_monitor_v2_tx_arvalid;
+  reg_bsn_monitor_v2_tx_axi4_copi.rready  <= reg_bsn_monitor_v2_tx_rready;
+  -- cipo
+  reg_bsn_monitor_v2_tx_awready <= reg_bsn_monitor_v2_tx_axi4_cipo.awready;
+  reg_bsn_monitor_v2_tx_wready  <= reg_bsn_monitor_v2_tx_axi4_cipo.wready;
+  reg_bsn_monitor_v2_tx_bresp   <= reg_bsn_monitor_v2_tx_axi4_cipo.bresp;
+  reg_bsn_monitor_v2_tx_bvalid  <= reg_bsn_monitor_v2_tx_axi4_cipo.bvalid;
+  reg_bsn_monitor_v2_tx_arready <= reg_bsn_monitor_v2_tx_axi4_cipo.arready;
+  reg_bsn_monitor_v2_tx_rdata   <= reg_bsn_monitor_v2_tx_axi4_cipo.rdata;
+  reg_bsn_monitor_v2_tx_rresp   <= reg_bsn_monitor_v2_tx_axi4_cipo.rresp;
+  reg_bsn_monitor_v2_tx_rvalid  <= reg_bsn_monitor_v2_tx_axi4_cipo.rvalid;
+
+  -- reg_strobe_total_count_tx
+  -- copi
+  reg_strobe_total_count_tx_axi4_copi.awaddr  <= reg_strobe_total_count_tx_awaddr;
+  reg_strobe_total_count_tx_axi4_copi.awprot  <= reg_strobe_total_count_tx_awprot;
+  reg_strobe_total_count_tx_axi4_copi.awvalid <= reg_strobe_total_count_tx_awvalid;
+  reg_strobe_total_count_tx_axi4_copi.wdata   <= reg_strobe_total_count_tx_wdata;
+  reg_strobe_total_count_tx_axi4_copi.wstrb   <= reg_strobe_total_count_tx_wstrb;
+  reg_strobe_total_count_tx_axi4_copi.wvalid  <= reg_strobe_total_count_tx_wvalid;
+  reg_strobe_total_count_tx_axi4_copi.bready  <= reg_strobe_total_count_tx_bready;
+  reg_strobe_total_count_tx_axi4_copi.araddr  <= reg_strobe_total_count_tx_araddr;
+  reg_strobe_total_count_tx_axi4_copi.arprot  <= reg_strobe_total_count_tx_arprot;
+  reg_strobe_total_count_tx_axi4_copi.arvalid <= reg_strobe_total_count_tx_arvalid;
+  reg_strobe_total_count_tx_axi4_copi.rready  <= reg_strobe_total_count_tx_rready;
+  -- cipo
+  reg_strobe_total_count_tx_awready <= reg_strobe_total_count_tx_axi4_cipo.awready;
+  reg_strobe_total_count_tx_wready  <= reg_strobe_total_count_tx_axi4_cipo.wready;
+  reg_strobe_total_count_tx_bresp   <= reg_strobe_total_count_tx_axi4_cipo.bresp;
+  reg_strobe_total_count_tx_bvalid  <= reg_strobe_total_count_tx_axi4_cipo.bvalid;
+  reg_strobe_total_count_tx_arready <= reg_strobe_total_count_tx_axi4_cipo.arready;
+  reg_strobe_total_count_tx_rdata   <= reg_strobe_total_count_tx_axi4_cipo.rdata;
+  reg_strobe_total_count_tx_rresp   <= reg_strobe_total_count_tx_axi4_cipo.rresp;
+  reg_strobe_total_count_tx_rvalid  <= reg_strobe_total_count_tx_axi4_cipo.rvalid;
+
+  -- reg_bsn_monitor_v2_rx
+  -- copi
+  reg_bsn_monitor_v2_rx_axi4_copi.awaddr  <= reg_bsn_monitor_v2_rx_awaddr;
+  reg_bsn_monitor_v2_rx_axi4_copi.awprot  <= reg_bsn_monitor_v2_rx_awprot;
+  reg_bsn_monitor_v2_rx_axi4_copi.awvalid <= reg_bsn_monitor_v2_rx_awvalid;
+  reg_bsn_monitor_v2_rx_axi4_copi.wdata   <= reg_bsn_monitor_v2_rx_wdata;
+  reg_bsn_monitor_v2_rx_axi4_copi.wstrb   <= reg_bsn_monitor_v2_rx_wstrb;
+  reg_bsn_monitor_v2_rx_axi4_copi.wvalid  <= reg_bsn_monitor_v2_rx_wvalid;
+  reg_bsn_monitor_v2_rx_axi4_copi.bready  <= reg_bsn_monitor_v2_rx_bready;
+  reg_bsn_monitor_v2_rx_axi4_copi.araddr  <= reg_bsn_monitor_v2_rx_araddr;
+  reg_bsn_monitor_v2_rx_axi4_copi.arprot  <= reg_bsn_monitor_v2_rx_arprot;
+  reg_bsn_monitor_v2_rx_axi4_copi.arvalid <= reg_bsn_monitor_v2_rx_arvalid;
+  reg_bsn_monitor_v2_rx_axi4_copi.rready  <= reg_bsn_monitor_v2_rx_rready;
+  -- cipo
+  reg_bsn_monitor_v2_rx_awready <= reg_bsn_monitor_v2_rx_axi4_cipo.awready;
+  reg_bsn_monitor_v2_rx_wready  <= reg_bsn_monitor_v2_rx_axi4_cipo.wready;
+  reg_bsn_monitor_v2_rx_bresp   <= reg_bsn_monitor_v2_rx_axi4_cipo.bresp;
+  reg_bsn_monitor_v2_rx_bvalid  <= reg_bsn_monitor_v2_rx_axi4_cipo.bvalid;
+  reg_bsn_monitor_v2_rx_arready <= reg_bsn_monitor_v2_rx_axi4_cipo.arready;
+  reg_bsn_monitor_v2_rx_rdata   <= reg_bsn_monitor_v2_rx_axi4_cipo.rdata;
+  reg_bsn_monitor_v2_rx_rresp   <= reg_bsn_monitor_v2_rx_axi4_cipo.rresp;
+  reg_bsn_monitor_v2_rx_rvalid  <= reg_bsn_monitor_v2_rx_axi4_cipo.rvalid;
+
+  -- reg_strobe_total_count_rx
+  -- copi
+  reg_strobe_total_count_rx_axi4_copi.awaddr  <= reg_strobe_total_count_rx_awaddr;
+  reg_strobe_total_count_rx_axi4_copi.awprot  <= reg_strobe_total_count_rx_awprot;
+  reg_strobe_total_count_rx_axi4_copi.awvalid <= reg_strobe_total_count_rx_awvalid;
+  reg_strobe_total_count_rx_axi4_copi.wdata   <= reg_strobe_total_count_rx_wdata;
+  reg_strobe_total_count_rx_axi4_copi.wstrb   <= reg_strobe_total_count_rx_wstrb;
+  reg_strobe_total_count_rx_axi4_copi.wvalid  <= reg_strobe_total_count_rx_wvalid;
+  reg_strobe_total_count_rx_axi4_copi.bready  <= reg_strobe_total_count_rx_bready;
+  reg_strobe_total_count_rx_axi4_copi.araddr  <= reg_strobe_total_count_rx_araddr;
+  reg_strobe_total_count_rx_axi4_copi.arprot  <= reg_strobe_total_count_rx_arprot;
+  reg_strobe_total_count_rx_axi4_copi.arvalid <= reg_strobe_total_count_rx_arvalid;
+  reg_strobe_total_count_rx_axi4_copi.rready  <= reg_strobe_total_count_rx_rready;
+  -- cipo
+  reg_strobe_total_count_rx_awready <= reg_strobe_total_count_rx_axi4_cipo.awready;
+  reg_strobe_total_count_rx_wready  <= reg_strobe_total_count_rx_axi4_cipo.wready;
+  reg_strobe_total_count_rx_bresp   <= reg_strobe_total_count_rx_axi4_cipo.bresp;
+  reg_strobe_total_count_rx_bvalid  <= reg_strobe_total_count_rx_axi4_cipo.bvalid;
+  reg_strobe_total_count_rx_arready <= reg_strobe_total_count_rx_axi4_cipo.arready;
+  reg_strobe_total_count_rx_rdata   <= reg_strobe_total_count_rx_axi4_cipo.rdata;
+  reg_strobe_total_count_rx_rresp   <= reg_strobe_total_count_rx_axi4_cipo.rresp;
+  reg_strobe_total_count_rx_rvalid  <= reg_strobe_total_count_rx_axi4_cipo.rvalid;
+
+END str;
diff --git a/libraries/technology/fifo/hdllib.cfg b/libraries/technology/fifo/hdllib.cfg
index e8bd853aafbd62706a63a2e6daabdef02571149b..292b8492dd0f004cecd8a519e9e270e34223d0ee 100644
--- a/libraries/technology/fifo/hdllib.cfg
+++ b/libraries/technology/fifo/hdllib.cfg
@@ -1,6 +1,6 @@
 hdl_lib_name = tech_fifo
 hdl_library_clause_name = tech_fifo_lib
-hdl_lib_uses_synth = technology ip_stratixiv_fifo ip_arria10_fifo ip_arria10_e3sge3_fifo ip_arria10_e1sg_fifo ip_arria10_e2sg_fifo
+hdl_lib_uses_synth = technology ip_stratixiv_fifo ip_arria10_fifo ip_arria10_e3sge3_fifo ip_arria10_e1sg_fifo ip_arria10_e2sg_fifo ip_ultrascale_fifo
 hdl_lib_uses_sim = 
 hdl_lib_technology = 
 hdl_lib_disclose_library_clause_names =
@@ -9,6 +9,7 @@ hdl_lib_disclose_library_clause_names =
     ip_arria10_e3sge3_fifo ip_arria10_e3sge3_fifo_lib
     ip_arria10_e1sg_fifo   ip_arria10_e1sg_fifo_lib
     ip_arria10_e2sg_fifo   ip_arria10_e2sg_fifo_lib
+    ip_ultrascale_fifo     ip_arria10_ultrascale_lib
 
 synth_files =
     tech_fifo_component_pkg.vhd
diff --git a/libraries/technology/fifo/tech_fifo_component_pkg.vhd b/libraries/technology/fifo/tech_fifo_component_pkg.vhd
index f325b78e7b904474735804721fbd1ddf1435034f..81efaf41d69922bf149028fa9f31423bd9e15a69 100644
--- a/libraries/technology/fifo/tech_fifo_component_pkg.vhd
+++ b/libraries/technology/fifo/tech_fifo_component_pkg.vhd
@@ -287,7 +287,7 @@ PACKAGE tech_fifo_component_pkg IS
   );
   END COMPONENT;
   
-   -----------------------------------------------------------------------------
+  -----------------------------------------------------------------------------
   -- ip_arria10_e2sg
   -----------------------------------------------------------------------------
   
@@ -351,6 +351,68 @@ PACKAGE tech_fifo_component_pkg IS
     wrusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0)
   );
   END COMPONENT;
+   
+  -----------------------------------------------------------------------------
+  -- ip_ultrascale
+  -----------------------------------------------------------------------------
+  
+  COMPONENT ip_ultrascale_fifo_sc IS
+  GENERIC (
+    g_dat_w     : NATURAL := 20;
+    g_nof_words : NATURAL := 1024
+  );
+  PORT (
+    aclr    : IN STD_LOGIC ;
+    clock   : IN STD_LOGIC ;
+    data    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdreq   : IN STD_LOGIC ;
+    wrreq   : IN STD_LOGIC ;
+    empty   : OUT STD_LOGIC ;
+    full    : OUT STD_LOGIC ;
+    q       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0) ;
+    usedw   : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0)
+  );
+  END COMPONENT;
+
+  COMPONENT ip_ultrascale_fifo_dc IS
+  GENERIC (
+    g_dat_w     : NATURAL := 20;
+    g_nof_words : NATURAL := 1024
+  );
+  PORT (
+    aclr    : IN STD_LOGIC  := '0';
+    data    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdclk   : IN STD_LOGIC ;
+    rdreq   : IN STD_LOGIC ;
+    wrclk   : IN STD_LOGIC ;
+    wrreq   : IN STD_LOGIC ;
+    q       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdempty : OUT STD_LOGIC ;
+    rdusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0);
+    wrfull  : OUT STD_LOGIC ;
+    wrusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0)
+  );
+  END COMPONENT;
+  
+  COMPONENT ip_ultrascale_fifo_dc_mixed_widths IS
+  GENERIC (
+    g_nof_words : NATURAL := 1024;  -- FIFO size in nof wr_dat words
+    g_wrdat_w   : NATURAL := 20;
+    g_rddat_w   : NATURAL := 10
+  );
+  PORT (
+    aclr    : IN STD_LOGIC  := '0';
+    data    : IN STD_LOGIC_VECTOR (g_wrdat_w-1 DOWNTO 0);
+    rdclk   : IN STD_LOGIC ;
+    rdreq   : IN STD_LOGIC ;
+    wrclk   : IN STD_LOGIC ;
+    wrreq   : IN STD_LOGIC ;
+    q       : OUT STD_LOGIC_VECTOR (g_rddat_w-1 DOWNTO 0);
+    rdempty : OUT STD_LOGIC ;
+    rdusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words*g_wrdat_w/g_rddat_w)-1 DOWNTO 0);
+    wrfull  : OUT STD_LOGIC ;
+    wrusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0)
+  );
+  END COMPONENT;
   
- 
 END tech_fifo_component_pkg;
diff --git a/libraries/technology/fifo/tech_fifo_dc.vhd b/libraries/technology/fifo/tech_fifo_dc.vhd
index 179aa1ff4cc2c73789dd245c1e5ef38871766008..08fd6a67589cb527a4140aae253efe34e63bf22e 100644
--- a/libraries/technology/fifo/tech_fifo_dc.vhd
+++ b/libraries/technology/fifo/tech_fifo_dc.vhd
@@ -31,6 +31,7 @@ LIBRARY ip_arria10_fifo_lib;
 LIBRARY ip_arria10_e3sge3_fifo_lib;
 LIBRARY ip_arria10_e1sg_fifo_lib;
 LIBRARY ip_arria10_e2sg_fifo_lib;
+LIBRARY ip_ultrascale_fifo_lib;
 
 ENTITY tech_fifo_dc IS
   GENERIC (
@@ -89,4 +90,10 @@ BEGIN
     PORT MAP (aclr, data, rdclk, rdreq, wrclk, wrreq, q, rdempty, rdusedw, wrfull, wrusedw);
   END GENERATE;
 
+  gen_ip_ultrascale : IF g_technology=c_tech_ultrascale GENERATE
+    u0 : ip_ultrascale_fifo_dc
+    GENERIC MAP (g_dat_w, g_nof_words)
+    PORT MAP (aclr, data, rdclk, rdreq, wrclk, wrreq, q, rdempty, rdusedw, wrfull, wrusedw);
+  END GENERATE;
+
 END ARCHITECTURE;
diff --git a/libraries/technology/fifo/tech_fifo_dc_mixed_widths.vhd b/libraries/technology/fifo/tech_fifo_dc_mixed_widths.vhd
index 58352cd3a6d44119d28b98925d9dff48a8a28a33..d3a654dfdcc72953d6f39a81e41219d8d528b0fc 100644
--- a/libraries/technology/fifo/tech_fifo_dc_mixed_widths.vhd
+++ b/libraries/technology/fifo/tech_fifo_dc_mixed_widths.vhd
@@ -31,6 +31,7 @@ LIBRARY ip_arria10_fifo_lib;
 LIBRARY ip_arria10_e3sge3_fifo_lib;
 LIBRARY ip_arria10_e1sg_fifo_lib;
 LIBRARY ip_arria10_e2sg_fifo_lib;
+LIBRARY ip_ultrascale_fifo_lib;
 
 ENTITY tech_fifo_dc_mixed_widths IS
   GENERIC (
@@ -89,4 +90,10 @@ BEGIN
     PORT MAP (aclr, data, rdclk, rdreq, wrclk, wrreq, q, rdempty, rdusedw, wrfull, wrusedw);
   END GENERATE;
  
+  gen_ip_ultrascale : IF g_technology=c_tech_ultrascale GENERATE
+    u0 : ip_ultrascale_fifo_dc_mixed_widths
+    GENERIC MAP (g_nof_words, g_wrdat_w, g_rddat_w)
+    PORT MAP (aclr, data, rdclk, rdreq, wrclk, wrreq, q, rdempty, rdusedw, wrfull, wrusedw);
+  END GENERATE;
+
 END ARCHITECTURE;
diff --git a/libraries/technology/fifo/tech_fifo_sc.vhd b/libraries/technology/fifo/tech_fifo_sc.vhd
index 2694bc2e8b95d2baaa56cb590d57509abf075d3d..b2543bd5ce9a9e6ff76a6591197cd8a09dd629d7 100644
--- a/libraries/technology/fifo/tech_fifo_sc.vhd
+++ b/libraries/technology/fifo/tech_fifo_sc.vhd
@@ -31,6 +31,7 @@ LIBRARY ip_arria10_fifo_lib;
 LIBRARY ip_arria10_e3sge3_fifo_lib;
 LIBRARY ip_arria10_e1sg_fifo_lib;
 LIBRARY ip_arria10_e2sg_fifo_lib;
+LIBRARY ip_ultrascale_fifo_lib;
 
 ENTITY tech_fifo_sc IS
   GENERIC (
@@ -87,4 +88,10 @@ BEGIN
     PORT MAP (aclr, clock, data, rdreq, wrreq, empty, full, q, usedw);
   END GENERATE;
   
+  gen_ip_ultrascale : IF g_technology=c_tech_ultrascale GENERATE
+    u0 : ip_ultrascale_fifo_sc
+    GENERIC MAP (g_dat_w, g_nof_words)
+    PORT MAP (aclr, clock, data, rdreq, wrreq, empty, full, q, usedw);
+  END GENERATE;
+
 END ARCHITECTURE;
diff --git a/libraries/technology/ip_ultrascale/fifo/hdllib.cfg b/libraries/technology/ip_ultrascale/fifo/hdllib.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..2fac5fdfdd043644c8d2a51341b30723d4e08dc1
--- /dev/null
+++ b/libraries/technology/ip_ultrascale/fifo/hdllib.cfg
@@ -0,0 +1,19 @@
+hdl_lib_name = ip_ultrascale_fifo
+hdl_library_clause_name = ip_ultrascale_fifo_lib
+hdl_lib_uses_synth = technology
+hdl_lib_uses_sim = 
+hdl_lib_technology = ip_ultrascale
+
+synth_files =
+    ip_ultrascale_fifo_sc.vhd
+    ip_ultrascale_fifo_dc.vhd
+    ip_ultrascale_fifo_dc_mixed_widths.vhd
+    
+test_bench_files =
+
+
+[modelsim_project_file]
+
+
+[quartus_project_file]
+
diff --git a/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_dc.vhd b/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_dc.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..4b901cdef5bf50e94235112398c0e13e352e4fbb
--- /dev/null
+++ b/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_dc.vhd
@@ -0,0 +1,176 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+-- Purpose: Instantiate FIFO IP with generics
+-- Description:
+--   Copied component instantiation from Vivado XPM template
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+LIBRARY technology_lib;
+USE technology_lib.technology_pkg.ALL;
+
+LIBRARY xpm;
+USE xpm.vcomponents.ALL;
+
+ENTITY ip_ultrascale_fifo_dc IS
+  GENERIC (
+    g_dat_w     : NATURAL := 20;
+    g_nof_words : NATURAL := 1024
+  );
+  PORT (
+    aclr    : IN STD_LOGIC  := '0';
+    data    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdclk   : IN STD_LOGIC ;
+    rdreq   : IN STD_LOGIC ;
+    wrclk   : IN STD_LOGIC ;
+    wrreq   : IN STD_LOGIC ;
+    q       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdempty : OUT STD_LOGIC ;
+    rdusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0);
+    wrfull  : OUT STD_LOGIC ;
+    wrusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0)
+  );
+END ip_ultrascale_fifo_dc;
+
+ARCHITECTURE SYN OF ip_ultrascale_fifo_dc IS
+
+BEGIN
+   -- xpm_fifo_async: Asynchronous FIFO
+   -- Xilinx Parameterized Macro, version 2022.1
+
+   xpm_fifo_async_inst : xpm_fifo_async
+   generic map (
+      CASCADE_HEIGHT => 0,        -- DECIMAL
+      CDC_SYNC_STAGES => 3,       -- DECIMAL
+      DOUT_RESET_VALUE => "0",    -- String
+      ECC_MODE => "no_ecc",       -- String
+      FIFO_MEMORY_TYPE => "auto", -- String
+      FIFO_READ_LATENCY => 1,     -- DECIMAL
+      FIFO_WRITE_DEPTH => g_nof_words,   -- DECIMAL
+      FULL_RESET_VALUE => 0,      -- DECIMAL
+      PROG_EMPTY_THRESH => 10,    -- DECIMAL
+      PROG_FULL_THRESH => 10,     -- DECIMAL
+      RD_DATA_COUNT_WIDTH => tech_ceil_log2(g_nof_words),   -- DECIMAL
+      READ_DATA_WIDTH => g_dat_w,  -- DECIMAL
+      READ_MODE => "std",          -- String
+      RELATED_CLOCKS => 0,         -- DECIMAL
+      SIM_ASSERT_CHK => 0,         -- DECIMAL; 0=disable simulation messages, 1=enable simulation messages
+      USE_ADV_FEATURES => "0404",  -- String
+      WAKEUP_TIME => 0,            -- DECIMAL
+      WRITE_DATA_WIDTH => g_dat_w, -- DECIMAL
+      WR_DATA_COUNT_WIDTH => tech_ceil_log2(g_nof_words)    -- DECIMAL
+   )
+   port map (
+      almost_empty => OPEN,        -- 1-bit output: Almost Empty : When asserted, this signal indicates that
+                                      -- only one more read can be performed before the FIFO goes to empty.
+
+      almost_full => OPEN,     -- 1-bit output: Almost Full: When asserted, this signal indicates that
+                                      -- only one more write can be performed before the FIFO is full.
+
+      data_valid => OPEN,       -- 1-bit output: Read Data Valid: When asserted, this signal indicates
+                                      -- that valid data is available on the output bus (dout).
+
+      dbiterr => OPEN,             -- 1-bit output: Double Bit Error: Indicates that the ECC decoder
+                                      -- detected a double-bit error and data in the FIFO core is corrupted.
+
+      dout => q,                      -- READ_DATA_WIDTH-bit output: Read Data: The output data bus is driven
+                                      -- when reading the FIFO.
+
+      empty => rdempty,               -- 1-bit output: Empty Flag: When asserted, this signal indicates that
+                                      -- the FIFO is empty. Read requests are ignored when the FIFO is empty,
+                                      -- initiating a read while empty is not destructive to the FIFO.
+
+      full => wrfull,                 -- 1-bit output: Full Flag: When asserted, this signal indicates that the
+                                      -- FIFO is full. Write requests are ignored when the FIFO is full,
+                                      -- initiating a write when the FIFO is full is not destructive to the
+                                      -- contents of the FIFO.
+
+      overflow => OPEN,               -- 1-bit output: Overflow: This signal indicates that a write request
+                                      -- (wren) during the prior clock cycle was rejected, because the FIFO is
+                                      -- full. Overflowing the FIFO is not destructive to the contents of the
+                                      -- FIFO.
+
+      prog_empty => OPEN,             -- 1-bit output: Programmable Empty: This signal is asserted when the
+                                      -- number of words in the FIFO is less than or equal to the programmable
+                                      -- empty threshold value. It is de-asserted when the number of words in
+                                      -- the FIFO exceeds the programmable empty threshold value.
+
+      prog_full => OPEN,              -- 1-bit output: Programmable Full: This signal is asserted when the
+                                      -- number of words in the FIFO is greater than or equal to the
+                                      -- programmable full threshold value. It is de-asserted when the number
+                                      -- of words in the FIFO is less than the programmable full threshold
+                                      -- value.
+
+      rd_data_count => rdusedw,       -- RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates
+                                      -- the number of words read from the FIFO.
+
+      rd_rst_busy => OPEN,            -- 1-bit output: Read Reset Busy: Active-High indicator that the FIFO
+                                      -- read domain is currently in a reset state.
+
+      sbiterr => OPEN,                -- 1-bit output: Single Bit Error: Indicates that the ECC decoder
+                                      -- detected and fixed a single-bit error.
+
+      underflow => OPEN,              -- 1-bit output: Underflow: Indicates that the read request (rd_en)
+                                      -- during the previous clock cycle was rejected because the FIFO is
+                                      -- empty. Under flowing the FIFO is not destructive to the FIFO.
+
+      wr_ack => OPEN,                 -- 1-bit output: Write Acknowledge: This signal indicates that a write
+                                      -- request (wr_en) during the prior clock cycle is succeeded.
+
+      wr_data_count => wrusedw,       -- WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates
+                                      -- the number of words written into the FIFO.
+
+      wr_rst_busy => OPEN,            -- 1-bit output: Write Reset Busy: Active-High indicator that the FIFO
+                                      -- write domain is currently in a reset state.
+
+      din => data,                    -- WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when
+                                      -- writing the FIFO.
+
+      injectdbiterr => '0',           -- 1-bit input: Double Bit Error Injection: Injects a double bit error if
+                                      -- the ECC feature is used on block RAMs or UltraRAM macros.
+
+      injectsbiterr => '0',           -- 1-bit input: Single Bit Error Injection: Injects a single bit error if
+                                      -- the ECC feature is used on block RAMs or UltraRAM macros.
+
+      rd_clk => rdclk,                -- 1-bit input: Read clock: Used for read operation. rd_clk must be a
+                                      -- free running clock.
+
+      rd_en => rdreq,                 -- 1-bit input: Read Enable: If the FIFO is not empty, asserting this
+                                      -- signal causes data (on dout) to be read from the FIFO. Must be held
+                                      -- active-low when rd_rst_busy is active high.
+
+      rst => aclr,                     -- 1-bit input: Reset: Must be synchronous to wr_clk. The clock(s) can be
+                                      -- unstable at the time of applying reset, but reset must be released
+                                      -- only after the clock(s) is/are stable.
+
+      sleep => '0',                   -- 1-bit input: Dynamic power saving: If sleep is High, the memory/fifo
+                                      -- block is in power saving mode.
+
+      wr_clk => wrclk,                -- 1-bit input: Write clock: Used for write operation. wr_clk must be a
+                                      -- free running clock.
+
+      wr_en => wrreq                  -- 1-bit input: Write Enable: If the FIFO is not full, asserting this
+                                      -- signal causes data (on din) to be written to the FIFO. Must be held
+                                      -- active-low when rst or wr_rst_busy is active high.
+   );
+
+   -- End of xpm_fifo_async_inst instantiation
+END SYN;
diff --git a/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_dc_mixed_widths.vhd b/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_dc_mixed_widths.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..936d0862322feb8db23d0f3b64dfc56c0c0bfc70
--- /dev/null
+++ b/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_dc_mixed_widths.vhd
@@ -0,0 +1,178 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+-- Purpose: Instantiate FIFO IP with generics
+-- Description:
+--   Copied component instantiation from Vivado XPM template
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+LIBRARY technology_lib;
+USE technology_lib.technology_pkg.ALL;
+
+LIBRARY xpm;
+USE xpm.vcomponents.ALL;
+
+ENTITY ip_ultrascale_fifo_dc_mixed_widths IS
+  GENERIC (
+    g_nof_words : NATURAL := 1024;  -- FIFO size in nof wr_dat words
+    g_wrdat_w   : NATURAL := 20;
+    g_rddat_w   : NATURAL := 10
+  );
+  PORT (
+    aclr    : IN STD_LOGIC  := '0';
+    data    : IN STD_LOGIC_VECTOR (g_wrdat_w-1 DOWNTO 0);
+    rdclk   : IN STD_LOGIC ;
+    rdreq   : IN STD_LOGIC ;
+    wrclk   : IN STD_LOGIC ;
+    wrreq   : IN STD_LOGIC ;
+    q       : OUT STD_LOGIC_VECTOR (g_rddat_w-1 DOWNTO 0);
+    rdempty : OUT STD_LOGIC ;
+    rdusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words*g_wrdat_w/g_rddat_w)-1 DOWNTO 0);
+    wrfull  : OUT STD_LOGIC ;
+    wrusedw : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0)
+  );
+END ip_ultrascale_fifo_dc_mixed_widths;
+
+ARCHITECTURE SYN OF ip_ultrascale_fifo_dc_mixed_widths IS
+    
+BEGIN
+   -- xpm_fifo_async: Asynchronous FIFO
+   -- Xilinx Parameterized Macro, version 2022.1
+
+   xpm_fifo_async_inst : xpm_fifo_async
+   generic map (
+      CASCADE_HEIGHT => 0,        -- DECIMAL
+      CDC_SYNC_STAGES => 3,       -- DECIMAL
+      DOUT_RESET_VALUE => "0",    -- String
+      ECC_MODE => "no_ecc",       -- String
+      FIFO_MEMORY_TYPE => "auto", -- String
+      FIFO_READ_LATENCY => 1,     -- DECIMAL
+      FIFO_WRITE_DEPTH => g_nof_words,   -- DECIMAL
+      FULL_RESET_VALUE => 0,      -- DECIMAL
+      PROG_EMPTY_THRESH => 10,    -- DECIMAL
+      PROG_FULL_THRESH => 10,     -- DECIMAL
+      RD_DATA_COUNT_WIDTH => tech_ceil_log2(g_nof_words*g_wrdat_w/g_rddat_w),   -- DECIMAL
+      READ_DATA_WIDTH => g_rddat_w,      -- DECIMAL
+      READ_MODE => "std",         -- String
+      RELATED_CLOCKS => 0,        -- DECIMAL
+      SIM_ASSERT_CHK => 0,        -- DECIMAL; 0=disable simulation messages, 1=enable simulation messages
+      USE_ADV_FEATURES => "0404", -- String
+      WAKEUP_TIME => 0,           -- DECIMAL
+      WRITE_DATA_WIDTH => g_wrdat_w,     -- DECIMAL
+      WR_DATA_COUNT_WIDTH => tech_ceil_log2(g_nof_words)    -- DECIMAL
+   )
+   port map (
+      almost_empty => OPEN,        -- 1-bit output: Almost Empty : When asserted, this signal indicates that
+                                      -- only one more read can be performed before the FIFO goes to empty.
+
+      almost_full => OPEN,     -- 1-bit output: Almost Full: When asserted, this signal indicates that
+                                      -- only one more write can be performed before the FIFO is full.
+
+      data_valid => OPEN,       -- 1-bit output: Read Data Valid: When asserted, this signal indicates
+                                      -- that valid data is available on the output bus (dout).
+
+      dbiterr => OPEN,             -- 1-bit output: Double Bit Error: Indicates that the ECC decoder
+                                      -- detected a double-bit error and data in the FIFO core is corrupted.
+
+      dout => q,                      -- READ_DATA_WIDTH-bit output: Read Data: The output data bus is driven
+                                      -- when reading the FIFO.
+
+      empty => rdempty,               -- 1-bit output: Empty Flag: When asserted, this signal indicates that
+                                      -- the FIFO is empty. Read requests are ignored when the FIFO is empty,
+                                      -- initiating a read while empty is not destructive to the FIFO.
+
+      full => wrfull,                 -- 1-bit output: Full Flag: When asserted, this signal indicates that the
+                                      -- FIFO is full. Write requests are ignored when the FIFO is full,
+                                      -- initiating a write when the FIFO is full is not destructive to the
+                                      -- contents of the FIFO.
+
+      overflow => OPEN,               -- 1-bit output: Overflow: This signal indicates that a write request
+                                      -- (wren) during the prior clock cycle was rejected, because the FIFO is
+                                      -- full. Overflowing the FIFO is not destructive to the contents of the
+                                      -- FIFO.
+
+      prog_empty => OPEN,             -- 1-bit output: Programmable Empty: This signal is asserted when the
+                                      -- number of words in the FIFO is less than or equal to the programmable
+                                      -- empty threshold value. It is de-asserted when the number of words in
+                                      -- the FIFO exceeds the programmable empty threshold value.
+
+      prog_full => OPEN,              -- 1-bit output: Programmable Full: This signal is asserted when the
+                                      -- number of words in the FIFO is greater than or equal to the
+                                      -- programmable full threshold value. It is de-asserted when the number
+                                      -- of words in the FIFO is less than the programmable full threshold
+                                      -- value.
+
+      rd_data_count => rdusedw,       -- RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates
+                                      -- the number of words read from the FIFO.
+
+      rd_rst_busy => OPEN,            -- 1-bit output: Read Reset Busy: Active-High indicator that the FIFO
+                                      -- read domain is currently in a reset state.
+
+      sbiterr => OPEN,                -- 1-bit output: Single Bit Error: Indicates that the ECC decoder
+                                      -- detected and fixed a single-bit error.
+
+      underflow => OPEN,              -- 1-bit output: Underflow: Indicates that the read request (rd_en)
+                                      -- during the previous clock cycle was rejected because the FIFO is
+                                      -- empty. Under flowing the FIFO is not destructive to the FIFO.
+
+      wr_ack => OPEN,                 -- 1-bit output: Write Acknowledge: This signal indicates that a write
+                                      -- request (wr_en) during the prior clock cycle is succeeded.
+
+      wr_data_count => wrusedw,       -- WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates
+                                      -- the number of words written into the FIFO.
+
+      wr_rst_busy => OPEN,            -- 1-bit output: Write Reset Busy: Active-High indicator that the FIFO
+                                      -- write domain is currently in a reset state.
+
+      din => data,                    -- WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when
+                                      -- writing the FIFO.
+
+      injectdbiterr => '0',           -- 1-bit input: Double Bit Error Injection: Injects a double bit error if
+                                      -- the ECC feature is used on block RAMs or UltraRAM macros.
+
+      injectsbiterr => '0',           -- 1-bit input: Single Bit Error Injection: Injects a single bit error if
+                                      -- the ECC feature is used on block RAMs or UltraRAM macros.
+
+      rd_clk => rdclk,                -- 1-bit input: Read clock: Used for read operation. rd_clk must be a
+                                      -- free running clock.
+
+      rd_en => rdreq,                 -- 1-bit input: Read Enable: If the FIFO is not empty, asserting this
+                                      -- signal causes data (on dout) to be read from the FIFO. Must be held
+                                      -- active-low when rd_rst_busy is active high.
+
+      rst => aclr,                     -- 1-bit input: Reset: Must be synchronous to wr_clk. The clock(s) can be
+                                      -- unstable at the time of applying reset, but reset must be released
+                                      -- only after the clock(s) is/are stable.
+
+      sleep => '0',                   -- 1-bit input: Dynamic power saving: If sleep is High, the memory/fifo
+                                      -- block is in power saving mode.
+
+      wr_clk => wrclk,                -- 1-bit input: Write clock: Used for write operation. wr_clk must be a
+                                      -- free running clock.
+
+      wr_en => wrreq                  -- 1-bit input: Write Enable: If the FIFO is not full, asserting this
+                                      -- signal causes data (on din) to be written to the FIFO. Must be held
+                                      -- active-low when rst or wr_rst_busy is active high.
+   );
+
+   -- End of xpm_fifo_async_inst instantiation
+
+END SYN;
diff --git a/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_sc.vhd b/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_sc.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..4184f4ab93aeca5afbd05e9581c53b822755d1ae
--- /dev/null
+++ b/libraries/technology/ip_ultrascale/fifo/ip_ultrascale_fifo_sc.vhd
@@ -0,0 +1,171 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+-- Purpose: Instantiate FIFO IP with generics
+-- Description:
+--   Copied component instantiation from Vivado XPM template
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+
+LIBRARY technology_lib;
+USE technology_lib.technology_pkg.ALL;
+
+LIBRARY xpm;
+USE xpm.vcomponents.ALL;
+
+ENTITY ip_ultrascale_fifo_sc IS
+  GENERIC (
+    g_dat_w     : NATURAL := 20;
+    g_nof_words : NATURAL := 1024
+  );
+  PORT (
+    aclr    : IN STD_LOGIC ;
+    clock   : IN STD_LOGIC ;
+    data    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdreq   : IN STD_LOGIC ;
+    wrreq   : IN STD_LOGIC ;
+    empty   : OUT STD_LOGIC ;
+    full    : OUT STD_LOGIC ;
+    q       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0) ;
+    usedw   : OUT STD_LOGIC_VECTOR (tech_ceil_log2(g_nof_words)-1 DOWNTO 0)
+  );
+END ip_ultrascale_fifo_sc;
+
+ARCHITECTURE SYN OF ip_ultrascale_fifo_sc IS
+
+BEGIN
+   -- xpm_fifo_sync: Synchronous FIFO
+   -- Xilinx Parameterized Macro, version 2022.1
+
+   xpm_fifo_sync_inst : xpm_fifo_sync
+   generic map (
+      CASCADE_HEIGHT => 0,        -- DECIMAL
+      DOUT_RESET_VALUE => "0",    -- String
+      ECC_MODE => "no_ecc",       -- String
+      FIFO_MEMORY_TYPE => "auto", -- String
+      FIFO_READ_LATENCY => 1,     -- DECIMAL
+      FIFO_WRITE_DEPTH => g_nof_words,   -- DECIMAL
+      FULL_RESET_VALUE => 0,      -- DECIMAL
+      PROG_EMPTY_THRESH => 10,    -- DECIMAL
+      PROG_FULL_THRESH => 10,     -- DECIMAL
+      RD_DATA_COUNT_WIDTH => tech_ceil_log2(g_nof_words),   -- DECIMAL
+      READ_DATA_WIDTH => g_dat_w,  -- DECIMAL
+      READ_MODE => "std",         -- String
+      SIM_ASSERT_CHK => 0,        -- DECIMAL; 0=disable simulation messages, 1=enable simulation messages
+      USE_ADV_FEATURES => "0404",  -- String
+      WAKEUP_TIME => 0,           -- DECIMAL
+      WRITE_DATA_WIDTH => g_dat_w, -- DECIMAL
+      WR_DATA_COUNT_WIDTH => tech_ceil_log2(g_nof_words)    -- DECIMAL
+
+   )
+   port map (
+      almost_empty => OPEN,           -- 1-bit output: Almost Empty : When asserted, this signal indicates that
+                                      -- only one more read can be performed before the FIFO goes to empty.
+
+      almost_full => OPEN,            -- 1-bit output: Almost Full: When asserted, this signal indicates that
+                                      -- only one more write can be performed before the FIFO is full.
+
+      data_valid => OPEN,             -- 1-bit output: Read Data Valid: When asserted, this signal indicates
+                                      -- that valid data is available on the output bus (dout).
+
+      dbiterr => OPEN,                -- 1-bit output: Double Bit Error: Indicates that the ECC decoder
+                                      -- detected a double-bit error and data in the FIFO core is corrupted.
+
+      dout => q,                      -- READ_DATA_WIDTH-bit output: Read Data: The output data bus is driven
+                                      -- when reading the FIFO.
+
+      empty => empty,                 -- 1-bit output: Empty Flag: When asserted, this signal indicates that
+                                      -- the FIFO is empty. Read requests are ignored when the FIFO is empty,
+                                      -- initiating a read while empty is not destructive to the FIFO.
+
+      full => full,                   -- 1-bit output: Full Flag: When asserted, this signal indicates that the
+                                      -- FIFO is full. Write requests are ignored when the FIFO is full,
+                                      -- initiating a write when the FIFO is full is not destructive to the
+                                      -- contents of the FIFO.
+
+      overflow => OPEN,               -- 1-bit output: Overflow: This signal indicates that a write request
+                                      -- (wren) during the prior clock cycle was rejected, because the FIFO is
+                                      -- full. Overflowing the FIFO is not destructive to the contents of the
+                                      -- FIFO.
+
+      prog_empty => OPEN,             -- 1-bit output: Programmable Empty: This signal is asserted when the
+                                      -- number of words in the FIFO is less than or equal to the programmable
+                                      -- empty threshold value. It is de-asserted when the number of words in
+                                      -- the FIFO exceeds the programmable empty threshold value.
+
+      prog_full => OPEN,              -- 1-bit output: Programmable Full: This signal is asserted when the
+                                      -- number of words in the FIFO is greater than or equal to the
+                                      -- programmable full threshold value. It is de-asserted when the number
+                                      -- of words in the FIFO is less than the programmable full threshold
+                                      -- value.
+
+      rd_data_count => OPEN,          -- RD_DATA_COUNT_WIDTH-bit output: Read Data Count: This bus indicates
+                                      -- the number of words read from the FIFO.
+
+      rd_rst_busy => OPEN,            -- 1-bit output: Read Reset Busy: Active-High indicator that the FIFO
+                                      -- read domain is currently in a reset state.
+
+      sbiterr => OPEN,                -- 1-bit output: Single Bit Error: Indicates that the ECC decoder
+                                      -- detected and fixed a single-bit error.
+
+      underflow => OPEN,              -- 1-bit output: Underflow: Indicates that the read request (rd_en)
+                                      -- during the previous clock cycle was rejected because the FIFO is
+                                      -- empty. Under flowing the FIFO is not destructive to the FIFO.
+
+      wr_ack => OPEN,                 -- 1-bit output: Write Acknowledge: This signal indicates that a write
+                                      -- request (wr_en) during the prior clock cycle is succeeded.
+
+      wr_data_count => usedw,         -- WR_DATA_COUNT_WIDTH-bit output: Write Data Count: This bus indicates
+                                      -- the number of words written into the FIFO.
+
+      wr_rst_busy => OPEN,            -- 1-bit output: Write Reset Busy: Active-High indicator that the FIFO
+                                      -- write domain is currently in a reset state.
+
+      din => data,                    -- WRITE_DATA_WIDTH-bit input: Write Data: The input data bus used when
+                                      -- writing the FIFO.
+
+      injectdbiterr => '0',           -- 1-bit input: Double Bit Error Injection: Injects a double bit error if
+                                      -- the ECC feature is used on block RAMs or UltraRAM macros.
+
+      injectsbiterr => '0',           -- 1-bit input: Single Bit Error Injection: Injects a single bit error if
+                                      -- the ECC feature is used on block RAMs or UltraRAM macros.
+
+      rd_en => rdreq,                 -- 1-bit input: Read Enable: If the FIFO is not empty, asserting this
+                                      -- signal causes data (on dout) to be read from the FIFO. Must be held
+                                      -- active-low when rd_rst_busy is active high.
+
+      rst => aclr,                    -- 1-bit input: Reset: Must be synchronous to wr_clk. The clock(s) can be
+                                      -- unstable at the time of applying reset, but reset must be released
+                                      -- only after the clock(s) is/are stable.
+
+      sleep => '0',                   -- 1-bit input: Dynamic power saving: If sleep is High, the memory/fifo
+                                      -- block is in power saving mode.
+
+      wr_clk => clock,                -- 1-bit input: Write clock: Used for write operation. wr_clk must be a
+                                      -- free running clock.
+
+      wr_en => wrreq                  -- 1-bit input: Write Enable: If the FIFO is not full, asserting this
+                                      -- signal causes data (on din) to be written to the FIFO. Must be held
+                                      -- active-low when rst or wr_rst_busy is active high.
+   );
+
+   -- End of xpm_fifo_async_inst instantiation
+
+END SYN;
diff --git a/libraries/technology/ip_ultrascale/ram/hdllib.cfg b/libraries/technology/ip_ultrascale/ram/hdllib.cfg
new file mode 100644
index 0000000000000000000000000000000000000000..0576df0e8c6d1557ff4c8ce8c3b10a05157ed2e1
--- /dev/null
+++ b/libraries/technology/ip_ultrascale/ram/hdllib.cfg
@@ -0,0 +1,24 @@
+hdl_lib_name = ip_ultrascale_ram
+hdl_library_clause_name = ip_ultrascale_ram_lib
+hdl_lib_uses_synth = technology
+hdl_lib_uses_sim = 
+hdl_lib_technology = ip_ultrascale
+
+synth_files =
+#    ip_ultrascale_true_dual_port_ram_dual_clock.vhd
+#    ip_ultrascale_simple_dual_port_ram_dual_clock.vhd
+#    ip_ultrascale_simple_dual_port_ram_single_clock.vhd
+    
+#    ip_ultrascale_ram_crwk_crw.vhd
+    ip_ultrascale_ram_crw_crw.vhd
+    ip_ultrascale_ram_cr_cw.vhd
+#    ip_ultrascale_ram_r_w.vhd
+    
+test_bench_files =
+
+
+[modelsim_project_file]
+
+
+[quartus_project_file]
+
diff --git a/libraries/technology/ip_ultrascale/ram/ip_ultrascale_ram_cr_cw.vhd b/libraries/technology/ip_ultrascale/ram/ip_ultrascale_ram_cr_cw.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a11ea8d4288019a28d06ef3973cc95b73e00bd53
--- /dev/null
+++ b/libraries/technology/ip_ultrascale/ram/ip_ultrascale_ram_cr_cw.vhd
@@ -0,0 +1,149 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+-- Purpose: Instantiate RAM IP with generics
+-- Description:
+--   Copied component instantiation from Vivado XPM template
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+USE ieee.numeric_std.all;
+
+LIBRARY xpm;
+USE xpm.vcomponents.ALL;
+
+ENTITY ip_ultrascale_ram_cr_cw IS
+  GENERIC (
+    g_inferred   : BOOLEAN := FALSE;
+    g_adr_w      : NATURAL := 5;
+    g_dat_w      : NATURAL := 8;
+    g_nof_words  : NATURAL := 2**5;
+    g_rd_latency : NATURAL := 1;  -- choose 1 or 2
+    g_init_file  : STRING  := "none"
+  );
+  PORT
+  (
+    data      : IN  STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdaddress : IN  STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    rdclk     : IN  STD_LOGIC ;
+    wraddress : IN  STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    wrclk     : IN  STD_LOGIC  := '1';
+    wren      : IN  STD_LOGIC  := '0';
+    q         : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0)
+  );
+END ip_ultrascale_ram_cr_cw;
+
+
+ARCHITECTURE SYN OF ip_ultrascale_ram_cr_cw IS
+
+BEGIN
+
+  ASSERT g_rd_latency=1 OR g_rd_latency=2 REPORT "ip_ultrascale_ram_cr_cw : read latency must be 1 (default) or 2" SEVERITY FAILURE;
+  
+  ASSERT g_inferred=FALSE REPORT "ip_ultrascale_ram_crw_crw : cannot infer RAM" SEVERITY FAILURE;
+
+   -- xpm_memory_sdpram: Simple Dual Port RAM
+   -- Xilinx Parameterized Macro, version 2022.1
+   xpm_memory_sdpram_inst : xpm_memory_sdpram
+   generic map (
+      ADDR_WIDTH_A => g_adr_w,              -- DECIMAL
+      ADDR_WIDTH_B => g_adr_w,              -- DECIMAL
+      AUTO_SLEEP_TIME => 0,                 -- DECIMAL
+      BYTE_WRITE_WIDTH_A => 32,             -- DECIMAL
+      CASCADE_HEIGHT => 0,                  -- DECIMAL
+      CLOCKING_MODE => "independent_clock", -- String
+      ECC_MODE => "no_ecc",                 -- String
+      MEMORY_INIT_FILE => g_init_file,      -- String
+      MEMORY_INIT_PARAM => "0",             -- String
+      MEMORY_OPTIMIZATION => "true",        -- String
+      MEMORY_PRIMITIVE => "auto",           -- String
+      MEMORY_SIZE => g_nof_words,           -- DECIMAL
+      MESSAGE_CONTROL => 0,                 -- DECIMAL
+      READ_DATA_WIDTH_B => g_dat_w,         -- DECIMAL
+      READ_LATENCY_B => g_rd_latency,       -- DECIMAL
+      READ_RESET_VALUE_B => "0",            -- String
+      RST_MODE_A => "SYNC",                 -- String
+      RST_MODE_B => "SYNC",                 -- String
+      SIM_ASSERT_CHK => 0,                  -- DECIMAL; 0=disable simulation messages, 1=enable simulation messages
+      USE_EMBEDDED_CONSTRAINT => 0,         -- DECIMAL
+      USE_MEM_INIT => 1,                    -- DECIMAL
+      USE_MEM_INIT_MMI => 0,                -- DECIMAL
+      WAKEUP_TIME => "disable_sleep",       -- String
+      WRITE_DATA_WIDTH_A => g_dat_w,        -- DECIMAL
+      WRITE_MODE_B => "no_change",          -- String
+      WRITE_PROTECT => 1                    -- DECIMAL
+   )
+   port map (
+
+      dbiterrb => OPEN,                 -- 1-bit output: Status signal to indicate double bit error occurrence
+                                        -- on the data output of port A.
+
+      doutb => q,                       -- READ_DATA_WIDTH_B-bit output: Data output for port B read operations.
+
+      sbiterrb => OPEN,                 -- 1-bit output: Status signal to indicate single bit error occurrence
+                                        -- on the data output of port B.
+
+      addra => wraddress,               -- ADDR_WIDTH_A-bit input: Address for port A write and read operations.
+      addrb => rdaddress,               -- ADDR_WIDTH_B-bit input: Address for port B write and read operations.
+      clka => wrclk,                    -- 1-bit input: Clock signal for port A. Also clocks port B when
+                                        -- parameter CLOCKING_MODE is "common_clock".
+
+      clkb => rdclk,                    -- 1-bit input: Clock signal for port B when parameter CLOCKING_MODE is
+                                        -- "independent_clock". Unused when parameter CLOCKING_MODE is
+                                        -- "common_clock".
+
+      dina => data,                     -- WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
+      ena => '1',                       -- 1-bit input: Memory enable signal for port A. Must be high on clock
+                                        -- cycles when read or write operations are initiated. Pipelined
+                                        -- internally.
+
+      enb => '1',                       -- 1-bit input: Memory enable signal for port B. Must be high on clock
+                                        -- cycles when read or write operations are initiated. Pipelined
+                                        -- internally.
+                                              
+      injectdbiterra => '0',            -- 1-bit input: Controls double bit error injection on input data when
+                                        -- ECC enabled (Error injection capability is not available in
+                                        -- "decode_only" mode).
+
+      injectsbiterra => '0',            -- 1-bit input: Controls single bit error injection on input data when
+                                        -- ECC enabled (Error injection capability is not available in
+                                        -- "decode_only" mode).
+
+      regceb => '1',                    -- 1-bit input: Clock Enable for the last register stage on the output
+                                        -- data path.
+
+      rstb => '0',                      -- 1-bit input: Reset signal for the final port B output register
+                                        -- stage. Synchronously resets output port doutb to the value specified
+                                        -- by parameter READ_RESET_VALUE_B.
+
+      sleep => '0',                     -- 1-bit input: sleep signal to enable the dynamic power saving feature.
+
+      wea(0) => wren                    -- WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A-bit input: Write enable vector
+                                        -- for port A input data port dina. 1 bit wide when word-wide writes
+                                        -- are used. In byte-wide write configurations, each bit controls the
+                                        -- writing one byte of dina to address addra. For example, to
+                                        -- synchronously write only bits [15-8] of dina when WRITE_DATA_WIDTH_A
+                                        -- is 32, wea would be 4'b0010.
+
+   );
+
+   -- End of xpm_memory_sdpram_inst instantiation
+
+
+END SYN;
diff --git a/libraries/technology/ip_ultrascale/ram/ip_ultrascale_ram_crw_crw.vhd b/libraries/technology/ip_ultrascale/ram/ip_ultrascale_ram_crw_crw.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ae4ffdc7358e18cce1b75fc74204a3576e4935fd
--- /dev/null
+++ b/libraries/technology/ip_ultrascale/ram/ip_ultrascale_ram_crw_crw.vhd
@@ -0,0 +1,184 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright 2023
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- Licensed under the Apache License, Version 2.0 (the "License");
+-- you may not use this file except in compliance with the License.
+-- You may obtain a copy of the License at
+--
+--     http://www.apache.org/licenses/LICENSE-2.0
+--
+-- Unless required by applicable law or agreed to in writing, software
+-- distributed under the License is distributed on an "AS IS" BASIS,
+-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+-- See the License for the specific language governing permissions and
+-- limitations under the License.
+--
+-------------------------------------------------------------------------------
+-- Purpose: Instantiate RAM IP with generics
+-- Description:
+--   Copied component instantiation from Vivado XPM template
+
+LIBRARY ieee;
+USE ieee.std_logic_1164.all;
+USE ieee.numeric_std.all;
+  
+LIBRARY xpm;
+USE xpm.vcomponents.ALL;
+
+ENTITY ip_ultrascale_ram_crw_crw IS
+  GENERIC (
+    g_inferred   : BOOLEAN := FALSE;
+    g_adr_w      : NATURAL := 5;
+    g_dat_w      : NATURAL := 8;
+    g_nof_words  : NATURAL := 2**5;
+    g_rd_latency : NATURAL := 1;  -- choose 1 or 2
+    g_init_file  : STRING  := "none"
+  );
+  PORT
+  (
+    address_a : IN STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    address_b : IN STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    clk_a     : IN STD_LOGIC  := '1';
+    clk_b     : IN STD_LOGIC ;
+    data_a    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    data_b    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    wren_a    : IN STD_LOGIC  := '0';
+    wren_b    : IN STD_LOGIC  := '0';
+    q_a       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    q_b       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0)
+  );
+END ip_ultrascale_ram_crw_crw;
+
+
+ARCHITECTURE SYN OF ip_ultrascale_ram_crw_crw IS
+  
+BEGIN
+
+  ASSERT g_rd_latency=1 OR g_rd_latency=2  REPORT "ip_ultrascale_ram_crw_crw : read latency must be 1 (default) or 2" SEVERITY FAILURE;
+  ASSERT g_inferred=FALSE REPORT "ip_ultrascale_ram_crw_crw : cannot infer RAM" SEVERITY FAILURE;
+  
+   -- xpm_memory_tdpram: True Dual Port RAM
+   -- Xilinx Parameterized Macro, version 2022.1
+
+   xpm_memory_tdpram_inst : xpm_memory_tdpram
+   generic map (
+      ADDR_WIDTH_A => g_adr_w,               -- DECIMAL
+      ADDR_WIDTH_B => g_adr_w,               -- DECIMAL
+      AUTO_SLEEP_TIME => 0,            -- DECIMAL
+      BYTE_WRITE_WIDTH_A => g_dat_w,        -- DECIMAL
+      BYTE_WRITE_WIDTH_B => g_dat_w,        -- DECIMAL
+      CASCADE_HEIGHT => 0,             -- DECIMAL
+      CLOCKING_MODE => "independent_clock", -- String
+      ECC_MODE => "no_ecc",            -- String
+      MEMORY_INIT_FILE => g_init_file,      -- String
+      MEMORY_INIT_PARAM => "0",        -- String
+      MEMORY_OPTIMIZATION => "true",   -- String
+      MEMORY_PRIMITIVE => "block",      -- String
+      MEMORY_SIZE => g_nof_words,             -- DECIMAL
+      MESSAGE_CONTROL => 0,            -- DECIMAL
+      READ_DATA_WIDTH_A => g_dat_w,         -- DECIMAL
+      READ_DATA_WIDTH_B => g_dat_w,         -- DECIMAL
+      READ_LATENCY_A => g_rd_latency,   -- DECIMAL
+      READ_LATENCY_B => g_rd_latency,   -- DECIMAL
+      READ_RESET_VALUE_A => "0",       -- String
+      READ_RESET_VALUE_B => "0",       -- String
+      RST_MODE_A => "SYNC",            -- String
+      RST_MODE_B => "SYNC",            -- String
+      SIM_ASSERT_CHK => 0,             -- DECIMAL; 0=disable simulation messages, 1=enable simulation messages
+      USE_EMBEDDED_CONSTRAINT => 0,    -- DECIMAL
+      USE_MEM_INIT => 1,               -- DECIMAL
+      USE_MEM_INIT_MMI => 0,           -- DECIMAL
+      WAKEUP_TIME => "disable_sleep",  -- String
+      WRITE_DATA_WIDTH_A => g_dat_w,   -- DECIMAL
+      WRITE_DATA_WIDTH_B => g_dat_w,   -- DECIMAL
+      WRITE_MODE_A => "no_change",     -- String
+      WRITE_MODE_B => "no_change",     -- String
+      WRITE_PROTECT => 1               -- DECIMAL
+   )
+   port map (
+      dbiterra => OPEN,                 -- 1-bit output: Status signal to indicate double bit error occurrence
+                                        -- on the data output of port A.
+
+      dbiterrb => OPEN,                 -- 1-bit output: Status signal to indicate double bit error occurrence
+                                        -- on the data output of port A.
+
+      douta => q_a,                     -- READ_DATA_WIDTH_A-bit output: Data output for port A read operations.
+      doutb => q_b,                     -- READ_DATA_WIDTH_B-bit output: Data output for port B read operations.
+      sbiterra => OPEN,                 -- 1-bit output: Status signal to indicate single bit error occurrence
+                                        -- on the data output of port A.
+
+      sbiterrb => OPEN,                 -- 1-bit output: Status signal to indicate single bit error occurrence
+                                        -- on the data output of port B.
+
+      addra => address_a,               -- ADDR_WIDTH_A-bit input: Address for port A write and read operations.
+      addrb => address_b,               -- ADDR_WIDTH_B-bit input: Address for port B write and read operations.
+      clka => clk_a,                    -- 1-bit input: Clock signal for port A. Also clocks port B when
+                                        -- parameter CLOCKING_MODE is "common_clock".
+
+      clkb => clk_b,                    -- 1-bit input: Clock signal for port B when parameter CLOCKING_MODE is
+                                        -- "independent_clock". Unused when parameter CLOCKING_MODE is
+                                        -- "common_clock".
+
+      dina => data_a,                     -- WRITE_DATA_WIDTH_A-bit input: Data input for port A write operations.
+      dinb => data_b,                     -- WRITE_DATA_WIDTH_B-bit input: Data input for port B write operations.
+      ena => '1',                       -- 1-bit input: Memory enable signal for port A. Must be high on clock
+                                        -- cycles when read or write operations are initiated. Pipelined
+                                        -- internally.
+
+      enb => '1',                       -- 1-bit input: Memory enable signal for port B. Must be high on clock
+                                        -- cycles when read or write operations are initiated. Pipelined
+                                        -- internally.
+                                              
+      injectdbiterra => '0',            -- 1-bit input: Controls double bit error injection on input data when
+                                        -- ECC enabled (Error injection capability is not available in
+                                        -- "decode_only" mode).
+
+      injectdbiterrb => '0',            -- 1-bit input: Controls double bit error injection on input data when
+                                        -- ECC enabled (Error injection capability is not available in
+                                        -- "decode_only" mode).
+
+      injectsbiterra => '0',            -- 1-bit input: Controls single bit error injection on input data when
+                                        -- ECC enabled (Error injection capability is not available in
+                                        -- "decode_only" mode).
+
+      injectsbiterrb => '0',            -- 1-bit input: Controls single bit error injection on input data when
+                                        -- ECC enabled (Error injection capability is not available in
+                                        -- "decode_only" mode).
+
+      regcea => '1',                    -- 1-bit input: Clock Enable for the last register stage on the output
+                                        -- data path.
+
+      regceb => '1',                    -- 1-bit input: Clock Enable for the last register stage on the output
+                                        -- data path.
+
+      rsta => '0',                      -- 1-bit input: Reset signal for the final port A output register
+                                        -- stage. Synchronously resets output port douta to the value specified
+                                        -- by parameter READ_RESET_VALUE_A.
+
+      rstb => '0',                      -- 1-bit input: Reset signal for the final port B output register
+                                        -- stage. Synchronously resets output port doutb to the value specified
+                                        -- by parameter READ_RESET_VALUE_B.
+
+      sleep => '0',                     -- 1-bit input: sleep signal to enable the dynamic power saving feature.
+      wea(0) => wren_a,                       -- WRITE_DATA_WIDTH_A/BYTE_WRITE_WIDTH_A-bit input: Write enable vector
+                                        -- for port A input data port dina. 1 bit wide when word-wide writes
+                                        -- are used. In byte-wide write configurations, each bit controls the
+                                        -- writing one byte of dina to address addra. For example, to
+                                        -- synchronously write only bits [15-8] of dina when WRITE_DATA_WIDTH_A
+                                        -- is 32, wea would be 4'b0010.
+
+      web(0) => wren_a                        -- WRITE_DATA_WIDTH_B/BYTE_WRITE_WIDTH_B-bit input: Write enable vector
+                                        -- for port B input data port dinb. 1 bit wide when word-wide writes
+                                        -- are used. In byte-wide write configurations, each bit controls the
+                                        -- writing one byte of dinb to address addrb. For example, to
+                                        -- synchronously write only bits [15-8] of dinb when WRITE_DATA_WIDTH_B
+                                        -- is 32, web would be 4'b0010.
+
+   );
+
+   -- End of xpm_memory_tdpram_inst instantiation
+				
+END SYN;
diff --git a/libraries/technology/memory/hdllib.cfg b/libraries/technology/memory/hdllib.cfg
index 5aa87085c513250719d8033851aa05b327891ed3..03824a363bbc29eb63f0ed759b60007b6088ec50 100644
--- a/libraries/technology/memory/hdllib.cfg
+++ b/libraries/technology/memory/hdllib.cfg
@@ -1,6 +1,6 @@
 hdl_lib_name = tech_memory
 hdl_library_clause_name = tech_memory_lib
-hdl_lib_uses_synth = technology ip_stratixiv_ram ip_arria10_ram ip_arria10_e3sge3_ram ip_arria10_e1sg_ram ip_arria10_e2sg_ram
+hdl_lib_uses_synth = technology ip_stratixiv_ram ip_arria10_ram ip_arria10_e3sge3_ram ip_arria10_e1sg_ram ip_arria10_e2sg_ram ip_ultrascale_ram
 hdl_lib_uses_sim = 
 hdl_lib_technology = 
 hdl_lib_disclose_library_clause_names =
@@ -9,6 +9,7 @@ hdl_lib_disclose_library_clause_names =
     ip_arria10_e3sge3_ram ip_arria10_e3sge3_ram_lib
     ip_arria10_e1sg_ram   ip_arria10_e1sg_ram_lib
     ip_arria10_e2sg_ram   ip_arria10_e2sg_ram_lib
+    ip_ultrascale_ram     ip_ultrascale_ram_lib
 
 synth_files =
     tech_memory_component_pkg.vhd
diff --git a/libraries/technology/memory/tech_memory_component_pkg.vhd b/libraries/technology/memory/tech_memory_component_pkg.vhd
index d0c4b1ebcd5ef4580e3e94a0661e92aad6afa539..d2b73ad4c6fa22037e2458a67ada284e91b717c4 100644
--- a/libraries/technology/memory/tech_memory_component_pkg.vhd
+++ b/libraries/technology/memory/tech_memory_component_pkg.vhd
@@ -516,4 +516,52 @@ PACKAGE tech_memory_component_pkg IS
   );
   END COMPONENT;
 
+  -----------------------------------------------------------------------------
+  -- ip_ultrascale
+  -----------------------------------------------------------------------------
+  COMPONENT ip_ultrascale_ram_crw_crw IS
+  GENERIC (
+    g_inferred   : BOOLEAN := FALSE;
+    g_adr_w      : NATURAL := 5;
+    g_dat_w      : NATURAL := 8;
+    g_nof_words  : NATURAL := 2**5;
+    g_rd_latency : NATURAL := 1;  -- choose 1 or 2
+    g_init_file  : STRING  := "none"
+  );
+  PORT
+  (
+    address_a : IN STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    address_b : IN STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    clk_a     : IN STD_LOGIC  := '1';
+    clk_b     : IN STD_LOGIC ;
+    data_a    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    data_b    : IN STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    wren_a    : IN STD_LOGIC  := '0';
+    wren_b    : IN STD_LOGIC  := '0';
+    q_a       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    q_b       : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0)
+  );
+  END COMPONENT;
+    
+  COMPONENT ip_ultrascale_ram_cr_cw IS
+  GENERIC (
+    g_inferred   : BOOLEAN := FALSE;
+    g_adr_w      : NATURAL := 5;
+    g_dat_w      : NATURAL := 8;
+    g_nof_words  : NATURAL := 2**5;
+    g_rd_latency : NATURAL := 1;  -- choose 1 or 2
+    g_init_file  : STRING  := "none"
+  );
+  PORT
+  (
+    data      : IN  STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0);
+    rdaddress : IN  STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    rdclk     : IN  STD_LOGIC ;
+    wraddress : IN  STD_LOGIC_VECTOR (g_adr_w-1 DOWNTO 0);
+    wrclk     : IN  STD_LOGIC  := '1';
+    wren      : IN  STD_LOGIC  := '0';
+    q         : OUT STD_LOGIC_VECTOR (g_dat_w-1 DOWNTO 0)
+  );
+  END COMPONENT;
+
 END tech_memory_component_pkg;
diff --git a/libraries/technology/memory/tech_memory_ram_cr_cw.vhd b/libraries/technology/memory/tech_memory_ram_cr_cw.vhd
index 9e0131c566d1f811f904c35f058f2a00baab86ab..ba85238ef3257ee8435a38099043eda4755a7615 100644
--- a/libraries/technology/memory/tech_memory_ram_cr_cw.vhd
+++ b/libraries/technology/memory/tech_memory_ram_cr_cw.vhd
@@ -31,6 +31,7 @@ LIBRARY ip_arria10_ram_lib;
 LIBRARY ip_arria10_e3sge3_ram_lib;
 LIBRARY ip_arria10_e1sg_ram_lib;
 LIBRARY ip_arria10_e2sg_ram_lib;
+LIBRARY ip_ultrascale_ram_lib;
 
 ENTITY tech_memory_ram_cr_cw IS
   GENERIC (
@@ -87,5 +88,11 @@ BEGIN
     GENERIC MAP (FALSE, g_adr_w, g_dat_w, g_nof_words, g_rd_latency, g_init_file)
     PORT MAP (data, rdaddress, rdclock, wraddress, wrclock, wren, q);
   END GENERATE;
-  
+ 
+  gen_ip_ultrascale : IF g_technology=c_tech_ultrascale GENERATE
+    u0 : ip_ultrascale_ram_cr_cw
+    GENERIC MAP (FALSE, g_adr_w, g_dat_w, g_nof_words, g_rd_latency, g_init_file)
+    PORT MAP (data, rdaddress, rdclock, wraddress, wrclock, wren, q);
+  END GENERATE; 
+
 END ARCHITECTURE;
diff --git a/libraries/technology/memory/tech_memory_ram_crw_crw.vhd b/libraries/technology/memory/tech_memory_ram_crw_crw.vhd
index 7421d579f9cac7a909b2fb05d8493a450afba66c..453147931d35006a4609a72fc1cc5d4b5e0be25d 100644
--- a/libraries/technology/memory/tech_memory_ram_crw_crw.vhd
+++ b/libraries/technology/memory/tech_memory_ram_crw_crw.vhd
@@ -31,6 +31,7 @@ LIBRARY ip_arria10_ram_lib;
 LIBRARY ip_arria10_e3sge3_ram_lib;
 LIBRARY ip_arria10_e1sg_ram_lib;
 LIBRARY ip_arria10_e2sg_ram_lib;
+LIBRARY ip_ultrascale_ram_lib;
 
 ENTITY tech_memory_ram_crw_crw IS
   GENERIC (
@@ -94,5 +95,12 @@ BEGIN
     GENERIC MAP (FALSE, g_adr_w, g_dat_w, g_nof_words, g_rd_latency, g_init_file)
     PORT MAP (address_a, address_b, clock_a, clock_b, data_a, data_b, wren_a, wren_b, q_a, q_b);
   END GENERATE;
+
+  gen_ip_ultrascale : IF g_technology=c_tech_ultrascale GENERATE
+    u0 : ip_ultrascale_ram_crw_crw
+    GENERIC MAP (FALSE, g_adr_w, g_dat_w, g_nof_words, g_rd_latency, g_init_file)
+    PORT MAP (address_a, address_b, clock_a, clock_b, data_a, data_b, wren_a, wren_b, q_a, q_b);
+  END GENERATE;
+
  
 END ARCHITECTURE;
diff --git a/libraries/technology/technology_pkg.vhd b/libraries/technology/technology_pkg.vhd
index f913ccfbf032850f4149b1b12cad8acc214fab7d..b9c88a24f8aa0100c43a1cafefb730f9fc382869 100644
--- a/libraries/technology/technology_pkg.vhd
+++ b/libraries/technology/technology_pkg.vhd
@@ -49,7 +49,8 @@ PACKAGE technology_pkg IS
   CONSTANT c_tech_arria10_e3sge3     : INTEGER := 6;   -- e.g. used on UniBoard2 second run (7 boards version "01" dec 2015)
   CONSTANT c_tech_arria10_e1sg       : INTEGER := 7;   -- e.g. used on UniBoard2b third run (5 ARTS boards version "01" feb 2017)
   CONSTANT c_tech_arria10_e2sg       : INTEGER := 8;   -- e.g. used on UniBoard2c (2 LOFAR2.0 SDP boards version "11" f 2021)
-  CONSTANT c_tech_nof_technologies   : INTEGER := 9;
+  CONSTANT c_tech_ultrascale         : INTEGER := 9;   -- e.g. used on Alveo FPGA platforms
+  CONSTANT c_tech_nof_technologies   : INTEGER := 10;
 
   -- Functions
   FUNCTION tech_sel_a_b(sel : BOOLEAN; a, b : STRING)  RETURN STRING;