diff --git a/boards/uniboard2b/libraries/unb2b_board/hdllib.cfg b/boards/uniboard2b/libraries/unb2b_board/hdllib.cfg
index 9e2592071927a866e7dd3e4d2a7c0d5b50410399..eeaa49ec3fb83c933044102a5f2bdec5a8746057 100644
--- a/boards/uniboard2b/libraries/unb2b_board/hdllib.cfg
+++ b/boards/uniboard2b/libraries/unb2b_board/hdllib.cfg
@@ -12,38 +12,38 @@ hdl_lib_include_ip = ip_arria10_e1sg_tse_sgmii_lvds
                      #ip_arria10_e1sg_pll_clk125
 
 synth_files =
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_pkg.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_system_info.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_system_info_reg.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/mms_unb2_board_system_info.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_clk200_pll.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_clk25_pll.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_clk125_pll.vhd
-#    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_clk200mm_pll.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_wdi_extend.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_node_ctrl.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_pmbus_ctrl.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_sens_ctrl.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_hmc_ctrl.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_sens.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_sens_reg.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_fpga_sens_reg.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/mms_unb2_board_sens.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/mms_unb2_fpga_sens.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_wdi_reg.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_qsfp_leds.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/ctrl_unb2_board.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_front_io.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_back_io.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_ring_io.vhd
-    ../../../uniboard2a/libraries/unb2a_board/src/vhdl/unb2_board_peripherals_pkg.vhd
+    src/vhdl/unb2_board_pkg.vhd
+    src/vhdl/unb2_board_system_info.vhd
+    src/vhdl/unb2_board_system_info_reg.vhd
+    src/vhdl/mms_unb2_board_system_info.vhd
+    src/vhdl/unb2_board_clk200_pll.vhd
+    src/vhdl/unb2_board_clk25_pll.vhd
+    src/vhdl/unb2_board_clk125_pll.vhd
+#    src/vhdl/unb2_board_clk200mm_pll.vhd
+    src/vhdl/unb2_board_wdi_extend.vhd
+    src/vhdl/unb2_board_node_ctrl.vhd
+    src/vhdl/unb2_board_pmbus_ctrl.vhd
+    src/vhdl/unb2_board_sens_ctrl.vhd
+    src/vhdl/unb2_board_hmc_ctrl.vhd
+    src/vhdl/unb2_board_sens.vhd
+    src/vhdl/unb2_board_sens_reg.vhd
+    src/vhdl/unb2_fpga_sens_reg.vhd
+    src/vhdl/mms_unb2_board_sens.vhd
+    src/vhdl/mms_unb2_fpga_sens.vhd
+    src/vhdl/unb2_board_wdi_reg.vhd
+    src/vhdl/unb2_board_qsfp_leds.vhd
+    src/vhdl/ctrl_unb2_board.vhd
+    src/vhdl/unb2_board_front_io.vhd
+    src/vhdl/unb2_board_back_io.vhd
+    src/vhdl/unb2_board_ring_io.vhd
+    src/vhdl/unb2_board_peripherals_pkg.vhd
     
 test_bench_files = 
