]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
first version of 125MHz SerDes
authorMichael Boehmer <mboehmer@ph.tum.de>
Mon, 14 Feb 2022 13:11:10 +0000 (14:11 +0100)
committerMichael Boehmer <mboehmer@ph.tum.de>
Mon, 14 Feb 2022 13:11:10 +0000 (14:11 +0100)
media_interfaces/med_ecp3_sfp_sync_all_125M_RS.vhd [new file with mode: 0644]

diff --git a/media_interfaces/med_ecp3_sfp_sync_all_125M_RS.vhd b/media_interfaces/med_ecp3_sfp_sync_all_125M_RS.vhd
new file mode 100644 (file)
index 0000000..e172e0e
--- /dev/null
@@ -0,0 +1,562 @@
+-- intended as "one for all" solution on sync TRBnet
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.all;
+
+library work;
+use work.trb_net_std.all;
+--use work.trb_net_components.all;
+use work.med_sync_define_RS.all;
+
+entity med_ecp3_sfp_sync_all_125M_RS is
+  generic(
+    IS_MODE            : int_array_t(0 to 3) := (c_IS_UNUSED, c_IS_UNUSED, c_IS_UNUSED, c_IS_UNUSED);
+    IS_WAP_ZERO        : integer := 1
+  );
+  port(
+    -- Clocks and reset
+    CLK_REF_FULL       : in  std_logic; -- TRBnet reference clock
+    SYSCLK             : in  std_logic; -- FPGA fabric clock
+    RESET              : in  std_logic; -- synchronous reset
+    -- Media Interface TX/RX
+    MEDIA_MED2INT      : out med2int_array_t(0 to 3);
+    MEDIA_INT2MED      : in  int2med_array_t(0 to 3);
+    -- komma operation
+    RX_DLM_OUT         : out std_logic_vector(3 downto 0); -- DLM received, one clock cycle active
+    RX_DLM_WORD_OUT    : out std_logic_vector(4*8-1 downto 0); -- DLM data byte, registered
+    TX_DLM_IN          : in  std_logic;
+    TX_DLM_WORD_IN     : in  std_logic_vector(7 downto 0);
+    RX_RST_OUT         : out std_logic; -- RST received, one clock cycle active
+    RX_RST_WORD_OUT    : out std_logic_vector(7 downto 0); -- RST data byte, registered
+    TX_RST_IN          : in  std_logic;
+    TX_RST_WORD_IN     : in  std_logic_vector(7 downto 0);
+    -- sync operation
+    WORD_SYNC_IN       : in  std_logic; -- byte alignment for DLM/RST forwarding (to master port)
+    WORD_SYNC_OUT      : out std_logic; -- byte alignment for DLM/RST forwarding (from slave port)
+    MASTER_CLK_IN      : in  std_logic; -- recovered RX clock in (only master ports in quad)
+    MASTER_CLK_OUT     : out std_logic; -- recovered RX clock out (slave port in quad)
+    QUAD_RST_IN        : in  std_logic; -- HANDLE WITH CARE
+    GLOBAL_RESET_OUT   : out std_logic; -- only available on MI with slave port
+    SLAVE_ACTIVE_OUT   : out std_logic; -- for delaying MPs in hub
+    SLAVE_ACTIVE_IN    : in  std_logic; -- set to '1' on normal endpoints
+    TX_PLL_LOL_IN      : in  std_logic; -- and'ed TX PLL LOL to sync startup
+    TX_PLL_LOL_OUT     : out std_logic; -- status signal of TX PLL
+    TX_CLK_AVAIL_OUT   : out std_logic; -- stable RX recovered clock available
+    TX_PCS_RST_IN      : in  std_logic; -- TX PCS reset signal
+    SYNC_TX_PLL_IN     : in  std_logic; -- bit0 alignment for TX serializer
+    LINK_TX_READY_IN   : in  std_logic; -- from TX reset generator
+    DESTROY_LINK_IN    : in  std_logic_vector(3 downto 0); -- hard reset for links
+    WAP_REQUESTED_IN   : in  std_logic_vector(3 downto 0); -- TESTTESTTEST
+    --SFP Connection
+    SD_PRSNT_N_IN      : in  std_logic_vector(3 downto 0);  -- SFP Present ('0' = SFP in place, '1' = no SFP mounted)
+    SD_LOS_IN          : in  std_logic_vector(3 downto 0);  -- SFP Loss Of Signal ('0' = OK, '1' = no signal)
+    SD_TXDIS_OUT       : out std_logic_vector(3 downto 0);  -- SFP disable
+    --Control Interface
+    BUS_RX             : in  CTRLBUS_RX;
+    BUS_TX             : out CTRLBUS_TX;
+    -- Status and control port
+    STAT_DEBUG         : out std_logic_vector(63 downto 0);
+    CTRL_DEBUG         : in  std_logic_vector(63 downto 0);
+    DEBUG_OUT          : out std_logic_vector(31 downto 0)
+  );
+end entity;
+
+architecture med_ecp3_sfp_sync_all_RS_arch of med_ecp3_sfp_sync_all_125M_RS is
+
+  -- Placer Directives
+  attribute HGROUP : string;
+  -- for whole architecture
+  attribute HGROUP of med_ecp3_sfp_sync_all_RS_arch : architecture  is "media_interface_group";
+  attribute syn_sharing : string;
+  attribute syn_sharing of med_ecp3_sfp_sync_all_RS_arch : architecture is "off";
+  attribute syn_hier : string;
+  attribute syn_hier of med_ecp3_sfp_sync_all_RS_arch : architecture is "hard";
+
+  signal clk_rx_full        : std_logic_vector(3 downto 0);
+  signal clk_rx_half        : std_logic_vector(3 downto 0);
+  signal clk_tx_full        : std_logic_vector(3 downto 0);
+  signal clk_tx_half        : std_logic_vector(3 downto 0);
+
+  signal tx_data            : std_logic_vector(4*8-1 downto 0);
+  signal tx_k               : std_logic_vector(3 downto 0);
+  signal tx_cd              : std_logic_vector(3 downto 0);  
+  signal rx_data            : std_logic_vector(4*8-1 downto 0);
+  signal rx_k               : std_logic_vector(3 downto 0);
+  signal rx_error           : std_logic_vector(3 downto 0);
+
+  signal rx_serdes_rst      : std_logic_vector(3 downto 0);
+  signal rx_pcs_rst         : std_logic_vector(3 downto 0);
+
+  signal rx_los_low         : std_logic_vector(3 downto 0);
+  signal lsm_status         : std_logic_vector(3 downto 0);
+  signal rx_cdr_lol         : std_logic_vector(3 downto 0);
+
+  signal sci_ch_i           : std_logic_vector(4 downto 0);
+  signal sci_addr_i         : std_logic_vector(5 downto 0);
+  signal sci_data_in_i      : std_logic_vector(7 downto 0);
+  signal sci_data_out_i     : std_logic_vector(7 downto 0);
+  signal sci_read_i         : std_logic;
+  signal sci_write_i        : std_logic;
+
+  signal wa_position_i      : std_logic_vector(15 downto 0) := x"FFFF";
+  signal wap_requested_i    : std_logic_vector(15 downto 0);
+  signal wap_req_i          : std_logic_vector(3 downto 0);
+  signal wap_req_all        : std_logic;
+--  signal wap_req_all_q      : std_logic;
+  signal wap_req_all_q      : std_logic_vector(2 downto 0);
+  
+  signal stat_rx_control_i  : std_logic_vector(4*32-1 downto 0);
+  signal stat_tx_control_i  : std_logic_vector(4*32-1 downto 0);
+  signal debug_rx_control_i : std_logic_vector(4*32-1 downto 0);
+  signal debug_tx_control_i : std_logic_vector(4*32-1 downto 0);
+  signal stat_fsm_reset_i   : std_logic_vector(4*32-1 downto 0);
+
+  signal debug_i            : std_logic_vector(4*32-1 downto 0);
+
+  signal  hdinp, hdinn, hdoutp, hdoutn : std_logic_vector(3 downto 0);
+  attribute nopad : string;
+  attribute nopad of  hdinp, hdinn, hdoutp, hdoutn : signal is "true";
+
+  type u8_arr is array (0 to 3) of unsigned(7 downto 0);
+  signal cv_cnt, cv_cnt_sys : u8_arr;
+
+  signal powerup_ch         : std_logic_vector(3 downto 0);
+  signal tx_ref_clk_i       : std_logic;
+
+  signal tx_rst_i           : std_logic_vector(3 downto 0);
+
+  signal rx_rst_word_i      : std_logic_vector(4*8-1 downto 0);
+  signal rx_rst_i           : std_logic_vector(3 downto 0);
+  signal rx_dlm_i           : std_logic_vector(3 downto 0);
+
+  signal global_reset_i     : std_logic_vector(3 downto 0);
+
+  signal pll_lol_i          : std_logic;
+
+  signal link_rx_ready_i    : std_logic_vector(3 downto 0);
+  signal tx_clk_avail_sel   : std_logic;
+  
+  signal word_sync_i        : std_logic_vector(3 downto 0);
+  signal word_sync_sel      : std_logic;
+
+  signal link_active_i      : std_logic_vector(3 downto 0);
+
+  signal quad_mode : integer range 0 to 100;
+
+begin
+
+-- constants used as reminder
+-- unused = 0, master = 1, slave = 8
+
+-------------------------------------------------      
+-- check settings of media interface
+-------------------------------------------------      
+  quad_mode <= IS_MODE(3) + IS_MODE(2) + IS_MODE(1) + IS_MODE(0);
+
+  -- reject illegal combinations
+  assert not (quad_mode = 0)                           report "Error: QUAD not used" severity error;
+  assert not (quad_mode > 11)                          report "Error: multi slave QUAD detected" severity error;
+
+  -- notify user on status
+  assert not ((quad_mode >= 1) and (quad_mode <= 4))   report "Note: QUAD with only master ports detected" severity note;
+  assert not (quad_mode = 8)                           report "Note: QUAD with one slave port detected" severity note;
+  assert not ((quad_mode >= 9) and (quad_mode <= 11))  report "Note: mixed master/slave QUAD detected" severity note;
+  
+-------------------------------------------------      
+-- SFPs are disabled on unused SerDes channels
+-------------------------------------------------
+-- BUG: slave ports need also disable with link_tx_ready(i)
+  SD_TXDIS_OUT(3) <= DESTROY_LINK_IN(3) or (not SLAVE_ACTIVE_IN) --or RESET
+                                              when IS_MODE(3) = c_IS_MASTER else
+                     not link_rx_ready_i(3)   when IS_MODE(3) = c_IS_SLAVE  else
+                     '1'                      when IS_MODE(3) = c_IS_UNUSED else
+                     '0';
+  SD_TXDIS_OUT(2) <= DESTROY_LINK_IN(2) or (not SLAVE_ACTIVE_IN) --or RESET
+                                              when IS_MODE(2) = c_IS_MASTER else 
+                     not link_rx_ready_i(2)   when IS_MODE(2) = c_IS_SLAVE  else
+                     '1'                      when IS_MODE(2) = c_IS_UNUSED else
+                     '0';
+  SD_TXDIS_OUT(1) <= DESTROY_LINK_IN(1) or (not SLAVE_ACTIVE_IN) --or RESET
+                                              when IS_MODE(1) = c_IS_MASTER else 
+                     not link_rx_ready_i(1)   when IS_MODE(1) = c_IS_SLAVE  else
+                     '1'                      when IS_MODE(1) = c_IS_UNUSED else
+                     '0';
+  SD_TXDIS_OUT(0) <= DESTROY_LINK_IN(0) or (not SLAVE_ACTIVE_IN) --or RESET
+                                              when IS_MODE(0) = c_IS_MASTER else 
+                     not link_rx_ready_i(0)   when IS_MODE(0) = c_IS_SLAVE  else
+                     '1'                      when IS_MODE(0) = c_IS_UNUSED else
+                     '0';
+
+-------------------------------------------------      
+-- TX ref clock
+-- output only if a slave port is available in QUAD
+-------------------------------------------------      
+  MASTER_CLK_OUT <= clk_rx_full(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE))  else
+                    clk_rx_full(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE))  else
+                    clk_rx_full(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE))  else
+                    clk_rx_full(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE))  else
+                    '0';
+
+-------------------------------------------------      
+-- global reset
+-- output only if a slave port is available in QUAD
+-------------------------------------------------      
+  GLOBAL_RESET_OUT <= global_reset_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else
+                      global_reset_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else
+                      global_reset_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else
+                      global_reset_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else
+                      '0';
+
+-------------------------------------------------
+-- stable RX recovered clock available
+-------------------------------------------------      
+  tx_clk_avail_sel <= link_rx_ready_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else
+                      link_rx_ready_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else
+                      link_rx_ready_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else
+                      link_rx_ready_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else
+                      '1';
+
+  TX_CLK_AVAIL_OUT <= tx_clk_avail_sel;
+
+-------------------------------------------------
+--
+-------------------------------------------------
+  SLAVE_ACTIVE_OUT <= link_active_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else
+                      link_active_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else
+                      link_active_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else
+                      link_active_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else
+                      '0';
+  
+-------------------------------------------------      
+-- byte/word alignment
+-------------------------------------------------      
+  word_sync_sel <= word_sync_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE))  else
+                   word_sync_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE))  else
+                   word_sync_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE))  else
+                   word_sync_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE))  else
+                   word_sync_i(0) when ((quad_mode = 1)  and (IS_MODE(0) = c_IS_MASTER)) else
+                   word_sync_i(1) when ((quad_mode = 1)  and (IS_MODE(1) = c_IS_MASTER)) else
+                   word_sync_i(2) when ((quad_mode = 1)  and (IS_MODE(2) = c_IS_MASTER)) else
+                   word_sync_i(3) when ((quad_mode = 1)  and (IS_MODE(3) = c_IS_MASTER)) else
+                   '1';
+
+  WORD_SYNC_OUT <= word_sync_sel;
+
+  -- if a SP is in the quad, we use the received WORD_SYNC.
+  -- in a MP only configuration, the TX WORD_SYNC is used as reference.
+  
+-------------------------------------------------      
+-- reset komma receive
+-- output only if a slave port is available in QUAD
+-------------------------------------------------      
+  RX_RST_OUT <= rx_rst_i(0) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else
+                rx_rst_i(1) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else
+                rx_rst_i(2) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else
+                rx_rst_i(3) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else
+                '0';
+
+  RX_RST_WORD_OUT <= rx_rst_word_i(0*8+7 downto 0*8) when ((quad_mode >= 8) and (IS_MODE(0) = c_IS_SLAVE)) else
+                     rx_rst_word_i(1*8+7 downto 1*8) when ((quad_mode >= 8) and (IS_MODE(1) = c_IS_SLAVE)) else
+                     rx_rst_word_i(2*8+7 downto 2*8) when ((quad_mode >= 8) and (IS_MODE(2) = c_IS_SLAVE)) else
+                     rx_rst_word_i(3*8+7 downto 3*8) when ((quad_mode >= 8) and (IS_MODE(3) = c_IS_SLAVE)) else
+                     x"00";
+
+-------------------------------------------------      
+-- reset komma transmit, only on master ports
+-------------------------------------------------      
+  tx_rst_i(0) <= TX_RST_IN when (IS_MODE(0) = c_IS_MASTER) else '0';
+  tx_rst_i(1) <= TX_RST_IN when (IS_MODE(1) = c_IS_MASTER) else '0';
+  tx_rst_i(2) <= TX_RST_IN when (IS_MODE(2) = c_IS_MASTER) else '0';
+  tx_rst_i(3) <= TX_RST_IN when (IS_MODE(3) = c_IS_MASTER) else '0';
+
+-------------------------------------------------      
+-- WAP request (for testing)
+-------------------------------------------------
+  wap_requested_i(0*4+3 downto 0*4) <= WAP_REQUESTED_IN when (IS_MODE(0) = c_IS_MASTER) else x"0";
+  wap_requested_i(1*4+3 downto 1*4) <= WAP_REQUESTED_IN when (IS_MODE(1) = c_IS_MASTER) else x"0";
+  wap_requested_i(2*4+3 downto 2*4) <= WAP_REQUESTED_IN when (IS_MODE(2) = c_IS_MASTER) else x"0";
+  wap_requested_i(3*4+3 downto 3*4) <= WAP_REQUESTED_IN when (IS_MODE(3) = c_IS_MASTER) else x"0";
+
+-------------------------------------------------      
+-- Serdes
+-------------------------------------------------      
+  THE_SERDES : entity work.serdes_sync_all_125M_RS
+    port map(
+      hdinp_ch0            => hdinp(0),
+      hdinn_ch0            => hdinn(0),
+      hdoutp_ch0           => hdoutp(0),
+      hdoutn_ch0           => hdoutn(0),
+      txiclk_ch0           => clk_tx_full(0), -- drives TX FIFO bridge
+      rx_full_clk_ch0      => clk_rx_full(0), -- recovered RX clock
+      rx_half_clk_ch0      => clk_rx_half(0),
+      tx_full_clk_ch0      => open, --clk_tx_full(0), -- TX clock from PLL
+      tx_half_clk_ch0      => clk_tx_half(0),
+      fpga_rxrefclk_ch0    => CLK_REF_FULL, -- reference RX clock
+      txdata_ch0           => tx_data(0*8+7 downto 0*8),
+      tx_k_ch0             => tx_k(0),
+      tx_force_disp_ch0    => '0', -- not needed
+      tx_disp_sel_ch0      => '0',
+      rxdata_ch0           => rx_data(0*8+7 downto 0*8),
+      rx_k_ch0             => rx_k(0),
+      rx_disp_err_ch0      => open,
+      rx_cv_err_ch0        => rx_error(0),
+      rx_serdes_rst_ch0_c  => rx_serdes_rst(0),
+      sb_felb_ch0_c        => '0',
+      sb_felb_rst_ch0_c    => '0',
+      tx_pcs_rst_ch0_c     => TX_PCS_RST_IN,
+      tx_pwrup_ch0_c       => powerup_ch(0),
+      rx_pcs_rst_ch0_c     => rx_pcs_rst(0),
+      rx_pwrup_ch0_c       => powerup_ch(0),
+      rx_los_low_ch0_s     => rx_los_low(0),
+      lsm_status_ch0_s     => lsm_status(0),
+      rx_cdr_lol_ch0_s     => rx_cdr_lol(0),
+      tx_div2_mode_ch0_c   => '0',
+      rx_div2_mode_ch0_c   => '0',
+      --
+      hdinp_ch1            => hdinp(1),
+      hdinn_ch1            => hdinn(1),
+      hdoutp_ch1           => hdoutp(1),
+      hdoutn_ch1           => hdoutn(1),
+      txiclk_ch1           => clk_tx_full(1),
+      rx_full_clk_ch1      => clk_rx_full(1),
+      rx_half_clk_ch1      => clk_rx_half(1),
+      tx_full_clk_ch1      => open, --clk_tx_full(1),
+      tx_half_clk_ch1      => clk_tx_half(1),
+      fpga_rxrefclk_ch1    => CLK_REF_FULL,
+      txdata_ch1           => tx_data(1*8+7 downto 1*8),
+      tx_k_ch1             => tx_k(1),
+      tx_force_disp_ch1    => '0', -- not needed
+      tx_disp_sel_ch1      => '0',
+      rxdata_ch1           => rx_data(1*8+7 downto 1*8),
+      rx_k_ch1             => rx_k(1),
+      rx_disp_err_ch1      => open,
+      rx_cv_err_ch1        => rx_error(1),
+      rx_serdes_rst_ch1_c  => rx_serdes_rst(1),
+      sb_felb_ch1_c        => '0',
+      sb_felb_rst_ch1_c    => '0',
+      tx_pcs_rst_ch1_c     => TX_PCS_RST_IN,
+      tx_pwrup_ch1_c       => powerup_ch(1),
+      rx_pcs_rst_ch1_c     => rx_pcs_rst(1),
+      rx_pwrup_ch1_c       => powerup_ch(1),
+      rx_los_low_ch1_s     => rx_los_low(1),
+      lsm_status_ch1_s     => lsm_status(1),
+      rx_cdr_lol_ch1_s     => rx_cdr_lol(1),
+      tx_div2_mode_ch1_c   => '0',
+      rx_div2_mode_ch1_c   => '0',
+      --
+      hdinp_ch2            => hdinp(2),
+      hdinn_ch2            => hdinn(2),
+      hdoutp_ch2           => hdoutp(2),
+      hdoutn_ch2           => hdoutn(2),
+      txiclk_ch2           => clk_tx_full(2),
+      rx_full_clk_ch2      => clk_rx_full(2),
+      rx_half_clk_ch2      => clk_rx_half(2),
+      tx_full_clk_ch2      => open, --clk_tx_full(2),
+      tx_half_clk_ch2      => clk_tx_half(2),
+      fpga_rxrefclk_ch2    => CLK_REF_FULL,
+      txdata_ch2           => tx_data(2*8+7 downto 2*8),
+      tx_k_ch2             => tx_k(2),
+      tx_force_disp_ch2    => '0', -- not needed
+      tx_disp_sel_ch2      => '0',
+      rxdata_ch2           => rx_data(2*8+7 downto 2*8),
+      rx_k_ch2             => rx_k(2),
+      rx_disp_err_ch2      => open,
+      rx_cv_err_ch2        => rx_error(2),
+      rx_serdes_rst_ch2_c  => rx_serdes_rst(2),
+      sb_felb_ch2_c        => '0',
+      sb_felb_rst_ch2_c    => '0',
+      tx_pcs_rst_ch2_c     => TX_PCS_RST_IN,
+      tx_pwrup_ch2_c       => powerup_ch(2),
+      rx_pcs_rst_ch2_c     => rx_pcs_rst(2),
+      rx_pwrup_ch2_c       => powerup_ch(2),
+      rx_los_low_ch2_s     => rx_los_low(2),
+      lsm_status_ch2_s     => lsm_status(2),
+      rx_cdr_lol_ch2_s     => rx_cdr_lol(2),
+      tx_div2_mode_ch2_c   => '0',
+      rx_div2_mode_ch2_c   => '0',
+      --
+      hdinp_ch3            => hdinp(3),
+      hdinn_ch3            => hdinn(3),
+      hdoutp_ch3           => hdoutp(3),
+      hdoutn_ch3           => hdoutn(3),
+      txiclk_ch3           => clk_tx_full(3),
+      rx_full_clk_ch3      => clk_rx_full(3),
+      rx_half_clk_ch3      => clk_rx_half(3),
+      tx_full_clk_ch3      => open, --clk_tx_full(3),
+      tx_half_clk_ch3      => clk_tx_half(3),
+      fpga_rxrefclk_ch3    => CLK_REF_FULL,
+      txdata_ch3           => tx_data(3*8+7 downto 3*8),
+      tx_k_ch3             => tx_k(3),
+      tx_force_disp_ch3    => '0', -- not needed
+      tx_disp_sel_ch3      => '0',
+      rxdata_ch3           => rx_data(3*8+7 downto 3*8),
+      rx_k_ch3             => rx_k(3),
+      rx_disp_err_ch3      => open,
+      rx_cv_err_ch3        => rx_error(3),
+      rx_serdes_rst_ch3_c  => rx_serdes_rst(3),
+      sb_felb_ch3_c        => '0',
+      sb_felb_rst_ch3_c    => '0',
+      tx_pcs_rst_ch3_c     => TX_PCS_RST_IN,
+      tx_pwrup_ch3_c       => powerup_ch(3),
+      rx_pcs_rst_ch3_c     => rx_pcs_rst(3),
+      rx_pwrup_ch3_c       => powerup_ch(3),
+      rx_los_low_ch3_s     => rx_los_low(3),
+      lsm_status_ch3_s     => lsm_status(3),
+      rx_cdr_lol_ch3_s     => rx_cdr_lol(3),
+      tx_div2_mode_ch3_c   => '0',
+      rx_div2_mode_ch3_c   => '0',      
+      --
+      SCI_WRDATA           => sci_data_in_i,
+      SCI_RDDATA           => sci_data_out_i,
+      SCI_ADDR             => sci_addr_i,
+      SCI_SEL_QUAD         => sci_ch_i(4),
+      SCI_SEL_CH0          => sci_ch_i(0),
+      SCI_SEL_CH1          => sci_ch_i(1),
+      SCI_SEL_CH2          => sci_ch_i(2),
+      SCI_SEL_CH3          => sci_ch_i(3),
+      SCI_RD               => sci_read_i,
+      SCI_WRN              => sci_write_i,
+      
+      fpga_txrefclk        => MASTER_CLK_IN, -- reference TX clock
+      tx_serdes_rst_c      => '0',
+      tx_pll_lol_qd_s      => TX_PLL_LOL_OUT,
+      rst_qd_c             => QUAD_RST_IN, 
+      serdes_rst_qd_c      => '0', -- was wrong
+      tx_sync_qd_c         => SYNC_TX_PLL_IN
+    );
+    
+    clk_tx_full(0) <= MASTER_CLK_IN;
+    clk_tx_full(1) <= MASTER_CLK_IN;
+    clk_tx_full(2) <= MASTER_CLK_IN;
+    clk_tx_full(3) <= MASTER_CLK_IN;
+    
+gen_control : for i in 0 to 3 generate   
+  gen_used_control : if (IS_MODE(i) = c_IS_SLAVE) or (IS_MODE(i) = c_IS_MASTER) generate
+    THE_MED_CONTROL : entity work.med_sync_control_RS
+      generic map(
+        IS_WAP_ZERO   => IS_WAP_ZERO,
+        IS_MODE       => IS_MODE(i)
+      )
+      port map(
+        -- clocks and resets
+        CLK_SYS            => SYSCLK,
+        CLK_RXI            => clk_rx_full(i),
+        CLK_RXHALF         => clk_rx_half(i),
+        CLK_TXI            => clk_tx_full(i),
+        CLK_REF            => CLK_REF_FULL,
+        RESET              => RESET,
+        -- Media Interface
+        MEDIA_MED2INT      => MEDIA_MED2INT(i),
+        MEDIA_INT2MED      => MEDIA_INT2MED(i),
+        -- status signals from SerDes
+        SFP_LOS_IN         => SD_LOS_IN(i),
+        RX_CDR_LOL_IN      => rx_cdr_lol(i),
+        RX_LOS_IN          => rx_los_low(i),
+        RX_CV_IN           => rx_error(i),
+        RX_LSM_IN          => lsm_status(i),
+        TX_PLL_LOL_IN      => TX_PLL_LOL_IN,
+        WA_POSITION_IN     => wa_position_i(i*4+3 downto i*4),
+        WAP_REQUESTED_IN   => wap_requested_i(i*4+3 downto i*4),
+        WAP_REQ_OUT        => wap_req_i(i),
+        -- control signals to SerDes
+        RX_SERDES_RST      => rx_serdes_rst(i),
+        RX_PCS_RST         => rx_pcs_rst(i),
+        -- SerDes data streams
+        TX_DATA_OUT        => tx_data(i*8+7 downto i*8),
+        TX_K_OUT           => tx_k(i),
+        RX_DATA_IN         => rx_data(i*8+7 downto i*8),
+        RX_K_IN            => rx_k(i),
+        -- ports for synchronous operation
+        WORD_SYNC_IN       => WORD_SYNC_IN,
+        WORD_SYNC_OUT      => word_sync_i(i), 
+        GLOBAL_RESET_OUT   => global_reset_i(i),
+        LINK_TX_READY_IN   => LINK_TX_READY_IN,
+        LINK_RX_READY_OUT  => link_rx_ready_i(i),
+        LINK_ACTIVE_OUT    => link_active_i(i),
+        -- komma operation
+        TX_DLM_IN          => TX_DLM_IN,
+        TX_DLM_WORD_IN     => TX_DLM_WORD_IN,
+        TX_RST_IN          => tx_rst_i(i),
+        TX_RST_WORD_IN     => TX_RST_WORD_IN,
+        RX_DLM_OUT         => rx_dlm_i(i),
+        RX_DLM_WORD_OUT    => RX_DLM_WORD_OUT(i*8+7 downto i*8),
+        RX_RST_OUT         => rx_rst_i(i),
+        RX_RST_WORD_OUT    => rx_rst_word_i(i*8+7 downto i*8),
+        -- Status and debug signals
+        STAT_TX_CONTROL    => stat_tx_control_i(i*32+31 downto i*32),
+        STAT_RX_CONTROL    => stat_rx_control_i(i*32+31 downto i*32),
+        DEBUG_TX_CONTROL   => debug_tx_control_i(i*32+31 downto i*32),
+        DEBUG_RX_CONTROL   => debug_rx_control_i(i*32+31 downto i*32),
+        STAT_RESET         => stat_fsm_reset_i(i*32+31 downto i*32),
+        DEBUG_OUT          => debug_i(i*32+31 downto i*32)
+      );
+    
+    powerup_ch(i) <= '1';
+    cv_cnt(i)     <= cv_cnt(i) + 1 when rx_error(i) = '1' and rising_edge(clk_rx_full(i));
+  end generate;
+
+  gen_not_used : if (IS_MODE(i) = c_IS_UNUSED) generate
+    powerup_ch(i)              <= '0'; -- keep in power down
+    rx_serdes_rst(i)           <= '1'; -- keep in reset
+    rx_pcs_rst(i)              <= '1'; -- keep in reset
+    wap_req_i(i)               <= '0';
+    MEDIA_MED2INT(i).dataready <= '0';
+    MEDIA_MED2INT(i).tx_read   <= '1';
+    MEDIA_MED2INT(i).stat_op   <= x"0007";
+  end generate;
+  
+end generate;
+
+  wap_req_all <= wap_req_i(0) or wap_req_i(1) or wap_req_i(2) or wap_req_i(3);
+
+  -- SIGNAL_SYNC fails. TAKE CARE!
+  wap_req_all_q(2 downto 0) <= wap_req_all_q(1 downto 0) & wap_req_all when rising_edge(SYSCLK);
+  
+  THE_SCI_READER : entity work.sci_reader_RS
+    port map(
+      CLK         => SYSCLK,
+      RESET       => RESET,
+      --SCI
+      SCI_WRDATA  => sci_data_in_i,
+      SCI_RDDATA  => sci_data_out_i,
+      SCI_ADDR    => sci_addr_i,
+      SCI_SEL     => sci_ch_i,
+      SCI_RD      => sci_read_i,
+      SCI_WR      => sci_write_i,
+      -- WAP
+      WA_POS_OUT  => wa_position_i,
+--      WA_REQ_IN   => wap_req_all_q,
+      WA_REQ_IN   => wap_req_all_q(2),
+      WA_ACK_OUT  => open,
+      --Slowcontrol
+      BUS_RX      => BUS_RX,
+      BUS_TX      => BUS_TX,
+      -- 
+      MEDIA_STATUS_REG_IN(31 downto 0)    => stat_rx_control_i(31 downto 0),
+      MEDIA_STATUS_REG_IN(63 downto 32)   => stat_tx_control_i(31 downto 0),
+      MEDIA_STATUS_REG_IN(191 downto 64)  => stat_fsm_reset_i(127 downto 0),
+      MEDIA_STATUS_REG_IN(199 downto 192) => cv_cnt_sys(0),
+      MEDIA_STATUS_REG_IN(207 downto 200) => cv_cnt_sys(1),
+      MEDIA_STATUS_REG_IN(215 downto 208) => cv_cnt_sys(2),
+      MEDIA_STATUS_REG_IN(223 downto 216) => cv_cnt_sys(3),
+      MEDIA_STATUS_REG_IN(255 downto 224) => (others => '0'),
+      DEBUG_OUT   => open
+    );
+
+  cv_cnt_sys <= cv_cnt when rising_edge(SYSCLK);    
+
+  STAT_DEBUG(3 downto 0)   <= clk_rx_full(3 downto 0);
+  STAT_DEBUG(7 downto 4)   <= clk_tx_full(3 downto 0);
+  STAT_DEBUG(63 downto 8)  <= (others => '0');
+
+  -- SerDes #3 is used for debugging
+--  DEBUG_OUT <= debug_i(0*32+31 downto 0*32);
+  -- all SerDes debug
+  DEBUG_OUT(31 downto 24) <= debug_i(3*32+7 downto 3*32);
+  DEBUG_OUT(23 downto 16) <= debug_i(2*32+7 downto 2*32);
+  DEBUG_OUT(15 downto 8)  <= debug_i(1*32+7 downto 1*32);
+  DEBUG_OUT(7 downto 0)   <= debug_i(0*32+7 downto 0*32);
+  
+end architecture;
+