diff --git a/boards/uniboard2c/libraries/unb2c_board/hdllib.cfg b/boards/uniboard2c/libraries/unb2c_board/hdllib.cfg
index 2c8c0275e1c60cd36b8fe99c65faeb1023bafd95..15a5c8eafcbc7a61794252995bb5da8dfaee29a7 100644
--- a/boards/uniboard2c/libraries/unb2c_board/hdllib.cfg
+++ b/boards/uniboard2c/libraries/unb2c_board/hdllib.cfg
@@ -1,7 +1,7 @@
 hdl_lib_name = unb2c_board
 hdl_library_clause_name = unb2c_board_lib
 hdl_lib_uses_synth = common dp ppsh i2c eth remu technology tech_clkbuf tech_pll tech_fractional_pll epcs fpga_sense
-hdl_lib_uses_sim = 
+hdl_lib_uses_sim =
 hdl_lib_technology = ip_arria10_e2sg
 hdl_lib_include_ip = ip_arria10_e2sg_tse_sgmii_lvds
                      ip_arria10_e2sg_clkbuf_global
@@ -23,18 +23,20 @@ synth_files =
     src/vhdl/mms_unb2c_fpga_sens.vhd
     src/vhdl/unb2c_board_wdi_reg.vhd
     src/vhdl/unb2c_board_qsfp_leds.vhd
+    src/vhdl/unb2c_board_qsfp_leds_v2.vhd
     src/vhdl/ctrl_unb2c_board.vhd
     src/vhdl/unb2c_board_front_io.vhd
     src/vhdl/unb2c_board_back_io.vhd
     src/vhdl/unb2c_board_ring_io.vhd
     src/vhdl/unb2c_board_peripherals_pkg.vhd
-    
-test_bench_files = 
+
+test_bench_files =
     tb/vhdl/tb_unb2c_board_clk200_pll.vhd
     tb/vhdl/tb_unb2c_board_clk25_pll.vhd
     tb/vhdl/tb_unb2c_board_node_ctrl.vhd
     tb/vhdl/tb_unb2c_board_qsfp_leds.vhd
-    
+    tb/vhdl/tb_unb2c_board_qsfp_leds_v2.vhd
+
 
 [modelsim_project_file]
 