-    ../../../uniboard2a/libraries/unb2a_board/tb/vhdl/tb_mms_unb2_board_sens.vhd
-    ../../../uniboard2a/libraries/unb2a_board/tb/vhdl/tb_unb2_board_clk200_pll.vhd
-    ../../../uniboard2a/libraries/unb2a_board/tb/vhdl/tb_unb2_board_clk25_pll.vhd
-    ../../../uniboard2a/libraries/unb2a_board/tb/vhdl/tb_unb2_board_node_ctrl.vhd
-    ../../../uniboard2a/libraries/unb2a_board/tb/vhdl/tb_unb2_board_qsfp_leds.vhd
+    tb/vhdl/tb_mms_unb2_board_sens.vhd
+    tb/vhdl/tb_unb2_board_clk200_pll.vhd
+    tb/vhdl/tb_unb2_board_clk25_pll.vhd
+    tb/vhdl/tb_unb2_board_node_ctrl.vhd
+    tb/vhdl/tb_unb2_board_qsfp_leds.vhd
     
 
 [modelsim_project_file]
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/ctrl_unb2_board.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/ctrl_unb2_board.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..4e76c651b8c47229d1b54c9e9320893d9d23b592
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/ctrl_unb2_board.vhd
@@ -0,0 +1,819 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Provide general control infrastructure
+-- Usage: In a design <design_name>.vhd that consists of:
+--   . mmm_<design_name>.vhd with a Nios2 and the MM bus and the peripherals
+--   . ctrl_unb2_board.vhd with e.g. 1GbE, PPS, I2C, Remu, EPCS
+
+LIBRARY IEEE, common_lib, dp_lib, ppsh_lib, i2c_lib, technology_lib, tech_tse_lib, eth_lib, remu_lib, epcs_lib, tech_pll_lib, tech_clkbuf_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+USE work.unb2_board_pkg.ALL;
+USE i2c_lib.i2c_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+USE tech_tse_lib.tech_tse_pkg.ALL;
+USE eth_lib.eth_pkg.ALL;
+
+ENTITY ctrl_unb2_board IS
+  GENERIC (
+    ----------------------------------------------------------------------------
+    -- General
+    ----------------------------------------------------------------------------
+    g_technology     : NATURAL := c_tech_arria10;
+    g_sim            : BOOLEAN := FALSE;
+    g_design_name    : STRING := "UNUSED";
+    g_fw_version     : t_unb2_board_fw_version := (0, 0);  -- firmware version x.y
+    g_stamp_date     : NATURAL := 0;
+    g_stamp_time     : NATURAL := 0;
+    g_stamp_svn      : NATURAL := 0;
+    g_design_note    : STRING  := "UNUSED";
+    g_base_ip        : STD_LOGIC_VECTOR(16-1 DOWNTO 0) := X"0A63"; -- Base IP address used by unb_osy: 10.99.xx.yy
+    g_mm_clk_freq    : NATURAL := c_unb2_board_mm_clk_freq_125M;
+    g_eth_clk_freq   : NATURAL := c_unb2_board_eth_clk_freq_125M;
+    g_tse_clk_buf    : BOOLEAN := FALSE;
+    
+    ----------------------------------------------------------------------------
+    -- External CLK
+    ----------------------------------------------------------------------------
+    g_dp_clk_freq    : NATURAL := c_unb2_board_ext_clk_freq_200M;
+    g_dp_clk_use_pll : BOOLEAN := TRUE;
+    -- PLL phase clk shift with respect to CLK
+    --     STRING :=    "0"             = 0
+    --     STRING :=  "156"             = 011.25
+    --     STRING :=  "313"             = 022.5 
+    --     STRING :=  "469"             = 033.75
+    --     STRING :=  "625"             = 045   
+    --     STRING :=  "781"             = 056.25
+    --     STRING :=  "938"             = 067.5 
+    --     STRING := "1094"             = 078.75
+    --     STRING := "1250"             = 090   
+    --     STRING := "1406" = 1250+ 156 = 101.25
+    --     STRING := "1563" = 1250+ 313 = 112.5 
+    --     STRING := "1719" = 1250+ 469 = 123.75
+    --     STRING := "1875" = 1250+ 625 = 135   
+    --     STRING := "2031" = 1250+ 781 = 146.25
+    --     STRING := "2188" = 1250+ 938 = 157.5 
+    --     STRING := "2344" = 1250+1094 = 168.75
+    --     STRING := "2500" = 1250+1250 = 180   
+    --     STRING := "2656" = 2500+ 156 = 191.25
+    --     STRING := "2813" = 2500+ 313 = 202.5 
+    --     STRING := "2969" = 2500+ 469 = 213.75
+    --     STRING := "3125" = 2500+ 625 = 225   
+    --     STRING := "3281" = 2500+ 781 = 236.25
+    --     STRING := "3438" = 2500+ 938 = 247.5 
+    --     STRING := "3594" = 2500+1094 = 258.75
+    --     STRING := "3750" = 2500+1250 = 270   
+    --     STRING := "3906" = 3750+ 156 = 281.25
+    --     STRING := "4063" = 3750+ 313 = 292.5 
+    --     STRING := "4219" = 3750+ 469 = 303.75
+    --     STRING := "4375" = 3750+ 625 = 315   
+    --     STRING := "4531" = 3750+ 781 = 326.25
+    --     STRING := "4688" = 3750+ 938 = 337.5 
+    --     STRING := "4844" = 3750+1094 = 348.75
+    --     STRING := "5000" = 3750+1250 = 360
+    g_dp_clk_phase         : STRING := "0";      -- phase offset for PLL c0, typically any phase is fine, do not use 225 +-30 degrees because there the PPS edge occurs
+    
+    ----------------------------------------------------------------------------
+    -- 1GbE UDP offload
+    ----------------------------------------------------------------------------
+    g_udp_offload             : BOOLEAN := FALSE;
+    g_udp_offload_nof_streams : NATURAL := c_eth_nof_udp_ports;
+    
+    ----------------------------------------------------------------------------
+    -- Auxiliary Interface
+    ----------------------------------------------------------------------------
+    g_fpga_temp_high    : NATURAL := 85;
+    g_app_led_red       : BOOLEAN := FALSE;  -- when TRUE use external LED control via app_led_red
+    g_app_led_green     : BOOLEAN := FALSE;  -- when TRUE use external LED control via app_led_green
+    
+    g_aux               : t_c_unb2_board_aux := c_unb2_board_aux;
+    g_factory_image     : BOOLEAN := FALSE;
+    g_protect_addr_range: BOOLEAN := FALSE;
+    g_protected_addr_lo : NATURAL := 0;       -- Byte address
+    g_protected_addr_hi : NATURAL := 41943039 -- Byte address, for UniBoard1 this is 640 sectors*256 pages*256 bytes -1 = 41943039
+  );
+  PORT (
+    --
+    -- >>> SOPC system with conduit peripheral MM bus
+    --
+    -- System
+    cs_sim                 : OUT STD_LOGIC;
+    
+    xo_ethclk              : OUT STD_LOGIC;   -- 125 MHz ETH_CLK
+    xo_rst                 : OUT STD_LOGIC;   -- reset in ETH_CLK domain released after few cycles
+    xo_rst_n               : OUT STD_LOGIC; 
+   
+    ext_clk200             : OUT STD_LOGIC;   -- 200 MHz CLK
+    ext_rst200             : OUT STD_LOGIC;   -- reset in CLK clock domain released after mm_rst
+    
+    mm_clk                 : OUT STD_LOGIC;   -- MM clock from xo_ethclk PLL
+    mm_rst                 : OUT STD_LOGIC;   -- reset in MM clock domain released after xo_ethclk PLL locked
+    
+    dp_rst                 : OUT STD_LOGIC;   -- reset in DP clock domain released after mm_rst and after CLK PLL locked in case g_dp_clk_use_pll=TRUE
+    dp_clk                 : OUT STD_LOGIC;   -- 200 MHz DP clock from CLK system clock direct or via CLK PLL dependent on g_dp_clk_use_pll
+    dp_pps                 : OUT STD_LOGIC;   -- PPS in dp_clk domain
+    dp_rst_in              : IN  STD_LOGIC;   -- externally wire OUT dp_rst to dp_rst_in to avoid delta cycle difference on dp_clk
+    dp_clk_in              : IN  STD_LOGIC;   -- externally wire OUT dp_clk to dp_clk_in to avoid delta cycle difference on dp_clk
+
+    mb_I_ref_rst           : OUT STD_LOGIC;   -- reset in MB_I_REF_CLK domain released after mm_rst
+    mb_II_ref_rst          : OUT STD_LOGIC;   -- reset in MB_II_REF_CLK domain released after mm_rst
+    
+    this_chip_id           : OUT STD_LOGIC_VECTOR(c_unb2_board_nof_chip_w-1 DOWNTO 0);      -- [1:0], so range 0-3 for PN
+    this_bck_id            : OUT STD_LOGIC_VECTOR(c_unb2_board_nof_uniboard_w-1 DOWNTO 0);  -- [1:0] used out of ID[7:2] to index boards 3..0 in subrack
+    
+    app_led_red            : IN  STD_LOGIC := '0';
+    app_led_green          : IN  STD_LOGIC := '1';
+    
+    -- PIOs
+    pout_wdi               : IN  STD_LOGIC;   -- Toggled by unb_osy; can be overriden by reg_wdi.
+
+    -- Manual WDI override
+    reg_wdi_mosi           : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_wdi_miso           : OUT t_mem_miso;
+
+    -- REMU
+    reg_remu_mosi          : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_remu_miso          : OUT t_mem_miso;
+
+    -- EPCS read
+    reg_dpmm_data_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_dpmm_data_miso     : OUT t_mem_miso;
+    reg_dpmm_ctrl_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_dpmm_ctrl_miso     : OUT t_mem_miso;
+
+    -- EPCS write
+    reg_mmdp_data_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_mmdp_data_miso     : OUT t_mem_miso;
+    reg_mmdp_ctrl_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_mmdp_ctrl_miso     : OUT t_mem_miso;
+
+    -- EPCS status/control
+    reg_epcs_mosi          : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_epcs_miso          : OUT t_mem_miso;
+
+    -- MM buses to/from mms_unb2_board_system_info
+    reg_unb_system_info_mosi : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_unb_system_info_miso : OUT t_mem_miso;
+
+    rom_unb_system_info_mosi : IN  t_mem_mosi := c_mem_mosi_rst;
+    rom_unb_system_info_miso : OUT t_mem_miso;
+
+    -- UniBoard I2C sensors
+    reg_unb_sens_mosi      : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_unb_sens_miso      : OUT t_mem_miso;
+
+    reg_unb_pmbus_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_unb_pmbus_miso     : OUT t_mem_miso;
+
+    -- FPGA sensors
+    reg_fpga_temp_sens_mosi     : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_fpga_temp_sens_miso     : OUT t_mem_miso;
+    reg_fpga_voltage_sens_mosi  : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_fpga_voltage_sens_miso  : OUT t_mem_miso;
+    
+    -- PPSH
+    reg_ppsh_mosi          : IN  t_mem_mosi := c_mem_mosi_rst;
+    reg_ppsh_miso          : OUT t_mem_miso;
+    
+    -- eth1g control&monitoring
+    eth1g_mm_rst           : IN  STD_LOGIC;
+    eth1g_tse_mosi         : IN  t_mem_mosi;  -- ETH TSE MAC registers
+    eth1g_tse_miso         : OUT t_mem_miso;
+    eth1g_reg_mosi         : IN  t_mem_mosi;  -- ETH control and status registers
+    eth1g_reg_miso         : OUT t_mem_miso;
+    eth1g_reg_interrupt    : OUT STD_LOGIC;   -- Interrupt
+    eth1g_ram_mosi         : IN  t_mem_mosi;  -- ETH rx frame and tx frame memory
+    eth1g_ram_miso         : OUT t_mem_miso;
+
+    -- eth1g UDP streaming ports
+    udp_tx_sosi_arr        : IN  t_dp_sosi_arr(g_udp_offload_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_sosi_rst);
+    udp_tx_siso_arr        : OUT t_dp_siso_arr(g_udp_offload_nof_streams-1 DOWNTO 0);  
+    udp_rx_sosi_arr        : OUT t_dp_sosi_arr(g_udp_offload_nof_streams-1 DOWNTO 0);
+    udp_rx_siso_arr        : IN  t_dp_siso_arr(g_udp_offload_nof_streams-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
+
+    --
+    -- >>> Ctrl FPGA pins
+    --
+    -- GENERAL
+    CLK                    : IN    STD_LOGIC; -- System Clock
+    PPS                    : IN    STD_LOGIC; -- System Sync
+    WDI                    : OUT   STD_LOGIC; -- Watchdog Clear
+    INTA                   : INOUT STD_LOGIC; -- FPGA interconnect line
+    INTB                   : INOUT STD_LOGIC; -- FPGA interconnect line
+
+    -- Others
+    VERSION                : IN    STD_LOGIC_VECTOR(g_aux.version_w-1 DOWNTO 0);
+    ID                     : IN    STD_LOGIC_VECTOR(g_aux.id_w-1 DOWNTO 0);
+    TESTIO                 : INOUT STD_LOGIC_VECTOR(g_aux.testio_w-1 DOWNTO 0);
+    
+    -- I2C Interface to Sensors
+    SENS_SC                : INOUT STD_LOGIC := 'Z';
+    SENS_SD                : INOUT STD_LOGIC := 'Z';
+
+    -- pmbus
+    PMBUS_SC               : INOUT STD_LOGIC := 'Z';
+    PMBUS_SD               : INOUT STD_LOGIC := 'Z';
+    PMBUS_ALERT            : IN    STD_LOGIC := '0';
+    
+    -- DDR reference clock domains reset creation
+    MB_I_REF_CLK           : IN    STD_LOGIC := '0';  -- 25 MHz
+    MB_II_REF_CLK          : IN    STD_LOGIC := '0';  -- 25 MHz
+    
+    -- 1GbE Control Interface
+    ETH_CLK                : IN    STD_LOGIC;  -- 125 MHz
+    ETH_SGIN               : IN    STD_LOGIC_VECTOR(c_unb2_board_nof_eth-1 DOWNTO 0) := (OTHERS=>'0');
+    ETH_SGOUT              : OUT   STD_LOGIC_VECTOR(c_unb2_board_nof_eth-1 DOWNTO 0)
+  );
+END ctrl_unb2_board;
+
+
+ARCHITECTURE str OF ctrl_unb2_board IS
+
+  CONSTANT c_rom_version : NATURAL := 1; -- Only increment when something changes to the register map of rom_system_info. 
+
+  CONSTANT c_reset_len   : NATURAL := 4;  -- >= c_meta_delay_len from common_pkg
+  CONSTANT c_mm_clk_freq : NATURAL := sel_a_b(g_sim=FALSE,g_mm_clk_freq,c_unb2_board_mm_clk_freq_10M);
+    
+  
+  -- Clock and reset
+  SIGNAL i_ext_clk200           : STD_LOGIC;
+  SIGNAL ext_pps                : STD_LOGIC;
+
+  SIGNAL common_areset_in_rst   : STD_LOGIC;
+ 
+  SIGNAL i_xo_ethclk            : STD_LOGIC;
+  SIGNAL i_xo_rst               : STD_LOGIC;
+  SIGNAL i_mm_rst               : STD_LOGIC;
+  SIGNAL i_mm_clk               : STD_LOGIC;
+  SIGNAL mm_locked              : STD_LOGIC;
+  SIGNAL mm_sim_clk             : STD_LOGIC := '1';
+  SIGNAL epcs_clk               : STD_LOGIC := '1';
+  SIGNAL clk125                 : STD_LOGIC := '1';
+  SIGNAL clk100                 : STD_LOGIC := '1';
+  SIGNAL clk50                  : STD_LOGIC := '1';
+
+  SIGNAL mm_wdi                 : STD_LOGIC;
+  SIGNAL eth1g_st_clk           : STD_LOGIC;
+  SIGNAL eth1g_st_rst           : STD_LOGIC;
+
+  SIGNAL mm_pulse_ms            : STD_LOGIC;
+  SIGNAL mm_pulse_s             : STD_LOGIC;
+  SIGNAL mm_board_sens_start    : STD_LOGIC;
+ 
+  SIGNAL led_toggle             : STD_LOGIC;
+  SIGNAL led_toggle_red         : STD_LOGIC;
+  SIGNAL led_toggle_green       : STD_LOGIC;
+ 
+  -- eth1g
+  SIGNAL i_tse_clk              : STD_LOGIC;
+  SIGNAL eth1g_led              : t_tech_tse_led;
+  
+  -- Manual WDI override
+  SIGNAL wdi_override           : STD_LOGIC;
+
+  -- Temperature alarm  (temp > g_fpga_temp_high) 
+  SIGNAL temp_alarm             : STD_LOGIC;
+
+  -- UDP offload I/O
+  SIGNAL eth1g_udp_tx_sosi_arr  : t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS=>c_dp_sosi_rst);
+  SIGNAL eth1g_udp_tx_siso_arr  : t_dp_siso_arr(c_eth_nof_udp_ports-1 DOWNTO 0);  
+  SIGNAL eth1g_udp_rx_sosi_arr  : t_dp_sosi_arr(c_eth_nof_udp_ports-1 DOWNTO 0);
+  SIGNAL eth1g_udp_rx_siso_arr  : t_dp_siso_arr(c_eth_nof_udp_ports-1 DOWNTO 0) := (OTHERS=>c_dp_siso_rdy);
+
+  attribute keep: boolean;
+  attribute keep of led_toggle_red:   signal is true;
+  attribute keep of led_toggle_green: signal is true;
+
+  attribute maxfan : integer;
+  attribute maxfan of dp_rst : signal is 1024;
+
+BEGIN
+
+  ext_clk200 <= i_ext_clk200;
+  xo_ethclk  <= i_xo_ethclk;
+  xo_rst     <=     i_xo_rst;
+  xo_rst_n   <= NOT i_xo_rst; 
+  mm_clk     <= i_mm_clk;
+  mm_rst     <= i_mm_rst;
+  
+  -- Default leave unused INOUT tri-state
+  INTA <= 'Z';
+  INTB <= 'Z';
+  
+  TESTIO <= (OTHERS=>'Z');  -- Leave unused INOUT tri-state
+ 
+  ext_pps <= PPS;  -- use more special name for PPS pin signal to ease searching for it in editor
+  
+  -----------------------------------------------------------------------------
+  -- ext_clk200 = CLK
+  -----------------------------------------------------------------------------
+  i_ext_clk200 <= CLK;  -- use more special name for CLK pin signal to ease searching for it in editor, the external 200 MHz CLK as ext_clk200
+  
+  u_common_areset_ext : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',       -- power up default will be inferred in FPGA
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => '0',         -- release reset after some clock cycles
+    clk       => i_ext_clk200,
+    out_rst   => ext_rst200
+  );
+  
+  -----------------------------------------------------------------------------
+  -- xo_ethclk = ETH_CLK
+  -----------------------------------------------------------------------------
+  
+  i_xo_ethclk <= ETH_CLK;   -- use the ETH_CLK pin as xo_clk
+  
+  u_common_areset_xo : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',       -- power up default will be inferred in FPGA
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => '0',         -- release reset after some clock cycles
+    clk       => i_xo_ethclk,
+    out_rst   => i_xo_rst
+  );
+
+
+  -----------------------------------------------------------------------------
+  -- MB_I_REF_CLK  --> mb_I_ref_rst
+  -- MB_II_REF_CLK --> mb_II_ref_rst
+  -----------------------------------------------------------------------------
+  
+  u_common_areset_mb_I : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',       -- power up default will be inferred in FPGA
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => i_mm_rst,   -- release reset some clock cycles after i_mm_rst went low
+    clk       => MB_I_REF_CLK,
+    out_rst   => mb_I_ref_rst
+  );
+  
+  u_common_areset_mb_II : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',       -- power up default will be inferred in FPGA
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => i_mm_rst,   -- release reset some clock cycles after i_mm_rst went low
+    clk       => MB_II_REF_CLK,
+    out_rst   => mb_II_ref_rst
+  );
+  
+  -----------------------------------------------------------------------------
+  -- dp_clk + dp_rst generation
+  -- . dp_clk = i_ext_clk200 in sim or on HW when PLL is not desired
+  -- . dp_rst always comes from common_areset
+  ----------------------------------------------------------------------------- 
+  no_pll: IF g_sim=TRUE OR (g_sim=FALSE AND g_dp_clk_use_pll=FALSE) GENERATE
+    dp_clk <= i_ext_clk200;
+    common_areset_in_rst <= i_mm_rst;
+  END GENERATE;
+  
+  gen_pll: IF g_sim=FALSE AND g_dp_clk_use_pll=TRUE GENERATE
+    u_unb2_board_clk200_pll : ENTITY work.unb2_board_clk200_pll
+    GENERIC MAP (
+      g_technology          => g_technology,
+      g_use_fpll            => TRUE,
+      g_clk200_phase_shift  => g_dp_clk_phase
+    )
+    PORT MAP (
+      arst       => i_mm_rst,
+      clk200     => i_ext_clk200,
+      st_clk200  => dp_clk,  -- = c0
+      st_rst200  => common_areset_in_rst
+    );
+  END GENERATE;     
+  
+  u_common_areset_dp_rst : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => common_areset_in_rst, -- release reset some clock cycles after i_mm_rst went low
+    clk       => dp_clk_in,
+    out_rst   => dp_rst
+  );    
+  
+  -----------------------------------------------------------------------------
+  -- mm_clk
+  -- . use mm_sim_clk in sim
+  -- . derived from ETH_CLK via PLL on hardware
+  -----------------------------------------------------------------------------
+
+  i_mm_clk <= mm_sim_clk WHEN g_sim = TRUE ELSE
+              clk125     WHEN g_mm_clk_freq = c_unb2_board_mm_clk_freq_125M ELSE
+              clk100     WHEN g_mm_clk_freq = c_unb2_board_mm_clk_freq_100M ELSE
+              clk50      WHEN g_mm_clk_freq = c_unb2_board_mm_clk_freq_50M  ELSE
+              clk50;  -- default
+
+  gen_mm_clk_sim: IF g_sim = TRUE GENERATE
+      epcs_clk    <= NOT epcs_clk AFTER 25 ns; -- 20 MHz, 50ns/2
+      clk50       <= NOT clk50 AFTER 10 ns;    -- 50 MHz, 20ns/2
+      clk100      <= NOT clk100 AFTER 5 ns;    -- 100 MHz, 10ns/2
+      clk125      <= NOT clk125 AFTER 4 ns;    -- 125 MHz, 8ns/2
+      mm_sim_clk  <= NOT mm_sim_clk AFTER 50 ns;  -- 10 MHz, 100ns/2  --> FIXME: this mm_sim_clk should come from the MMM so that its speed can be adapted
+      mm_locked   <= '0', '1' AFTER 70 ns;
+  END GENERATE;
+
+  gen_mm_clk_hardware: IF g_sim = FALSE GENERATE
+    u_unb2_board_clk125_pll : ENTITY work.unb2_board_clk125_pll
+    GENERIC MAP (
+      g_use_fpll   => TRUE,
+      g_technology => g_technology
+    )
+    PORT MAP (
+      arst       => i_xo_rst,
+      clk125     => i_xo_ethclk,
+      c0_clk20   => epcs_clk,
+      c1_clk50   => clk50,
+      c2_clk100  => clk100,
+      c3_clk125  => clk125,
+      pll_locked => mm_locked
+    );
+  END GENERATE;
+
+  u_unb2_board_node_ctrl : ENTITY work.unb2_board_node_ctrl
+  GENERIC MAP (
+    g_pulse_us => c_mm_clk_freq / (10**6)     -- nof system clock cycles to get us period, equal to system clock frequency / 10**6
+  )
+  PORT MAP (
+    -- MM clock domain reset
+    mm_clk      => i_mm_clk,
+    mm_locked   => mm_locked,
+    mm_rst      => i_mm_rst,
+    -- WDI extend
+    mm_wdi_in   => pout_wdi,
+    mm_wdi_out  => mm_wdi,  -- actively toggle the WDI via pout_wdi from software with toggle extend to allow software reload
+    -- Pulses
+    mm_pulse_us => OPEN,
+    mm_pulse_ms => mm_pulse_ms,
+    mm_pulse_s  => mm_pulse_s  -- could be used to toggle a LED
+  );
+  
+  -----------------------------------------------------------------------------
+  -- System info
+  -----------------------------------------------------------------------------
+  cs_sim <= is_true(g_sim);
+  
+  u_mms_unb2_board_system_info : ENTITY work.mms_unb2_board_system_info
+  GENERIC MAP (
+    g_sim         => g_sim,
+    g_technology  => g_technology,
+    g_design_name => g_design_name,
+    g_fw_version  => g_fw_version,
+    g_stamp_date  => g_stamp_date,
+    g_stamp_time  => g_stamp_time,
+    g_stamp_svn   => g_stamp_svn,
+    g_design_note => g_design_note,
+    g_rom_version => c_rom_version
+  )
+  PORT MAP (
+    mm_clk      => i_mm_clk,
+    mm_rst      => i_mm_rst,
+
+    hw_version  => VERSION,
+    id          => ID,
+
+    reg_mosi    => reg_unb_system_info_mosi, 
+    reg_miso    => reg_unb_system_info_miso,
+
+    rom_mosi    => rom_unb_system_info_mosi, 
+    rom_miso    => rom_unb_system_info_miso,
+
+    chip_id     => this_chip_id,
+    bck_id      => this_bck_id
+  );
+
+
+  -----------------------------------------------------------------------------
+  -- Red LED control
+  -----------------------------------------------------------------------------
+
+  gen_app_led_red: IF g_app_led_red = TRUE GENERATE
+    -- Let external app control the LED via the app_led_red input
+    TESTIO(c_unb2_board_testio_led_red)   <= app_led_red;
+  END GENERATE;
+
+  no_app_led_red: IF g_app_led_red = FALSE GENERATE
+    TESTIO(c_unb2_board_testio_led_red)   <= led_toggle_red;   
+  END GENERATE;
+
+
+  -----------------------------------------------------------------------------
+  -- Green LED control
+  -----------------------------------------------------------------------------
+
+  gen_app_led_green: IF g_app_led_green = TRUE GENERATE
+    -- Let external app control the LED via the app_led_green input
+    TESTIO(c_unb2_board_testio_led_green) <= app_led_green;  
+  END GENERATE;
+
+  no_app_led_green: IF g_app_led_green = FALSE GENERATE
+    TESTIO(c_unb2_board_testio_led_green) <= led_toggle_green;   
+  END GENERATE;
+
+
+  ------------------------------------------------------------------------------
+  -- Toggle red LED when unb2_minimal is running, green LED for other designs.
+  ------------------------------------------------------------------------------
+  led_toggle_red   <= sel_a_b(g_factory_image=TRUE,  led_toggle, '0');
+  led_toggle_green <= sel_a_b(g_factory_image=FALSE, led_toggle, '0');
+
+  u_toggle : ENTITY common_lib.common_toggle
+  PORT MAP (
+    rst         => i_mm_rst,
+    clk         => i_mm_clk,
+    in_dat      => mm_pulse_s,
+    out_dat     => led_toggle
+  );
+
+
+  ------------------------------------------------------------------------------
+  -- WDI override
+  ------------------------------------------------------------------------------
+  -- Actively reset watchdog from software when used, else disable watchdog by leaving the WDI at tri-state level.
+  -- A high temp_alarm will keep WDI asserted, causing the watch dog to reset the FPGA.
+  -- A third option is to override the WDI manually using the output of a dedicated reg_wdi.
+  WDI <= mm_wdi OR temp_alarm OR wdi_override; 
+
+  u_unb2_board_wdi_reg : ENTITY work.unb2_board_wdi_reg
+  PORT MAP (
+    mm_rst              => i_mm_rst,
+    mm_clk              => i_mm_clk,
+     
+    sla_in              => reg_wdi_mosi,
+    sla_out             => reg_wdi_miso,
+    
+    wdi_override        => wdi_override
+  );
+
+
+  ------------------------------------------------------------------------------
+  -- Remote upgrade
+  ------------------------------------------------------------------------------                                       
+  -- Every design instantiates an mms_remu instance + MM status & control ports.
+  -- So there is full control over the memory mapped registers to set start address of the flash 
+  -- and reconfigure from that address.
+  u_mms_remu: ENTITY remu_lib.mms_remu
+  GENERIC MAP ( 
+    g_technology       => g_technology
+  )
+  PORT MAP (
+    mm_rst             => i_mm_rst,
+    mm_clk             => i_mm_clk,
+
+    epcs_clk           => epcs_clk,
+
+    remu_mosi          => reg_remu_mosi,
+    remu_miso          => reg_remu_miso
+  );
+
+  -------------------------------------------------------------------------------
+  ---- EPCS
+  -------------------------------------------------------------------------------
+  u_mms_epcs: ENTITY epcs_lib.mms_epcs
+  GENERIC MAP ( 
+    g_technology         => g_technology,
+    g_protect_addr_range => g_protect_addr_range,
+    g_protected_addr_lo  => g_protected_addr_lo,
+    g_protected_addr_hi  => g_protected_addr_hi
+  )
+  PORT MAP (
+    mm_rst             => i_mm_rst,
+    mm_clk             => i_mm_clk,
+
+    epcs_clk           => epcs_clk,
+
+    epcs_mosi          => reg_epcs_mosi,
+    epcs_miso          => reg_epcs_miso,
+
+    dpmm_ctrl_mosi     => reg_dpmm_ctrl_mosi,
+    dpmm_ctrl_miso     => reg_dpmm_ctrl_miso,
+
+    dpmm_data_mosi     => reg_dpmm_data_mosi,
+    dpmm_data_miso     => reg_dpmm_data_miso,
+
+    mmdp_ctrl_mosi     => reg_mmdp_ctrl_mosi,
+    mmdp_ctrl_miso     => reg_mmdp_ctrl_miso,
+
+    mmdp_data_mosi     => reg_mmdp_data_mosi,
+    mmdp_data_miso     => reg_mmdp_data_miso
+  );
+  
+  ------------------------------------------------------------------------------
+  -- PPS input
+  ------------------------------------------------------------------------------
+  
+  u_mms_ppsh : ENTITY ppsh_lib.mms_ppsh
+  GENERIC MAP (
+    g_technology      => g_technology,
+    g_st_clk_freq     => g_dp_clk_freq
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst           => i_mm_rst,
+    mm_clk           => i_mm_clk,
+    st_rst           => dp_rst_in,
+    st_clk           => dp_clk_in,
+    pps_ext          => ext_pps,           -- with unknown but constant phase to st_clk
+    
+    -- Memory-mapped clock domain
+    reg_mosi         => reg_ppsh_mosi,
+    reg_miso         => reg_ppsh_miso,
+    
+    -- Streaming clock domain
+    pps_sys          => dp_pps
+  );
+  
+  
+  ------------------------------------------------------------------------------
+  -- I2C control for UniBoard sensors
+  ------------------------------------------------------------------------------
+  
+  mm_board_sens_start <= mm_pulse_s WHEN g_sim=FALSE ELSE mm_pulse_s; --mm_pulse_ms; ms pulse comes before the end of the I2C frame, this results in an overflow in simulation  -- speed up in simulation
+  
+  u_mms_unb2_board_sens : ENTITY work.mms_unb2_board_sens
+  GENERIC MAP (
+    g_sim             => g_sim,
+    g_i2c_peripheral  => c_i2c_peripheral_sens,
+    g_sens_nof_result => 40,
+    g_clk_freq        => g_mm_clk_freq,
+    g_comma_w         => 13
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst    => i_mm_rst,
+    mm_clk    => i_mm_clk,
+    mm_start  => mm_board_sens_start,
+    
+    -- Memory-mapped clock domain
+    reg_mosi  => reg_unb_sens_mosi,
+    reg_miso  => reg_unb_sens_miso,
+    
+    -- i2c bus
+    scl       => SENS_SC,
+    sda       => SENS_SD
+  );
+
+  u_mms_unb2_board_pmbus : ENTITY work.mms_unb2_board_sens
+  GENERIC MAP (
+    g_sim             => g_sim,
+    g_i2c_peripheral  => c_i2c_peripheral_pmbus,
+    g_sens_nof_result => 42,
+    g_clk_freq        => g_mm_clk_freq,
+    g_comma_w         => 13
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst    => i_mm_rst,
+    mm_clk    => i_mm_clk,
+    mm_start  => mm_board_sens_start,
+
+    -- Memory-mapped clock domain
+    reg_mosi  => reg_unb_pmbus_mosi,
+    reg_miso  => reg_unb_pmbus_miso,
+
+    -- i2c bus
+    scl       => PMBUS_SC,
+    sda       => PMBUS_SD
+  );
+
+  u_mms_unb2_fpga_sens : ENTITY work.mms_unb2_fpga_sens
+  GENERIC MAP (
+    g_sim        => g_sim,
+    g_technology => g_technology,
+    g_temp_high  => g_fpga_temp_high
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst    => i_mm_rst,
+    mm_clk    => i_mm_clk,
+
+    --mm_start  => mm_board_sens_start, -- this does not work, perhaps pulsewidth is too small
+    mm_start  => '1', -- this works
+    
+    -- Memory-mapped clock domain
+    reg_temp_mosi  => reg_fpga_temp_sens_mosi,
+    reg_temp_miso  => reg_fpga_temp_sens_miso,
+    reg_voltage_mosi  => reg_fpga_voltage_sens_mosi,
+    reg_voltage_miso  => reg_fpga_voltage_sens_miso,
+    
+    -- Temperature alarm
+    temp_alarm => temp_alarm
+  );
+
+
+  ------------------------------------------------------------------------------
+  -- Ethernet 1GbE
+  ------------------------------------------------------------------------------
+
+  gen_tse_clk_buf: IF g_tse_clk_buf=TRUE GENERATE
+    -- Separate clkbuf for the 1GbE tse_clk:
+    u_tse_clk_buf : ENTITY tech_clkbuf_lib.tech_clkbuf
+    GENERIC MAP (
+      g_technology   => g_technology,
+      g_clock_net    => "GLOBAL"
+    )
+    PORT MAP (
+      inclk  => i_xo_ethclk,
+      outclk => i_tse_clk
+    );
+  END GENERATE;
+
+  gen_tse_no_clk_buf: IF g_tse_clk_buf=FALSE GENERATE
+      i_tse_clk <= i_xo_ethclk;
+  END GENERATE;
+
+  
+  wire_udp_offload: FOR i IN 0 TO g_udp_offload_nof_streams-1 GENERATE
+    eth1g_udp_tx_sosi_arr(i) <= udp_tx_sosi_arr(i);
+    udp_tx_siso_arr(i)       <= eth1g_udp_tx_siso_arr(i);
+  
+    udp_rx_sosi_arr(i)       <= eth1g_udp_rx_sosi_arr(i);
+    eth1g_udp_rx_siso_arr(i) <= udp_rx_siso_arr(i);
+  END GENERATE;
+
+  -- In simulation use file IO for MM control. In simulation only use 1GbE for streaming DP data offload (or on load) via 1GbE. 
+  no_eth1g : IF g_sim=TRUE AND g_udp_offload=FALSE GENERATE
+    eth1g_reg_interrupt <= '0';
+    eth1g_tse_miso <= c_mem_miso_rst;
+    eth1g_reg_miso <= c_mem_miso_rst;
+    eth1g_ram_miso <= c_mem_miso_rst;
+  END GENERATE;
+  
+  --On hardware always generate 1GbE for MM control. In simulation only use 1GbE for streaming DP data offload (or on load) via 1GbE. 
+  gen_eth: IF g_sim=FALSE OR g_udp_offload=TRUE GENERATE
+
+    eth1g_st_clk <= dp_clk_in WHEN g_udp_offload=TRUE ELSE i_mm_clk;
+    eth1g_st_rst <= dp_rst_in WHEN g_udp_offload=TRUE ELSE eth1g_mm_rst;
+
+    u_eth : ENTITY eth_lib.eth
+    GENERIC MAP (
+      g_technology         => g_technology,
+      g_init_ip_address    => g_base_ip & X"0000", -- Last two bytes set by board/FPGA ID.
+      g_cross_clock_domain => g_udp_offload,
+      g_frm_discard_en     => TRUE
+    )
+    PORT MAP (
+      -- Clocks and reset
+      mm_rst            => eth1g_mm_rst, -- use reset from QSYS
+      mm_clk            => i_mm_clk,     -- use mm_clk direct
+      eth_clk           => i_tse_clk,    -- 125 MHz clock
+      st_rst            => eth1g_st_rst,
+      st_clk            => eth1g_st_clk,
+    
+      -- UDP transmit interface
+      udp_tx_snk_in_arr  => eth1g_udp_tx_sosi_arr, 
+      udp_tx_snk_out_arr => eth1g_udp_tx_siso_arr,
+      -- UDP receive interface
+      udp_rx_src_in_arr  => eth1g_udp_rx_siso_arr,
+      udp_rx_src_out_arr => eth1g_udp_rx_sosi_arr,
+ 
+      -- Memory Mapped Slaves
+      tse_sla_in        => eth1g_tse_mosi,
+      tse_sla_out       => eth1g_tse_miso,
+      reg_sla_in        => eth1g_reg_mosi,
+      reg_sla_out       => eth1g_reg_miso,
+      reg_sla_interrupt => eth1g_reg_interrupt,
+      ram_sla_in        => eth1g_ram_mosi,
+      ram_sla_out       => eth1g_ram_miso,
+  
+      -- PHY interface
+      eth_txp           => ETH_SGOUT(0),
+      eth_rxp           => ETH_SGIN(0),
+  
+      -- LED interface
+      tse_led           => eth1g_led
+    );
+  END GENERATE;
+
+END str;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_board_sens.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_board_sens.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..99c8a77fc9f765c6aa1fe3c80cf8b2c7951337a6
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_board_sens.vhd
@@ -0,0 +1,122 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose : MMS for unb2_board_sens
+-- Description: See unb2_board_sens.vhd
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+
+
+ENTITY mms_unb2_board_sens IS
+  GENERIC (
+    g_sim             : BOOLEAN := FALSE;
+    g_i2c_peripheral  : NATURAL;
+    g_sens_nof_result : NATURAL;  -- Should match nof read bytes via I2C in the unb2_board_sens_ctrl SEQUENCE list
+    g_clk_freq        : NATURAL := 100*10**6;  -- clk frequency in Hz
+    g_temp_high       : NATURAL := 85;
+    g_comma_w         : NATURAL := 0
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst            : IN  STD_LOGIC;  -- reset synchronous with mm_clk
+    mm_clk            : IN  STD_LOGIC;  -- memory-mapped bus clock
+    mm_start          : IN  STD_LOGIC;
+    
+    -- Memory-mapped clock domain
+    reg_mosi          : IN  t_mem_mosi := c_mem_mosi_rst;  -- actual ranges defined by c_mm_reg
+    reg_miso          : OUT t_mem_miso;                    -- actual ranges defined by c_mm_reg
+    
+    -- i2c bus
+    scl               : INOUT STD_LOGIC := 'Z';
+    sda               : INOUT STD_LOGIC := 'Z';
+
+    -- Temperature alarm output
+    temp_alarm        : OUT STD_LOGIC
+  );
+END mms_unb2_board_sens;
+
+
+ARCHITECTURE str OF mms_unb2_board_sens IS
+
+  CONSTANT c_temp_high_w     : NATURAL := 7;  -- Allow user to use only 7 (no sign, only positive) of 8 bits to set set max temp
+
+  SIGNAL sens_err  : STD_LOGIC;
+  SIGNAL sens_data : t_slv_8_arr(0 TO g_sens_nof_result-1);
+
+  SIGNAL temp_high : STD_LOGIC_VECTOR(c_temp_high_w-1 DOWNTO 0);
+
+BEGIN
+
+  u_unb2_board_sens_reg : ENTITY work.unb2_board_sens_reg
+  GENERIC MAP (
+    g_sens_nof_result => g_sens_nof_result,
+    g_temp_high       => g_temp_high  
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst       => mm_rst,
+    mm_clk       => mm_clk,
+    
+    -- Memory Mapped Slave in mm_clk domain
+    sla_in       => reg_mosi,
+    sla_out      => reg_miso,
+    
+    -- MM registers
+    sens_err     => sens_err,  -- using same protocol list for both node2 and all nodes implies that sens_err is only valid for node2.
+    sens_data    => sens_data,
+
+    -- Max temp threshold
+    temp_high    => temp_high
+  );
+  
+  u_unb2_board_sens : ENTITY work.unb2_board_sens
+  GENERIC MAP (
+    g_sim             => g_sim,
+    g_i2c_peripheral  => g_i2c_peripheral,
+    g_clk_freq        => g_clk_freq,
+    g_temp_high       => g_temp_high,
+    g_sens_nof_result => g_sens_nof_result,
+    g_comma_w         => g_comma_w
+  )
+  PORT MAP (
+    clk          => mm_clk,
+    rst          => mm_rst,
+    start        => mm_start,
+    -- i2c bus
+    scl          => scl,
+    sda          => sda,
+    -- read results
+    sens_evt     => OPEN,
+    sens_err     => sens_err,
+    sens_data    => sens_data
+  );
+
+  -- Temperature: 7 bits (1 bit per degree) plus sign. A faulty readout (never pulled down = all ones) 
+  -- would produce -1 degrees so does not trigger a temperature alarm.
+  -- temp_high is 7 bits, preceded by a '0' to allow only positive temps to be set. 
+  temp_alarm <= '1' WHEN (SIGNED(sens_data(0)) > SIGNED('0' & temp_high)) ELSE '0';
+    
+END str;
+
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_board_system_info.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_board_system_info.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..69c9f0c602854dfa773e96fc6f03a3e1b83d7a2f
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_board_system_info.vhd
@@ -0,0 +1,141 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, technology_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE work.unb2_board_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+
+ENTITY mms_unb2_board_system_info IS
+  GENERIC (
+    g_sim         : BOOLEAN := FALSE;
+    g_technology  : NATURAL := c_tech_arria10;
+    g_design_name : STRING;
+    g_fw_version  : t_unb2_board_fw_version := c_unb2_board_fw_version;  -- firmware version x.y
+    g_stamp_date  : NATURAL := 0;
+    g_stamp_time  : NATURAL := 0;
+    g_stamp_svn   : NATURAL := 0;
+    g_design_note : STRING  := "";
+    g_rom_version : NATURAL := 1;
+    g_aux         : t_c_unb2_board_aux := c_unb2_board_aux               -- aux contains the hardware version
+  );
+  PORT (
+    mm_rst          : IN    STD_LOGIC;
+    mm_clk          : IN    STD_LOGIC;
+
+    -- MM registers
+    reg_mosi        : IN    t_mem_mosi := c_mem_mosi_rst;
+    reg_miso        : OUT   t_mem_miso;
+
+    rom_mosi        : IN    t_mem_mosi := c_mem_mosi_rst;
+    rom_miso        : OUT   t_mem_miso;
+
+    hw_version      : IN  STD_LOGIC_VECTOR(g_aux.version_w-1 DOWNTO 0);
+    id              : IN  STD_LOGIC_VECTOR(g_aux.id_w-1 DOWNTO 0);
+
+    chip_id         : OUT STD_LOGIC_VECTOR(c_unb2_board_nof_chip_w-1 DOWNTO 0);
+    bck_id          : OUT STD_LOGIC_VECTOR(c_unb2_board_nof_uniboard_w-1 DOWNTO 0);
+
+    -- Info output still supported for older designs
+    info            : OUT STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0)
+    );
+END mms_unb2_board_system_info;
+
+
+ARCHITECTURE str OF mms_unb2_board_system_info IS
+
+  -- Provide different prefixes (absolute and relative) for the same path. ModelSim understands $UNB, Quartus does not.
+  -- Required because the work paths of ModelSim and Quartus are different.
+  CONSTANT c_quartus_path_prefix  : STRING := "";
+  CONSTANT c_modelsim_path_prefix : STRING := "$UNB/Firmware/designs/" & g_design_name & "/build/synth/quartus/";
+  CONSTANT c_path_prefix          : STRING := sel_a_b(g_sim, c_modelsim_path_prefix, c_quartus_path_prefix);
+
+-- No longer supporting MIF files in sim as non-$UNB (e.g. $AARTFAAC) designs will cause path error.
+--  CONSTANT c_mif_name    : STRING := sel_a_b((g_design_name="UNUSED"), g_design_name, c_path_prefix & g_design_name & ".mif");
+  CONSTANT c_mif_name    : STRING :=  sel_a_b(g_sim, "UNUSED", sel_a_b((g_design_name="UNUSED"), g_design_name, c_path_prefix & g_design_name & ".mif"));
+
+  CONSTANT c_rom_addr_w  : NATURAL := 10; -- 2^10 = 1024 addresses * 32 bits = 4 kiB
+
+  CONSTANT c_mm_rom      : t_c_mem := (latency  => 1,
+                                      adr_w    => c_rom_addr_w,
+                                      dat_w    => c_word_w,
+                                      nof_dat  => 2**c_rom_addr_w,  -- = 2**adr_w
+                                      init_sl  => '0');
+ 
+  SIGNAL i_info          : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+
+BEGIN
+
+ info <= i_info;
+ 
+  u_unb2_board_system_info: ENTITY work.unb2_board_system_info
+  GENERIC MAP (
+    g_sim        => g_sim,
+    g_fw_version => g_fw_version,
+    g_rom_version => g_rom_version,
+    g_technology  => g_technology
+  )            
+  PORT MAP (        
+    clk        => mm_clk, 
+    hw_version => hw_version,
+    id         => id,
+    info       => i_info,
+    chip_id    => chip_id,
+    bck_id     => bck_id
+   );
+
+  u_unb2_board_system_info_reg: ENTITY work.unb2_board_system_info_reg                   
+  GENERIC MAP (
+    g_design_name => g_design_name,
+    g_stamp_date  => g_stamp_date,
+    g_stamp_time  => g_stamp_time,
+    g_stamp_svn   => g_stamp_svn,
+    g_design_note => g_design_note
+  )    
+  PORT MAP (       
+    mm_rst    => mm_rst, 
+    mm_clk    => mm_clk,
+
+    sla_in    => reg_mosi,
+    sla_out   => reg_miso,
+
+    info      => i_info
+  );
+
+  u_common_rom : ENTITY common_lib.common_rom
+  GENERIC MAP (
+    g_technology => g_technology,
+    g_ram       => c_mm_rom,
+    g_init_file => c_mif_name
+  )
+  PORT MAP (
+    rst     => mm_rst,
+    clk     => mm_clk,
+    rd_en   => rom_mosi.rd,
+    rd_adr  => rom_mosi.address(c_mm_rom.adr_w-1 DOWNTO 0),
+    rd_dat  => rom_miso.rddata(c_mm_rom.dat_w-1 DOWNTO 0),
+    rd_val  => rom_miso.rdval
+  );
+  
+END str;
+
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_fpga_sens.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_fpga_sens.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..96ae8dc74dd007749a9ceafa6f9b081e45e2085e
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/mms_unb2_fpga_sens.vhd
@@ -0,0 +1,122 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose : MMS for unb2_fpga_sens
+-- Description: See unb2_fpga_sens.vhd
+
+LIBRARY IEEE, technology_lib, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+
+
+ENTITY mms_unb2_fpga_sens IS
+  GENERIC (
+    g_sim             : BOOLEAN := FALSE;
+    g_technology      : NATURAL := c_tech_arria10;
+    g_temp_high       : NATURAL := 85
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst            : IN  STD_LOGIC;  -- reset synchronous with mm_clk
+    mm_clk            : IN  STD_LOGIC;  -- memory-mapped bus clock
+    mm_start          : IN  STD_LOGIC;
+    
+    -- Memory-mapped clock domain
+    reg_temp_mosi          : IN  t_mem_mosi := c_mem_mosi_rst;  -- actual ranges defined by c_mm_reg
+    reg_temp_miso          : OUT t_mem_miso;                    -- actual ranges defined by c_mm_reg
+    reg_voltage_mosi          : IN  t_mem_mosi := c_mem_mosi_rst;  -- actual ranges defined by c_mm_reg
+    reg_voltage_miso          : OUT t_mem_miso;                    -- actual ranges defined by c_mm_reg
+    
+    -- Temperature alarm output
+    temp_alarm        : OUT STD_LOGIC
+  );
+END mms_unb2_fpga_sens;
+
+
+ARCHITECTURE str OF mms_unb2_fpga_sens IS
+
+  CONSTANT c_sens_nof_result : NATURAL := 1;  -- 
+  CONSTANT c_temp_high_w     : NATURAL := 7;  -- Allow user to use only 7 (no sign, only positive) of 8 bits to set set max temp
+
+  SIGNAL sens_err  : STD_LOGIC;
+  SIGNAL sens_data : t_slv_8_arr(0 TO c_sens_nof_result-1);
+
+  SIGNAL temp_high : STD_LOGIC_VECTOR(c_temp_high_w-1 DOWNTO 0);
+
+BEGIN
+
+  u_unb2_fpga_sens_reg : ENTITY work.unb2_fpga_sens_reg
+  GENERIC MAP (
+    g_sim             => g_sim,
+    g_technology      => g_technology,
+    g_sens_nof_result => c_sens_nof_result,
+    g_temp_high       => g_temp_high  
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst       => mm_rst,
+    mm_clk       => mm_clk,
+    start        => mm_start,
+    
+    -- Memory Mapped Slave in mm_clk domain
+    sla_temp_in       => reg_temp_mosi,
+    sla_temp_out      => reg_temp_miso,
+    sla_voltage_in    => reg_voltage_mosi,
+    sla_voltage_out   => reg_voltage_miso,
+    
+    -- MM registers
+    --sens_err     => sens_err,  -- using same protocol list for both node2 and all nodes implies that sens_err is only valid for node2.
+    --sens_data    => sens_data,
+
+    -- Max temp threshold
+    temp_high    => temp_high
+  );
+  
+--  u_unb2_board_sens : ENTITY work.unb2_board_sens
+--  GENERIC MAP (
+--    g_sim             => g_sim,
+--    g_clk_freq        => g_clk_freq,
+--    g_temp_high       => g_temp_high,
+--    g_sens_nof_result => c_sens_nof_result
+--  )
+--  PORT MAP (
+--    clk          => mm_clk,
+--    rst          => mm_rst,
+--    start        => mm_start,
+--    -- i2c bus
+--    scl          => scl,
+--    sda          => sda,
+--    -- read results
+--    sens_evt     => OPEN,
+--    sens_err     => sens_err,
+--    sens_data    => sens_data
+--  );
+
+  -- Temperature: 7 bits (1 bit per degree) plus sign. A faulty readout (never pulled down = all ones) 
+  -- would produce -1 degrees so does not trigger a temperature alarm.
+  -- temp_high is 7 bits, preceded by a '0' to allow only positive temps to be set. 
+  temp_alarm <= '0';--<= '1' WHEN (SIGNED(sens_data(0)) > SIGNED('0' & temp_high)) ELSE '0';
+    
+END str;
+
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_back_io.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_back_io.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8142ed4527a9840b4b19c806788f9fb1da0b1737
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_back_io.vhd
@@ -0,0 +1,68 @@
+------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE work.unb2_board_pkg.ALL;
+
+
+ENTITY unb2_board_back_io IS
+  GENERIC (
+    g_nof_back_bus : NATURAL := c_unb2_board_tr_back.nof_bus
+  );
+  PORT (
+    serial_tx_arr  : IN  STD_LOGIC_VECTOR(g_nof_back_bus * c_unb2_board_tr_back.bus_w-1 DOWNTO 0) := (OTHERS=>'0');
+    serial_rx_arr  : OUT STD_LOGIC_VECTOR(g_nof_back_bus * c_unb2_board_tr_back.bus_w-1 DOWNTO 0);
+
+    -- back transceivers
+    BCK_RX       : IN    t_unb2_board_back_bus_2arr(g_nof_back_bus-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
+    BCK_TX       : OUT   t_unb2_board_back_bus_2arr(g_nof_back_bus-1 DOWNTO 0);
+
+    BCK_SDA      : INOUT STD_LOGIC_VECTOR(c_unb2_board_tr_back.i2c_w-1 DOWNTO 0);
+    BCK_SCL      : INOUT STD_LOGIC_VECTOR(c_unb2_board_tr_back.i2c_w-1 DOWNTO 0);
+    BCK_ERR      : INOUT STD_LOGIC_VECTOR(c_unb2_board_tr_back.i2c_w-1 DOWNTO 0)
+  );
+END unb2_board_back_io;
+
+ARCHITECTURE str OF unb2_board_back_io IS
+
+  -- help signals so we can iterate through buses
+  SIGNAL si_tx_2arr : t_unb2_board_back_bus_2arr(g_nof_back_bus-1 DOWNTO 0);
+  SIGNAL si_rx_2arr : t_unb2_board_back_bus_2arr(g_nof_back_bus-1 DOWNTO 0);
+
+BEGIN
+
+  gen_buses : FOR i IN 0 TO g_nof_back_bus-1 GENERATE
+    BCK_TX(i)     <= si_tx_2arr(i);
+    si_rx_2arr(i) <= BCK_RX(i);
+  END GENERATE;
+
+
+  gen_wire_bus : FOR i IN 0 TO g_nof_back_bus-1 GENERATE
+    gen_wire_signals : FOR j IN 0 TO c_unb2_board_tr_back.bus_w-1 GENERATE
+
+      si_tx_2arr(i)(j) <= serial_tx_arr(i*c_unb2_board_tr_back.bus_w + j);
+      serial_rx_arr(i*c_unb2_board_tr_back.bus_w + j) <= si_rx_2arr(i)(j);
+
+    END GENERATE;
+  END GENERATE;
+
+END;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk125_pll.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk125_pll.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..858cc68b92013637641691b30cdb7eb3bf206202
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk125_pll.vhd
@@ -0,0 +1,110 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, technology_lib, tech_clkbuf_lib, tech_pll_lib, tech_fractional_pll_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+
+-- Purpose: PLL for UniBoard node CLK input @ 125 MHz
+-- Description:
+--   c0 = 20 MHz
+--   c1 = 50 MHz
+--   c2 = 100 MHz
+--   c3 = 125 MHz
+-- 
+
+ENTITY unb2_board_clk125_pll IS
+  GENERIC (
+    g_technology : NATURAL := c_tech_arria10;
+    g_use_clkbuf : BOOLEAN := TRUE;
+    g_use_fpll   : BOOLEAN := FALSE
+  );
+  PORT (
+    arst        : IN  STD_LOGIC := '0';
+    clk125      : IN  STD_LOGIC := '0'; -- connect to UniBoard ETH_clk pin (125 MHz)
+
+    c0_clk20    : OUT STD_LOGIC;  -- PLL c0
+    c1_clk50    : OUT STD_LOGIC;  -- PLL c1
+    c2_clk100   : OUT STD_LOGIC;  -- PLL c2
+    c3_clk125   : OUT STD_LOGIC;  -- PLL c3
+    pll_locked  : OUT STD_LOGIC
+  );
+END unb2_board_clk125_pll;
+
+
+ARCHITECTURE arria10 OF unb2_board_clk125_pll IS
+
+  SIGNAL clk125buf : STD_LOGIC;
+
+BEGIN
+
+  no_clkbuf : IF g_use_clkbuf=FALSE GENERATE
+    clk125buf <= clk125;
+  END GENERATE;
+  
+  gen_clkbuf : IF g_use_clkbuf=TRUE GENERATE
+    u_clkbuf : ENTITY tech_clkbuf_lib.tech_clkbuf
+    GENERIC MAP (
+      g_technology   => g_technology,
+      g_clock_net    => "GLOBAL"
+    )
+    PORT MAP (
+      inclk  => clk125,
+      outclk => clk125buf
+    );
+  END GENERATE;
+
+
+  gen_pll : IF g_use_fpll=FALSE GENERATE
+    u_pll : ENTITY tech_pll_lib.tech_pll_clk125
+    GENERIC MAP (
+      g_technology => g_technology
+    )
+    PORT MAP (
+      areset  => arst,
+      inclk0  => clk125buf,
+      c0      => c0_clk20,
+      c1      => c1_clk50,
+      c2      => c2_clk100,
+      c3      => c3_clk125,
+      locked  => pll_locked
+    );
+  END GENERATE;
+
+  gen_fractional_pll : IF g_use_fpll=TRUE GENERATE
+    u_pll : ENTITY tech_fractional_pll_lib.tech_fractional_pll_clk125
+    GENERIC MAP (
+      g_technology => g_technology
+    )
+    PORT MAP (
+      areset  => arst,
+      inclk0  => clk125buf,
+      c0      => c0_clk20,
+      c1      => c1_clk50,
+      c2      => c2_clk100,
+      c3      => c3_clk125,
+      locked  => pll_locked
+    );
+  END GENERATE;
+
+END arria10;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk200_pll.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk200_pll.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..63e575d26d41b00f75fa42ee937f963b5cf02aac
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk200_pll.vhd
@@ -0,0 +1,222 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2010-2014
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, technology_lib, tech_clkbuf_lib, tech_pll_lib, tech_fractional_pll_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+
+-- Purpose: PLL for UniBoard node CLK input @ 200 MHz
+-- Description:
+-- . The PLL runs in normal mode using c0 to compensate for the internal clock
+--   network delay, so that c0 = st_clk200 is aligned to the input clk200.
+-- . The assumption is that default the streaming DSP will run on the 200 MHz
+--   clock from the CLK input via c1 = st_clk200p.
+-- . The PLL normal mode operation compensates for internal clock network
+--   delays of c0. This compensations aligns c0 to inclk0. With
+--   tb_unb2_board_clk200_pll.vhd it appears that the phase setting for c0 does
+--   not influence the compensation. Therefore it is llso possible to use
+--   g_clk200_phase_shift /= 0 and touse c0 as processing clock instead of c1.
+-- . The phase offset of c0 and c1 in the clk200_pll MegaWizard component 
+--   can be set in steps of 11.25 degrees (and even finer):
+--                       g_clk200_phase_shift  (for c0)
+--     phase [degrees]   g_clk200p_phase_shift (for c1)
+--       0                 "0"
+--       11.25             "156"
+--       22.5              "313"
+--       33.75             "469"
+--       45                "625"
+--       56.25             "781"
+--       67.5              "938"
+--       78.75             "1094"
+--       90                "1250"
+--      101.25             "1406"  = 1250+ 156
+--      112.5              "1563"  = 1250+ 313
+--      123.75             "1719"  = 1250+ 469
+--      135                "1875"  = 1250+ 625
+--      146.25             "2031"  = 1250+ 781
+--      157.5              "2188"  = 1250+ 938
+--      168.75             "2344"  = 1250+1094
+--      180                "2500"  = 1250+1250
+--      191.25             "2656"  = 2500+ 156
+--      202.5              "2813"  = 2500+ 313
+--      213.75             "2969"  = 2500+ 469
+--      225                "3125"  = 2500+ 625
+--      236.25             "3281"  = 2500+ 781
+--      247.5              "3438"  = 2500+ 938
+--      258.75             "3594"  = 2500+1094
+--      270                "3750"  = 2500+1250
+--      281.25             "3906"  = 3750+ 156
+--      292.5              "4063"  = 3750+ 313
+--      303.75             "4219"  = 3750+ 469
+--      315                "4375"  = 3750+ 625
+--      326.25             "4531"  = 3750+ 781
+--      337.5              "4688"  = 3750+ 938
+--      348.75             "4844"  = 3750+1094
+--      360                "5000"  = 3750+1250
+-- . With a phase offset of 22.5 degrees the c1 = clk200p is offset by a 1/16
+--   period of 200 MHz, so 1/8 period of the 400 MHz DCLK from ADU and 1/4
+--   period of the 800 MHz sample SCLK of ADU. This phase offset can be used
+--   to achieve stable timing between the DCLK and the clk200p domain.
+-- . Some DSP may also be possible at 400 MHz via st_clk400. Note that this
+--   400 MHz can also be used at places where only a little more than 200 MHz
+--   would be needed, e.g. to create packets at full data rate.
+--   Therefore it is not necessary to create yet another st clock frequency.
+--   This to also avoid the EMI or RFI that a non integer factor of 200 MHz
+--   like e.g. 250 MHz would cause.
+-- . At 400 MHz ADC samples can be clocked in at 800 MSps using DDIO. At 800
+--   MSps the sample period is 1250 ns. Input timing can be tuned via fixed
+--   pad input delays and/or by using another phase of the PLL output clock.
+-- Remarks:
+-- . If necessary more 400 M clock phase could be made available, via g_sel.
+-- 
+
+ENTITY unb2_board_clk200_pll IS
+  GENERIC (
+    g_technology          : NATURAL := c_tech_arria10;
+    g_use_clkbuf          : BOOLEAN := TRUE;
+    g_use_fpll            : BOOLEAN := FALSE;
+    g_operation_mode      : STRING  := "NORMAL";  -- "NORMAL", "NO_COMPENSATION", or "SOURCE_SYNCHRONOUS" --> requires PLL_COMPENSATE assignment to an input pin to compensate for (stratixiv)
+    g_clk200_phase_shift  : STRING := "0";  -- default use 0 degrees, see clk200_pll.vhd for other phase values
+    g_clk200p_phase_shift : STRING := "0"  -- default use 0 degrees, see clk200_pll.vhd for other phase values
+  );
+  PORT (
+    -- It depends on g_sel which outputs are actually available
+    -- . common
+    arst        : IN  STD_LOGIC := '0';
+    clk200      : IN  STD_LOGIC := '0';       -- connect to UniBoard CLK pin
+    st_clk200   : OUT STD_LOGIC;  -- PLL c0 = g_clk200_phase_shift  degrees phase offset to input clk200
+    st_rst200   : OUT STD_LOGIC;
+    st_clk200p  : OUT STD_LOGIC;  -- PLL c1 = g_clk200p_phase_shift degrees phase offset to input clk200 (see clk200_pll.vhd from MegaWizard)
+    st_rst200p  : OUT STD_LOGIC;
+    st_clk400   : OUT STD_LOGIC;  -- PLL c2 = 0                     degrees phase offset to input clk200
+    st_rst400   : OUT STD_LOGIC
+  );
+END unb2_board_clk200_pll;
+
+
+ARCHITECTURE arria10 OF unb2_board_clk200_pll IS
+
+  CONSTANT c_reset_len : NATURAL := c_meta_delay_len;
+    
+  SIGNAL clk200buf    : STD_LOGIC;
+  SIGNAL i_st_rst200  : STD_LOGIC;
+  SIGNAL i_st_clk200  : STD_LOGIC;
+  SIGNAL i_st_clk200p : STD_LOGIC;
+  SIGNAL i_st_clk400  : STD_LOGIC;
+  
+  SIGNAL st_locked    : STD_LOGIC;
+  SIGNAL st_locked_n  : STD_LOGIC;
+
+BEGIN
+
+  st_rst200  <= i_st_rst200;
+  st_clk200  <= i_st_clk200;
+  st_clk200p <= i_st_clk200p;
+  st_clk400  <= i_st_clk400;
+    
+  no_clkbuf : IF g_use_clkbuf=FALSE GENERATE
+    clk200buf <= clk200;
+  END GENERATE;
+  
+  gen_clkbuf : IF g_use_clkbuf=TRUE GENERATE
+    u_clkbuf : ENTITY tech_clkbuf_lib.tech_clkbuf
+    GENERIC MAP (
+      g_technology   => g_technology,
+      g_clock_net    => "GLOBAL"
+    )
+    PORT MAP (
+      inclk  => clk200,
+      outclk => clk200buf
+    );
+  END GENERATE;
+  
+  gen_st_pll : IF g_use_fpll=FALSE GENERATE
+    u_st_pll : ENTITY tech_pll_lib.tech_pll_clk200
+    GENERIC MAP (
+      g_technology       => g_technology,
+      g_operation_mode   => g_operation_mode,
+      g_clk0_phase_shift => g_clk200_phase_shift,
+      g_clk1_phase_shift => g_clk200p_phase_shift
+    )
+    PORT MAP (
+      areset  => arst,
+      inclk0  => clk200buf,
+      c0      => i_st_clk200,
+      c1      => i_st_clk200p,
+      c2      => i_st_clk400,
+      locked  => st_locked
+    );
+  END GENERATE;
+  
+  gen_st_fractional_pll : IF g_use_fpll=TRUE GENERATE
+    u_st_fractional_pll : ENTITY tech_fractional_pll_lib.tech_fractional_pll_clk200
+    GENERIC MAP (
+      g_technology       => g_technology
+    )
+    PORT MAP (
+      areset  => arst,        
+      inclk0  => clk200buf,     -- 200 MHz
+      c0      => i_st_clk200,   -- 200 MHz
+      c1      => i_st_clk200p,  -- 200 MHz shifted 90 degrees
+      c2      => i_st_clk400,   -- 400 MHz
+      locked  => st_locked    
+    );
+  END GENERATE;
+  
+  -- Release clock domain resets after some clock cycles when the PLL has locked  
+  st_locked_n <= NOT st_locked;
+  
+  u_rst200 : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => st_locked_n,
+    clk       => i_st_clk200,
+    out_rst   => i_st_rst200
+  );
+
+  u_rst200p : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => st_locked_n,
+    clk       => i_st_clk200p,
+    out_rst   => st_rst200p
+  );
+  
+  u_rst400 : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => st_locked_n,
+    clk       => i_st_clk400,
+    out_rst   => st_rst400
+  );
+  
+END arria10;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk25_pll.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk25_pll.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a4f7612305993083e11746a92216ab1586e1126c
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk25_pll.vhd
@@ -0,0 +1,69 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, technology_lib, tech_pll_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+
+-- Purpose: PLL for UniBoard node CLK input @ 25 MHz
+-- Description:
+--   c0 = 20 MHz
+--   c1 = 50 MHz
+--   c2 = 100 MHz
+--   c3 = 125 MHz
+-- 
+
+ENTITY unb2_board_clk25_pll IS
+  GENERIC (
+    g_technology : NATURAL := c_tech_arria10
+  );
+  PORT (
+    arst        : IN  STD_LOGIC := '0';
+    clk25       : IN  STD_LOGIC := '0'; -- connect to UniBoard ETH_clk pin (25 MHz)
+
+    c0_clk20    : OUT STD_LOGIC;  -- PLL c0
+    c1_clk50    : OUT STD_LOGIC;  -- PLL c1
+    c2_clk100   : OUT STD_LOGIC;  -- PLL c2
+    c3_clk125   : OUT STD_LOGIC;  -- PLL c3
+    pll_locked  : OUT STD_LOGIC
+  );
+END unb2_board_clk25_pll;
+
+
+ARCHITECTURE arria10 OF unb2_board_clk25_pll IS
+BEGIN
+
+  u_pll : ENTITY tech_pll_lib.tech_pll_clk25
+  GENERIC MAP (
+    g_technology => g_technology
+  )
+  PORT MAP (
+    areset  => arst,
+    inclk0  => clk25,
+    c0      => c0_clk20,
+    c1      => c1_clk50,
+    c2      => c2_clk100,
+    c3      => c3_clk125,
+    locked  => pll_locked
+  );
+END arria10;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk_rst.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk_rst.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..561075cf83b12b408cda4871c1272434f693beeb
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_clk_rst.vhd
@@ -0,0 +1,86 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2010-2014
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+-- Purpose:
+--   1) initial power up xo_rst_n that can be used to reset a SOPC system (via
+--      reset_n).
+--   2) sys_rst released when the sys_clk PLL from the SOPC system has locked,
+--      can be used as a system reset for the sys_clk domain.
+
+ENTITY unb2_board_clk_rst IS
+  PORT (
+    -- Reference clock and reset to SOPC system PLL
+    xo_clk                 : IN  STD_LOGIC;  -- reference XO clock (e.g. 25 MHz also use by PLL in SOPC)
+    xo_rst_n               : OUT STD_LOGIC;  -- NOT xo_rst (e.g. to reset the SOPC with NIOS2 uP)
+    -- System clock and locked from SOPC system PLL
+    sys_clk                : IN  STD_LOGIC;  -- system clock derived from the reference XO clock (e.g. 125 MHz by a PLL from SOPC with NIOS2 uP)
+    sys_locked             : IN  STD_LOGIC;  -- system clock PLL locked
+    sys_rst                : OUT STD_LOGIC   -- system reset released some cycles after the system clock PLL has in locked
+  );
+END unb2_board_clk_rst;
+
+
+ARCHITECTURE str OF unb2_board_clk_rst IS
+
+  CONSTANT c_reset_len   : NATURAL := 4;  -- >= c_meta_delay_len from common_pkg
+  
+  -- XO clock domain
+  SIGNAL xo_rst          : STD_LOGIC;  -- initial reset released after some XO clock cycles
+  
+  -- SYS clock domain
+  SIGNAL sys_locked_n    : STD_LOGIC;
+  
+BEGIN
+
+  -- Reference clock and reset to SOPC system PLL
+  xo_rst_n <= NOT xo_rst;
+
+  u_common_areset_xo : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',       -- power up default will be inferred in FPGA
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => '0',         -- release reset after some clock cycles
+    clk       => xo_clk,
+    out_rst   => xo_rst
+  );
+
+  -- System clock from SOPC system PLL and system reset
+  sys_locked_n <= NOT sys_locked;
+  
+  u_common_areset_sys : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',       -- power up default will be inferred in FPGA
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => sys_locked_n,  -- release reset after some clock cycles when the PLL has locked
+    clk       => sys_clk,
+    out_rst   => sys_rst
+  );
+  
+END str;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_front_io.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_front_io.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..73927379317d0a4639fbd006f8af9da384338e59
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_front_io.vhd
@@ -0,0 +1,78 @@
+------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE work.unb2_board_pkg.ALL;
+
+
+ENTITY unb2_board_front_io IS
+  GENERIC (
+    g_nof_qsfp_bus : NATURAL := c_unb2_board_tr_qsfp.nof_bus
+  );
+  PORT (
+    serial_tx_arr  : IN  STD_LOGIC_VECTOR(g_nof_qsfp_bus * c_unb2_board_tr_qsfp.bus_w-1 DOWNTO 0) := (OTHERS=>'0');
+    serial_rx_arr  : OUT STD_LOGIC_VECTOR(g_nof_qsfp_bus * c_unb2_board_tr_qsfp.bus_w-1 DOWNTO 0);
+
+    green_led_arr  : IN  STD_LOGIC_VECTOR(g_nof_qsfp_bus-1 DOWNTO 0) := (OTHERS=>'0');
+    red_led_arr    : IN  STD_LOGIC_VECTOR(g_nof_qsfp_bus-1 DOWNTO 0) := (OTHERS=>'0');
+
+    QSFP_RX        : IN  t_unb2_board_qsfp_bus_2arr(g_nof_qsfp_bus-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
+    QSFP_TX        : OUT t_unb2_board_qsfp_bus_2arr(g_nof_qsfp_bus-1 DOWNTO 0);
+
+    --QSFP_SDA       : INOUT STD_LOGIC_VECTOR(c_unb2_board_tr_qsfp.i2c_w-1 downto 0);
+    --QSFP_SCL       : INOUT STD_LOGIC_VECTOR(c_unb2_board_tr_qsfp.i2c_w-1 downto 0);
+    --QSFP_RST       : INOUT STD_LOGIC;
+
+    QSFP_LED       : OUT   STD_LOGIC_VECTOR(c_unb2_board_tr_qsfp_nof_leds-1 DOWNTO 0)
+  );
+END unb2_board_front_io;
+
+ARCHITECTURE str OF unb2_board_front_io IS
+
+  -- help signals so we can iterate through buses
+  SIGNAL si_tx_2arr : t_unb2_board_qsfp_bus_2arr(g_nof_qsfp_bus-1 DOWNTO 0);
+  SIGNAL si_rx_2arr : t_unb2_board_qsfp_bus_2arr(g_nof_qsfp_bus-1 DOWNTO 0);
+
+BEGIN
+
+  gen_leds : FOR i IN 0 TO g_nof_qsfp_bus-1 GENERATE
+    QSFP_LED(i*2)   <=  green_led_arr(i);
+    QSFP_LED(i*2+1) <=  red_led_arr(i);
+  END GENERATE;
+
+
+  gen_buses : FOR i IN 0 TO g_nof_qsfp_bus-1 GENERATE
+    QSFP_TX(i)    <= si_tx_2arr(i);
+    si_rx_2arr(i) <= QSFP_RX(i);
+  END GENERATE;
+
+
+  gen_wire_bus : FOR i IN 0 TO g_nof_qsfp_bus-1 GENERATE
+    gen_wire_signals : FOR j IN 0 TO c_unb2_board_tr_qsfp.bus_w-1 GENERATE
+
+        si_tx_2arr(i)(j) <= serial_tx_arr(i*c_unb2_board_tr_qsfp.bus_w + j);
+        serial_rx_arr(i*c_unb2_board_tr_qsfp.bus_w + j) <= si_rx_2arr(i)(j);
+
+    END GENERATE;
+  END GENERATE;
+
+END;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_hmc_ctrl.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_hmc_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..12b817b2abf10ac61c4c575bd3e8bf7301bc8c59
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_hmc_ctrl.vhd
@@ -0,0 +1,192 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, i2c_lib;
+USE IEEE.std_logic_1164.ALL;
+USE i2c_lib.i2c_smbus_pkg.ALL;
+USE i2c_lib.i2c_dev_unb2_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+
+
+ENTITY unb2_board_hmc_ctrl IS
+  GENERIC (
+    g_sim        : BOOLEAN := FALSE;
+    g_nof_result : NATURAL := 42;
+    g_temp_high  : NATURAL := 85
+  );
+  PORT (
+    rst        : IN  STD_LOGIC;
+    clk        : IN  STD_LOGIC;
+    start      : IN  STD_LOGIC;  -- pulse to start the I2C sequence to read out the sensors
+    out_dat    : OUT STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    out_val    : OUT STD_LOGIC;    
+    in_dat     : IN  STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    in_val     : IN  STD_LOGIC;
+    in_err     : IN  STD_LOGIC; 
+    in_ack     : IN  STD_LOGIC;
+    in_end     : IN  STD_LOGIC;
+    result_val : OUT STD_LOGIC;
+    result_err : OUT STD_LOGIC;
+    result_dat : OUT t_slv_8_arr(0 TO g_nof_result-1)
+  );
+END ENTITY;
+
+
+ARCHITECTURE rtl OF unb2_board_hmc_ctrl IS
+
+  TYPE t_SEQUENCE IS ARRAY (NATURAL RANGE <>) OF NATURAL;
+  
+  -- The I2C bit rate is c_i2c_bit_rate = 50 [kbps], so 20 us period. Hence 20 us wait time for SDA is enough
+  -- Assume clk <= 200 MHz, so 5 ns period. Hence timeout of 4000 is enough.
+  CONSTANT c_timeout_sda : NATURAL := sel_a_b(g_sim, 0, 16);  -- wait 16 * 256 = 4096 clk periods
+  
+  CONSTANT c_SEQ : t_SEQUENCE := (
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE, -- RX supply
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE, -- TX supply
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_C_SAMPLE_SDA, 0, c_timeout_sda, 0, 0,
+    SMBUS_C_END,
+    SMBUS_C_NOP
+  );
+    
+  CONSTANT c_seq_len : NATURAL := c_SEQ'LENGTH-1;
+  
+  -- The protocol list c_SEQ yields a list of result bytes (result_dat)
+  -- make sure that g_nof_result matches the number of result bytes
+  
+  SIGNAL start_reg       : STD_LOGIC;
+  
+  SIGNAL seq_cnt         : NATURAL RANGE 0 TO c_seq_len := c_seq_len;
+  SIGNAL nxt_seq_cnt     : NATURAL;
+  
+  SIGNAL rx_cnt          : NATURAL RANGE 0 TO g_nof_result;
+  SIGNAL nxt_rx_cnt      : NATURAL;
+  
+  SIGNAL rx_val          : STD_LOGIC;
+  SIGNAL nxt_rx_val      : STD_LOGIC;
+  SIGNAL rx_err          : STD_LOGIC;
+  SIGNAL nxt_rx_err      : STD_LOGIC;
+  SIGNAL rx_dat          : t_slv_8_arr(result_dat'RANGE);  
+  SIGNAL nxt_rx_dat      : t_slv_8_arr(result_dat'RANGE); 
+  SIGNAL nxt_result_val  : STD_LOGIC;
+  SIGNAL nxt_result_err  : STD_LOGIC;
+  SIGNAL i_result_dat    : t_slv_8_arr(result_dat'RANGE);  
+  SIGNAL nxt_result_dat  : t_slv_8_arr(result_dat'RANGE);   
+  
+BEGIN
+
+  result_dat <= i_result_dat;
+
+  regs: PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      start_reg     <= '0';
+      seq_cnt       <= c_seq_len;
+      rx_cnt        <= 0;
+      rx_val        <= '0';
+      rx_err        <= '0';
+      rx_dat        <= (OTHERS=>(OTHERS=>'0'));
+      result_val    <= '0';
+      result_err    <= '0';
+      i_result_dat  <= (OTHERS=>(OTHERS=>'0'));
+    ELSIF rising_edge(clk) THEN
+      start_reg     <= start;
+      seq_cnt       <= nxt_seq_cnt;
+      rx_cnt        <= nxt_rx_cnt;
+      rx_val        <= nxt_rx_val;
+      rx_err        <= nxt_rx_err;
+      rx_dat        <= nxt_rx_dat;
+      result_val    <= nxt_result_val;
+      result_err    <= nxt_result_err;
+      i_result_dat  <= nxt_result_dat;
+    END IF;
+  END PROCESS;
+  
+  -- Issue the protocol list
+  p_seq_cnt : PROCESS(seq_cnt, start_reg, in_ack)
+  BEGIN
+    nxt_seq_cnt <= seq_cnt;
+    IF start_reg = '1' THEN
+      nxt_seq_cnt <= 0;
+    ELSIF seq_cnt<c_seq_len AND in_ack='1' THEN
+      nxt_seq_cnt <= seq_cnt + 1;
+    END IF;
+  END PROCESS;
+
+  out_dat <= STD_LOGIC_VECTOR(TO_UVEC(c_SEQ(seq_cnt), c_byte_w));
+  out_val <= '1' WHEN seq_cnt<c_seq_len ELSE '0';
+  
+  -- Fill the rx_dat byte array
+  p_rx_dat : PROCESS(start_reg, rx_err, in_err, rx_dat, rx_cnt, in_dat, in_val)
+  BEGIN
+    nxt_rx_err <= rx_err;
+    IF start_reg = '1' THEN
+      nxt_rx_err <= '0';
+    ELSIF in_err='1' THEN
+      nxt_rx_err <= '1';
+    END IF;
+    
+    nxt_rx_dat <= rx_dat;
+    nxt_rx_cnt <= rx_cnt;
+    IF start_reg = '1' THEN
+      nxt_rx_dat <= (OTHERS=>(OTHERS=>'0'));
+      nxt_rx_cnt <= 0;
+    ELSIF in_val='1' THEN
+      nxt_rx_dat(rx_cnt) <= in_dat;
+      nxt_rx_cnt         <= rx_cnt + 1;
+    END IF;
+  END PROCESS;
+
+  nxt_rx_val <= in_end;
+  
+  -- Capture the complete rx_dat byte array
+  nxt_result_val <= rx_val;
+  nxt_result_err <= rx_err;
+  nxt_result_dat <= rx_dat WHEN rx_val='1' ELSE i_result_dat;
+    
+END rtl;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_node_ctrl.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_node_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..afe1feab4e4d7fc402bc8adc4a0519c823ab754c
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_node_ctrl.vhd
@@ -0,0 +1,114 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2010-2014
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+-- Purpose: Provide the basic node clock control (resets, pulses, WDI)
+-- Description:
+--   . Create mm_rst for mm_clk:
+--   . Extend WDI to avoid watchdog reset during software reload
+--   . Pulse every 1 us, 1 ms and 1 s
+
+ENTITY unb2_board_node_ctrl IS
+  GENERIC (
+    g_pulse_us     : NATURAL := 125;     -- nof system clock cycles to get us period, equal to system clock frequency / 10**6
+    g_pulse_ms     : NATURAL := 1000;    -- nof pulse_us pulses to get ms period (fixed, use less to speed up simulation)
+    g_pulse_s      : NATURAL := 1000;    -- nof pulse_ms pulses to get  s period (fixed, use less to speed up simulation)
+    g_wdi_extend_w : NATURAL := 14       -- extend the mm_wdi_in by toggling the mm_wdi_out for about 2**(14-1)= 8 s more
+  );
+  PORT (
+    -- MM clock domain reset
+    mm_clk          : IN  STD_LOGIC;         -- MM clock
+    mm_locked       : IN  STD_LOGIC := '1';  -- MM clock PLL locked (or use default '1')
+    mm_rst          : OUT STD_LOGIC;         -- MM reset released after MM clock PLL has locked
+    
+    -- WDI extend
+    mm_wdi_in       : IN  STD_LOGIC;         -- from software running on the NIOS2 in the SOPC design
+    mm_wdi_out      : OUT STD_LOGIC;         -- to FPGA pin
+    
+    -- Pulses
+    mm_pulse_us     : OUT STD_LOGIC;         -- pulses every us
+    mm_pulse_ms     : OUT STD_LOGIC;         -- pulses every ms
+    mm_pulse_s      : OUT STD_LOGIC          -- pulses every s
+  );
+END unb2_board_node_ctrl;
+
+
+ARCHITECTURE str OF unb2_board_node_ctrl IS
+
+  CONSTANT c_reset_len   : NATURAL := 4;  -- >= c_meta_delay_len from common_pkg
+
+  SIGNAL mm_locked_n     : STD_LOGIC;
+  SIGNAL i_mm_rst        : STD_LOGIC;
+  SIGNAL i_mm_pulse_ms   : STD_LOGIC;
+  
+BEGIN
+
+  -- Create mm_rst reset in mm_clk domain based on mm_locked 
+  mm_rst <= i_mm_rst;  
+  
+  mm_locked_n <= NOT mm_locked;
+  
+  u_common_areset_mm : ENTITY common_lib.common_areset
+  GENERIC MAP (
+    g_rst_level => '1',       -- power up default will be inferred in FPGA
+    g_delay_len => c_reset_len
+  )
+  PORT MAP (
+    in_rst    => mm_locked_n,  -- release reset after some clock cycles when the PLL has locked
+    clk       => mm_clk,
+    out_rst   => i_mm_rst
+  );  
+  
+  -- Create 1 pulse per us, per ms and per s  
+  mm_pulse_ms <= i_mm_pulse_ms;
+
+  u_common_pulser_us_ms_s : ENTITY common_lib.common_pulser_us_ms_s
+  GENERIC MAP (
+    g_pulse_us  => g_pulse_us,
+    g_pulse_ms  => g_pulse_ms,
+    g_pulse_s   => g_pulse_s
+  )
+  PORT MAP (
+    rst         => i_mm_rst,
+    clk         => mm_clk,
+    pulse_us    => mm_pulse_us,
+    pulse_ms    => i_mm_pulse_ms,
+    pulse_s     => mm_pulse_s
+  );
+
+  -- Toggle the WDI every 1 ms
+  u_unb2_board_wdi_extend : ENTITY work.unb2_board_wdi_extend
+  GENERIC MAP (
+    g_extend_w => g_wdi_extend_w
+  )
+  PORT MAP (
+    rst        => i_mm_rst,
+    clk        => mm_clk, 
+    pulse_ms   => i_mm_pulse_ms,
+    wdi_in     => mm_wdi_in,
+    wdi_out    => mm_wdi_out
+  );
+
+END str;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_peripherals_pkg.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_peripherals_pkg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..18e45198042d4743f27025fb08a8b775157d74f0
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_peripherals_pkg.vhd
@@ -0,0 +1,173 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2009-2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Central location for collecting the peripheral MM register widths
+-- Description:
+--   The MM register width can be fixed or application dependent. When the MM
+--   register width is fixed it can be defined as a local constant in the
+--   module *_reg.vhd file or it may be defined in a module package.
+--   When modules are used in a design the MM register widths are needed to
+--   connect the 'node' part of the design to the 'sopc' part. Most designs do
+--   use the same widths also for the variable width MM registers. Therefore
+--   rather then obtaining the variable MM register widths from local design
+--   constants and the fixed widths from module packages, it seems easier to
+--   collect them here in t_c_unb2_board_peripherals_mm_reg.
+-- Remarks:
+-- . The c_unb2_board_peripherals_mm_reg_default suits most designs, if
+--   necessary design specific t_c_unb2_board_peripherals_mm_reg constants
+--   can be defined here as well.
+-- . If some design would need different widths for multiple instances, then
+--   these widths need to be defined locally in that design.
+
+LIBRARY IEEE;
+USE IEEE.STD_LOGIC_1164.ALL;
+
+PACKAGE unb2_board_peripherals_pkg IS
+
+  
+  -- *_adr_w : Actual MM address widths
+  -- *_dat_w : The default MM data width is c_word_w=32, otherwise it is specified in the record
+  TYPE t_c_unb2_board_peripherals_mm_reg IS RECORD
+    cross_clock_domain         : BOOLEAN;  -- = TRUE  -- use FALSE when mm_clk and dp_clk are the same, else use TRUE to cross the clock domain
+    
+    -- 1GbE
+    reg_tse_adr_w              : NATURAL;  -- = 10  -- = c_tse_byte_addr_w from tse_pkg.vhd
+    reg_eth_adr_w              : NATURAL;  -- = 4   -- = c_eth_reg_addr_w from eth_pkg.vhd
+    ram_eth_adr_w              : NATURAL;  -- = 10  -- = c_eth_ram_addr_w from eth_pkg.vhd
+    
+    -- pi_system_info (first word of reg_unb_system_info_adr_w is backwards compatible with the original single word PIO system info)
+    reg_unb_system_info_adr_w  : NATURAL;  -- = 5   -- fixed, from c_mm_reg in unb_system_info_reg
+    rom_unb_system_info_adr_w  : NATURAL;  -- = 10  -- fixed, from c_mm_rom in mms_unb_system_info
+    -- pi_reg_common
+    reg_common_adr_w           : NATURAL;  -- = 1   -- fixed, from c_mem_reg in mms_common_reg
+    
+    -- pi_ppsh
+    reg_ppsh_adr_w             : NATURAL;  -- = 1   -- fixed, from c_mm_reg in ppsh_reg
+    
+    -- pi_unb_sens
+    reg_unb_sens_adr_w         : NATURAL;  -- = 6   -- fixed, from c_mm_reg in unb_sens_reg
+    
+    -- pi_dpmm
+    reg_dpmm_data_adr_w        : NATURAL;  -- = 1   -- fixed, see dp_fifo_to_mm.vhd
+    reg_dpmm_ctrl_adr_w        : NATURAL;  -- = 1   -- fixed, from c_mm_reg in dp_fifo_to_mm_reg.vhd
+    
+    -- pi_mmdp
+    reg_mmdp_data_adr_w        : NATURAL;  -- = 1   -- fixed, see dp_fifo_from_mm.vhd
+    reg_mmdp_ctrl_adr_w        : NATURAL;  -- = 1   -- fixed, from c_mm_reg in dp_fifo_from_mm_reg.vhd
+
+    -- pi_dp_ram_from_mm
+    reg_dp_ram_from_mm_adr_w   : NATURAL;  -- = 1   -- fixed, see dp_ram_from_mm.vhd
+ -- ram_dp_ram_from_mm_adr_w   : NATURAL;  -- = VAR -- Variable, from c_mm_reg in dp_ram_from_mm_reg.vhd
+
+    -- pi_dp_ram_to_mm
+--  ram_dp_ram_to_mm_adr_w     : NATURAL;  -- = VAR -- Variable, from c_mm_reg in dp_ram_to_mm_reg.vhd
+    
+    -- pi_epcs (uses DP-MM read and write FIFOs for data access)
+    reg_epcs_adr_w             : NATURAL;  -- = 3   -- fixed, from c_mm_reg in epcs_reg
+    
+    -- pi_remu
+    reg_remu_adr_w             : NATURAL;  -- = 3   -- fixed, from c_mm_reg in remu_reg
+    
+    -- pi_ddr
+    -- pi_ddr_capture (uses DP-MM read FIFO for data access)
+    reg_ddr_adr_w              : NATURAL;  -- = 3   -- fixed, from c_mm_reg in ddr_reg
+    
+    -- pi_io_ddr
+    reg_io_ddr_adr_w           : NATURAL;  -- = 16  -- fixed, from c_mm_reg in io_ddr (3) and in io_ddr_reg (8) that get multiplexed in on addresses 0..2, 8..15
+    
+    -- pi_tr_nonbonded
+    reg_tr_nonbonded_adr_w     : NATURAL;  -- = 4   -- fixed, from c_mm_reg in tr_nonbonded_reg
+
+    -- pi_diagnostics
+    reg_diagnostics_adr_w      : NATURAL;  -- = 6   -- fixed, from c_mm_reg in diagnostics_reg
+
+    -- pi_dp_throttle
+    reg_dp_throttle_adr_w      : NATURAL;  -- = 2   -- fixed, from c_mm_reg in dp_throttle_reg
+    
+    -- pi_bsn_source
+    reg_bsn_source_adr_w       : NATURAL;  -- = 2   -- fixed, from c_mm_reg in dp_bsn_source_reg.vhd
+    
+    -- pi_bsn_schedurer
+    reg_bsn_scheduler_adr_w    : NATURAL;  -- = 1   -- fixed, from c_mm_reg in dp_bsn_scheduler_reg.vhd
+    
+    -- pi_bsn_monitor
+    reg_bsn_monitor_adr_w      : NATURAL;  -- = 4   -- fixed, from c_mm_reg in dp_bsn_monitor_reg.vhd
+    
+    -- pi_aduh_quad (defaults for ADU)
+    reg_adc_quad_adr_w         : NATURAL;  -- = 3   -- fixed, from c_mm_reg in aduh_quad_reg.vhd
+    
+    -- pi_aduh_i2c_commander (defaults for ADU)
+    reg_i2c_commander_adr_w    : NATURAL;  -- = 6   -- = c_i2c_cmdr_aduh_i2c_mm.control_adr_w,  from i2c_commander_aduh_pkg, used to pass on commander_adr_w
+    ram_i2c_protocol_adr_w     : NATURAL;  -- = 13  -- = c_i2c_cmdr_aduh_i2c_mm.protocol_adr_w, from i2c_commander_aduh_pkg
+    ram_i2c_result_adr_w       : NATURAL;  -- = 12  -- = c_i2c_cmdr_aduh_i2c_mm.result_adr_w,   from i2c_commander_aduh_pkg
+    
+    -- pi_aduh_monitor (defaults for ADU or WG used in bn_capture)
+    reg_aduh_mon_adr_w         : NATURAL;  -- = 2   -- fixed, from c_mm_reg in aduh_monitor_reg.vhd
+    ram_aduh_mon_dat_w         : NATURAL;  -- = 32  -- = c_sp_data_w, see node_bn_capture.vhd
+    ram_aduh_mon_adr_w         : NATURAL;  -- = 8   -- = ceil_log2(c_bn_capture.sp.monitor_buffer_nof_samples/c_wideband_factor), see node_bn_capture.vhd
+    
+    -- pi_diag_wg_wideband.py (defaults for WG used in bn_capture)
+    reg_diag_wg_adr_w          : NATURAL;  -- = 2   -- fixed, from c_mm_reg in diag_wg_wideband_reg
+    ram_diag_wg_dat_w          : NATURAL;  -- = 8   -- defined here, see bn_capture_input.vhd
+    ram_diag_wg_adr_w          : NATURAL;  -- = 10  -- defined here, see bn_capture_input.vhd
+    
+    -- pi_diag_data_buffer.py
+    ram_diag_db_nof_buf        : NATURAL;  -- = 16
+    ram_diag_db_buf_size       : NATURAL;  -- = 1024
+    ram_diag_db_adr_w          : NATURAL;  -- = 14  -- = ram_diag_db_nof_buf*ceil_log2(ram_diag_db_buf_size)
+    reg_diag_db_adr_w          : NATURAL;  -- = 5   -- 32 words for 16 streams max
+
+    -- pi_diag_block_gen (defaults when used with the BF for Apertif)
+    reg_diag_bg_adr_w          : NATURAL;  -- = 3
+    ram_diag_bg_adr_w          : NATURAL;  -- = 11  -- = ceil_log2(c_bf.nof_subbands*c_bf.nof_signal_paths/c_bf.nof_input_streams = 24*64/16 = 96) + ceil_log2(c_bf.nof_input_streams = 16)
+  
+    -- pi_diag_tx_seq.py
+    reg_diag_tx_seq_w          : NATURAL;  -- = 2
+    
+    -- pi_diag_tx_seq.py
+    reg_diag_rx_seq_w          : NATURAL;  -- = 3
+    
+    -- pi_bf_bf (defaults for the BF for Apertif)
+    reg_bf_offsets_adr_w       : NATURAL;  -- = 5   -- = ceil_log2(c_bf.nof_offsets = 6) + ceil_log2(c_bf.nof_bf_units = 4)
+    ram_bf_weights_adr_w       : NATURAL;  -- = 16  -- = ceil_log2(c_bf.nof_bf_units*c_bf.nof_signal_paths*c_bf.nof_weights = 4 * 64 * 256 = 65536)
+    ram_st_sst_bf_adr_w        : NATURAL;  -- = 11  -- = ceil_log2(c_bf.nof_bf_units*c_bf.stat_data_sz*c_bf.nof_weights = 4 * 2 * 256 = 2048)
+
+    -- pi_mdio
+    reg_mdio_adr_w             : NATURAL;  -- = 3
+
+    -- dp_offload
+    reg_dp_offload_tx_adr_w    : NATURAL;  -- = 1
+
+    -- pi_unb_fpga_sensors
+    reg_fpga_temp_sens_adr_w    : NATURAL;  -- = 3
+    reg_fpga_voltage_sens_adr_w : NATURAL;  -- = 4
+
+    -- pi_unb_pmbus
+    reg_unb_pmbus_adr_w        : NATURAL;  -- = 6
+  END RECORD;
+  
+  CONSTANT c_unb2_board_peripherals_mm_reg_default    : t_c_unb2_board_peripherals_mm_reg := (TRUE, 10, 4, 10, 5, 10, 1, 1, 6, 1, 1, 1, 1, 1, 3, 3, 3, 16, 4, 6, 2, 2, 1, 4, 3, 6, 13, 12, 2, 32, 8, 2, 8, 10, 16, 1024, 14, 5, 3, 11, 2, 3, 5, 16, 11, 3, 1, 3, 4, 6);
+  
+END unb2_board_peripherals_pkg;
+
+PACKAGE BODY unb2_board_peripherals_pkg IS
+END unb2_board_peripherals_pkg;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_pkg.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_pkg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a811f49c45e417bdd3488a25b295196c7aeddf1f
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_pkg.vhd
@@ -0,0 +1,175 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2009-2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, dp_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE dp_lib.dp_stream_pkg.ALL;
+
+PACKAGE unb2_board_pkg IS
+
+  -- UniBoard
+  CONSTANT c_unb2_board_nof_node             : NATURAL := 4;                     -- number of nodes on UniBoard
+  CONSTANT c_unb2_board_nof_node_w           : NATURAL := 2;                     -- = ceil_log2(c_unb2_board_nof_node)
+  CONSTANT c_unb2_board_nof_chip             : NATURAL := c_unb2_board_nof_node; -- = 4
+  CONSTANT c_unb2_board_nof_chip_w           : NATURAL := 2;                     -- = ceil_log2(c_unb2_board_nof_chip)
+  CONSTANT c_unb2_board_nof_ddr              : NATURAL := 2;                     -- each node has 2 DDR modules
+  
+  -- Subrack
+  CONSTANT c_unb2_board_nof_uniboard         : NATURAL := 4;   -- nof UniBoard in a subrack
+  CONSTANT c_unb2_board_nof_uniboard_w       : NATURAL := 6;   -- Only 2 required for 4 boards; full width is 6.
+  
+  -- Clock frequencies
+  CONSTANT c_unb2_board_ext_clk_freq_200M    : NATURAL := 200 * 10**6;  -- external clock, SMA clock
+  CONSTANT c_unb2_board_eth_clk_freq_25M     : NATURAL :=  25 * 10**6;  -- fixed 25 MHz  ETH XO clock used as reference clock for the PLL
+  CONSTANT c_unb2_board_eth_clk_freq_125M    : NATURAL := 125 * 10**6;  -- fixed 125 MHz ETH XO clock used as direct clock for TSE
+  CONSTANT c_unb2_board_tse_clk_freq         : NATURAL := 125 * 10**6;  -- fixed 125 MHz TSE reference clock derived from ETH_clk by PLL
+  CONSTANT c_unb2_board_cal_clk_freq         : NATURAL :=  40 * 10**6;  -- fixed 40 MHz IO calibration clock derived from ETH_clk by PLL
+  CONSTANT c_unb2_board_mm_clk_freq_10M      : NATURAL :=  10 * 10**6;  -- clock when g_sim=TRUE
+  CONSTANT c_unb2_board_mm_clk_freq_25M      : NATURAL :=  25 * 10**6;  -- clock derived from ETH_clk by PLL
+  CONSTANT c_unb2_board_mm_clk_freq_50M      : NATURAL :=  50 * 10**6;  -- clock derived from ETH_clk by PLL
+  CONSTANT c_unb2_board_mm_clk_freq_100M     : NATURAL := 100 * 10**6;  -- clock derived from ETH_clk by PLL
+  CONSTANT c_unb2_board_mm_clk_freq_125M     : NATURAL := 125 * 10**6;  -- clock derived from ETH_clk by PLL
+  
+  -- I2C
+  CONSTANT c_unb2_board_reg_sens_adr_w       : NATURAL := 3;  -- must match ceil_log2(c_mm_nof_dat) in unb2_board_sens_reg.vhd
+
+  CONSTANT c_i2c_peripheral_sens             : NATURAL := 0;
+  CONSTANT c_i2c_peripheral_pmbus            : NATURAL := 1;
+  CONSTANT c_i2c_peripheral_hmc              : NATURAL := 2;
+
+  -- ETH
+  CONSTANT c_unb2_board_nof_eth              : NATURAL := 2;  -- number of ETH channels per node
+  
+  -- CONSTANT RECORD DECLARATIONS ---------------------------------------------
+  
+  -- c_unb2_board_signature_* : random signature words used for unused status bits to ensure that the software reads the correct interface address
+  CONSTANT c_unb2_board_signature_eth1g_slv   : STD_LOGIC_VECTOR(31 DOWNTO 0) := X"46e46cbc";
+  CONSTANT c_unb2_board_signature_eth10g_slv  : STD_LOGIC_VECTOR(31 DOWNTO 0) := X"2bd2e40a";
+
+  CONSTANT c_unb2_board_signature_eth1g       : INTEGER := TO_SINT(c_unb2_board_signature_eth1g_slv  );
+  CONSTANT c_unb2_board_signature_eth10g      : INTEGER := TO_SINT(c_unb2_board_signature_eth10g_slv );
+  
+  -- Transceivers
+  TYPE t_c_unb2_board_tr IS RECORD
+    nof_bus                           : NATURAL;
+    bus_w                             : NATURAL;
+    i2c_w                             : NATURAL;
+  END RECORD;
+
+  --CONSTANT c_unb2_board_tr_back              : t_c_unb2_board_tr := (2, 24, 3); -- per node: 2 buses with 24 channels
+  CONSTANT c_unb2_board_tr_back              : t_c_unb2_board_tr := (1, 24, 3); -- per node: 1 buses with 24 channels (testing)
+  --CONSTANT c_unb2_board_tr_back              : t_c_unb2_board_tr := (2, 12, 3); -- per node: 2 buses with 24 channels (testing)
+  --CONSTANT c_unb2_board_tr_back              : t_c_unb2_board_tr := (2, 4, 3); -- per node: 2 buses with 24 channels (testing)
+
+  CONSTANT c_unb2_board_tr_ring              : t_c_unb2_board_tr := (2, 12, 0); -- per node: 2 buses with 12 channels
+  --CONSTANT c_unb2_board_tr_ring              : t_c_unb2_board_tr := (2, 4, 0); -- per node: 2 buses with 12 channels (testing)
+
+  CONSTANT c_unb2_board_tr_qsfp              : t_c_unb2_board_tr := (6, 4,  6); -- per node: 6 buses with 4 channels
+  CONSTANT c_unb2_board_tr_qsfp_nof_leds     : NATURAL := c_unb2_board_tr_qsfp.nof_bus * 2; -- 2 leds per qsfp
+
+
+  TYPE t_unb2_board_qsfp_bus_2arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_unb2_board_tr_qsfp.bus_w-1 DOWNTO 0);
+  TYPE t_unb2_board_ring_bus_2arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_unb2_board_tr_ring.bus_w-1 DOWNTO 0);
+  TYPE t_unb2_board_back_bus_2arr IS ARRAY (INTEGER RANGE <>) OF STD_LOGIC_VECTOR(c_unb2_board_tr_back.bus_w-1 DOWNTO 0);
+
+
+  -- Auxiliary
+  
+  -- Test IO Interface
+  TYPE t_c_unb2_board_testio IS RECORD  
+    tst_w                             : NATURAL;  -- = nof tst = 2; [tst_w-1 +tst_lo : tst_lo] = [5:4],
+    led_w                             : NATURAL;  -- = nof led = 2; [led_w-1 +led_lo : led_lo] = [3:2],
+    jmp_w                             : NATURAL;  -- = nof jmp = 2; [jmp_w-1 +jmp_lo : jmp_lo] = [1:0],
+    tst_lo                            : NATURAL;  -- = 2;
+    led_lo                            : NATURAL;  -- = 2;
+    jmp_lo                            : NATURAL;  -- = 0;
+  END RECORD;
+
+  CONSTANT c_unb2_board_testio               : t_c_unb2_board_testio := (2, 2, 2, 2, 2, 0);
+  CONSTANT c_unb2_board_testio_led_green     : NATURAL := c_unb2_board_testio.led_lo;
+  CONSTANT c_unb2_board_testio_led_red       : NATURAL := c_unb2_board_testio.led_lo+1;
+  
+  TYPE t_c_unb2_board_aux IS RECORD
+    version_w                         : NATURAL;  -- = 2;
+    id_w                              : NATURAL;  -- = 8;  -- 6+2 bits wide = total node ID for up to 64 UniBoards in a system and 4 nodes per board
+    chip_id_w                         : NATURAL;  -- = 2;  -- board node ID for the 4 FPGA nodes on a UniBoard
+    testio_w                          : NATURAL;  -- = 6;
+    testio                            : t_c_unb2_board_testio;
+  END RECORD;
+  
+  CONSTANT c_unb2_board_aux           : t_c_unb2_board_aux := (2, 8, c_unb2_board_nof_chip_w, 6, c_unb2_board_testio);
+  
+  TYPE t_e_unb2_board_node IS (e_any);
+
+  TYPE t_unb2_board_fw_version IS RECORD
+    hi                                : NATURAL;  -- = 0..15
+    lo                                : NATURAL;  -- = 0..15, firmware version is: hi.lo
+  END RECORD;
+  
+  CONSTANT c_unb2_board_fw_version    : t_unb2_board_fw_version := (0, 0);
+    
+  -- SIGNAL RECORD DECLARATIONS -----------------------------------------------
+  
+  
+  -- I2C, MDIO
+  -- . If no I2C bus arbitration or clock stretching is needed then the SCL only needs to be output.
+  -- . Can also be used for a PHY Management Data IO interface with serial clock MDC and serial data MDIO
+  TYPE t_unb2_board_i2c_inout IS RECORD  
+    scl : STD_LOGIC;  -- serial clock
+    sda : STD_LOGIC;  -- serial data
+  END RECORD;
+    
+  -- System info
+  TYPE t_c_unb2_board_system_info IS RECORD
+    version  : NATURAL;  -- UniBoard board HW version (2 bit value)
+    id       : NATURAL;  -- UniBoard FPGA node id (8 bit value)
+                         -- Derived ID info:
+    bck_id   : NATURAL;  -- = id[7:2], ID part from back plane
+    chip_id  : NATURAL;  -- = id[1:0], ID part from UniBoard
+    node_id  : NATURAL;  -- = id[1:0], node ID: 0, 1, 2 or 3
+    is_node2 : NATURAL;  -- 1 for Node 2, else 0.
+  END RECORD;
+
+  FUNCTION func_unb2_board_system_info(VERSION : IN STD_LOGIC_VECTOR(c_unb2_board_aux.version_w-1 DOWNTO 0);
+                                       ID      : IN STD_LOGIC_VECTOR(c_unb2_board_aux.id_w-1 DOWNTO 0)) RETURN t_c_unb2_board_system_info;
+                                
+END unb2_board_pkg;
+
+
+PACKAGE BODY unb2_board_pkg IS
+
+  FUNCTION func_unb2_board_system_info(VERSION : IN STD_LOGIC_VECTOR(c_unb2_board_aux.version_w-1 DOWNTO 0);
+                                       ID      : IN STD_LOGIC_VECTOR(c_unb2_board_aux.id_w-1 DOWNTO 0)) RETURN t_c_unb2_board_system_info IS
+    VARIABLE v_system_info : t_c_unb2_board_system_info;
+  BEGIN
+    v_system_info.version := TO_INTEGER(UNSIGNED(VERSION));
+    v_system_info.id      := TO_INTEGER(UNSIGNED(ID));
+    v_system_info.bck_id  := TO_INTEGER(UNSIGNED(ID(7 DOWNTO 2)));
+    v_system_info.chip_id := TO_INTEGER(UNSIGNED(ID(1 DOWNTO 0)));
+    v_system_info.node_id := TO_INTEGER(UNSIGNED(ID(1 DOWNTO 0)));
+    IF UNSIGNED(ID(1 DOWNTO 0))=2 THEN v_system_info.is_node2 := 1; ELSE v_system_info.is_node2 := 0; END IF;
+    RETURN v_system_info;
+  END;
+  
+END unb2_board_pkg;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_pmbus_ctrl.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_pmbus_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..934ac9f4beb8ca5a97cf3803134d19477c0a57fa
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_pmbus_ctrl.vhd
@@ -0,0 +1,192 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, i2c_lib;
+USE IEEE.std_logic_1164.ALL;
+USE i2c_lib.i2c_smbus_pkg.ALL;
+USE i2c_lib.i2c_dev_unb2_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+
+
+ENTITY unb2_board_pmbus_ctrl IS
+  GENERIC (
+    g_sim        : BOOLEAN := FALSE;
+    g_nof_result : NATURAL := 42;
+    g_temp_high  : NATURAL := 85
+  );
+  PORT (
+    rst        : IN  STD_LOGIC;
+    clk        : IN  STD_LOGIC;
+    start      : IN  STD_LOGIC;  -- pulse to start the I2C sequence to read out the sensors
+    out_dat    : OUT STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    out_val    : OUT STD_LOGIC;    
+    in_dat     : IN  STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    in_val     : IN  STD_LOGIC;
+    in_err     : IN  STD_LOGIC; 
+    in_ack     : IN  STD_LOGIC;
+    in_end     : IN  STD_LOGIC;
+    result_val : OUT STD_LOGIC;
+    result_err : OUT STD_LOGIC;
+    result_dat : OUT t_slv_8_arr(0 TO g_nof_result-1)
+  );
+END ENTITY;
+
+
+ARCHITECTURE rtl OF unb2_board_pmbus_ctrl IS
+
+  TYPE t_SEQUENCE IS ARRAY (NATURAL RANGE <>) OF NATURAL;
+  
+  -- The I2C bit rate is c_i2c_bit_rate = 50 [kbps], so 20 us period. Hence 20 us wait time for SDA is enough
+  -- Assume clk <= 200 MHz, so 5 ns period. Hence timeout of 4000 is enough.
+  CONSTANT c_timeout_sda : NATURAL := sel_a_b(g_sim, 0, 16);  -- wait 16 * 256 = 4096 clk periods
+  
+  CONSTANT c_SEQ : t_SEQUENCE := (
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE, -- RX supply
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR0_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE, -- TX supply
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_TCVR1_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CORE_BMR464_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_CTRL_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_FPGAIO_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_PMB_VCCRAM_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_C_SAMPLE_SDA, 0, c_timeout_sda, 0, 0,
+    SMBUS_C_END,
+    SMBUS_C_NOP
+  );
+    
+  CONSTANT c_seq_len : NATURAL := c_SEQ'LENGTH-1;
+  
+  -- The protocol list c_SEQ yields a list of result bytes (result_dat)
+  -- make sure that g_nof_result matches the number of result bytes
+  
+  SIGNAL start_reg       : STD_LOGIC;
+  
+  SIGNAL seq_cnt         : NATURAL RANGE 0 TO c_seq_len := c_seq_len;
+  SIGNAL nxt_seq_cnt     : NATURAL;
+  
+  SIGNAL rx_cnt          : NATURAL RANGE 0 TO g_nof_result;
+  SIGNAL nxt_rx_cnt      : NATURAL;
+  
+  SIGNAL rx_val          : STD_LOGIC;
+  SIGNAL nxt_rx_val      : STD_LOGIC;
+  SIGNAL rx_err          : STD_LOGIC;
+  SIGNAL nxt_rx_err      : STD_LOGIC;
+  SIGNAL rx_dat          : t_slv_8_arr(result_dat'RANGE);  
+  SIGNAL nxt_rx_dat      : t_slv_8_arr(result_dat'RANGE); 
+  SIGNAL nxt_result_val  : STD_LOGIC;
+  SIGNAL nxt_result_err  : STD_LOGIC;
+  SIGNAL i_result_dat    : t_slv_8_arr(result_dat'RANGE);  
+  SIGNAL nxt_result_dat  : t_slv_8_arr(result_dat'RANGE);   
+  
+BEGIN
+
+  result_dat <= i_result_dat;
+
+  regs: PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      start_reg     <= '0';
+      seq_cnt       <= c_seq_len;
+      rx_cnt        <= 0;
+      rx_val        <= '0';
+      rx_err        <= '0';
+      rx_dat        <= (OTHERS=>(OTHERS=>'0'));
+      result_val    <= '0';
+      result_err    <= '0';
+      i_result_dat  <= (OTHERS=>(OTHERS=>'0'));
+    ELSIF rising_edge(clk) THEN
+      start_reg     <= start;
+      seq_cnt       <= nxt_seq_cnt;
+      rx_cnt        <= nxt_rx_cnt;
+      rx_val        <= nxt_rx_val;
+      rx_err        <= nxt_rx_err;
+      rx_dat        <= nxt_rx_dat;
+      result_val    <= nxt_result_val;
+      result_err    <= nxt_result_err;
+      i_result_dat  <= nxt_result_dat;
+    END IF;
+  END PROCESS;
+  
+  -- Issue the protocol list
+  p_seq_cnt : PROCESS(seq_cnt, start_reg, in_ack)
+  BEGIN
+    nxt_seq_cnt <= seq_cnt;
+    IF start_reg = '1' THEN
+      nxt_seq_cnt <= 0;
+    ELSIF seq_cnt<c_seq_len AND in_ack='1' THEN
+      nxt_seq_cnt <= seq_cnt + 1;
+    END IF;
+  END PROCESS;
+
+  out_dat <= STD_LOGIC_VECTOR(TO_UVEC(c_SEQ(seq_cnt), c_byte_w));
+  out_val <= '1' WHEN seq_cnt<c_seq_len ELSE '0';
+  
+  -- Fill the rx_dat byte array
+  p_rx_dat : PROCESS(start_reg, rx_err, in_err, rx_dat, rx_cnt, in_dat, in_val)
+  BEGIN
+    nxt_rx_err <= rx_err;
+    IF start_reg = '1' THEN
+      nxt_rx_err <= '0';
+    ELSIF in_err='1' THEN
+      nxt_rx_err <= '1';
+    END IF;
+    
+    nxt_rx_dat <= rx_dat;
+    nxt_rx_cnt <= rx_cnt;
+    IF start_reg = '1' THEN
+      nxt_rx_dat <= (OTHERS=>(OTHERS=>'0'));
+      nxt_rx_cnt <= 0;
+    ELSIF in_val='1' THEN
+      nxt_rx_dat(rx_cnt) <= in_dat;
+      nxt_rx_cnt         <= rx_cnt + 1;
+    END IF;
+  END PROCESS;
+
+  nxt_rx_val <= in_end;
+  
+  -- Capture the complete rx_dat byte array
+  nxt_result_val <= rx_val;
+  nxt_result_err <= rx_err;
+  nxt_result_dat <= rx_dat WHEN rx_val='1' ELSE i_result_dat;
+    
+END rtl;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_qsfp_leds.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_qsfp_leds.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..f90d2dc68961b44125a049a8e170d394778f678e
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_qsfp_leds.vhd
@@ -0,0 +1,186 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+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;
+
+-- 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.
+--
+--   LED lights:
+--  
+--   1) Default behaviour for all QSFP leds:
+--      . off = no FPGA image is running
+--
+--   2) For factory image:
+--      . green off
+--      . red toggling every 1 s = factory image is running (g_factory_image=TRUE)
+--  
+--   3) For a user image without Gbps lane functionality: 
+--      . red off
+--      . green toggling every 1 s = user image is running (g_factory_image=FALSE and green_on_arr(I)='0' default)
+--
+--   4) For a user image with Gbps lane functionality:
+--      . red off
+--      . 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.
+--
+
+ENTITY unb2_board_qsfp_leds 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_pulse_us        : NATURAL := 200           -- nof clk cycles to get us period
+  );
+  PORT (
+    rst               : IN  STD_LOGIC;
+    clk               : IN  STD_LOGIC;
+    -- internal pulser outputs
+    pulse_us          : OUT STD_LOGIC;
+    pulse_ms          : OUT STD_LOGIC;
+    pulse_s           : OUT STD_LOGIC;
+    -- lane status
+    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 unb2_board_qsfp_leds;
+
+
+ARCHITECTURE str OF unb2_board_qsfp_leds 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
+  
+  SIGNAL i_pulse_ms         : STD_LOGIC;
+  SIGNAL i_pulse_s          : STD_LOGIC;
+  SIGNAL toggle_s           : STD_LOGIC;
+  
+  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
+
+  pulse_ms <= i_pulse_ms;
+  pulse_s  <= i_pulse_s;
+
+  -- Also output the pulses, because they could be useful for other purposes in the clk clock domain as well
+  u_common_pulser_us_ms_s : ENTITY common_lib.common_pulser_us_ms_s
+  GENERIC MAP (
+    g_pulse_us  => g_pulse_us,                 -- nof 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         => rst,
+    clk         => clk,
+    pulse_us    => pulse_us,
+    pulse_ms    => i_pulse_ms,
+    pulse_s     => i_pulse_s
+  );
+
+  u_common_toggle_s : ENTITY common_lib.common_toggle
+  PORT MAP (
+    rst         => rst,
+    clk         => clk,
+    in_dat      => i_pulse_s,
+    out_dat     => toggle_s
+  );
+  
+  gen_factory_image : IF g_factory_image=TRUE GENERATE
+    green_led_arr <= (OTHERS=>'0');
+    
+    gen_red_led_arr : FOR I IN g_nof_qsfp-1 DOWNTO 0 GENERATE
+      u_red_led_controller : ENTITY common_lib.common_led_controller
+      GENERIC MAP (
+        g_nof_ms      => c_nof_ms
+      )
+      PORT MAP (
+        rst           => rst,
+        clk           => clk,
+        -- led control
+        ctrl_input    => toggle_s,
+        -- led output
+        led           => red_led_arr(I)
+      );
+    END GENERATE;
+  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(clk);
+      green_evt_arr(I) <= tx_sosi_arr(I).sop OR rx_sosi_arr(I).sop WHEN rising_edge(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           => rst,
+        clk           => clk,
+        pulse_ms      => i_pulse_ms,
+        -- led control
+        ctrl_on       => qsfp_on_arr(I),
+        ctrl_evt      => qsfp_evt_arr(I),
+        ctrl_input    => toggle_s,
+        -- led output
+        led           => green_led_arr(I)
+      );
+    END GENERATE;    
+  END GENERATE;
+  
+END str;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_ring_io.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_ring_io.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..2c924997a546d3de8092e6107b80f868482b3617
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_ring_io.vhd
@@ -0,0 +1,63 @@
+------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE work.unb2_board_pkg.ALL;
+
+
+ENTITY unb2_board_ring_io IS
+  GENERIC (
+    g_nof_ring_bus : NATURAL := c_unb2_board_tr_ring.nof_bus
+  );
+  PORT (
+    serial_tx_arr  : IN  STD_LOGIC_VECTOR(g_nof_ring_bus * c_unb2_board_tr_ring.bus_w-1 DOWNTO 0) := (OTHERS=>'0');
+    serial_rx_arr  : OUT STD_LOGIC_VECTOR(g_nof_ring_bus * c_unb2_board_tr_ring.bus_w-1 DOWNTO 0);
+
+    RING_RX        : IN    t_unb2_board_ring_bus_2arr(g_nof_ring_bus-1 DOWNTO 0) := (OTHERS=>(OTHERS=>'0'));
+    RING_TX        : OUT   t_unb2_board_ring_bus_2arr(g_nof_ring_bus-1 DOWNTO 0)
+  );
+END unb2_board_ring_io;
+
+ARCHITECTURE str OF unb2_board_ring_io IS
+
+  -- help signals so we can iterate through buses
+  SIGNAL si_tx_2arr : t_unb2_board_ring_bus_2arr(g_nof_ring_bus-1 DOWNTO 0);
+  SIGNAL si_rx_2arr : t_unb2_board_ring_bus_2arr(g_nof_ring_bus-1 DOWNTO 0);
+
+BEGIN
+
+  gen_buses : FOR i IN 0 TO g_nof_ring_bus-1 GENERATE
+    RING_TX(i)    <= si_tx_2arr(i);
+    si_rx_2arr(i) <= RING_RX(i);
+  END GENERATE;
+
+
+  gen_wire_bus : FOR i IN 0 TO g_nof_ring_bus-1 GENERATE
+    gen_wire_signals : FOR j IN 0 TO c_unb2_board_tr_ring.bus_w-1 GENERATE
+
+      si_tx_2arr(i)(j) <= serial_tx_arr(i*c_unb2_board_tr_ring.bus_w + j);
+      serial_rx_arr(i*c_unb2_board_tr_ring.bus_w + j) <= si_rx_2arr(i)(j);
+
+    END GENERATE;
+  END GENERATE;
+
+END;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..6ef9b2c0ccd50fbd649779aa295f69409429b47c
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens.vhd
@@ -0,0 +1,176 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, i2c_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE i2c_lib.i2c_pkg.ALL;
+USE work.unb2_board_pkg.ALL;
+
+ENTITY unb2_board_sens is
+  GENERIC (
+    g_sim             : BOOLEAN := FALSE;
+    g_i2c_peripheral  : NATURAL;
+    g_clk_freq        : NATURAL := 100*10**6;  -- clk frequency in Hz
+    g_temp_high       : NATURAL := 85;
+    g_sens_nof_result : NATURAL; -- Should match nof read bytes via I2C in the unb2_board_sens_ctrl SEQUENCE list
+    g_comma_w         : NATURAL := 0
+  );
+  PORT (
+    rst          : IN    STD_LOGIC;
+    clk          : IN    STD_LOGIC;
+    start        : IN    STD_LOGIC;
+    -- i2c bus
+    scl          : INOUT STD_LOGIC;
+    sda          : INOUT STD_LOGIC;
+    -- read results
+    sens_evt     : OUT   STD_LOGIC;
+    sens_err     : OUT   STD_LOGIC;
+    sens_data    : OUT   t_slv_8_arr(0 TO g_sens_nof_result-1)
+  );
+END ENTITY;
+
+
+ARCHITECTURE str OF unb2_board_sens IS
+
+  -- I2C clock rate settings
+  CONSTANT c_sens_clk_cnt      : NATURAL := sel_a_b(g_sim, 1, func_i2c_calculate_clk_cnt(g_clk_freq/10**6));  -- define I2C clock rate
+  --CONSTANT c_sens_comma_w      : NATURAL := 13;  -- 2**c_i2c_comma_w * system clock period comma time after I2C start and after each octet
+                                                -- 0 = no comma time
+
+-- octave:4> t=1/50e6
+-- t =  2.0000e-08
+-- octave:5> delay=2^13 * t
+-- delay =  1.6384e-04
+-- octave:6> delay/t
+-- ans =  8192
+-- octave:7> log2(ans)
+-- ans =  13
+-- octave:8> log2(delay/t)
+-- ans =  13
+
+  
+  --CONSTANT c_sens_phy          : t_c_i2c_phy := (c_sens_clk_cnt, c_sens_comma_w);
+  CONSTANT c_sens_phy          : t_c_i2c_phy := (c_sens_clk_cnt, g_comma_w);
+  
+  SIGNAL smbus_in_dat  : STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+  SIGNAL smbus_in_val  : STD_LOGIC;
+  SIGNAL smbus_out_dat : STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+  SIGNAL smbus_out_val : STD_LOGIC;
+  SIGNAL smbus_out_err : STD_LOGIC;
+  SIGNAL smbus_out_ack : STD_LOGIC;
+  SIGNAL smbus_out_end : STD_LOGIC;
+
+BEGIN
+
+  gen_unb2_board_sens_ctrl : IF g_i2c_peripheral=c_i2c_peripheral_sens GENERATE
+    u_unb2_board_sens_ctrl : ENTITY work.unb2_board_sens_ctrl
+    GENERIC MAP (
+      g_sim        => g_sim,
+      g_nof_result => g_sens_nof_result,
+      g_temp_high  => g_temp_high
+    )
+    PORT MAP (
+      clk         => clk,
+      rst         => rst,
+      start       => start,
+      in_dat      => smbus_out_dat,
+      in_val      => smbus_out_val,
+      in_err      => smbus_out_err,
+      in_ack      => smbus_out_ack,
+      in_end      => smbus_out_end,
+      out_dat     => smbus_in_dat,
+      out_val     => smbus_in_val,
+      result_val  => sens_evt,
+      result_err  => sens_err,
+      result_dat  => sens_data
+    );
+  END GENERATE;
+
+  gen_unb2_board_pmbus_ctrl : IF g_i2c_peripheral=c_i2c_peripheral_pmbus GENERATE
+    u_unb2_board_pmbus_ctrl : ENTITY work.unb2_board_pmbus_ctrl
+    GENERIC MAP (
+      g_sim        => g_sim,
+      g_nof_result => g_sens_nof_result,
+      g_temp_high  => g_temp_high
+    )
+    PORT MAP (
+      clk         => clk,
+      rst         => rst,
+      start       => start,
+      in_dat      => smbus_out_dat,
+      in_val      => smbus_out_val,
+      in_err      => smbus_out_err,
+      in_ack      => smbus_out_ack,
+      in_end      => smbus_out_end,
+      out_dat     => smbus_in_dat,
+      out_val     => smbus_in_val,
+      result_val  => sens_evt,
+      result_err  => sens_err,
+      result_dat  => sens_data
+    );
+  END GENERATE;
+
+  gen_unb2_board_hmc_ctrl : IF g_i2c_peripheral=c_i2c_peripheral_hmc GENERATE
+    u_unb2_board_hmc_ctrl : ENTITY work.unb2_board_hmc_ctrl
+    GENERIC MAP (
+      g_sim        => g_sim,
+      g_nof_result => g_sens_nof_result,
+      g_temp_high  => g_temp_high
+    )
+    PORT MAP (
+      clk         => clk,
+      rst         => rst,
+      start       => start,
+      in_dat      => smbus_out_dat,
+      in_val      => smbus_out_val,
+      in_err      => smbus_out_err,
+      in_ack      => smbus_out_ack,
+      in_end      => smbus_out_end,
+      out_dat     => smbus_in_dat,
+      out_val     => smbus_in_val,
+      result_val  => sens_evt,
+      result_err  => sens_err,
+      result_dat  => sens_data
+    );
+  END GENERATE;
+
+  u_i2c_smbus : ENTITY i2c_lib.i2c_smbus
+  GENERIC MAP (
+    g_i2c_phy                 => c_sens_phy,
+    g_clock_stretch_sense_scl => TRUE
+  )
+  PORT MAP (
+    gs_sim      => g_sim,
+    clk         => clk,
+    rst         => rst,
+    in_dat      => smbus_in_dat,
+    in_req      => smbus_in_val,
+    out_dat     => smbus_out_dat,
+    out_val     => smbus_out_val,
+    out_err     => smbus_out_err,
+    out_ack     => smbus_out_ack,
+    st_end      => smbus_out_end,
+    scl         => scl,
+    sda         => sda
+  );
+
+END ARCHITECTURE;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens_ctrl.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..fcaac6c2a37bc42a48a04406b3af61057853699b
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens_ctrl.vhd
@@ -0,0 +1,208 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib, i2c_lib;
+USE IEEE.std_logic_1164.ALL;
+USE i2c_lib.i2c_smbus_pkg.ALL;
+USE i2c_lib.i2c_dev_max1617_pkg.ALL;
+USE i2c_lib.i2c_dev_ltc4260_pkg.ALL;
+USE i2c_lib.i2c_dev_unb2_pkg.ALL;
+USE common_lib.common_pkg.ALL;
+
+
+ENTITY unb2_board_sens_ctrl IS
+  GENERIC (
+    g_sim        : BOOLEAN := FALSE;
+    g_nof_result : NATURAL := 40;
+    g_temp_high  : NATURAL := 85
+  );
+  PORT (
+    rst        : IN  STD_LOGIC;
+    clk        : IN  STD_LOGIC;
+    start      : IN  STD_LOGIC;  -- pulse to start the I2C sequence to read out the sensors
+    out_dat    : OUT STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    out_val    : OUT STD_LOGIC;    
+    in_dat     : IN  STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+    in_val     : IN  STD_LOGIC;
+    in_err     : IN  STD_LOGIC; 
+    in_ack     : IN  STD_LOGIC;
+    in_end     : IN  STD_LOGIC;
+    result_val : OUT STD_LOGIC;
+    result_err : OUT STD_LOGIC;
+    result_dat : OUT t_slv_8_arr(0 TO g_nof_result-1)
+  );
+END ENTITY;
+
+
+ARCHITECTURE rtl OF unb2_board_sens_ctrl IS
+
+  -- I2C slave commands of the devices on the I2C bus on UniBoard
+  CONSTANT TMP451_LOC_HI : NATURAL := 16#00#;
+  CONSTANT TMP451_LOC_LO : NATURAL := 16#15#;
+  CONSTANT TMP451_REM_HI : NATURAL := 16#01#;
+  CONSTANT TMP451_REM_LO : NATURAL := 16#10#;
+
+  CONSTANT CAT24C02_ADR_00 : NATURAL := 16#00#; -- should contain 'H'
+  CONSTANT CAT24C02_ADR_01 : NATURAL := 16#01#; -- should contain 'a'
+  CONSTANT CAT24C02_ADR_02 : NATURAL := 16#02#; -- should contain 'r'
+  CONSTANT CAT24C02_ADR_03 : NATURAL := 16#03#; -- should contain 'r'
+  CONSTANT CAT24C02_ADR_04 : NATURAL := 16#04#; -- should contain 'o'
+
+  TYPE t_SEQUENCE IS ARRAY (NATURAL RANGE <>) OF NATURAL;
+  
+  -- The I2C bit rate is c_i2c_bit_rate = 50 [kbps], so 20 us period. Hence 20 us wait time for SDA is enough
+  -- Assume clk <= 200 MHz, so 5 ns period. Hence timeout of 4000 is enough.
+  CONSTANT c_timeout_sda : NATURAL := sel_a_b(g_sim, 0, 16);  -- wait 16 * 256 = 4096 clk periods
+  
+  CONSTANT c_SEQ : t_SEQUENCE := (
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_EEPROM_CAT24C02_ADR, CAT24C02_ADR_00,
+
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_TEMP_TMP451_ADR, TMP451_LOC_HI,
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_TEMP_TMP451_ADR, TMP451_LOC_LO,
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_TEMP_TMP451_ADR, TMP451_REM_HI,
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_TEMP_TMP451_ADR, TMP451_REM_LO,
+
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_QSFP0_BMR464_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_QSFP0_BMR464_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_QSFP0_BMR464_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_QSFP0_BMR464_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_QSFP1_BMR464_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_QSFP1_BMR464_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_QSFP1_BMR464_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_QSFP1_BMR464_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_CLK_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_CLK_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_CLK_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_CLK_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_3V3_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_3V3_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_3V3_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_3V3_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_READ_BYTE , I2C_UNB2_SENS_1V2_BMR461_ADR, PMBUS_REG_READ_VOUT_MODE,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_1V2_BMR461_ADR, PMBUS_REG_READ_VOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_1V2_BMR461_ADR, PMBUS_REG_READ_IOUT,
+    SMBUS_READ_WORD , I2C_UNB2_SENS_1V2_BMR461_ADR, PMBUS_REG_READ_TEMP,
+
+    SMBUS_C_SAMPLE_SDA, 0, c_timeout_sda, 0, 0,
+    SMBUS_C_END,
+    SMBUS_C_NOP
+  );
+    
+  CONSTANT c_seq_len : NATURAL := c_SEQ'LENGTH-1;
+  
+  -- The protocol list c_SEQ yields a list of result bytes (result_dat)
+  -- make sure that g_nof_result matches the number of result bytes
+  
+  SIGNAL start_reg       : STD_LOGIC;
+  
+  SIGNAL seq_cnt         : NATURAL RANGE 0 TO c_seq_len := c_seq_len;
+  SIGNAL nxt_seq_cnt     : NATURAL;
+  
+  SIGNAL rx_cnt          : NATURAL RANGE 0 TO g_nof_result;
+  SIGNAL nxt_rx_cnt      : NATURAL;
+  
+  SIGNAL rx_val          : STD_LOGIC;
+  SIGNAL nxt_rx_val      : STD_LOGIC;
+  SIGNAL rx_err          : STD_LOGIC;
+  SIGNAL nxt_rx_err      : STD_LOGIC;
+  SIGNAL rx_dat          : t_slv_8_arr(result_dat'RANGE);  
+  SIGNAL nxt_rx_dat      : t_slv_8_arr(result_dat'RANGE); 
+  SIGNAL nxt_result_val  : STD_LOGIC;
+  SIGNAL nxt_result_err  : STD_LOGIC;
+  SIGNAL i_result_dat    : t_slv_8_arr(result_dat'RANGE);  
+  SIGNAL nxt_result_dat  : t_slv_8_arr(result_dat'RANGE);   
+  
+BEGIN
+
+  result_dat <= i_result_dat;
+
+  regs: PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      start_reg     <= '0';
+      seq_cnt       <= c_seq_len;
+      rx_cnt        <= 0;
+      rx_val        <= '0';
+      rx_err        <= '0';
+      rx_dat        <= (OTHERS=>(OTHERS=>'0'));
+      result_val    <= '0';
+      result_err    <= '0';
+      i_result_dat  <= (OTHERS=>(OTHERS=>'0'));
+    ELSIF rising_edge(clk) THEN
+      start_reg     <= start;
+      seq_cnt       <= nxt_seq_cnt;
+      rx_cnt        <= nxt_rx_cnt;
+      rx_val        <= nxt_rx_val;
+      rx_err        <= nxt_rx_err;
+      rx_dat        <= nxt_rx_dat;
+      result_val    <= nxt_result_val;
+      result_err    <= nxt_result_err;
+      i_result_dat  <= nxt_result_dat;
+    END IF;
+  END PROCESS;
+  
+  -- Issue the protocol list
+  p_seq_cnt : PROCESS(seq_cnt, start_reg, in_ack)
+  BEGIN
+    nxt_seq_cnt <= seq_cnt;
+    IF start_reg = '1' THEN
+      nxt_seq_cnt <= 0;
+    ELSIF seq_cnt<c_seq_len AND in_ack='1' THEN
+      nxt_seq_cnt <= seq_cnt + 1;
+    END IF;
+  END PROCESS;
+
+  out_dat <= STD_LOGIC_VECTOR(TO_UVEC(c_SEQ(seq_cnt), c_byte_w));
+  out_val <= '1' WHEN seq_cnt<c_seq_len ELSE '0';
+  
+  -- Fill the rx_dat byte array
+  p_rx_dat : PROCESS(start_reg, rx_err, in_err, rx_dat, rx_cnt, in_dat, in_val)
+  BEGIN
+    nxt_rx_err <= rx_err;
+    IF start_reg = '1' THEN
+      nxt_rx_err <= '0';
+    ELSIF in_err='1' THEN
+      nxt_rx_err <= '1';
+    END IF;
+    
+    nxt_rx_dat <= rx_dat;
+    nxt_rx_cnt <= rx_cnt;
+    IF start_reg = '1' THEN
+      nxt_rx_dat <= (OTHERS=>(OTHERS=>'0'));
+      nxt_rx_cnt <= 0;
+    ELSIF in_val='1' THEN
+      nxt_rx_dat(rx_cnt) <= in_dat;
+      nxt_rx_cnt         <= rx_cnt + 1;
+    END IF;
+  END PROCESS;
+
+  nxt_rx_val <= in_end;
+  
+  -- Capture the complete rx_dat byte array
+  nxt_result_val <= rx_val;
+  nxt_result_err <= rx_err;
+  nxt_result_dat <= rx_dat WHEN rx_val='1' ELSE i_result_dat;
+    
+END rtl;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens_reg.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens_reg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..e38265c892ebbcc6bf09e1ba56aaa5eeef87cdb0
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_sens_reg.vhd
@@ -0,0 +1,162 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Provide MM slave register for unb2_board_sens
+-- Description:
+--
+--   31             24 23             16 15              8 7               0  wi
+--  |-----------------|-----------------|-----------------|-----------------|
+--  |                xxx                     fpga_temp   = sens_data[0][7:0]|  0
+--  |-----------------------------------------------------------------------|
+--  |                xxx                     eth_temp    = sens_data[1][7:0]|  1
+--  |-----------------------------------------------------------------------|
+--  |                xxx               hot_swap_v_sense  = sens_data[2][7:0]|  2
+--  |-----------------------------------------------------------------------|
+--  |                xxx               hot_swap_v_source = sens_data[3][7:0]|  3
+--  |-----------------------------------------------------------------------|
+--  |                xxx                                         sens_err[0]|  4
+--  |-----------------------------------------------------------------------|
+--  |                xxx                                      temp_high[6:0]|  5
+--  |-----------------------------------------------------------------------|
+--
+-- * The fpga_temp and eth_temp are in degrees (two's complement)
+-- * The hot swap voltages depend on:
+--   . From i2c_dev_ltc4260_pkg:
+--     LTC4260_V_UNIT_SENSE        = 0.0003  --   0.3 mV over Rs for current sense
+--     LTC4260_V_UNIT_SOURCE       = 0.4     -- 400   mV supply voltage (e.g +48 V)
+--     LTC4260_V_UNIT_ADIN         = 0.01    --  10   mV ADC
+--
+--   . From UniBoard unb_sensors.h:
+--     SENS_HOT_SWAP_R_SENSE       = 0.005   -- R sense on UniBoard is 5 mOhm (~= 10 mOhm // 10 mOhm)
+--     SENS_HOT_SWAP_I_UNIT_SENSE  = LTC4260_V_UNIT_SENSE / SENS_HOT_SWAP_R_SENSE
+--     SENS_HOT_SWAP_V_UNIT_SOURCE = LTC4260_V_UNIT_SOURCE
+--
+-- ==> 
+--   Via all nodes:
+--   0 = FPGA temperature                 = TInt8(fpga_temp)
+--   Only via node2:
+--   1 = UniBoard ETH PHY temperature     = TInt8(eth_temp)
+--   2 = UniBoard hot swap supply current = hot_swap_v_sense * SENS_HOT_SWAP_I_UNIT_SENSE
+--   3 = UniBoard hot swap supply voltage = hot_swap_v_source * SENS_HOT_SWAP_V_UNIT_SOURCE
+--   4 = I2C error status for node2 sensors access only, 0 = ok
+--   
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+
+ENTITY unb2_board_sens_reg IS
+  GENERIC (
+    g_sens_nof_result : NATURAL := 4;
+    g_temp_high       : NATURAL := 85
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst     : IN  STD_LOGIC;   -- reset synchronous with mm_clk
+    mm_clk     : IN  STD_LOGIC;   -- memory-mapped bus clock
+    
+    -- Memory Mapped Slave in mm_clk domain
+    sla_in     : IN  t_mem_mosi;  -- actual ranges defined by c_mm_reg
+    sla_out    : OUT t_mem_miso;  -- actual ranges defined by c_mm_reg
+    
+    -- MM registers
+    sens_err   : IN  STD_LOGIC := '0';
+    sens_data  : IN  t_slv_8_arr(0 TO g_sens_nof_result-1);
+
+    -- Max temp output
+    temp_high  : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
+
+  );
+END unb2_board_sens_reg;
+
+
+ARCHITECTURE rtl OF unb2_board_sens_reg IS
+
+  -- Define the actual size of the MM slave register
+  CONSTANT c_mm_nof_dat : NATURAL := g_sens_nof_result+1+1;  -- +1 to fit user set temp_high one additional address
+                                                             -- +1 to fit sens_err in the last address
+
+  CONSTANT c_mm_reg     : t_c_mem := (latency  => 1,
+                                      adr_w    => ceil_log2(c_mm_nof_dat),
+                                      dat_w    => c_word_w,  -- Use MM bus data width = c_word_w = 32 for all MM registers
+                                      nof_dat  => c_mm_nof_dat,
+                                      init_sl  => '0');
+
+  SIGNAL i_temp_high    : STD_LOGIC_VECTOR(6 DOWNTO 0);
+                                  
+BEGIN
+
+  temp_high <= i_temp_high;
+
+  ------------------------------------------------------------------------------
+  -- MM register access in the mm_clk domain
+  -- . Hardcode the shared MM slave register directly in RTL instead of using
+  --   the common_reg_r_w instance. Directly using RTL is easier when the large
+  --   MM register has multiple different fields and with different read and
+  --   write options per field in one MM register.
+  ------------------------------------------------------------------------------
+  
+  p_mm_reg : PROCESS (mm_rst, mm_clk)
+    VARIABLE vA : NATURAL := 0;
+  BEGIN
+    IF mm_rst = '1' THEN
+      -- Read access
+      sla_out <= c_mem_miso_rst;
+      -- Write access, register values
+      i_temp_high <= TO_UVEC(g_temp_high, 7);
+
+    ELSIF rising_edge(mm_clk) THEN
+      vA := TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0));
+      
+      -- Read access defaults
+      sla_out.rdval <= '0';
+      
+      -- Write access: set register value
+      IF sla_in.wr = '1' THEN
+        IF vA = g_sens_nof_result+1 THEN
+            -- Only change temp_high if user writes a max. 7-bit value. This prevents accidentally
+            -- setting a negative temp as temp_high, e.g. 128 which becomes -128. 
+            IF UNSIGNED(sla_in.wrdata(c_word_w-1 DOWNTO 7)) = 0 THEN 
+              i_temp_high <= sla_in.wrdata(6 DOWNTO 0);
+            END IF;
+        END IF;
+  
+      -- Read access: get register value
+      ELSIF sla_in.rd = '1' THEN
+        sla_out        <= c_mem_miso_rst;  -- set unused rddata bits to '0' when read
+        sla_out.rdval  <= '1';             -- c_mm_reg.latency = 1
+        
+        -- no need to capture sens_data, it is not critical if the sens_data happens to be read just before and after an I2C access occurred
+        IF vA < g_sens_nof_result THEN
+          sla_out.rddata <= RESIZE_MEM_DATA(sens_data(vA)(c_byte_w-1 DOWNTO 0));
+        ELSIF vA = g_sens_nof_result THEN
+          sla_out.rddata(0) <= sens_err;   -- only valid for node2
+        ELSE
+          sla_out.rddata(6 DOWNTO 0) <= i_temp_high; 
+        END IF;
+        -- else unused addresses read zero
+      END IF;
+    END IF;
+  END PROCESS;
+  
+END rtl;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_system_info.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_system_info.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a2be55ca47eb6b352b5cbee26ae7a584d3b23a6e
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_system_info.vhd
@@ -0,0 +1,102 @@
+--------------------------------------------------------------------------------
+--
+-- Copyright (C) 2009-2014
+-- 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/>.
+--
+--------------------------------------------------------------------------------
+ 
+LIBRARY IEEE, common_lib, technology_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE work.unb2_board_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+
+-- Keep the UniBoard system info knowledge in this HDL entity and in the
+-- corresponding software functions in unb_common.c,h. This avoids having to
+-- define named constants for indexing the fields in the info word.
+
+ENTITY unb2_board_system_info IS
+  GENERIC (
+    g_sim        : BOOLEAN := FALSE;
+    g_fw_version : t_unb2_board_fw_version := c_unb2_board_fw_version;  -- firmware version x.y (4b.4b)
+    g_aux        : t_c_unb2_board_aux := c_unb2_board_aux;              -- aux contains the hardware version
+    g_rom_version: NATURAL := 1;
+    g_technology : NATURAL := c_tech_arria10
+  );
+  PORT (
+    clk         : IN  STD_LOGIC;
+    hw_version  : IN  STD_LOGIC_VECTOR(g_aux.version_w-1 DOWNTO 0);
+    id          : IN  STD_LOGIC_VECTOR(g_aux.id_w-1 DOWNTO 0);
+    info        : OUT STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0);
+    bck_id      : OUT STD_LOGIC_VECTOR(c_unb2_board_nof_uniboard_w-1 DOWNTO 0); -- ID[7:2]
+    chip_id     : OUT STD_LOGIC_VECTOR(c_unb2_board_nof_chip_w-1 DOWNTO 0);     -- ID[1:0]
+    node_id     : OUT STD_LOGIC_VECTOR(c_unb2_board_nof_node_w-1 DOWNTO 0);     -- ID[1:0]
+    is_node2    : OUT STD_LOGIC   -- '1' for Node 2, else '0'.
+  );
+END unb2_board_system_info;
+
+
+ARCHITECTURE str OF unb2_board_system_info IS
+
+  SIGNAL cs_sim         : STD_LOGIC;
+  
+  SIGNAL hw_version_reg : STD_LOGIC_VECTOR(hw_version'RANGE);
+  SIGNAL id_reg         : STD_LOGIC_VECTOR(id'RANGE);
+  SIGNAL nxt_info       : STD_LOGIC_VECTOR(info'RANGE);
+
+  SIGNAL nxt_bck_id     : STD_LOGIC_VECTOR(bck_id'RANGE);
+  SIGNAL nxt_chip_id    : STD_LOGIC_VECTOR(chip_id'RANGE);
+  SIGNAL nxt_node_id    : STD_LOGIC_VECTOR(node_id'RANGE);
+  SIGNAL nxt_is_node2   : STD_LOGIC;
+  
+BEGIN
+
+  p_reg : PROCESS(clk)
+  BEGIN
+    IF rising_edge(clk) THEN
+      -- inputs
+      hw_version_reg <= hw_version;
+      id_reg         <= id;
+      -- output
+      info           <= nxt_info;
+      bck_id         <= nxt_bck_id;
+      chip_id        <= nxt_chip_id;
+      node_id        <= nxt_node_id;
+      is_node2       <= nxt_is_node2;
+    END IF;
+  END PROCESS;
+  
+  cs_sim <= is_true(g_sim);
+
+  p_info : PROCESS(cs_sim, hw_version_reg, id_reg)
+  BEGIN
+    nxt_info(31 DOWNTO 27) <= TO_UVEC(g_technology, 5);
+    nxt_info(26 DOWNTO 24) <= TO_UVEC(g_rom_version, 3);
+    nxt_info(23 DOWNTO 20) <= TO_UVEC(g_fw_version.hi, 4);
+    nxt_info(19 DOWNTO 16) <= TO_UVEC(g_fw_version.lo, 4);
+    nxt_info(10)           <= cs_sim;
+    nxt_info(9 DOWNTO 8)   <= hw_version_reg;
+    nxt_info(7 DOWNTO 0)   <= id_reg;
+  END PROCESS;
+ 
+  nxt_bck_id   <= id_reg(7 DOWNTO 2);
+  nxt_chip_id  <= id_reg(1 DOWNTO 0);
+  nxt_node_id  <= id_reg(1 DOWNTO 0);
+  nxt_is_node2 <= '1' WHEN TO_UINT(id_reg(1 DOWNTO 0)) = 2 ELSE '0';
+  
+END str;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_system_info_reg.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_system_info_reg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..08e9c515ba5ee06a3cbe13078105adcb0c14f806
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_system_info_reg.vhd
@@ -0,0 +1,144 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+--  RO  read only  (no VHDL present to access HW in write mode)
+--  WO  write only (no VHDL present to access HW in read mode)
+--  WE  write event (=WO)
+--  WR  write control, read control
+--  RW  read status, write control  
+--  RC  read, clear on read
+--  FR  FIFO read
+--  FW  FIFO write
+--
+--  wi  Bits    R/W Name          Default  Description      |REG_UNB2_BOARD_SYSTEM_INFO|
+--  =============================================================================
+--  0   [31..0] RO  info          
+--  1   [7..0]  RO  0
+--  2   [31..0] RO  design_name
+--  .   ..      .   ..
+--  9   [31..0] RO  design name
+--  10  [31..0] RO  date stamp             (YYYYMMDD)
+--  11  [31..0] RO  time stamp             (HHMMSS)
+--  12  [31..0] RO  SVN  stamp         
+--  13  [31..0] RO  note
+--  .   .       .   ..
+--  20  [31..0] RO  note
+--  =============================================================================
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_str_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE work.unb2_board_pkg.ALL;
+
+ENTITY unb2_board_system_info_reg IS
+  GENERIC (
+    g_design_name : STRING;
+    g_stamp_date  : NATURAL := 0;
+    g_stamp_time  : NATURAL := 0;
+    g_stamp_svn   : NATURAL := 0;
+    g_design_note : STRING
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst      : IN  STD_LOGIC;    
+    mm_clk      : IN  STD_LOGIC;
+    
+    -- Memory Mapped Slave 
+    sla_in      : IN  t_mem_mosi; 
+    sla_out     : OUT t_mem_miso; 
+    
+    info        : IN  STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0)
+    );
+END unb2_board_system_info_reg;
+
+
+ARCHITECTURE rtl OF unb2_board_system_info_reg IS
+
+  CONSTANT c_nof_fixed_regs       : NATURAL := 2;  -- info, use_phy
+  CONSTANT c_nof_design_name_regs : NATURAL := 13; -- design_name
+  CONSTANT c_nof_stamp_regs       : NATURAL := 3;  -- date, time, svn rev
+  CONSTANT c_nof_design_note_regs : NATURAL := 13; -- note
+
+  CONSTANT c_nof_regs             : NATURAL := c_nof_fixed_regs + c_nof_design_name_regs + c_nof_stamp_regs + c_nof_design_note_regs;
+
+  CONSTANT c_mm_reg        : t_c_mem := (latency  => 1,
+                                         adr_w    => ceil_log2(c_nof_regs),
+                                         dat_w    => c_word_w,       -- Use MM bus data width = c_word_w = 32 for all MM registers
+                                         nof_dat  => c_nof_regs,
+                                         init_sl  => '0');   
+
+  CONSTANT c_use_phy_w     : NATURAL := 8;
+  CONSTANT c_use_phy       : STD_LOGIC_VECTOR(c_use_phy_w-1 DOWNTO 0) := (OTHERS=> '0'); -- Unused but keep for compatibillity
+
+  CONSTANT c_design_name    : t_slv_32_arr(0 TO c_nof_design_name_regs-1) := str_to_ascii_slv_32_arr(g_design_name, c_nof_design_name_regs);
+  CONSTANT c_design_note    : t_slv_32_arr(0 TO c_nof_design_note_regs-1) := str_to_ascii_slv_32_arr(g_design_note, c_nof_design_note_regs);
+ 
+BEGIN
+
+  p_mm_reg : PROCESS (mm_rst, mm_clk)
+    VARIABLE vA : NATURAL := 0;
+  BEGIN
+    IF mm_rst = '1' THEN
+      -- Read access
+      sla_out   <= c_mem_miso_rst;
+    ELSIF rising_edge(mm_clk) THEN
+      -- Read access defaults
+      sla_out.rdval <= '0';
+           
+      -- Read access: get register value
+      IF sla_in.rd = '1' THEN
+        sla_out       <= c_mem_miso_rst;    -- set unused rddata bits to '0' when read
+        sla_out.rdval <= '1';               -- c_mm_reg.latency = 1
+
+        vA := TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0));
+        IF vA = 0 THEN         
+          sla_out.rddata(c_word_w-1 DOWNTO 0) <= info;
+          -- Use bit 11 to indicate that we're using the MM bus (not the info SLV).
+          -- Using the MM bus enables user to also read use_phy, design_name etc.
+          sla_out.rddata(11) <= '1';
+        ELSIF vA = 1 THEN  
+          sla_out.rddata(c_use_phy_w-1 DOWNTO 0) <= c_use_phy;
+        ELSIF vA < c_nof_fixed_regs + c_nof_design_name_regs THEN      
+          sla_out.rddata(c_word_w-1 DOWNTO 0) <= c_design_name(vA-c_nof_fixed_regs);
+
+        ELSIF vA = c_nof_fixed_regs + c_nof_design_name_regs THEN      
+          sla_out.rddata(c_word_w-1 DOWNTO 0) <= TO_UVEC(g_stamp_date, c_word_w);
+
+        ELSIF vA = c_nof_fixed_regs + c_nof_design_name_regs+1 THEN      
+          sla_out.rddata(c_word_w-1 DOWNTO 0) <= TO_UVEC(g_stamp_time, c_word_w);
+
+        ELSIF vA = c_nof_fixed_regs + c_nof_design_name_regs+2 THEN      
+          sla_out.rddata(c_word_w-1 DOWNTO 0) <= TO_UVEC(g_stamp_svn, c_word_w);
+
+        ELSIF vA < c_nof_fixed_regs + c_nof_design_name_regs+c_nof_stamp_regs+c_nof_design_note_regs THEN      
+          sla_out.rddata(c_word_w-1 DOWNTO 0) <= c_design_note(vA-c_nof_fixed_regs-c_nof_design_name_regs-c_nof_stamp_regs);
+
+        END IF;
+
+      END IF;
+    END IF;
+  END PROCESS;
+
+ 
+END rtl;
+
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_wdi_extend.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_wdi_extend.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..ffc5345b51204581561602c2e42a2cf28f7bece8
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_wdi_extend.vhd
@@ -0,0 +1,98 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2010-2014
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+-- Purpose:
+--   Extend the input WDI that is controlled in SW (as it should be) to avoid
+--   that the watchdog reset will occur when new SW is loaded, while keeping
+--   the HDL image. This component extends the last input WDI by toggling the
+--   output WDI for about 2**(g_extend_w-1) ms more.
+
+ENTITY unb2_board_wdi_extend IS
+  GENERIC (
+    g_extend_w : NATURAL := 14
+  );
+  PORT (
+    rst              : IN  STD_LOGIC;
+    clk              : IN  STD_LOGIC;
+    pulse_ms         : IN  STD_LOGIC;  -- pulses every 1 ms
+    wdi_in           : IN  STD_LOGIC;
+    wdi_out          : OUT STD_LOGIC
+  );
+END unb2_board_wdi_extend;
+
+
+ARCHITECTURE str OF unb2_board_wdi_extend IS
+
+  SIGNAL wdi_evt     : STD_LOGIC;
+  
+  SIGNAL wdi_cnt     : STD_LOGIC_VECTOR(g_extend_w-1 DOWNTO 0);
+  SIGNAL wdi_cnt_en  : STD_LOGIC;
+  
+  SIGNAL i_wdi_out   : STD_LOGIC;
+  SIGNAL nxt_wdi_out : STD_LOGIC;
+  
+BEGIN
+
+  wdi_out <= i_wdi_out;
+  
+  p_clk : PROCESS(rst, clk)
+  BEGIN
+    IF rst='1' THEN
+      i_wdi_out <= '0';
+    ELSIF rising_edge(clk) THEN
+      i_wdi_out <= nxt_wdi_out;
+    END IF;
+  END PROCESS;
+  
+  wdi_cnt_en <= '1' WHEN pulse_ms='1' AND wdi_cnt(wdi_cnt'HIGH)='0' ELSE '0';
+
+  nxt_wdi_out <= NOT i_wdi_out WHEN wdi_cnt_en='1' ELSE i_wdi_out;
+  
+  u_common_evt : ENTITY common_lib.common_evt
+  GENERIC MAP (
+    g_evt_type => "BOTH",
+    g_out_reg  => TRUE
+  )
+  PORT MAP (
+    rst      => rst,
+    clk      => clk,
+    in_sig   => wdi_in,
+    out_evt  => wdi_evt
+  );
+  
+  u_common_counter : ENTITY common_lib.common_counter
+  GENERIC MAP (
+    g_width   => g_extend_w
+  )
+  PORT MAP (
+    rst     => rst,
+    clk     => clk,
+    cnt_clr => wdi_evt,
+    cnt_en  => wdi_cnt_en,
+    count   => wdi_cnt
+  );
+  
+END str;
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_wdi_reg.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_wdi_reg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..42a42742a54008100adefd7cc0b25a5df68ba5fa
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_board_wdi_reg.vhd
@@ -0,0 +1,90 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: 
+--   Manually override WDI to initiate reconfiguratioon of the FPGA.
+--   Write 0xB007FAC7 to address 0x0.
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+
+ENTITY unb2_board_wdi_reg IS
+  PORT (
+    -- Clocks and reset
+    mm_rst            : IN  STD_LOGIC;   -- reset synchronous with mm_clk
+    mm_clk            : IN  STD_LOGIC;   -- memory-mapped bus clock
+     
+    -- Memory Mapped Slave in mm_clk domain
+    sla_in            : IN  t_mem_mosi;  -- actual ranges defined by c_mm_reg
+    sla_out           : OUT t_mem_miso;  -- actual ranges defined by c_mm_reg
+    
+    -- MM registers in st_clk domain
+    wdi_override      : OUT STD_LOGIC
+ );
+END unb2_board_wdi_reg;
+
+
+ARCHITECTURE rtl OF unb2_board_wdi_reg IS
+
+  -- Define the actual size of the MM slave register
+  CONSTANT c_mm_reg : t_c_mem := (latency  => 1,
+                                  adr_w    => ceil_log2(1),
+                                  dat_w    => c_word_w,       -- Use MM bus data width = c_word_w = 32 for all MM registers
+                                  nof_dat  => 1,
+                                  init_sl  => '0');                       
+
+  -- For safety, WDI override requires the following word to be written:
+  CONSTANT c_cmd_reconfigure : STD_LOGIC_VECTOR(c_word_w-1 DOWNTO 0 ) := x"B007FAC7"; -- "Boot factory"  
+
+BEGIN
+
+  p_mm_reg : PROCESS (mm_rst, mm_clk)
+  BEGIN
+    IF mm_rst = '1' THEN
+      -- Read access
+      sla_out   <= c_mem_miso_rst;
+      -- Write access, register values
+        wdi_override <= '0';
+    ELSIF rising_edge(mm_clk) THEN
+      -- Read access defaults: unused
+      sla_out   <= c_mem_miso_rst;   
+   
+      -- Write access: set register value
+      IF sla_in.wr = '1' THEN
+        CASE TO_UINT(sla_in.address(c_mm_reg.adr_w-1 DOWNTO 0)) IS
+          -- Write Block Sync
+          WHEN 0 => 
+            IF sla_in.wrdata(c_word_w-1 DOWNTO 0) = c_cmd_reconfigure THEN
+              wdi_override <= '1';
+            ELSE
+              wdi_override <= '0';
+            END IF;
+          WHEN OTHERS => NULL;  -- unused MM addresses
+        END CASE;
+      END IF;
+  
+    END IF;
+  END PROCESS;
+
+END rtl;
+
diff --git a/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_fpga_sens_reg.vhd b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_fpga_sens_reg.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..eb233b1ac5546e80db457f343112f05d94548181
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/src/vhdl/unb2_fpga_sens_reg.vhd
@@ -0,0 +1,89 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012-2014
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Provide MM slave register for unb2_fpga_sens
+--
+
+LIBRARY IEEE, common_lib, technology_lib, fpga_sense_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE IEEE.NUMERIC_STD.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE technology_lib.technology_pkg.ALL;
+
+
+ENTITY unb2_fpga_sens_reg IS
+  GENERIC (
+    g_sim             : BOOLEAN;
+    g_technology      : NATURAL := c_tech_arria10;
+    g_sens_nof_result : NATURAL := 1;
+    g_temp_high       : NATURAL := 85
+  );
+  PORT (
+    -- Clocks and reset
+    mm_rst     : IN  STD_LOGIC;   -- reset synchronous with mm_clk
+    mm_clk     : IN  STD_LOGIC;   -- memory-mapped bus clock
+    start      : IN  STD_LOGIC;
+    
+    -- Memory Mapped Slave in mm_clk domain
+    sla_temp_in     : IN  t_mem_mosi;  -- actual ranges defined by c_mm_reg
+    sla_temp_out    : OUT t_mem_miso;  -- actual ranges defined by c_mm_reg
+    
+    sla_voltage_in     : IN  t_mem_mosi;  -- actual ranges defined by c_mm_reg
+    sla_voltage_out    : OUT t_mem_miso;  -- actual ranges defined by c_mm_reg
+
+    -- MM registers
+    --sens_err   : IN  STD_LOGIC := '0';
+    --sens_data  : IN  t_slv_8_arr(0 TO g_sens_nof_result-1); -- FIXME should be OUT
+
+    -- Max temp output
+    temp_high  : OUT STD_LOGIC_VECTOR(6 DOWNTO 0)
+  );
+END unb2_fpga_sens_reg;
+
+
+ARCHITECTURE str OF unb2_fpga_sens_reg IS
+
+  --SIGNAL i_temp_high    : STD_LOGIC_VECTOR(6 DOWNTO 0);
+                                  
+BEGIN
+
+  temp_high <= (others => '0'); --i_temp_high;
+
+  u_fpga_sense: ENTITY fpga_sense_lib.fpga_sense
+  GENERIC MAP (
+    g_technology => g_technology,
+    g_sim        => g_sim
+  )
+  PORT MAP (
+    mm_clk      => mm_clk,
+    mm_rst      => mm_rst,
+
+    start_sense => start,
+
+    reg_temp_mosi    => sla_temp_in,
+    reg_temp_miso    => sla_temp_out,
+
+    reg_voltage_store_mosi    => sla_voltage_in,
+    reg_voltage_store_miso    => sla_voltage_out
+  );
+
+END str;
diff --git a/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_mms_unb2_board_sens.vhd b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_mms_unb2_board_sens.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..8d4444e6ec52404e78df2d8a4af7000658e82be4
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_mms_unb2_board_sens.vhd
@@ -0,0 +1,215 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012
+-- ASTRON (Netherlands Institute for Radio Astronomy) <http://www.astron.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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Test bench for mms_unb2_board_sens
+--
+-- Features:
+-- . Verify that the UniBoard sensors are read.
+--
+-- Usage:
+-- . > as 10
+-- . > run -all
+
+ENTITY tb_mms_unb2_board_sens IS
+END tb_mms_unb2_board_sens;
+
+LIBRARY IEEE, common_lib, i2c_lib;
+USE IEEE.std_logic_1164.ALL;
+USE common_lib.common_pkg.ALL;
+USE common_lib.common_mem_pkg.ALL;
+USE common_lib.tb_common_pkg.ALL;
+USE common_lib.tb_common_mem_pkg.ALL;
+USE work.unb2_board_pkg.ALL;
+
+ARCHITECTURE tb OF tb_mms_unb2_board_sens IS
+
+  CONSTANT c_sim              : BOOLEAN := TRUE;  --FALSE;
+  CONSTANT c_repeat           : NATURAL := 2;
+  CONSTANT c_clk_freq         : NATURAL := 100*10**6;
+  CONSTANT c_clk_period       : TIME    := (10**9/c_clk_freq) * 1 ns;  
+  CONSTANT c_rst_period       : TIME    := 4 * c_clk_period;  
+  
+  -- Model I2C sensor slaves as on the UniBoard
+  CONSTANT c_temp_high           : NATURAL := 85;
+  CONSTANT c_fpga_temp_address   : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0011000";  -- MAX1618 address LOW LOW
+  CONSTANT c_fpga_temp           : INTEGER := 60;
+  CONSTANT c_eth_temp_address    : STD_LOGIC_VECTOR(6 DOWNTO 0) := "0101001";  -- MAX1618 address MID LOW
+  CONSTANT c_eth_temp            : INTEGER := 40;
+  CONSTANT c_hot_swap_address    : STD_LOGIC_VECTOR(6 DOWNTO 0) := "1000100";  -- LTC4260 address L L L
+  CONSTANT c_hot_swap_R_sense    : REAL := 0.01;                               -- = 10 mOhm on UniBoard
+  
+  CONSTANT c_uniboard_current    : REAL := 5.0;   -- = assume 5.0 A on UniBoard  --> hot swap = 5010 mAmpere (167)
+  CONSTANT c_uniboard_supply     : REAL := 48.0;  -- = assume 48.0 V on UniBoard --> hot swap = 48000 mVolt (120)
+  CONSTANT c_uniboard_adin       : REAL := -1.0;  -- = NC on UniBoard
+  
+  CONSTANT c_sens_nof_result  : NATURAL := 4 + 1;
+  CONSTANT c_sens_expected    : t_natural_arr(0 TO c_sens_nof_result-1) := (60, 40, 167, 120, 0);  -- 4 bytes as read by c_SEQ in unb2_board_sens_ctrl + sens_err
+  
+  SIGNAL tb_end          : STD_LOGIC := '0';
+  SIGNAL clk             : STD_LOGIC := '0';
+  SIGNAL rst             : STD_LOGIC := '1';
+  SIGNAL start           : STD_LOGIC;
+ 
+  SIGNAL reg_mosi        : t_mem_mosi := c_mem_mosi_rst;
+  SIGNAL reg_miso        : t_mem_miso;
+  
+  SIGNAL sens_val        : STD_LOGIC;
+  SIGNAL sens_dat        : STD_LOGIC_VECTOR(c_byte_w-1 DOWNTO 0);
+  
+  SIGNAL scl_stretch     : STD_LOGIC := 'Z';
+  SIGNAL scl             : STD_LOGIC;
+  SIGNAL sda             : STD_LOGIC;  
+  
+BEGIN
+
+  rst <= '0' AFTER 4*c_clk_period;
+  clk <= (NOT clk) OR tb_end AFTER c_clk_period/2;
+  
+  -- I2C bus
+  scl <= 'H';   -- model I2C pull up
+  sda <= 'H';   -- model I2C pull up, use '0' and '1' to verify sens_err
+
+  scl <= scl_stretch;
+
+  sens_clk_stretch : PROCESS (scl)
+  BEGIN
+    IF falling_edge(scl) THEN
+      scl_stretch <= '0', 'Z' AFTER 50 ns;   -- < 10 ns to effectively disable stretching, >= 50 ns to enable it
+    END IF;
+  END PROCESS;
+  
+  p_mm_reg_stimuli : PROCESS
+    VARIABLE v_bsn : NATURAL;
+    VARIABLE vI    : NATURAL;
+    VARIABLE vJ    : NATURAL;
+  BEGIN
+    start     <= '0';
+    reg_mosi  <= c_mem_mosi_rst;
+    
+    proc_common_wait_until_low(clk, rst);
+    proc_common_wait_some_cycles(clk, 10);
+    
+    FOR I IN 0 TO c_repeat-1 LOOP
+      -- start I2C access
+      start <= '1';
+      proc_common_wait_some_cycles(clk, 1);
+      start <= '0';
+      
+      -- wait for I2C access to have finished
+      proc_common_wait_some_cycles(clk, sel_a_b(c_sim, 5000, 500000));
+      
+      -- read I2C result data
+      FOR I IN 0 TO c_sens_nof_result-1 LOOP
+        proc_mem_mm_bus_rd(I, clk, reg_miso, reg_mosi);  -- read sens_data
+      END LOOP;
+      
+      proc_common_wait_some_cycles(clk, 1000);
+    END LOOP;
+    
+    proc_common_wait_some_cycles(clk, 100);
+    tb_end <= '1';
+    WAIT;
+  END PROCESS;
+  
+  sens_val <= reg_miso.rdval;
+  sens_dat <= reg_miso.rddata(c_byte_w-1 DOWNTO 0);
+  
+  -- Verify sensor data
+  p_verify : PROCESS
+  BEGIN
+    WAIT UNTIL rising_edge(clk);  -- Added this line to avoid warning: (vcom-1090) Possible infinite loop: Process contains no WAIT statement.
+    
+    proc_common_wait_until_high(clk, sens_val);
+    ASSERT TO_UINT(sens_dat)=c_sens_expected(0) REPORT "Wrong FPGA temperature value" SEVERITY ERROR;
+    proc_common_wait_some_cycles(clk, 1);
+    ASSERT TO_UINT(sens_dat)=c_sens_expected(1) REPORT "Wrong ETH temperature value" SEVERITY ERROR;
+    proc_common_wait_some_cycles(clk, 1);
+    ASSERT TO_UINT(sens_dat)=c_sens_expected(2) REPORT "Wrong hot swap V sense value" SEVERITY ERROR;
+    proc_common_wait_some_cycles(clk, 1);
+    ASSERT TO_UINT(sens_dat)=c_sens_expected(3) REPORT "Wrong hot swap V source value" SEVERITY ERROR;
+    proc_common_wait_some_cycles(clk, 1);
+    ASSERT TO_UINT(sens_dat)=c_sens_expected(4) REPORT "An I2C error occurred" SEVERITY ERROR;
+    
+  END PROCESS;
+  
+
+  -- I2C sensors master
+  u_mms_unb2_board_sens : ENTITY work.mms_unb2_board_sens
+  GENERIC MAP (
+    g_sim             => c_sim,
+    g_i2c_peripheral  => c_i2c_peripheral_sens,
+    g_sens_nof_result => 40,
+    g_clk_freq        => c_clk_freq,
+    g_temp_high       => c_temp_high,
+    g_comma_w         => 13
+  )
+  PORT MAP (
+    -- Clocks and reset
+    mm_rst    => rst,
+    mm_clk    => clk,
+    mm_start  => start,
+    
+    -- Memory-mapped clock domain
+    reg_mosi  => reg_mosi,
+    reg_miso  => reg_miso,
+    
+    -- i2c bus
+    scl       => scl,
+    sda       => sda
+  );
+  
+  -- I2C slaves that are available for each FPGA
+  u_fpga_temp : ENTITY i2c_lib.dev_max1618
+  GENERIC MAP (
+    g_address => c_fpga_temp_address
+  )
+  PORT MAP (
+    scl  => scl,
+    sda  => sda,
+    temp => c_fpga_temp
+  );
+
+  -- I2C slaves that are available only via FPGA node 3
+  u_eth_temp : ENTITY i2c_lib.dev_max1618
+  GENERIC MAP (
+    g_address => c_eth_temp_address
+  )
+  PORT MAP (
+    scl  => scl,
+    sda  => sda,
+    temp => c_eth_temp
+  );
+  
+  u_power : ENTITY i2c_lib.dev_ltc4260
+  GENERIC MAP (
+    g_address => c_hot_swap_address,
+    g_R_sense => c_hot_swap_R_sense
+  )
+  PORT MAP (
+    scl               => scl,
+    sda               => sda,
+    ana_current_sense => c_uniboard_current,
+    ana_volt_source   => c_uniboard_supply,
+    ana_volt_adin     => c_uniboard_adin
+  );
+    
+END tb;
+
diff --git a/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk125_pll.vhd b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk125_pll.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..13f29d91913a0a613615e253ad05da073e3e694c
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk125_pll.vhd
@@ -0,0 +1,71 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+
+-- Purpose: Simulate phase behaviour of PLL in normal mode
+-- Description:
+-- Usage:
+-- > as 3
+-- > run -all
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+
+ENTITY tb_unb2_board_clk125_pll IS
+END tb_unb2_board_clk125_pll;
+
+
+ARCHITECTURE tb OF tb_unb2_board_clk125_pll IS
+
+  CONSTANT c_ext_clk_period  : TIME := 8 ns; -- 125 MHz
+  
+  SIGNAL tb_end      : STD_LOGIC := '0';
+  SIGNAL ext_clk     : STD_LOGIC := '0';
+  SIGNAL ext_rst     : STD_LOGIC;
+  SIGNAL c0_clk20    : STD_LOGIC;
+  SIGNAL c1_clk50    : STD_LOGIC;
+  SIGNAL c2_clk100   : STD_LOGIC;
+  SIGNAL c3_clk125   : STD_LOGIC;
+  SIGNAL pll_locked  : STD_LOGIC;
+  
+BEGIN
+
+  tb_end <= '0', '1' AFTER c_ext_clk_period*5000;
+  
+  ext_clk <= NOT ext_clk OR tb_end AFTER c_ext_clk_period/2;
+  ext_rst <= '1', '0' AFTER c_ext_clk_period*7;
+  
+  dut_0 : ENTITY work.unb2_board_clk125_pll
+  PORT MAP (
+    arst      => ext_rst,
+    clk125    => ext_clk,
+
+    c0_clk20  => c0_clk20,
+    c1_clk50  => c1_clk50,
+    c2_clk100  => c2_clk100,
+    c3_clk125  => c3_clk125,
+
+    pll_locked => pll_locked
+  );
+END tb;
diff --git a/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk200_pll.vhd b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk200_pll.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a2e442c17a96dc1432cee7897a8e1f79917bea4d
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk200_pll.vhd
@@ -0,0 +1,116 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2012
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+
+-- Purpose: Simulate phase behaviour of PLL in normal mode
+-- Description:
+-- Usage:
+-- > as 3
+-- > run -all
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+
+ENTITY tb_unb2_board_clk200_pll IS
+END tb_unb2_board_clk200_pll;
+
+
+ARCHITECTURE tb OF tb_unb2_board_clk200_pll IS
+
+  CONSTANT c_ext_clk_period    : TIME := 5 ns;               -- 200 MHz
+  CONSTANT c_clk_vec_w         : NATURAL := 6;
+  CONSTANT c_clk_div           : NATURAL := 32;
+  
+  SIGNAL tb_end         : STD_LOGIC := '0';
+  SIGNAL ext_clk        : STD_LOGIC := '0';
+  SIGNAL ext_rst        : STD_LOGIC;
+  
+  SIGNAL st_clk200_0    : STD_LOGIC;
+  SIGNAL st_rst200_0    : STD_LOGIC;
+  
+  SIGNAL st_clk200p0    : STD_LOGIC;
+  SIGNAL st_rst200p0    : STD_LOGIC;
+  
+  SIGNAL st_clk200_45   : STD_LOGIC;
+  SIGNAL st_rst200_45   : STD_LOGIC;
+  
+  SIGNAL st_clk200p45   : STD_LOGIC;
+  SIGNAL st_rst200p45   : STD_LOGIC;
+  
+  SIGNAL st_clk400      : STD_LOGIC;
+  SIGNAL st_rst400      : STD_LOGIC;
+  
+  SIGNAL dp_clk200      : STD_LOGIC;
+  SIGNAL dp_rst200      : STD_LOGIC;
+  
+BEGIN
+
+  tb_end <= '0', '1' AFTER c_ext_clk_period*5000;
+  
+  ext_clk <= NOT ext_clk OR tb_end AFTER c_ext_clk_period/2;
+  ext_rst <= '1', '0' AFTER c_ext_clk_period*7;
+  
+  dut_0 : ENTITY work.unb2_board_clk200_pll
+  GENERIC MAP (
+    g_clk200_phase_shift  => "0"
+  )
+  PORT MAP (
+    arst       => ext_rst,
+    clk200     => ext_clk,
+    st_clk200  => st_clk200_0,
+    st_rst200  => st_rst200_0,
+    st_clk200p => st_clk200p0,
+    st_rst200p => st_rst200p0,
+    st_clk400  => st_clk400,
+    st_rst400  => st_rst400
+  );
+  
+  dut_45 : ENTITY work.unb2_board_clk200_pll
+  GENERIC MAP (
+    g_clk200_phase_shift  => "625",
+    g_clk200p_phase_shift => "625"
+  )
+  PORT MAP (
+    arst       => ext_rst,
+    clk200     => ext_clk,
+    st_clk200  => st_clk200_45,
+    st_rst200  => st_rst200_45,
+    st_clk200p => st_clk200p45,
+    st_rst200p => st_rst200p45,
+    st_clk400  => OPEN,
+    st_rst400  => OPEN
+  );
+  
+  dut_p6 : ENTITY work.unb2_board_clk200_pll
+  GENERIC MAP (
+    g_clk200_phase_shift  => "0"
+  )
+  PORT MAP (
+    arst       => ext_rst,
+    clk200     => ext_clk,
+    st_clk200  => dp_clk200,
+    st_rst200  => dp_rst200
+  );
+  
+END tb;
diff --git a/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk25_pll.vhd b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk25_pll.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..cbd3d0290147c376a450c5b718e38c57f8d652db
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_clk25_pll.vhd
@@ -0,0 +1,71 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2014
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+
+-- Purpose: Simulate phase behaviour of PLL in normal mode
+-- Description:
+-- Usage:
+-- > as 3
+-- > run -all
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+
+ENTITY tb_unb2_board_clk25_pll IS
+END tb_unb2_board_clk25_pll;
+
+
+ARCHITECTURE tb OF tb_unb2_board_clk25_pll IS
+
+  CONSTANT c_ext_clk_period  : TIME := 40 ns; -- 25 MHz
+  
+  SIGNAL tb_end      : STD_LOGIC := '0';
+  SIGNAL ext_clk     : STD_LOGIC := '0';
+  SIGNAL ext_rst     : STD_LOGIC;
+  SIGNAL c0_clk20    : STD_LOGIC;
+  SIGNAL c1_clk50    : STD_LOGIC;
+  SIGNAL c2_clk100   : STD_LOGIC;
+  SIGNAL c3_clk125   : STD_LOGIC;
+  SIGNAL pll_locked  : STD_LOGIC;
+  
+BEGIN
+
+  tb_end <= '0', '1' AFTER c_ext_clk_period*5000;
+  
+  ext_clk <= NOT ext_clk OR tb_end AFTER c_ext_clk_period/2;
+  ext_rst <= '1', '0' AFTER c_ext_clk_period*7;
+  
+  dut_0 : ENTITY work.unb2_board_clk25_pll
+  PORT MAP (
+    arst      => ext_rst,
+    clk25     => ext_clk,
+
+    c0_clk20  => c0_clk20,
+    c1_clk50  => c1_clk50,
+    c2_clk100  => c2_clk100,
+    c3_clk125  => c3_clk125,
+
+    pll_locked => pll_locked
+  );
+END tb;
diff --git a/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_node_ctrl.vhd b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_node_ctrl.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..a5dbd064dc9a2edc29f28336cfbba3bc4270b09c
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_node_ctrl.vhd
@@ -0,0 +1,99 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2010
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+LIBRARY IEEE, common_lib;
+USE IEEE.STD_LOGIC_1164.ALL;
+USE common_lib.common_pkg.ALL;
+
+
+ENTITY tb_unb2_board_node_ctrl IS
+END tb_unb2_board_node_ctrl;
+
+
+ARCHITECTURE tb OF tb_unb2_board_node_ctrl IS
+
+  CONSTANT c_scale             : NATURAL := 100;             -- scale to speed up simulation
+  
+  CONSTANT c_xo_clk_period     : TIME := 1 us;               -- 1 MHz XO, slow XO to speed up simulation
+  CONSTANT c_mm_clk_period     : TIME := c_xo_clk_period/5;  -- 5 MHz PLL output from XO reference
+  CONSTANT c_mm_locked_time    : TIME := 10 us;
+    
+  CONSTANT c_pulse_us          : NATURAL := 5;              -- nof 5 MHz clk cycles to get us period
+  CONSTANT c_pulse_ms          : NATURAL := 1000/c_scale;   -- nof pulse_us pulses to get ms period
+  CONSTANT c_pulse_s           : NATURAL := 1000;           -- nof pulse_ms pulses to get  s period
+  
+  CONSTANT c_wdi_extend_w      : NATURAL := 14;     -- extend wdi by about 2**(14-1)= 8 s (as defined by c_pulse_ms)
+  CONSTANT c_wdi_period        : TIME :=  1000 ms;  -- wdi toggle after c_wdi_period
+  
+  -- Use c_sw_period=40000 ms to show that the c_wdi_extend_w=5 is not enough, the WD will kick in when the sw is off during reload
+  CONSTANT c_sw_period         : TIME := 40000 ms;  -- sw active for c_sw_period then inactive during reload for c_sw_period, etc.
+  -- Use c_sw_period=10000 ms to show that the c_wdi_extend_w=5 is enough, the WD will not kick in when the sw is off during reload
+  --CONSTANT c_sw_period         : TIME := 6000 ms;  -- sw active for c_sw_period then inactive during reload for c_sw_period, etc.
+  
+  SIGNAL mm_clk      : STD_LOGIC := '0';
+  SIGNAL mm_locked   : STD_LOGIC := '0';
+  SIGNAL mm_rst      : STD_LOGIC;
+  
+  SIGNAL wdi         : STD_LOGIC := '0';
+  SIGNAL wdi_in      : STD_LOGIC;
+  SIGNAL wdi_out     : STD_LOGIC;
+  
+  SIGNAL sw          : STD_LOGIC := '0';
+  
+  SIGNAL pulse_us    : STD_LOGIC;
+  SIGNAL pulse_ms    : STD_LOGIC;
+  SIGNAL pulse_s     : STD_LOGIC;
+  
+BEGIN
+
+  -- run 2000 ms
+  
+  mm_clk <= NOT mm_clk AFTER c_mm_clk_period/2;
+  mm_locked <= '0', '1' AFTER c_mm_locked_time;
+  
+  wdi    <= NOT wdi AFTER c_wdi_period/c_scale;  -- wd interrupt
+  sw     <= NOT sw  AFTER c_sw_period/c_scale;   -- sw active / reload
+  
+  wdi_in <= wdi AND sw;  -- sw wdi only when sw is active, during sw inactive the wdi_out will be extended
+  
+  dut : ENTITY work.unb2_board_node_ctrl
+  GENERIC MAP (
+    g_pulse_us     => c_pulse_us,
+    g_pulse_ms     => c_pulse_ms,
+    g_pulse_s      => c_pulse_s,
+    g_wdi_extend_w => c_wdi_extend_w
+  )
+  PORT MAP (
+    -- MM clock domain reset
+    mm_clk      => mm_clk,
+    mm_locked   => mm_locked,
+    mm_rst      => mm_rst,
+    -- WDI extend
+    mm_wdi_in   => wdi_in,
+    mm_wdi_out  => wdi_out,
+    -- Pulses
+    mm_pulse_us => pulse_us,
+    mm_pulse_ms => pulse_ms,
+    mm_pulse_s  => pulse_s
+  );
+  
+END tb;
diff --git a/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_qsfp_leds.vhd b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_qsfp_leds.vhd
new file mode 100644
index 0000000000000000000000000000000000000000..06f7e52d03b4c4be727e5f18049b20f9778e2ebd
--- /dev/null
+++ b/boards/uniboard2b/libraries/unb2b_board/tb/vhdl/tb_unb2_board_qsfp_leds.vhd
@@ -0,0 +1,190 @@
+-------------------------------------------------------------------------------
+--
+-- Copyright (C) 2015
+-- 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/>.
+--
+-------------------------------------------------------------------------------
+
+-- Purpose: Test bench for unb2_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_unb2_board_qsfp_leds IS
+END tb_unb2_board_qsfp_leds;
+
+ARCHITECTURE tb OF tb_unb2_board_qsfp_leds IS
+
+  CONSTANT c_clk_freq_hz    : NATURAL := 200 * 10**6;
+  CONSTANT c_clk_period_ns  : NATURAL := 10**9 / c_clk_freq_hz;
+  CONSTANT c_nof_clk_per_us : NATURAL := 1000 / c_clk_period_ns;
+  
+  CONSTANT clk_period       : TIME := c_clk_period_ns * 1 ns;
+  
+  CONSTANT c_nof_qsfp       : NATURAL := 2;
+  CONSTANT c_nof_lanes      : NATURAL := c_nof_qsfp*c_quad;
+  
+  SIGNAL tb_end                  : STD_LOGIC := '0';
+  SIGNAL rst                     : STD_LOGIC;
+  SIGNAL clk                     : STD_LOGIC := '0';
+  SIGNAL pulse_us                : STD_LOGIC;
+  SIGNAL pulse_ms                : STD_LOGIC;
+  SIGNAL pulse_s                 : STD_LOGIC;
+ 
+  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
+  
+  clk <= NOT clk OR tb_end AFTER clk_period/2;
+  rst <= '1', '0' AFTER clk_period*7;
+  
+  -- 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(clk, pulse_ms, 50);
+    
+    -- 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(clk, pulse_ms, 10);
+    END LOOP;
+    proc_common_wait_some_pulses(clk, 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(clk);
+      tx_sosi_arr(I).sop <= '0';
+      proc_common_wait_some_pulses(clk, pulse_ms, 10);
+    END LOOP;
+    proc_common_wait_some_pulses(clk, 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(clk);
+      rx_sosi_arr(I).sop <= '0';
+      proc_common_wait_some_pulses(clk, pulse_ms, 10);
+    END LOOP;
+    proc_common_wait_some_pulses(clk, 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(clk, pulse_ms, 10);
+    END LOOP;
+    proc_common_wait_some_pulses(clk, pulse_ms, 50);
+    
+    tb_end <= '1';
+    proc_common_wait_some_pulses(clk, pulse_ms, 10);
+    WAIT;
+  END PROCESS;
+  
+  u_unb2_factory_qsfp_leds : ENTITY work.unb2_board_qsfp_leds
+  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_pulse_us        => c_nof_clk_per_us  -- nof clk cycles to get us period
+  )
+  PORT MAP (
+    rst               => rst,
+    clk               => clk,
+    -- internal pulser outputs
+    pulse_us          => pulse_us,
+    pulse_ms          => pulse_ms,
+    pulse_s           => pulse_s,
+    -- lane status
+    tx_siso_arr       => tx_siso_arr,
+    tx_sosi_arr       => tx_sosi_arr,
+    rx_sosi_arr       => rx_sosi_arr,
+    -- leds
+    green_led_arr     => factory_green_led_arr,
+    red_led_arr       => factory_red_led_arr
+  );
+  
+  u_unb2_user_qsfp_leds : ENTITY work.unb2_board_qsfp_leds
+  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_pulse_us        => c_nof_clk_per_us  -- nof clk cycles to get us period
+  )
+  PORT MAP (
+    rst               => rst,
+    clk               => clk,
+    -- internal pulser outputs
+    pulse_us          => pulse_us,
+    pulse_ms          => pulse_ms,
+    pulse_s           => pulse_s,
+    -- 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;