diff --git a/boards/uniboard2c/libraries/unb2c_board/src/vhdl/unb2c_board_qsfp_leds_v2.vhd b/boards/uniboard2c/libraries/unb2c_board/src/vhdl/unb2c_board_qsfp_leds_v2.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..81a8010a008919ad437063f36ce9f23558788c03
--- /dev/null
+++ b/boards/uniboard2c/libraries/unb2c_board/src/vhdl/unb2c_board_qsfp_leds_v2.vhd
@@ -0,0 +1,222 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2024
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-------------------------------------------------------------------------------
+-- Author: E. Kooistra
+-- Purpose: Provide visual activity information via the UniBoard2 front panel QSFP LEDs.
+-- Description:
+--   The testio LED on UniBoard2 is not visible via the front panel. The
+--   front panel does have a dual colour LED for each QSFP lane. Therefore
+--   these QSFP LEDs are used to signal some application information and lane
+--   status/activity information.
+--
+--   Comparison unb2c_board_qsfp_leds_v2 and unb2c_board_qsfp_leds:
+--   . unb2c_board_qsfp_leds_v2 does not output the internal us, ms and s pulses,
+--     because they depend on the clock domain and are typically left open with
+--     unb2c_board_qsfp_leds
+--   . For g_factory_image = false the unb2c_board_qsfp_leds_v2 = unb2c_board_qsfp_leds
+--     except use dp_clk to detect the transceiver activity strobes.
+--   . For g_factory_image = true unb2c_board_qsfp_leds_v2 also shows status of dp_clk,
+--     dp_pps, and ddr_I_cal_ok, ddr_II_cal_ok
+--
+--   LED lights:
+--
+--   1) Default behaviour for all QSFP leds:
+--      . off = no FPGA image is running
+--
+--   2) For factory image only use the red leds:
+--      . green off
+--      . red[0] on = factory image is running (g_factory_image=true)
+--               off = no image is running
+--      . red[1] toggling every 1 s = 125 MHz clock present (= mm_clk = clk)
+--      . red[2] toggling every 1 s = pps present (= dp_pps)
+--      . red[3] toggling every 1 s = 200 MHz clock present (= dp_clk)
+--      . red[4] on = DDR4 bank I calibrated = ctlr_tech_miso.done in io_ddr
+--               off = not calibrated or no DDR4 module present
+--      . red[5] on = DDR4 bank II calibrated = ctlr_tech_miso.done in io_ddr
+--               off = not calibrated or no DDR4 module present
+--
+--   3) For a user image only use green leds:
+--      . red off
+--
+--      a) without Gbps lane functionality:
+--      . green toggling every 1 s = user image is running (g_factory_image=FALSE and green_on_arr(I)='0' default)
+--
+--      b) with Gbps lane functionality:
+--      . green toggling every 1 s when the lane status is not OK (green_on_arr(I)=xon='0')
+--      . green on continously when the lane status is OK (green_on_arr(I)=xon='1')
+--      . green led goes off briefly off when there is an Tx or Rx packet (green_evt_arr(I).sop='1')
+--
+--   The combined colour amber (= red + green) is not used. The factory image
+--   only uses the red led and the user image only uses the green led.
+--
+--   Each QSFP carries c_quad = 4 lanes, therefore the green led LED can only
+--   signal a combined status of the lanes. The combined status eg. be:
+--
+--     'and-status' = combined status is on when all lanes are on
+--     'or-status'  = combined status is on when at least 1 lane is on
+--
+--   Choose using 'or-status', because then the LED can give lane status
+--   information when less than all 4 lane are connected.
+--
+library IEEE, common_lib, dp_lib;
+use IEEE.std_logic_1164.all;
+use common_lib.common_pkg.all;
+use dp_lib.dp_stream_pkg.all;
+
+entity unb2c_board_qsfp_leds_v2 is
+  generic (
+    g_sim             : boolean := false;  -- when true speed up led toggling in simulation
+    g_factory_image   : boolean := false;  -- distinguish factory image and user images
+    g_nof_qsfp        : natural := 6;  -- number of QSFP cages each with one dual led that can light red or green (or amber = red + green)
+    g_mm_pulse_us     : natural := 125;  -- nof mm_clk cycles to get us period
+    g_dp_pulse_us     : natural := 200  -- nof dp_clk cycles to get us period
+  );
+  port (
+    mm_rst            : in  std_logic;
+    mm_clk            : in  std_logic;
+    dp_rst            : in  std_logic := '0';
+    dp_clk            : in  std_logic := '0';
+    dp_pps            : in  std_logic := '0';
+    -- ddr status (level signals)
+    ddr_I_cal_ok      : in std_logic := '0';
+    ddr_II_cal_ok     : in std_logic := '0';
+    -- lane status (sop strobe signals in dp_clk domain)
+    tx_siso_arr       : in  t_dp_siso_arr(g_nof_qsfp * c_quad - 1 downto 0) := (others => c_dp_siso_rst);
+    tx_sosi_arr       : in  t_dp_sosi_arr(g_nof_qsfp * c_quad - 1 downto 0) := (others => c_dp_sosi_rst);
+    rx_sosi_arr       : in  t_dp_sosi_arr(g_nof_qsfp * c_quad - 1 downto 0) := (others => c_dp_sosi_rst);
+    -- leds
+    green_led_arr     : out std_logic_vector(g_nof_qsfp - 1 downto 0);
+    red_led_arr       : out std_logic_vector(g_nof_qsfp - 1 downto 0)
+  );
+end unb2c_board_qsfp_leds_v2;
+
+architecture str of unb2c_board_qsfp_leds_v2 is
+  constant c_nof_ms         : natural := sel_a_b(g_sim, 1, 100);  -- force off for c_nof_ms and then on for at least c_nof_ms
+  constant c_nof_lanes      : natural := g_nof_qsfp * c_quad;  -- number of transceiver lanes, fixed 4 per Quad-SFP cage
+
+  -- internal pulses
+  signal mm_pulse_s         : std_logic;  -- pulse 1 mm_clk cycle every 1 s
+  signal mm_toggle_s        : std_logic;  -- toggle every 1 s in mm_clk domain
+
+  signal dp_pulse_ms        : std_logic;  -- pulse 1 dp_clk cycle every 1 ms
+  signal dp_pulse_s         : std_logic;  -- pulse 1 dp_clk cycle every 1 us
+  signal dp_toggle_s        : std_logic;  -- toggle every 1 s in dp_clk domain
+
+  signal dp_toggle_pps      : std_logic;  -- pulse 1 dp_clk cycle every 1 s
+
+  signal green_on_arr       : std_logic_vector(g_nof_qsfp * c_quad - 1 downto 0);
+  signal green_evt_arr      : std_logic_vector(g_nof_qsfp * c_quad - 1 downto 0);
+
+  signal qsfp_on_arr        : std_logic_vector(g_nof_qsfp - 1 downto 0);
+  signal qsfp_evt_arr       : std_logic_vector(g_nof_qsfp - 1 downto 0);
+begin
+  -- mm_clk domain pulsers
+  u_mm_common_pulser_us_ms_s : entity common_lib.common_pulser_us_ms_s
+  generic map (
+    g_pulse_us  => g_mm_pulse_us,  -- nof mm_clk cycles to get us period
+    g_pulse_ms  => sel_a_b(g_sim, 10, 1000),  -- nof pulse_us pulses to get ms period
+    g_pulse_s   => sel_a_b(g_sim, 10, 1000)  -- nof pulse_ms pulses to get s period
+  )
+  port map (
+    rst         => mm_rst,
+    clk         => mm_clk,
+    pulse_s     => mm_pulse_s
+  );
+
+  u_mm_common_toggle_s : entity common_lib.common_toggle
+  port map (
+    rst         => mm_rst,
+    clk         => mm_clk,
+    in_dat      => mm_pulse_s,
+    out_dat     => mm_toggle_s
+  );
+
+  -- dp_clk domain pulsers
+  u_dp_common_pulser_us_ms_s : entity common_lib.common_pulser_us_ms_s
+  generic map (
+    g_pulse_us  => g_dp_pulse_us,  -- nof dp_clk cycles to get us period
+    g_pulse_ms  => sel_a_b(g_sim, 10, 1000),  -- nof pulse_us pulses to get ms period
+    g_pulse_s   => sel_a_b(g_sim, 10, 1000)  -- nof pulse_ms pulses to get s period
+  )
+  port map (
+    rst         => dp_rst,
+    clk         => dp_clk,
+    pulse_ms    => dp_pulse_ms,
+    pulse_s     => dp_pulse_s
+  );
+
+  u_dp_common_toggle_s : entity common_lib.common_toggle
+  port map (
+    rst         => dp_rst,
+    clk         => dp_clk,
+    in_dat      => dp_pulse_s,
+    out_dat     => dp_toggle_s
+  );
+
+  gen_factory_image : if g_factory_image = true generate
+    green_led_arr <= (others => '0');
+
+    red_led_arr(0) <= '1';
+    red_led_arr(1) <= mm_toggle_s;
+    red_led_arr(2) <= dp_toggle_pps;
+    red_led_arr(3) <= dp_toggle_s;
+    red_led_arr(4) <= ddr_I_cal_ok;
+    red_led_arr(5) <= ddr_II_cal_ok;
+
+    u_dp_common_toggle_pps : entity common_lib.common_toggle
+    port map (
+      rst         => dp_rst,
+      clk         => dp_clk,
+      in_dat      => dp_pps,
+      out_dat     => dp_toggle_pps
+    );
+  end generate;
+
+  gen_user_image : if g_factory_image = false generate
+    red_led_arr <= (others => '0');
+
+    gen_green_ctrl_arr : for I in c_nof_lanes - 1 downto 0 generate
+      green_on_arr(I)  <= tx_siso_arr(I).xon                       when rising_edge(dp_clk);
+      green_evt_arr(I) <= tx_sosi_arr(I).sop or rx_sosi_arr(I).sop when rising_edge(dp_clk);
+    end generate;
+
+    gen_green_led_arr : for I in g_nof_qsfp - 1 downto 0 generate
+      qsfp_on_arr(I)  <= orv(green_on_arr( (I + 1) * c_quad - 1 downto + I * c_quad));
+      qsfp_evt_arr(I) <= orv(green_evt_arr((I + 1) * c_quad - 1 downto + I * c_quad));
+
+      u_green_led_controller : entity common_lib.common_led_controller
+      generic map (
+        g_nof_ms      => c_nof_ms
+      )
+      port map (
+        rst           => dp_rst,
+        clk           => dp_clk,
+        pulse_ms      => dp_pulse_ms,
+        -- led control
+        ctrl_on       => qsfp_on_arr(I),
+        ctrl_evt      => qsfp_evt_arr(I),
+        ctrl_input    => dp_toggle_s,
+        -- led output
+        led           => green_led_arr(I)
+      );
+    end generate;
+  end generate;
+end str;
diff --git a/boards/uniboard2c/libraries/unb2c_board/tb/vhdl/tb_unb2c_board_qsfp_leds_v2.vhd b/boards/uniboard2c/libraries/unb2c_board/tb/vhdl/tb_unb2c_board_qsfp_leds_v2.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..3f63e429586530a8e7ee0a6495a455168dc33cf0
--- /dev/null
+++ b/boards/uniboard2c/libraries/unb2c_board/tb/vhdl/tb_unb2c_board_qsfp_leds_v2.vhd
@@ -0,0 +1,210 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2024
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.nl/>
+-- JIVE (Joint Institute for VLBI in Europe) <http://www.jive.nl/>
+-- P.O.Box 2, 7990 AA Dwingeloo, The Netherlands
+--
+-- This program is free software: you can redistribute it and/or modify
+-- it under the terms of the GNU General Public License as published by
+-- the Free Software Foundation, either version 3 of the License, or
+-- (at your option) any later version.
+--
+-- This program is distributed in the hope that it will be useful,
+-- but WITHOUT ANY WARRANTY; without even the implied warranty of
+-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+-- GNU General Public License for more details.
+--
+-- You should have received a copy of the GNU General Public License
+-- along with this program.  If not, see <http://www.gnu.org/licenses/>.
+--
+-------------------------------------------------------------------------------
+-- Author: E. Kooistra
+-- Purpose: Test bench for unb2c_board_qsfp_leds
+-- Description:
+--   The test bench is self-stopping but not self-checking. Manually obeserve
+--   in the wave window that:
+--   1) factory image:
+--      - green led is off
+--      - red led toggles
+--   2) user image
+--      - red led is off
+--      - green led toggles when any xon='0'
+--      - green led is on continously when any xon='1'
+--      - green led goes briefly off when any sop='1'
+-- Usage:
+--   > as 3
+--   > run -a
+
+library IEEE, common_lib, dp_lib;
+use IEEE.std_logic_1164.all;
+use common_lib.common_pkg.all;
+use common_lib.tb_common_pkg.all;
+use dp_lib.dp_stream_pkg.all;
+
+entity tb_unb2c_board_qsfp_leds_v2 is
+end tb_unb2c_board_qsfp_leds_v2;
+
+architecture tb of tb_unb2c_board_qsfp_leds_v2 is
+  constant c_sim_factor        : natural := 100;  -- same as in unb2c_board_qsfp_leds_v2.vhd
+
+  constant c_mm_clk_freq_hz    : natural := 125 * 10**6;
+  constant c_mm_clk_period_ns  : natural := 10**9 / c_mm_clk_freq_hz;
+  constant c_nof_mm_clk_per_us : natural := 1000 / c_mm_clk_period_ns;
+
+  constant c_dp_clk_freq_hz    : natural := 125 * 10**6;
+  constant c_dp_clk_period_ns  : natural := 10**9 / c_dp_clk_freq_hz;
+  constant c_nof_dp_clk_per_us : natural := 1000 / c_dp_clk_period_ns;
+
+  constant mm_clk_period       : time := c_mm_clk_period_ns * 1 ns;
+  constant dp_clk_period       : time := c_dp_clk_period_ns * 1 ns;
+
+  constant c_nof_qsfp       : natural := 6;
+  constant c_nof_lanes      : natural := c_nof_qsfp * c_quad;
+
+  signal tb_end                  : std_logic := '0';
+  signal mm_rst                  : std_logic := '1';
+  signal mm_clk                  : std_logic := '0';
+  signal mm_pulse_ms             : std_logic := '0';
+  signal dp_rst                  : std_logic := '1';
+  signal dp_clk                  : std_logic := '0';
+  signal dp_pps                  : std_logic := '0';
+
+  signal ddr_I_cal_ok            : std_logic := '0';
+  signal ddr_II_cal_ok           : std_logic := '0';
+
+  signal tx_siso_arr             : t_dp_siso_arr(c_nof_lanes - 1 downto 0) := (others => c_dp_siso_rst);
+  signal tx_sosi_arr             : t_dp_sosi_arr(c_nof_lanes - 1 downto 0) := (others => c_dp_sosi_rst);
+  signal rx_sosi_arr             : t_dp_sosi_arr(c_nof_lanes - 1 downto 0) := (others => c_dp_sosi_rst);
+
+  signal dbg_xon_arr             : std_logic_vector(c_nof_lanes - 1 downto 0);
+  signal dbg_tx_sop_arr          : std_logic_vector(c_nof_lanes - 1 downto 0);
+  signal dbg_rx_sop_arr          : std_logic_vector(c_nof_lanes - 1 downto 0);
+
+  signal factory_green_led_arr   : std_logic_vector(c_nof_qsfp - 1 downto 0);
+  signal factory_red_led_arr     : std_logic_vector(c_nof_qsfp - 1 downto 0);
+
+  signal user_green_led_arr      : std_logic_vector(c_nof_qsfp - 1 downto 0);
+  signal user_red_led_arr        : std_logic_vector(c_nof_qsfp - 1 downto 0);
+
+  -- Cannot use proc_common_gen_pulse() to create sop in array.
+  -- proc_common_gen_pulse() works for dbg_sop, dbg_sosi.sop but not for dbg_sop_slv(I) or for tx_sosi_arr(I).sop.
+  -- The compiler then gives Error: "(vcom-1450) Actual (indexed name) for formal "pulse" is not a static signal name"
+  -- It does work if the array index is from a GENERATE statement, but it does not work when it is from a LOOP statement.
+  signal dbg_sop      : std_logic;
+  signal dbg_sop_slv  : std_logic_vector(c_nof_lanes - 1 downto 0);
+  signal dbg_sosi : t_dp_sosi;
+begin
+  mm_clk <= not mm_clk or tb_end after mm_clk_period / 2;
+  mm_rst <= '1', '0' after mm_clk_period * 7;
+  dp_clk <= not dp_clk or tb_end after dp_clk_period / 2;
+  dp_rst <= '1', '0' after dp_clk_period * 7;
+
+  proc_common_gen_pulse(1, (c_nof_mm_clk_per_us * 10**3) / c_sim_factor, '1', mm_rst, mm_clk, mm_pulse_ms);
+  proc_common_gen_pulse(1, (c_nof_dp_clk_per_us * 10**6) / c_sim_factor**2, '1', dp_rst, dp_clk, dp_pps);
+
+  -- Ease observation of record fields in Wave window, by mapping them to a SLV
+  dbg_xon_arr    <= func_dp_stream_arr_get(tx_siso_arr, "XON");
+  dbg_tx_sop_arr <= func_dp_stream_arr_get(tx_sosi_arr, "SOP");
+  dbg_rx_sop_arr <= func_dp_stream_arr_get(rx_sosi_arr, "SOP");
+
+  p_stimuli : process
+  begin
+    tx_siso_arr <= (others => c_dp_siso_rst);
+    tx_sosi_arr <= (others => c_dp_sosi_rst);
+    rx_sosi_arr <= (others => c_dp_sosi_rst);
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
+
+    -- Toggle ddr calibration status
+    ddr_I_cal_ok <= '1';
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 5);
+    ddr_II_cal_ok <= '1';
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
+    ddr_I_cal_ok <= '0';
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 5);
+    ddr_II_cal_ok <= '0';
+
+    -- Switch on each lane
+    for I in 0 to c_nof_lanes - 1 loop
+      tx_siso_arr(I).xon <= '1';
+      proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
+    end loop;
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
+
+    -- Issue the sop of a Tx packet on each lane
+    for I in 0 to c_nof_lanes - 1 loop
+      -- Cannot use proc_common_gen_pulse(), because index I in a LOOP is not static
+      tx_sosi_arr(I).sop <= '1';
+      wait until rising_edge(mm_clk);
+      tx_sosi_arr(I).sop <= '0';
+      proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
+    end loop;
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
+
+    -- Issue the sop of an Rx packet on each lane
+    for I in 0 to c_nof_lanes - 1 loop
+      -- Cannot use proc_common_gen_pulse(), because index I in a LOOP is not static
+      rx_sosi_arr(I).sop <= '1';
+      wait until rising_edge(mm_clk);
+      rx_sosi_arr(I).sop <= '0';
+      proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
+    end loop;
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
+
+    -- Switch off each lane
+    for I in 0 to c_nof_lanes - 1 loop
+      tx_siso_arr(I).xon <= '0';
+      proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
+    end loop;
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 50);
+
+    tb_end <= '1';
+    proc_common_wait_some_pulses(mm_clk, mm_pulse_ms, 10);
+    wait;
+  end process;
+
+  u_unb2c_factory_qsfp_leds_v2 : entity work.unb2c_board_qsfp_leds_v2
+  generic map (
+    g_sim             => true,  -- when true speed up led toggling in simulation
+    g_factory_image   => true,  -- distinguish factory image and user images
+    g_nof_qsfp        => c_nof_qsfp,  -- number of QSFP cages each with one dual led that can light red or green (or amber = red + green)
+    g_mm_pulse_us     => c_nof_mm_clk_per_us,  -- nof mm_clk cycles to get us period<
+    g_dp_pulse_us     => c_nof_dp_clk_per_us   -- nof dp_clk cycles to get us period<
+  )
+  port map (
+    mm_rst            => mm_rst,
+    mm_clk            => mm_clk,
+    dp_rst            => dp_rst,
+    dp_clk            => dp_clk,
+    dp_pps            => dp_pps,
+    -- ddr status
+    ddr_I_cal_ok      => ddr_I_cal_ok,
+    ddr_II_cal_ok     => ddr_II_cal_ok,
+    -- leds
+    green_led_arr     => factory_green_led_arr,
+    red_led_arr       => factory_red_led_arr
+  );
+
+  u_unb2c_user_qsfp_leds_v2 : entity work.unb2c_board_qsfp_leds_v2
+  generic map (
+    g_sim             => true,  -- when true speed up led toggling in simulation
+    g_factory_image   => false,  -- distinguish factory image and user images
+    g_nof_qsfp        => c_nof_qsfp,  -- number of QSFP cages each with one dual led that can light red or green (or amber = red + green)
+    g_mm_pulse_us     => c_nof_mm_clk_per_us,  -- nof mm_clk cycles to get us period<
+    g_dp_pulse_us     => c_nof_dp_clk_per_us   -- nof dp_clk cycles to get us period<
+  )
+  port map (
+    mm_rst            => mm_rst,
+    mm_clk            => mm_clk,
+    dp_rst            => dp_rst,
+    dp_clk            => dp_clk,
+    dp_pps            => dp_pps,
+    -- lane status
+    tx_siso_arr       => tx_siso_arr,
+    tx_sosi_arr       => tx_sosi_arr,
+    rx_sosi_arr       => rx_sosi_arr,
+    -- leds
+    green_led_arr     => user_green_led_arr,
+    red_led_arr       => user_red_led_arr
+  );
+end tb;