]> jspc29.x-matter.uni-frankfurt.de Git - trbnet.git/commitdiff
first DLM operation included, state of code is approx. 04/2020
authorMichael Boehmer <mboehmer@ph.tum.de>
Mon, 15 Nov 2021 13:15:23 +0000 (14:15 +0100)
committerMichael Boehmer <mboehmer@ph.tum.de>
Mon, 15 Nov 2021 13:15:23 +0000 (14:15 +0100)
media_interfaces/med_ecp3_sfp_sync_RS.vhd [new file with mode: 0644]
media_interfaces/sync/med_sync_control_RS.vhd [new file with mode: 0644]
media_interfaces/sync/med_sync_define_RS.vhd [new file with mode: 0644]
media_interfaces/sync/rx_control_RS.vhd [new file with mode: 0644]
media_interfaces/sync/rx_reset_fsm_RS.vhd [new file with mode: 0644]
media_interfaces/sync/sci_reader_RS.vhd [new file with mode: 0644]
media_interfaces/sync/tx_control_RS.vhd [new file with mode: 0644]
media_interfaces/sync/tx_reset_fsm_RS.vhd [new file with mode: 0644]

diff --git a/media_interfaces/med_ecp3_sfp_sync_RS.vhd b/media_interfaces/med_ecp3_sfp_sync_RS.vhd
new file mode 100644 (file)
index 0000000..c576d59
--- /dev/null
@@ -0,0 +1,304 @@
+--Media interface for Lattice ECP3 using PCS at 2GHz
+
+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.all;
+
+entity med_ecp3_sfp_sync_RS is
+  generic(
+    SERDES_NUM      : integer range 0 to 3 := 0;
+    IS_SYNC_SLAVE   : integer := c_NO;      --select slave mode
+    IS_WAP_ZERO     : integer := c_NO
+  );
+  port(
+    CLK_REF_FULL       : in  std_logic; -- 200 MHz reference clock
+    CLK_INTERNAL_FULL  : in  std_logic; -- internal 200 MHz, always on
+    SYSCLK             : in  std_logic; -- 100 MHz main clock net, synchronous to RX clock
+    RESET              : in  std_logic; -- synchronous reset
+    CLEAR              : in  std_logic; -- asynchronous reset
+
+    --Internal Connection TX
+    MEDIA_MED2INT      : out MED2INT;
+    MEDIA_INT2MED      : in  INT2MED;
+    
+    --Sync operation
+    RX_DLM_OUT         : out std_logic := '0';
+    RX_DLM_WORD_OUT    : out std_logic_vector(7 downto 0) := x"00";
+    TX_DLM_IN          : in  std_logic := '0';
+    TX_DLM_WORD_IN     : in  std_logic_vector(7 downto 0) := x"00";
+    WORD_SYNC_IN       : in  std_logic := '1';
+    WORD_SYNC_OUT      : out std_logic;
+    
+    --SFP Connection
+    SD_PRSNT_N_IN      : in  std_logic;  -- SFP Present ('0' = SFP in place, '1' = no SFP mounted)
+    SD_LOS_IN          : in  std_logic;  -- SFP Loss Of Signal ('0' = OK, '1' = no signal)
+    SD_TXDIS_OUT       : out  std_logic := '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) := (others => '0')
+  );
+end entity;
+
+
+architecture med_ecp3_sfp_sync_arch of med_ecp3_sfp_sync_RS is
+
+  -- Placer Directives
+  attribute HGROUP : string;
+  -- for whole architecture
+  attribute HGROUP of med_ecp3_sfp_sync_arch : architecture  is "media_interface_group";
+  attribute syn_sharing : string;
+  attribute syn_sharing of med_ecp3_sfp_sync_arch : architecture is "off";
+  attribute syn_hier : string;
+  attribute syn_hier of med_ecp3_sfp_sync_arch : architecture is "hard";
+
+  -- signal clk_200_i         : std_logic;
+  signal clk_rx_full, clk_rx_half : std_logic;
+  signal clk_tx_full, clk_tx_half : std_logic;
+
+  signal tx_data           : std_logic_vector(7 downto 0);
+  signal tx_k              : std_logic;
+  signal rx_data           : std_logic_vector(7 downto 0);
+  signal rx_k              : std_logic;
+  signal rx_error          : std_logic;
+
+  signal rst_n             : std_logic;
+  signal rx_serdes_rst     : std_logic;
+  signal tx_serdes_rst     : std_logic;
+  signal tx_pcs_rst        : std_logic;
+  signal rx_pcs_rst        : std_logic;
+  signal rst_qd            : std_logic;
+  signal serdes_rst_qd     : std_logic;
+
+  signal rx_los_low        : std_logic;
+  signal lsm_status        : std_logic;
+  signal rx_cdr_lol        : std_logic;
+  signal tx_pll_lol        : std_logic;
+
+  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        : std_logic_vector(15 downto 0) := x"FFFF";
+  signal wa_position_sel    : std_logic_vector(3 downto 0);
+
+  signal stat_rx_control_i  : std_logic_vector(31 downto 0);
+  signal stat_tx_control_i  : std_logic_vector(31 downto 0);
+  signal debug_rx_control_i : std_logic_vector(31 downto 0);
+  signal debug_tx_control_i : std_logic_vector(31 downto 0);
+  signal stat_fsm_reset_i   : std_logic_vector(31 downto 0);
+  signal debug_i            : std_logic_vector(31 downto 0);
+
+  signal  hdinp, hdinn, hdoutp, hdoutn : std_logic;
+  attribute nopad : string;
+  attribute nopad of  hdinp, hdinn, hdoutp, hdoutn : signal is "true";
+
+
+begin
+
+-- we keep TX alive, at the moment, forever
+  SD_TXDIS_OUT <= '0';
+
+-------------------------------------------------      
+-- Serdes
+-------------------------------------------------      
+gen_pcs0 : if SERDES_NUM = 0 generate
+  THE_SERDES : entity work.serdes_sync_0 
+    port map(
+      hdinp_ch0            => hdinp,
+      hdinn_ch0            => hdinn,
+      hdoutp_ch0           => hdoutp,
+      hdoutn_ch0           => hdoutn,
+      txiclk_ch0           => CLK_REF_FULL,
+      rx_full_clk_ch0      => clk_rx_full,
+      rx_half_clk_ch0      => clk_rx_half,
+      tx_full_clk_ch0      => clk_tx_full,
+      tx_half_clk_ch0      => clk_tx_half,
+      fpga_rxrefclk_ch0    => CLK_INTERNAL_FULL,
+      txdata_ch0           => tx_data,
+      tx_k_ch0             => tx_k,
+      tx_force_disp_ch0    => '0',
+      tx_disp_sel_ch0      => '0',
+      rxdata_ch0           => rx_data,
+      rx_k_ch0             => rx_k,
+      rx_disp_err_ch0      => open,
+      rx_cv_err_ch0        => rx_error,
+      rx_serdes_rst_ch0_c  => rx_serdes_rst,
+      sb_felb_ch0_c        => '0',
+      sb_felb_rst_ch0_c    => '0',
+      tx_pcs_rst_ch0_c     => tx_pcs_rst,
+      tx_pwrup_ch0_c       => '1',
+      rx_pcs_rst_ch0_c     => rx_pcs_rst,
+      rx_pwrup_ch0_c       => '1',
+      rx_los_low_ch0_s     => rx_los_low,
+      lsm_status_ch0_s     => lsm_status,
+      rx_cdr_lol_ch0_s     => rx_cdr_lol,
+      tx_div2_mode_ch0_c   => '0',
+      rx_div2_mode_ch0_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_RD               => sci_read_i,
+      SCI_WRN              => sci_write_i,
+      
+      fpga_txrefclk        => CLK_REF_FULL,
+      tx_serdes_rst_c      => '0',
+      tx_pll_lol_qd_s      => tx_pll_lol,
+      rst_qd_c             => rst_qd,
+      serdes_rst_qd_c      => '0'
+    );
+end generate;
+
+gen_pcs3 : if SERDES_NUM = 3 generate
+  THE_SERDES : entity work.serdes_sync_3 
+    port map(
+      hdinp_ch3            => hdinp,
+      hdinn_ch3            => hdinn,
+      hdoutp_ch3           => hdoutp,
+      hdoutn_ch3           => hdoutn,
+      txiclk_ch3           => CLK_REF_FULL,
+      rx_full_clk_ch3      => clk_rx_full,
+      rx_half_clk_ch3      => clk_rx_half,
+      tx_full_clk_ch3      => clk_tx_full,
+      tx_half_clk_ch3      => clk_tx_half,
+      fpga_rxrefclk_ch3    => CLK_INTERNAL_FULL,
+      txdata_ch3           => tx_data,
+      tx_k_ch3             => tx_k,
+      tx_force_disp_ch3    => '0',
+      tx_disp_sel_ch3      => '0',
+      rxdata_ch3           => rx_data,
+      rx_k_ch3             => rx_k,
+      rx_disp_err_ch3      => open,
+      rx_cv_err_ch3        => rx_error,
+      rx_serdes_rst_ch3_c  => rx_serdes_rst,
+      sb_felb_ch3_c        => '0',
+      sb_felb_rst_ch3_c    => '0',
+      tx_pcs_rst_ch3_c     => tx_pcs_rst,
+      tx_pwrup_ch3_c       => '1',
+      rx_pcs_rst_ch3_c     => rx_pcs_rst,
+      rx_pwrup_ch3_c       => '1',
+      rx_los_low_ch3_s     => rx_los_low,
+      lsm_status_ch3_s     => lsm_status,
+      rx_cdr_lol_ch3_s     => rx_cdr_lol,
+      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_CH3          => sci_ch_i(3),
+      SCI_RD               => sci_read_i,
+      SCI_WRN              => sci_write_i,
+      
+      fpga_txrefclk        => CLK_REF_FULL,
+      tx_serdes_rst_c      => '0',
+      tx_pll_lol_qd_s      => tx_pll_lol,
+      rst_qd_c             => rst_qd,
+      serdes_rst_qd_c      => '0'
+    );
+end generate;
+
+  tx_serdes_rst <= '0'; --no function
+  serdes_rst_qd <= '0'; --included in rst_qd
+  wa_position_sel <= wa_position(3 downto 0)   when SERDES_NUM = 0 
+                else wa_position(15 downto 12) when SERDES_NUM = 3;
+    
+THE_MED_CONTROL : entity work.med_sync_control_RS
+  generic map(
+    IS_SYNC_SLAVE => IS_SYNC_SLAVE,
+    IS_WAP_ZERO   => IS_WAP_ZERO,
+    IS_TX_RESET   => 1
+  )
+  port map(
+    CLK_SYS            => SYSCLK,
+    CLK_RXI            => clk_rx_full,
+    CLK_RXHALF         => clk_rx_half,
+    CLK_TXI            => CLK_REF_FULL,
+    CLK_REF            => CLK_INTERNAL_FULL,
+    RESET              => RESET,
+    CLEAR              => CLEAR,
+    
+    SFP_LOS            => SD_LOS_IN,
+    TX_LOL             => tx_pll_lol,
+    RX_CDR_LOL         => rx_cdr_lol,
+    RX_LOS             => rx_los_low,
+    WA_POSITION        => wa_position_sel,
+   
+    WORD_SYNC_IN       => WORD_SYNC_IN,
+    WORD_SYNC_OUT      => WORD_SYNC_OUT,
+    RX_SERDES_RST      => rx_serdes_rst,
+    RX_PCS_RST         => rx_pcs_rst,
+    QUAD_RST           => rst_qd,
+    TX_PCS_RST         => tx_pcs_rst,
+
+    MEDIA_MED2INT      => MEDIA_MED2INT,
+    MEDIA_INT2MED      => MEDIA_INT2MED,
+    
+    TX_DATA            => tx_data,
+    TX_K               => tx_k,
+    RX_DATA            => rx_data,
+    RX_K               => rx_k,
+    
+    TX_DLM_WORD        => TX_DLM_WORD_IN,
+    TX_DLM             => TX_DLM_IN,
+    RX_DLM_WORD        => RX_DLM_WORD_OUT,
+    RX_DLM             => RX_DLM_OUT,
+    SERDES_RX_READY_IN => '1',
+    SERDES_TX_READY_IN => '1',
+    STAT_TX_CONTROL    => stat_tx_control_i,
+    STAT_RX_CONTROL    => stat_rx_control_i,
+    DEBUG_TX_CONTROL   => debug_tx_control_i,
+    DEBUG_RX_CONTROL   => debug_rx_control_i,
+    STAT_RESET         => stat_fsm_reset_i,
+    DEBUG_OUT          => debug_i
+  );
+
+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,
+    --Slowcontrol
+    BUS_RX      => BUS_RX,
+    BUS_TX      => BUS_TX,
+    -- 
+    MEDIA_STATUS_REG_IN(31 downto 0)   => stat_rx_control_i,
+    MEDIA_STATUS_REG_IN(63 downto 32)  => stat_tx_control_i,
+    MEDIA_STATUS_REG_IN(95 downto 64)  => stat_fsm_reset_i,
+    MEDIA_STATUS_REG_IN(255 downto 96) => (others => '0'),
+    DEBUG_OUT   => open
+  );
+
+  STAT_DEBUG(63)           <= clk_tx_full;
+  STAT_DEBUG(62 downto 32) <= (others => '0');
+  STAT_DEBUG(31 downto 0)  <= debug_i;
+end architecture;
+
diff --git a/media_interfaces/sync/med_sync_control_RS.vhd b/media_interfaces/sync/med_sync_control_RS.vhd
new file mode 100644 (file)
index 0000000..350389f
--- /dev/null
@@ -0,0 +1,403 @@
+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.all;
+
+entity med_sync_control_RS is
+  generic(
+    IS_SYNC_SLAVE : integer := 1;
+    IS_WAP_ZERO   : integer := 0;
+    IS_TX_RESET   : integer := 1
+    );
+  port(
+    CLK_SYS       : in  std_logic; -- 100MHz system clock
+    CLK_RXI       : in  std_logic; -- recovered RX clock, 200MHz
+    CLK_RXHALF    : in  std_logic; -- used for media interface
+    CLK_TXI       : in  std_logic; -- TX clock, 200MHz
+    CLK_REF       : in  std_logic; -- 200MHz local clock
+    RESET         : in  std_logic;
+    CLEAR         : in  std_logic;
+    
+    SFP_LOS       : in  std_logic;
+    TX_LOL        : in  std_logic;
+    RX_CDR_LOL    : in  std_logic;
+    RX_LOS        : in  std_logic;
+    WA_POSITION   : in  std_logic_vector(3 downto 0);
+
+    WORD_SYNC_IN  : in  std_logic; -- for isochronous operation
+    WORD_SYNC_OUT : out std_logic; -- for isochronous operation
+
+    RX_SERDES_RST : out std_logic;
+    RX_PCS_RST    : out std_logic;
+    QUAD_RST      : out std_logic;
+    TX_PCS_RST    : out std_logic;
+
+    MEDIA_MED2INT : out MED2INT;
+    MEDIA_INT2MED : in  INT2MED;
+    
+    TX_DATA       : out std_logic_vector(7 downto 0);
+    TX_K          : out std_logic;
+    TX_CD         : out std_logic;
+    RX_DATA       : in  std_logic_vector(7 downto 0);
+    RX_K          : in  std_logic;
+    
+    TX_DLM_WORD   : in  std_logic_vector(7 downto 0);
+    TX_DLM        : in  std_logic;
+    RX_DLM_WORD   : out std_logic_vector(7 downto 0);
+    RX_DLM        : out std_logic;
+    
+    SERDES_RX_READY_IN : in std_logic := '1';
+    SERDES_TX_READY_IN : in std_logic := '1';
+    
+    STAT_TX_CONTROL  : out std_logic_vector(31 downto 0);
+    STAT_RX_CONTROL  : out std_logic_vector(31 downto 0);
+    DEBUG_TX_CONTROL : out std_logic_vector(31 downto 0);
+    DEBUG_RX_CONTROL : out std_logic_vector(31 downto 0);
+    STAT_RESET       : out std_logic_vector(31 downto 0);
+    DEBUG_OUT        : out std_logic_vector(31 downto 0)
+    );
+end entity;
+
+
+architecture med_sync_control_arch of med_sync_control_RS is
+
+signal rx_fsm_state             : std_logic_vector(3 downto 0);
+signal tx_fsm_state             : std_logic_vector(3 downto 0);
+signal wa_position_rx           : std_logic_vector(3 downto 0);
+signal start_timer              : unsigned(21 downto 0) := (others => '0');
+
+signal request_retr_i           : std_logic;
+signal start_retr_i             : std_logic;
+signal request_retr_position_i  : std_logic_vector(7 downto 0);
+signal start_retr_position_i    : std_logic_vector(7 downto 0);
+signal rx_dlm_i                 : std_logic;
+
+signal led_ok                   : std_logic;
+signal led_dlm, last_led_dlm    : std_logic;
+signal led_rx, last_led_rx      : std_logic;
+signal led_tx, last_led_tx      : std_logic;
+signal timer                    : unsigned(20 downto 0);
+signal sd_los_i                 : std_logic;
+
+signal rx_allow                 : std_logic;
+signal tx_allow                 : std_logic;
+signal got_link_ready_i         : std_logic;
+signal make_link_reset_i        : std_logic;
+signal send_link_reset_i        : std_logic;
+signal make_link_reset_real_i   : std_logic := '0';
+signal make_link_reset_sys_i    : std_logic := '0';
+signal send_link_reset_real_i   : std_logic := '0';
+signal send_link_reset_sys_i    : std_logic := '0';
+
+signal reset_i                  : std_logic;
+signal rst_n                    : std_logic;
+signal rst_n_tx                 : std_logic;
+signal finished_reset_rx        : std_logic;
+signal finished_reset_rx_q      : std_logic;
+signal finished_reset_tx        : std_logic;
+signal finished_reset_tx_q      : std_logic;
+
+signal media_med2int_i          : MED2INT;
+
+signal rx_serdes_rst_i          : std_logic;
+signal rx_pcs_rst_i             : std_logic;
+
+signal rx_serdes_rst_i_q        : std_logic_vector(2 downto 0);
+signal rx_pcs_rst_i_q           : std_logic_vector(2 downto 0);
+
+signal tx_pcs_rst_i             : std_logic;
+signal quad_rst_i               : std_logic;
+
+signal wap_is_zero_i            : std_logic;
+signal rx_reset_finished_i      : std_logic;
+signal tx_k_i                   : std_logic;
+
+signal debug_tx_control_i       : std_logic_vector(31 downto 0);
+--signal debug_rx_control_i       : std_logic_vector(31 downto 0);
+
+begin
+
+rst_n_tx  <=       not (CLEAR or sd_los_i or make_link_reset_real_i or RESET) when (IS_SYNC_SLAVE = 1 and IS_TX_RESET = 1)
+              else not (CLEAR or make_link_reset_real_i or RESET);
+
+rst_n     <= not (CLEAR or sd_los_i or make_link_reset_real_i or RESET);
+reset_i   <=     (RESET or sd_los_i or make_link_reset_real_i);
+
+media_med2int_i.clk_half <= CLK_RXHALF;
+media_med2int_i.clk_full <= CLK_RXI;
+
+-------------------------------------------------      
+-- Reset RX FSM
+-------------------------------------------------      
+THE_RX_FSM : rx_reset_fsm_RS
+  port map(
+    RST_N                => rst_n,
+    RX_REFCLK            => CLK_REF,
+    TX_PLL_LOL_QD_S      => '0', --TX_LOL, -- we don't use this one
+    RX_SERDES_RST_CH_C   => rx_serdes_rst_i,
+    RX_CDR_LOL_CH_S      => RX_CDR_LOL,
+    RX_LOS_LOW_CH_S      => RX_LOS,
+    RX_PCS_RST_CH_C      => rx_pcs_rst_i,
+    WA_POSITION          => wa_position_rx,
+    NORMAL_OPERATION_OUT => finished_reset_rx,
+    STATE_OUT            => rx_fsm_state
+    );
+
+-- crossing the abbyss
+THE_ABBYSS_PROC: process( CLK_RXI )
+begin 
+  if( rising_edge(CLK_RXI) ) then
+    rx_serdes_rst_i_q <= rx_serdes_rst_i_q(1 downto 0) & rx_serdes_rst_i;
+    rx_pcs_rst_i_q    <= rx_pcs_rst_i_q(1 downto 0)    & rx_pcs_rst_i;
+  end if;
+end process THE_ABBYSS_PROC;
+
+RX_SERDES_RST <= rx_serdes_rst_i_q(2);
+RX_PCS_RST    <= rx_pcs_rst_i_q(2);
+    
+-------------------------------------------------      
+-- Reset TX FSM
+-------------------------------------------------      
+THE_TX_FSM : tx_reset_fsm_RS
+  port map(
+    RST_N                => rst_n_tx,
+    TX_REFCLK            => CLK_REF,
+    TX_PLL_LOL_QD_S      => TX_LOL,
+    RX_RESET_FINISHED_IN => rx_reset_finished_i,
+    RST_QD_C             => quad_rst_i,
+    TX_PCS_RST_CH_C      => tx_pcs_rst_i,
+    NORMAL_OPERATION_OUT => finished_reset_tx,
+    STATE_OUT            => tx_fsm_state
+    );
+
+rx_reset_finished_i <= finished_reset_rx when IS_SYNC_SLAVE = 1 else '1';
+
+-- may also need sync?
+TX_PCS_RST    <= tx_pcs_rst_i;
+QUAD_RST      <= quad_rst_i;
+
+-- take it in
+SYNC_WA_POSITION_PROC: process( CLK_REF )
+begin
+  if( rising_edge(CLK_REF) ) then
+    if IS_WAP_ZERO = 1 then
+      wa_position_rx <= WA_POSITION;
+    else
+      wa_position_rx <= x"0";
+    end if;
+  end if;
+end process SYNC_WA_POSITION_PROC;
+    
+-------------------------------------------------      
+-- RX & TX allow
+-------------------------------------------------  
+-- Slave enables RX/TX when sync is done, Master waits additional time to make sure link is stable
+PROC_ALLOW : process begin
+  wait until rising_edge(CLK_SYS);
+  if( (finished_reset_rx_q = '1')   
+            and (IS_SYNC_SLAVE = 1 or start_timer(start_timer'left) = '1') ) then
+    rx_allow <= '1';
+  else
+    rx_allow <= '0';
+  end if;
+  if( (finished_reset_tx_q = '1' and finished_reset_rx_q = '1') 
+            and (IS_SYNC_SLAVE = 1 or start_timer(start_timer'left) = '1') ) then
+    tx_allow <= '1';
+  else
+    tx_allow <= '0';
+  end if;
+end process;
+
+LINK_RESET_FIN_TX  : signal_sync port map(RESET => '0',CLK0 => CLK_SYS, CLK1 => CLK_SYS,
+                                          D_IN(0)  => finished_reset_tx, 
+                                          D_OUT(0) => finished_reset_tx_q);
+LINK_RESET_FIN_RX  : signal_sync port map(RESET => '0',CLK0 => CLK_SYS, CLK1 => CLK_SYS,
+                                          D_IN(0)  => finished_reset_rx, 
+                                          D_OUT(0) => finished_reset_rx_q);
+
+START_TIMER_PROC : process( CLK_SYS )
+begin
+  if( rising_edge(CLK_SYS) ) then
+--    if( (finished_reset_tx_q = '1') and (finished_reset_rx_q = '1') ) then
+    if( (finished_reset_tx_q = '1') and (finished_reset_rx_q = '1') and (got_link_ready_i = '1' or IS_SYNC_SLAVE = 1) ) then
+      if start_timer(start_timer'left) = '0' then
+        start_timer <= start_timer + 1;
+      end if;  
+    else
+      start_timer <= (others => '0');
+    end if;
+  end if;
+end process START_TIMER_PROC;
+    
+-------------------------------------------------      
+-- TX Data
+-------------------------------------------------         
+THE_TX : tx_control_RS
+  port map(
+    CLK_200                => CLK_TXI,
+    CLK_100                => CLK_SYS,
+    RESET_IN               => reset_i,
+
+    WORD_SYNC_IN           => WORD_SYNC_IN,
+
+    TX_DATA_IN             => MEDIA_INT2MED.data,
+    TX_PACKET_NUMBER_IN    => MEDIA_INT2MED.packet_num,
+    TX_WRITE_IN            => MEDIA_INT2MED.dataready,
+    TX_READ_OUT            => media_med2int_i.tx_read,
+
+    TX_DATA_OUT            => TX_DATA,
+    TX_K_OUT               => tx_k_i, --TX_K,
+    TX_CD_OUT              => TX_CD,
+
+    SEND_DLM               => TX_DLM,
+    SEND_DLM_WORD          => TX_DLM_WORD,
+    
+    SEND_LINK_RESET_IN     => MEDIA_INT2MED.ctrl_op(15),
+    TX_ALLOW_IN            => tx_allow,
+    RX_ALLOW_IN            => rx_allow,
+
+    DEBUG_OUT              => debug_tx_control_i, --DEBUG_TX_CONTROL,
+    STAT_REG_OUT           => STAT_TX_CONTROL
+  );  
+
+TX_K <= tx_k_i;
+
+-------------------------------------------------      
+-- RX Data
+-------------------------------------------------             
+THE_RX_CONTROL : rx_control_RS
+  port map(
+    CLK_200                        => CLK_RXI,
+    CLK_100                        => CLK_SYS,
+    RESET_IN                       => reset_i,
+
+    WORD_SYNC_OUT                  => WORD_SYNC_OUT,
+
+    RX_DATA_OUT                    => media_med2int_i.data,
+    RX_PACKET_NUMBER_OUT           => media_med2int_i.packet_num,
+    RX_WRITE_OUT                   => media_med2int_i.dataready,
+
+    RX_DATA_IN                     => RX_DATA,
+    RX_K_IN                        => RX_K,
+
+    RX_DLM                         => rx_dlm_i,
+    RX_DLM_WORD                    => RX_DLM_WORD,
+    
+    SEND_LINK_RESET_OUT            => send_link_reset_i,
+    MAKE_RESET_OUT                 => make_link_reset_i,
+    RX_ALLOW_IN                    => rx_allow,
+    RX_RESET_FINISHED              => finished_reset_rx,
+    GOT_LINK_READY                 => got_link_ready_i,
+
+    DEBUG_OUT                      => DEBUG_RX_CONTROL,
+    STAT_REG_OUT                   => STAT_RX_CONTROL
+  );   
+
+RX_DLM           <= rx_dlm_i;
+MEDIA_MED2INT    <= media_med2int_i;
+
+-------------------------------------------------      
+-- Generate LED signals
+-------------------------------------------------   
+led_ok  <= rx_allow and tx_allow when rising_edge(CLK_SYS); 
+led_rx  <= (media_med2int_i.dataready or led_rx)  and not timer(20) when rising_edge(CLK_SYS);
+led_tx  <= (MEDIA_INT2MED.dataready or led_tx or sd_los_i)  and not timer(20) when rising_edge(CLK_SYS);
+led_dlm <= (led_dlm or rx_dlm_i) and not timer(20) when rising_edge(CLK_SYS);
+
+ROC_TIMER_PROC: process( CLK_SYS )
+begin
+  if( rising_edge(CLK_SYS) ) then
+    timer <= timer + 1 ;
+    if timer(20) = '1' then
+      timer <= (others => '0');
+      last_led_rx <= led_rx ;
+      last_led_tx <= led_tx;
+      last_led_dlm <= led_dlm;
+    end if;
+  end if;
+end process ROC_TIMER_PROC;
+        
+-------------------------------------------------      
+-- Status signals
+-------------------------------------------------   
+
+STAT_RESET(3 downto 0)   <= rx_fsm_state;
+STAT_RESET(7 downto 4)   <= tx_fsm_state;
+STAT_RESET(8)            <= tx_allow;
+STAT_RESET(9)            <= rx_allow;
+STAT_RESET(15 downto 10) <= (others => '0');
+STAT_RESET(16)           <= RX_CDR_LOL;
+STAT_RESET(17)           <= RX_LOS;
+STAT_RESET(18)           <= '0';
+STAT_RESET(19)           <= '0';
+STAT_RESET(20)           <= TX_LOL;
+STAT_RESET(21)           <= rst_n;
+STAT_RESET(22)           <= rst_n_tx;
+STAT_RESET(30 downto 23) <= (others => '0');
+STAT_RESET(31) <= start_timer(start_timer'left);
+
+
+gen_link_reset : if IS_SYNC_SLAVE = 1 generate
+  link_reset_pulse : pulse_sync port map( CLK_A_IN => CLK_RXI, CLK_B_IN => CLK_SYS,
+                                          PULSE_A_IN => make_link_reset_i, 
+                                          PULSE_B_OUT => make_link_reset_sys_i);
+  link_reset_send  : signal_sync port map(RESET => '0',CLK0 => CLK_RXI,CLK1 => CLK_SYS,
+                                          D_IN(0)  => send_link_reset_i, 
+                                          D_OUT(0) => send_link_reset_sys_i);
+end generate;
+
+make_link_reset_real_i <= make_link_reset_sys_i or sd_los_i when IS_SYNC_SLAVE = 1
+                          else '0';
+send_link_reset_real_i <= send_link_reset_sys_i when IS_SYNC_SLAVE = 1
+                          else '0';
+
+sd_los_i <= SFP_LOS when rising_edge(CLK_SYS);
+
+media_med2int_i.stat_op(15) <= send_link_reset_real_i when rising_edge(CLK_SYS);
+media_med2int_i.stat_op(14) <= '0';
+media_med2int_i.stat_op(13) <= make_link_reset_real_i when rising_edge(CLK_SYS); --make trbnet reset
+media_med2int_i.stat_op(12) <= led_dlm  when rising_edge(CLK_SYS); -- or last_led_dlm;
+media_med2int_i.stat_op(11) <= led_tx; -- or last_led_tx;
+media_med2int_i.stat_op(10) <= led_rx or last_led_rx;
+media_med2int_i.stat_op(9)  <= tx_allow; --led_ok
+media_med2int_i.stat_op(8 downto 5) <= (others => '0');
+media_med2int_i.stat_op(4)  <= rx_allow;
+media_med2int_i.stat_op(3 downto 0) <= x"0" when rx_allow = '1' and tx_allow = '1' else x"7";
+
+wap_is_zero_i <= '1' when WA_POSITION = x"0" else '0';
+
+-- TEST_LINE signals
+DEBUG_OUT(0)  <= TX_LOL;
+DEBUG_OUT(1)  <= RX_CDR_LOL;
+DEBUG_OUT(2)  <= RX_LOS;
+DEBUG_OUT(3)  <= rst_n;
+DEBUG_OUT(4)  <= rst_n_tx;
+DEBUG_OUT(5)  <= quad_rst_i;
+DEBUG_OUT(6)  <= rx_pcs_rst_i;
+DEBUG_OUT(7)  <= tx_pcs_rst_i;
+DEBUG_OUT(8)  <= rx_serdes_rst_i;
+DEBUG_OUT(9)  <= finished_reset_rx;
+DEBUG_OUT(10) <= finished_reset_tx;
+DEBUG_OUT(11) <= make_link_reset_i;
+DEBUG_OUT(12) <= send_link_reset_i;
+DEBUG_OUT(13) <= got_link_ready_i;
+DEBUG_OUT(14) <= rx_allow;
+DEBUG_OUT(15) <= tx_allow;
+-- not used 
+
+DEBUG_OUT(25 downto 16) <= (others => '0');
+
+DEBUG_OUT(26) <= wap_is_zero_i;
+DEBUG_OUT(27) <= rx_dlm_i;
+DEBUG_OUT(28) <= debug_tx_control_i(29); -- send_reset
+DEBUG_OUT(29) <= got_link_ready_i; --tx_k_i;
+DEBUG_OUT(30) <= debug_tx_control_i(30); -- send_dlm_i
+DEBUG_OUT(31) <= debug_tx_control_i(31); -- sending_dlm
+
+DEBUG_TX_CONTROL <= debug_tx_control_i;
+
+end architecture;
diff --git a/media_interfaces/sync/med_sync_define_RS.vhd b/media_interfaces/sync/med_sync_define_RS.vhd
new file mode 100644 (file)
index 0000000..c9e7720
--- /dev/null
@@ -0,0 +1,122 @@
+library ieee;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.std_logic_ARITH.ALL;
+USE IEEE.std_logic_UNSIGNED.ALL;
+
+use work.trb_net_std.all;
+
+package med_sync_define is
+
+constant K_IDLE   : std_logic_vector(7 downto 0) := x"BC";
+constant D_IDLE0  : std_logic_vector(7 downto 0) := x"C5";
+constant D_IDLE1  : std_logic_vector(7 downto 0) := x"50";
+constant K_SOP    : std_logic_vector(7 downto 0) := x"FB"; -- not used
+constant K_EOP    : std_logic_vector(7 downto 0) := x"FD"; -- not used
+constant K_BGN    : std_logic_vector(7 downto 0) := x"1C"; -- not used
+constant K_REQ    : std_logic_vector(7 downto 0) := x"7C"; -- not used
+constant K_RST    : std_logic_vector(7 downto 0) := x"FE"; -- will be extended
+constant K_DLM    : std_logic_vector(7 downto 0) := x"DC"; -- will be used :)
+
+component rx_control_RS is
+  port(
+    CLK_200                        : in  std_logic;
+    CLK_100                        : in  std_logic;
+    RESET_IN                       : in  std_logic;
+
+    WORD_SYNC_OUT                  : out std_logic;
+
+    RX_DATA_OUT                    : out std_logic_vector(15 downto 0);
+    RX_PACKET_NUMBER_OUT           : out std_logic_vector(2 downto 0);
+    RX_WRITE_OUT                   : out std_logic;
+
+    RX_DATA_IN                     : in  std_logic_vector( 7 downto 0);
+    RX_K_IN                        : in  std_logic;
+
+    RX_DLM                         : out std_logic := '0';
+    RX_DLM_WORD                    : out std_logic_vector( 7 downto 0) := (others => '0');
+
+    SEND_LINK_RESET_OUT            : out std_logic := '0';
+    MAKE_RESET_OUT                 : out std_logic := '0';
+    RX_ALLOW_IN                    : in  std_logic := '0';
+    RX_RESET_FINISHED              : in  std_logic := '0';
+    GOT_LINK_READY                 : out std_logic := '0';
+
+    DEBUG_OUT                      : out std_logic_vector(31 downto 0);
+    STAT_REG_OUT                   : out std_logic_vector(31 downto 0)
+  );
+end component;
+
+component tx_control_RS is
+  port(
+    CLK_200                        : in  std_logic;
+    CLK_100                        : in  std_logic;
+    RESET_IN                       : in  std_logic;
+
+    WORD_SYNC_IN                   : in  std_logic;
+
+    TX_DATA_IN                     : in  std_logic_vector(15 downto 0);
+    TX_PACKET_NUMBER_IN            : in  std_logic_vector( 2 downto 0);
+    TX_WRITE_IN                    : in  std_logic;
+    TX_READ_OUT                    : out std_logic;
+
+    TX_DATA_OUT                    : out std_logic_vector( 7 downto 0);
+    TX_K_OUT                       : out std_logic;
+    TX_CD_OUT                      : out std_logic;
+
+    SEND_DLM                       : in  std_logic := '0';
+    SEND_DLM_WORD                  : in  std_logic_vector( 7 downto 0) := (others => '0');
+    
+    SEND_LINK_RESET_IN             : in  std_logic := '0';
+    TX_ALLOW_IN                    : in  std_logic := '0';
+    RX_ALLOW_IN                    : in  std_logic := '0';
+
+    DEBUG_OUT                      : out std_logic_vector(31 downto 0);
+    STAT_REG_OUT                   : out std_logic_vector(31 downto 0)
+  );
+end component;
+  
+component rx_reset_fsm_RS is
+  port (
+    RST_N                : in  std_logic;
+    RX_REFCLK            : in  std_logic;
+    TX_PLL_LOL_QD_S      : in  std_logic;
+    RX_SERDES_RST_CH_C   : out std_logic;
+    RX_CDR_LOL_CH_S      : in  std_logic;
+    RX_LOS_LOW_CH_S      : in  std_logic;
+    RX_PCS_RST_CH_C      : out std_logic;
+    WA_POSITION          : in  std_logic_vector(3 downto 0) := x"0";
+    NORMAL_OPERATION_OUT : out std_logic;
+    STATE_OUT            : out std_logic_vector(3 downto 0)
+  );
+end component;
+
+component tx_reset_fsm_RS is
+  port (
+    RST_N                : in  std_logic;
+    TX_REFCLK            : in  std_logic;   
+    TX_PLL_LOL_QD_S      : in  std_logic;
+    RX_RESET_FINISHED_IN : in  std_logic;
+    RST_QD_C             : out std_logic;
+    TX_PCS_RST_CH_C      : out std_logic;
+    NORMAL_OPERATION_OUT : out std_logic;
+    STATE_OUT            : out std_logic_vector(3 downto 0)
+  );
+end component;
+
+component lattice_ecp3_fifo_18x16_dualport_oreg
+  port (
+    Data        : in  std_logic_vector(17 downto 0);
+    WrClock     : in  std_logic;
+    RdClock     : in  std_logic;
+    WrEn        : in  std_logic;
+    RdEn        : in  std_logic;
+    Reset       : in  std_logic;
+    RPReset     : in  std_logic;
+    Q           : out  std_logic_vector(17 downto 0);
+    Empty       : out  std_logic;
+    Full        : out  std_logic;
+    AlmostFull  : out std_logic
+  );
+end component;
+
+end package;
diff --git a/media_interfaces/sync/rx_control_RS.vhd b/media_interfaces/sync/rx_control_RS.vhd
new file mode 100644 (file)
index 0000000..4120d4a
--- /dev/null
@@ -0,0 +1,285 @@
+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.all;
+
+entity rx_control_RS is
+  port(
+    CLK_200                        : in  std_logic;
+    CLK_100                        : in  std_logic;
+    RESET_IN                       : in  std_logic;
+
+    WORD_SYNC_OUT                  : out std_logic;
+
+--clk_sys signals
+    RX_DATA_OUT                    : out std_logic_vector(15 downto 0);
+    RX_PACKET_NUMBER_OUT           : out std_logic_vector(2 downto 0);
+    RX_WRITE_OUT                   : out std_logic;
+
+-- clk_rx signals
+    RX_DATA_IN                     : in  std_logic_vector( 7 downto 0);
+    RX_K_IN                        : in  std_logic;
+
+--send_dlm: 200 MHz, 1 clock strobe, data valid until next DLM
+    RX_DLM                         : out std_logic := '0';
+    RX_DLM_WORD                    : out std_logic_vector( 7 downto 0) := (others => '0');
+
+--other signals    
+    SEND_LINK_RESET_OUT            : out std_logic := '0'; --clk_rx
+    MAKE_RESET_OUT                 : out std_logic := '0'; --clk_rx
+    RX_ALLOW_IN                    : in  std_logic := '0'; --clk_sys
+    RX_RESET_FINISHED              : in  std_logic := '0'; --clk_rx
+    GOT_LINK_READY                 : out std_logic := '0'; --clk_rx
+
+    DEBUG_OUT                      : out std_logic_vector(31 downto 0);
+    STAT_REG_OUT                   : out std_logic_vector(31 downto 0)
+    );
+end entity;
+
+
+architecture rx_control_arch of rx_control_RS is
+
+type rx_state_t is (SLEEP, WAIT_1, FIRST, GET_DATA, GET_IDLE, GET_DLM, MAKE_RESET);
+signal rx_state            : rx_state_t;
+signal rx_state_bits       : std_logic_vector(3 downto 0);
+signal rx_packet_num       : std_logic_vector(2 downto 0);
+signal buf_rx_write_out    : std_logic := '0';
+
+signal rx_data             : std_logic_vector(17 downto 0);
+signal ct_fifo_write       : std_logic := '0';
+signal ct_fifo_read        : std_logic := '0';
+signal ct_fifo_reset       : std_logic := '0';
+signal ct_fifo_data_out    : std_logic_vector(17 downto 0);
+signal ct_fifo_empty       : std_logic;
+signal ct_fifo_full        : std_logic;
+signal ct_fifo_afull       : std_logic;
+signal last_ct_fifo_empty  : std_logic;
+signal last_ct_fifo_read   : std_logic;
+
+signal idle_hist_i         : std_logic_vector(3 downto 0) := x"0";
+signal got_link_ready_i    : std_logic := '0';
+signal rx_dlm_i            : std_logic;
+signal rx_dlm_word_i       : std_logic_vector(7 downto 0);
+
+signal send_link_reset_i   : std_logic;
+signal make_reset_i        : std_logic;
+signal next_sop            : std_logic;
+
+signal reg_rx_data_in      : std_logic_vector(7 downto 0);
+signal reg_rx_k_in         : std_logic;
+
+signal reset_cnt           : unsigned(11 downto 0);
+
+signal sync_k_i            : std_logic;
+
+begin
+
+----------------------------------------------------------------------
+-- Data to Endpoint
+----------------------------------------------------------------------
+
+ct_fifo_read <= not ct_fifo_reset and not ct_fifo_empty; -- when rising_edge(CLK_100);
+buf_rx_write_out <=  last_ct_fifo_read and not last_ct_fifo_empty  when rising_edge(CLK_100);
+
+RX_DATA_OUT   <= ct_fifo_data_out(15 downto 0) ;
+RX_WRITE_OUT  <= buf_rx_write_out;
+RX_PACKET_NUMBER_OUT <= rx_packet_num;
+
+last_ct_fifo_read  <= ct_fifo_read  when rising_edge(CLK_100);
+last_ct_fifo_empty <= ct_fifo_empty when rising_edge(CLK_100);
+
+process begin
+  wait until rising_edge(CLK_100);
+  if RX_ALLOW_IN = '0' then
+    rx_packet_num <= "100";
+  elsif buf_rx_write_out = '1' then
+    if rx_packet_num = "100" then
+      rx_packet_num <= "000";
+    else
+      rx_packet_num <= std_logic_vector(unsigned(rx_packet_num)+1);
+    end if;  
+  end if;
+end process;
+
+----------------------------------------------------------------------
+-- Clock Domain Transfer
+----------------------------------------------------------------------
+THE_CT_FIFO : entity work.lattice_ecp3_fifo_18x16_dualport_oreg
+  port map(
+    Data              => rx_data,
+    WrClock           => CLK_200,
+    RdClock           => CLK_100,
+    WrEn              => ct_fifo_write,
+    RdEn              => ct_fifo_read,
+    Reset             => ct_fifo_reset,
+    RPReset           => ct_fifo_reset,
+    Q(17 downto 0)    => ct_fifo_data_out,
+    Empty             => ct_fifo_empty,
+    Full              => ct_fifo_full,
+    AlmostFull        => ct_fifo_afull
+  );
+
+ct_fifo_reset <= not RX_ALLOW_IN when rising_edge(CLK_200);    
+
+----------------------------------------------------------------------
+-- Read incoming data
+----------------------------------------------------------------------
+PROC_RX_FSM : process begin
+  wait until rising_edge(CLK_200);
+  ct_fifo_write        <= '0';
+  rx_dlm_i             <= '0';
+  idle_hist_i(3 downto 1) <= idle_hist_i(2 downto 0);
+  idle_hist_i(0)       <= got_link_ready_i;
+  sync_k_i             <= '0';  
+
+  case rx_state is
+    when SLEEP =>
+      rx_state_bits         <= x"1";
+      got_link_ready_i      <= '0';
+      make_reset_i          <= '0';
+      rx_data(7 downto 0)   <= reg_rx_data_in;
+      if reg_rx_k_in = '1' and reg_rx_data_in = K_IDLE then
+        rx_state            <= WAIT_1;
+        sync_k_i            <= '1';
+      end if;
+    
+    when WAIT_1 =>
+      rx_state <= FIRST;
+    
+    when FIRST =>
+      rx_state_bits         <= x"2";
+      rx_data(7 downto 0) <= reg_rx_data_in;
+      sync_k_i              <= '1';
+      if reg_rx_k_in = '1' then
+        case reg_rx_data_in is
+          when K_IDLE =>
+            rx_state        <= GET_IDLE;
+          when K_RST =>
+            rx_state        <= MAKE_RESET;
+            reset_cnt <= x"000";
+          when K_DLM =>
+            rx_state        <= GET_DLM;
+          when others => null;
+        end case;
+      else
+        rx_state            <= GET_DATA;
+      end if;
+      
+    when GET_IDLE =>
+      rx_state_bits         <= x"3";
+      rx_state              <= FIRST;
+      next_sop              <= '1';
+      if  reg_rx_k_in = '0' and reg_rx_data_in = D_IDLE1 then
+        idle_hist_i(0)      <= '1';
+        got_link_ready_i    <= got_link_ready_i or (idle_hist_i(1) and idle_hist_i(3));
+      elsif  reg_rx_k_in = '1' then -- not needed?
+        rx_state <= FIRST; -- not needed?
+      end if;
+      
+    when GET_DATA =>
+      rx_state_bits         <= x"4";
+      -- rx_state <= FIRST
+      if reg_rx_k_in = '0' then
+        next_sop            <= '0';
+        rx_data(15 downto 8)<= reg_rx_data_in;
+        rx_data(16)         <= next_sop;
+        rx_data(17)         <= '0';
+        ct_fifo_write       <= '1';
+        rx_state            <= FIRST;
+      else -- not needed?
+        rx_state <= FIRST; -- not needed?   
+      end if;
+     
+    when GET_DLM =>
+      rx_state_bits         <= x"5";
+      rx_dlm_i              <= '1';
+      rx_dlm_word_i         <= reg_rx_data_in;
+      rx_state              <= FIRST;
+
+    when MAKE_RESET =>
+      rx_state_bits         <= x"F";
+      sync_k_i              <= not sync_k_i; -- toggle while in reset
+      if reg_rx_k_in = '1' and reg_rx_data_in = K_RST then
+        send_link_reset_i   <= '1';
+        make_reset_i        <= '0';
+        got_link_ready_i    <= '0';
+        if reset_cnt <= x"3ff" then
+          reset_cnt           <= reset_cnt + 1;
+        end if;  
+      elsif reset_cnt > x"3ff" then 
+        send_link_reset_i   <= '0';
+        make_reset_i        <= '1';
+        rx_state            <= SLEEP;
+      else
+        if reset_cnt <= x"3ff" then
+          reset_cnt <= reset_cnt + 1;
+        end if;  
+        send_link_reset_i   <= '1';
+      end if;
+      
+  end case;
+  
+  if RESET_IN = '1' or RX_RESET_FINISHED = '0' then
+    rx_state <= SLEEP;
+    if rx_state = MAKE_RESET then
+      make_reset_i      <= '1';
+    else  
+      make_reset_i      <= '0';
+    end if;  
+    send_link_reset_i <= '0';
+  end if;
+end process;
+
+reg_rx_data_in <= RX_DATA_IN when rising_edge(CLK_200);
+reg_rx_k_in    <= RX_K_IN    when rising_edge(CLK_200);
+
+WORD_SYNC_OUT <= sync_k_i; --reg_rx_k_in;
+
+----------------------------------------------------------------------
+-- Signals out
+---------------------------------------------------------------------- 
+GOT_LINK_READY <= got_link_ready_i;
+
+RX_DLM       <= rx_dlm_i when rising_edge(CLK_200);
+RX_DLM_WORD  <= rx_dlm_word_i when rising_edge(CLK_200);
+
+SEND_LINK_RESET_OUT    <= send_link_reset_i when rising_edge(CLK_200);
+MAKE_RESET_OUT         <= make_reset_i when rising_edge(CLK_200);
+
+----------------------------------------------------------------------
+-- Debug and Status
+---------------------------------------------------------------------- 
+STAT_REG_OUT(3 downto 0)   <= rx_state_bits;
+STAT_REG_OUT(4)            <= got_link_ready_i;
+STAT_REG_OUT(5)            <= ct_fifo_afull;
+STAT_REG_OUT(6)            <= ct_fifo_empty;
+STAT_REG_OUT(7)            <= ct_fifo_write;
+STAT_REG_OUT(15 downto 8)  <= reg_rx_data_in when rising_edge(clk_100); --rx_data(7 downto 0);
+STAT_REG_OUT(16)           <= rx_data(16);
+STAT_REG_OUT(17)           <= '0';
+STAT_REG_OUT(31 downto 18) <= (others => '0');
+
+
+DEBUG_OUT(3 downto 0)   <= rx_state_bits;
+DEBUG_OUT(4)            <= got_link_ready_i;
+DEBUG_OUT(5)            <= ct_fifo_afull;
+DEBUG_OUT(6)            <= ct_fifo_empty;
+DEBUG_OUT(7)            <= ct_fifo_write;
+DEBUG_OUT(15 downto 8)  <= rx_data(7 downto 0);
+DEBUG_OUT(16)           <= reg_rx_k_in;
+DEBUG_OUT(17)           <= make_reset_i;
+DEBUG_OUT(18)           <= send_link_reset_i;
+DEBUG_OUT(19)           <= '1' when rx_state_bits = x"f" else '0';
+--DEBUG_OUT(16)           <= rx_data(16);
+DEBUG_OUT(31 downto 20) <= (others => '0');
+-- DEBUG_OUT(23 downto 16) <= rx_data(7 downto 0);
+-- DEBUG_OUT(31 downto 24) <= ct_fifo_data_out(7 downto 0);
+
+
+
+end architecture;
diff --git a/media_interfaces/sync/rx_reset_fsm_RS.vhd b/media_interfaces/sync/rx_reset_fsm_RS.vhd
new file mode 100644 (file)
index 0000000..aa06bb5
--- /dev/null
@@ -0,0 +1,188 @@
+--Media interface RX state machine
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.all;
+
+entity rx_reset_fsm_RS is
+  port (
+    RST_N             : in std_logic;
+    RX_REFCLK         : in std_logic;
+    TX_PLL_LOL_QD_S   : in std_logic;
+    RX_SERDES_RST_CH_C: out std_logic;
+    RX_CDR_LOL_CH_S   : in std_logic;
+    RX_LOS_LOW_CH_S   : in std_logic;
+    RX_PCS_RST_CH_C   : out std_logic;
+    --fix word alignment position to 0 for non-slave links!
+    WA_POSITION       : in  std_logic_vector(3 downto 0) := x"0";
+    NORMAL_OPERATION_OUT : out std_logic;
+    STATE_OUT         : out std_logic_vector(3 downto 0)
+    );
+end entity ;
+                                                                                              
+architecture rx_reset_fsm_arch of rx_reset_fsm_RS is
+            
+constant count_index : integer := 19;
+type statetype is ( WAIT_FOR_PLOL, RX_SERDES_RESET, WAIT_FOR_TIMER1, CHECK_LOL_LOS, WAIT_FOR_TIMER2, CHECK_WAP, NORMAL );
+                                                                                              
+signal cs : statetype;  -- current state of lsm
+signal ns : statetype;  -- next state of lsm
+                                                                                              
+signal tx_pll_lol_qd_q        : std_logic;
+signal rx_cdr_lol_ch_q        : std_logic;
+signal rx_los_low_ch_q        : std_logic;
+signal rx_lol_los             : std_logic;
+signal rx_lol_los_int         : std_logic;
+signal rx_lol_los_del         : std_logic;
+signal rx_pcs_rst_ch_c_int    : std_logic;
+signal rx_serdes_rst_ch_c_int : std_logic;
+                                                                                              
+signal reset_timer2           : std_logic;
+signal counter2               : unsigned(19 downto 0);
+signal timer2                 : std_logic;
+                                                                                              
+begin
+                                                                                              
+rx_lol_los <= rx_cdr_lol_ch_q or rx_los_low_ch_q ;
+                                                                                              
+sync_sfp_sigs : entity work.signal_sync 
+  generic map(WIDTH => 3)
+  port map(RESET => '0',CLK0 => RX_REFCLK, CLK1 => RX_REFCLK,
+           D_IN(0)  => TX_PLL_LOL_QD_S,
+           D_IN(1)  => RX_CDR_LOL_CH_S,
+           D_IN(2)  => RX_LOS_LOW_CH_S,
+           D_OUT(0) => tx_pll_lol_qd_q,
+           D_OUT(1) => rx_cdr_lol_ch_q,
+           D_OUT(2) => rx_los_low_ch_q
+           );
+
+                                                                                              
+--timer2 = 400,000 Refclk cycles or 200,000 REFCLKDIV2 cycles
+--An 18 bit counter ([17:0]) counts 262144 cycles, so a 19 bit ([18:0]) counter will do if we set timer2 = bit[18]
+
+THE_TIMER2_PROC: process( RX_REFCLK ) 
+begin
+  if( rising_edge(RX_REFCLK) ) then
+    if reset_timer2 = '1' then
+      counter2 <= (others => '0');
+      timer2 <= '0';
+    else
+      if counter2(count_index) = '1' then
+        timer2 <= '1';
+      else
+        timer2 <= '0';
+        counter2 <= counter2 + 1 ;
+      end if;
+    end if;
+  end if;
+end process THE_TIMER2_PROC;
+                                                                                              
+-- State machine clocked process
+THE_FSM_PROC: process( RX_REFCLK )
+begin
+  if rising_edge(RX_REFCLK) then
+    if RST_N = '0' then
+      cs <= WAIT_FOR_PLOL;
+      rx_lol_los_int <= '1';
+      rx_lol_los_del <= '1';
+      RX_PCS_RST_CH_C <= '1';
+      RX_SERDES_RST_CH_C <= '0';
+    else
+      cs <= ns;
+      rx_lol_los_del <= rx_lol_los;
+      rx_lol_los_int <= rx_lol_los_del;
+      RX_PCS_RST_CH_C <= rx_pcs_rst_ch_c_int;
+      RX_SERDES_RST_CH_C <= rx_serdes_rst_ch_c_int;
+    end if;
+  end if;
+end process;
+
+THE_FSM_DECODE_PROC: process( cs, tx_pll_lol_qd_q, rx_los_low_ch_q, rx_lol_los_int, timer2, wa_position, rx_lol_los_del )
+begin
+  reset_timer2 <= '0';
+  STATE_OUT <= x"F";        
+  NORMAL_OPERATION_OUT <= '0';
+  
+  case cs is
+    when WAIT_FOR_PLOL =>
+      rx_pcs_rst_ch_c_int <= '1';
+      rx_serdes_rst_ch_c_int <= '0';
+      if( (tx_pll_lol_qd_q = '1') or (rx_los_low_ch_q = '1') ) then  -- also make sure a Signal
+        ns <= WAIT_FOR_PLOL;                                         -- is present prior to moving to the next
+      else
+        ns <= RX_SERDES_RESET;
+      end if;
+      STATE_OUT <= x"1";
+                                                                                            
+    when RX_SERDES_RESET =>
+      rx_pcs_rst_ch_c_int <= '1';
+      rx_serdes_rst_ch_c_int <= '1';
+      ns <= WAIT_FOR_TIMER1;
+      STATE_OUT <= x"2";
+                                                                                
+    when WAIT_FOR_TIMER1 =>
+      rx_pcs_rst_ch_c_int <= '1';
+      rx_serdes_rst_ch_c_int <= '1';
+      ns <= CHECK_LOL_LOS;
+      STATE_OUT <= x"3";
+
+    when CHECK_LOL_LOS =>
+      rx_pcs_rst_ch_c_int <= '1';
+      rx_serdes_rst_ch_c_int <= '0';
+      reset_timer2 <= '1';
+      ns <= WAIT_FOR_TIMER2;
+      STATE_OUT <= x"4";
+
+    when WAIT_FOR_TIMER2 =>
+      rx_pcs_rst_ch_c_int <= '1';
+      rx_serdes_rst_ch_c_int <= '0';
+      if rx_lol_los_int = rx_lol_los_del then   --NO RISING OR FALLING EDGES
+        if timer2 = '1' then
+          if rx_lol_los_int = '1' then
+            ns <= WAIT_FOR_PLOL;
+          else
+            ns <= CHECK_WAP;
+            reset_timer2 <= '1';
+          end if;
+        else
+          ns <= WAIT_FOR_TIMER2;
+        end if;
+      else
+        ns <= CHECK_LOL_LOS;    --RESET timer2
+      end if;
+      STATE_OUT <= x"5";
+
+    when CHECK_WAP =>
+      rx_pcs_rst_ch_c_int <= '0';
+      rx_serdes_rst_ch_c_int <= '0';
+--      if timer2 = '1' then
+      if std_logic(counter2(16)) = '1' then -- may be too long
+        if WA_POSITION /= x"0" then
+          ns <= WAIT_FOR_PLOL;
+        else
+          ns <= NORMAL;
+        end if;
+      else
+        ns <= CHECK_WAP;
+      end if; 
+      STATE_OUT <= x"7";
+
+    when NORMAL =>
+      rx_pcs_rst_ch_c_int <= '0';
+      rx_serdes_rst_ch_c_int <= '0';
+      if rx_lol_los_int = '1' or WA_POSITION /= x"0" then
+        ns <= WAIT_FOR_PLOL;
+      else
+        NORMAL_OPERATION_OUT <= '1';
+        ns <= NORMAL;
+      end if;
+      STATE_OUT <= x"6";
+                                                                                            
+    when others =>
+      ns <= WAIT_FOR_PLOL;
+                                                                                            
+  end case;
+                                                                                              
+end process THE_FSM_DECODE_PROC;
+                                                               
+end architecture;
diff --git a/media_interfaces/sync/sci_reader_RS.vhd b/media_interfaces/sync/sci_reader_RS.vhd
new file mode 100644 (file)
index 0000000..20721d7
--- /dev/null
@@ -0,0 +1,153 @@
+library ieee;
+  use ieee.std_logic_1164.all;
+  use ieee.numeric_std.all;
+  
+library work;
+  use work.trb_net_components.all;
+  use work.trb_net_std.all;
+  use work.trb3_components.all;
+  use work.config.all;
+
+entity sci_reader_RS is
+
+  port(
+    CLK         : in std_logic;
+    RESET       : in std_logic;
+    
+    --SCI
+    SCI_WRDATA  : out std_logic_vector(7 downto 0);
+    SCI_RDDATA  : in  std_logic_vector(7 downto 0);
+    SCI_ADDR    : out std_logic_vector(5 downto 0);
+    SCI_SEL     : out std_logic_vector(4 downto 0);
+    SCI_RD      : out std_logic;
+    SCI_WR      : out std_logic;
+    
+    WA_POS_OUT  : out std_logic_vector(15 downto 0);
+    WA_READ_OUT : out std_logic;
+    
+    --Slowcontrol
+    BUS_RX      : in  CTRLBUS_RX;
+    BUS_TX      : out CTRLBUS_TX;    
+    
+    MEDIA_STATUS_REG_IN : in std_logic_vector(255 downto 0) := (others => '0');
+    DEBUG_OUT   : out std_logic_vector(31 downto 0)
+    );
+end entity;
+
+
+
+architecture sci_reader_arch of sci_reader_RS is
+
+signal sci_reg_i  : std_logic;
+type sci_ctrl is (IDLE, SCTRL, SCTRL_WAIT, SCTRL_WAIT2, SCTRL_FINISH, GET_WA, GET_WA_WAIT, GET_WA_WAIT2, GET_WA_FINISH);
+signal sci_state         : sci_ctrl;
+signal sci_timer         : unsigned(12 downto 0) := (others => '0');
+signal wa_position       : std_logic_vector(15 downto 0);
+signal next_sci_wr       : std_logic;
+signal wa_read_i         : std_logic;
+
+begin
+
+WA_POS_OUT <= wa_position;
+
+-------------------------------------------------      
+-- SCI
+-------------------------------------------------      
+--gives access to serdes config port from slow control and reads word alignment every ~ 40 us
+  BUS_TX.unknown <= '0';
+  BUS_TX.rack    <= '0';
+  BUS_TX.wack    <= '0';
+
+PROC_SCI_CTRL: process 
+  variable cnt : integer range 0 to 4 := 0;
+begin
+  wait until rising_edge(CLK);
+  BUS_TX.ack <= '0';
+  BUS_TX.nack <= '0';
+  
+  SCI_WR <= next_sci_wr;
+  
+  case sci_state is
+    when IDLE =>
+      SCI_SEL     <= (others => '0');
+      sci_reg_i   <= '0';
+      SCI_RD      <= '0';
+      next_sci_wr <= '0';
+      sci_timer   <= sci_timer + 1;
+      wa_read_i   <= '0';
+      if BUS_RX.read = '1' or BUS_RX.write = '1' then
+        SCI_SEL(0)    <= not BUS_RX.addr(6) and not BUS_RX.addr(7) and not BUS_RX.addr(8);
+        SCI_SEL(1)    <=     BUS_RX.addr(6) and not BUS_RX.addr(7) and not BUS_RX.addr(8);
+        SCI_SEL(2)    <= not BUS_RX.addr(6) and     BUS_RX.addr(7) and not BUS_RX.addr(8);
+        SCI_SEL(3)    <=     BUS_RX.addr(6) and     BUS_RX.addr(7) and not BUS_RX.addr(8);
+        SCI_SEL(4)    <= not BUS_RX.addr(6) and not BUS_RX.addr(7) and     BUS_RX.addr(8);
+        sci_reg_i     <=     BUS_RX.addr(6) and not BUS_RX.addr(7) and     BUS_RX.addr(8);
+        SCI_ADDR      <= BUS_RX.addr(5 downto 0);
+        SCI_WRDATA    <= BUS_RX.data(7 downto 0);
+        SCI_RD        <= BUS_RX.read  and not (BUS_RX.addr(6) and not BUS_RX.addr(7) and     BUS_RX.addr(8));
+        next_sci_wr   <= BUS_RX.write and not (BUS_RX.addr(6) and not BUS_RX.addr(7) and     BUS_RX.addr(8));
+        sci_state     <= SCTRL;
+      elsif sci_timer(sci_timer'left) = '1' then
+        sci_timer     <= (others => '0');
+        sci_state     <= GET_WA;
+        wa_read_i     <= '1';
+      end if;      
+    when SCTRL =>
+      if sci_reg_i = '1' then
+        BUS_TX.data   <= MEDIA_STATUS_REG_IN(32*(to_integer(unsigned(BUS_RX.addr(3 downto 0))))+31 downto 32*(to_integer(unsigned(BUS_RX.addr(3 downto 0)))));
+        BUS_TX.ack    <= '1';
+        next_sci_wr   <= '0';
+        SCI_RD        <= '0';
+        sci_state     <= IDLE;
+      else
+        sci_state     <= SCTRL_WAIT;
+      end if;
+    when SCTRL_WAIT   =>
+      sci_state       <= SCTRL_WAIT2;
+    when SCTRL_WAIT2  =>
+      sci_state       <= SCTRL_FINISH;
+    when SCTRL_FINISH =>
+      BUS_TX.data(7 downto 0) <= SCI_RDDATA;
+      BUS_TX.ack      <= '1';
+      next_sci_wr     <= '0';
+      SCI_RD          <= '0';
+      sci_state       <= IDLE;
+    
+    when GET_WA =>
+      if (cnt = 4 and FPGA_TYPE = 3) or (cnt = 2 and FPGA_TYPE = 5) then
+        cnt           := 0;
+        sci_state     <= IDLE;
+      else
+        sci_state     <= GET_WA_WAIT;
+        wa_read_i     <= '1';
+        if FPGA_TYPE = 3 then
+          SCI_ADDR      <= "100010";--'0' & x"22"; --for ECP3
+        elsif FPGA_TYPE = 5 then
+          SCI_ADDR      <= "110010";--'0' & x"32"; --for ECP5
+        end if;  
+        SCI_SEL       <= (others => '0');
+        SCI_SEL(cnt)  <= '1';
+        SCI_RD        <= '1';
+      end if;
+    when GET_WA_WAIT  =>
+      sci_state       <= GET_WA_WAIT2;
+      wa_read_i       <= '1';
+    when GET_WA_WAIT2 =>
+      sci_state       <= GET_WA_FINISH;
+      wa_read_i       <= '1';
+    when GET_WA_FINISH =>
+      wa_position(cnt*4+3 downto cnt*4) <= SCI_RDDATA(3 downto 0);
+      sci_state       <= GET_WA; 
+      wa_read_i       <= '1';   
+      cnt             := cnt + 1;
+  end case;
+  
+  if (BUS_RX.read = '1' or BUS_RX.write = '1') and sci_state /= IDLE then
+    BUS_TX.nack <= '1'; BUS_TX.ack <= '0';
+  end if;
+  
+end process;
+
+WA_READ_OUT <= wa_read_i;
+
+end architecture;
diff --git a/media_interfaces/sync/tx_control_RS.vhd b/media_interfaces/sync/tx_control_RS.vhd
new file mode 100644 (file)
index 0000000..fd8831c
--- /dev/null
@@ -0,0 +1,363 @@
+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.all;
+
+entity tx_control_RS is
+  port(
+    CLK_200                        : in  std_logic;
+    CLK_100                        : in  std_logic;
+    RESET_IN                       : in  std_logic;
+
+    WORD_SYNC_IN                   : in  std_logic;
+
+    TX_DATA_IN                     : in  std_logic_vector(15 downto 0);
+    TX_PACKET_NUMBER_IN            : in  std_logic_vector(2 downto 0);
+    TX_WRITE_IN                    : in  std_logic;
+    TX_READ_OUT                    : out std_logic;
+
+    TX_DATA_OUT                    : out std_logic_vector( 7 downto 0);
+    TX_K_OUT                       : out std_logic;
+    TX_CD_OUT                      : out std_logic;
+
+    SEND_DLM                       : in  std_logic := '0';
+    SEND_DLM_WORD                  : in  std_logic_vector( 7 downto 0) := (others => '0');
+    
+    SEND_LINK_RESET_IN             : in  std_logic := '0';
+    TX_ALLOW_IN                    : in  std_logic := '0';
+    RX_ALLOW_IN                    : in  std_logic := '0';
+
+    DEBUG_OUT                      : out std_logic_vector(31 downto 0);
+    STAT_REG_OUT                   : out std_logic_vector(31 downto 0)
+  );
+end entity;
+
+
+
+architecture arch of tx_control_RS is
+
+  type state_t is (SEND_IDLE_L, SEND_IDLE_H, SEND_DATA_L, SEND_DATA_H, SEND_DLM_L, SEND_DLM_H,
+                   SEND_RESET);
+  signal current_state           : state_t;
+  signal state_bits              : std_logic_vector(3 downto 0);
+  
+  type ram_t is array(0 to 255) of std_logic_vector(17 downto 0);
+  signal ram                     : ram_t;
+
+  signal ram_write               : std_logic := '0';
+  signal ram_write_addr          : unsigned(7 downto 0) := (others => '0');
+  signal last_ram_write_addr     : unsigned(7 downto 0) := (others => '0');
+  signal ram_read                : std_logic := '0';
+  signal ram_read_addr           : unsigned(7 downto 0) := (others => '0');
+  signal ram_dout                : std_logic_vector(17 downto 0);
+  signal next_ram_dout           : std_logic_vector(17 downto 0);
+  signal ram_fill_level          : unsigned(7 downto 0);
+  signal ram_empty               : std_logic;
+  signal ram_afull               : std_logic;
+
+  signal send_dlm_in_i           : std_logic;
+  signal send_dlm_i              : std_logic;
+
+  signal buf_tx_read_out         : std_logic;
+  signal tx_data_200             : std_logic_vector(17 downto 0);
+  signal tx_allow_qtx            : std_logic;
+  signal rx_allow_qtx            : std_logic;
+  signal tx_allow_q              : std_logic;
+  signal send_link_reset_qtx     : std_logic;
+  signal ct_fifo_empty           : std_logic;
+  signal ct_fifo_write           : std_logic := '0';
+  signal ct_fifo_read            : std_logic := '0';
+  signal ct_fifo_full            : std_logic;
+  signal ct_fifo_afull           : std_logic;
+  signal ct_fifo_reset           : std_logic;
+  signal last_ct_fifo_empty      : std_logic;
+  signal last_ct_fifo_read       : std_logic;
+  signal debug_sending_dlm       : std_logic;
+  signal debug_sending_rst       : std_logic;
+
+  signal save_sop                : std_logic;
+  signal save_eop                : std_logic;
+  signal load_sop                : std_logic;
+  signal load_eop                : std_logic;
+  signal first_idle              : std_logic;
+  signal toggle_idle             : std_logic;
+begin
+
+----------------------------------------------------------------------
+-- Clock Domain Transfer
+----------------------------------------------------------------------
+-- gk 05.10.10
+  THE_CT_FIFO : lattice_ecp3_fifo_18x16_dualport_oreg
+    port map(
+      Data(15 downto 0) => TX_DATA_IN,
+      Data(16)          => save_sop,
+      Data(17)          => save_eop,
+      WrClock           => CLK_100,
+      RdClock           => CLK_200,
+      WrEn              => ct_fifo_write,
+      RdEn              => ct_fifo_read,
+      Reset             => ct_fifo_reset,
+      RPReset           => ct_fifo_reset,
+      Q(17 downto 0)    => tx_data_200,
+      Empty             => ct_fifo_empty,
+      Full              => ct_fifo_full,
+      AlmostFull        => ct_fifo_afull
+      );
+
+  THE_RD_PROC : process(CLK_100)
+    begin
+      if rising_edge(CLK_100) then
+        buf_tx_read_out  <= tx_allow_q  and not ct_fifo_afull ;
+      end if;
+    end process;
+
+  ct_fifo_reset <= not tx_allow_qtx;
+  TX_READ_OUT   <= buf_tx_read_out;
+
+  ct_fifo_write <= buf_tx_read_out and TX_WRITE_IN;
+  ct_fifo_read  <= tx_allow_qtx and not ram_afull and not ct_fifo_empty;
+  
+  last_ct_fifo_read   <= ct_fifo_read  when rising_edge(CLK_200);
+  last_ct_fifo_empty  <= ct_fifo_empty when rising_edge(CLK_200);
+  
+  save_sop <= '1' when (TX_PACKET_NUMBER_IN = c_H0) else '0';
+  save_eop <= '1' when (TX_PACKET_NUMBER_IN = c_F3) else '0';
+
+----------------------------------------------------------------------
+-- RAM
+----------------------------------------------------------------------
+  THE_RAM_WR_PROC : process(CLK_200)
+    begin
+      if rising_edge(CLK_200) then
+        ram_write   <= last_ct_fifo_read and not last_ct_fifo_empty;
+      end if;
+    end process;
+
+--RAM
+  THE_RAM_PROC : process(CLK_200)
+    begin
+      if rising_edge(CLK_200) then
+        if ram_write = '1' then
+          ram((to_integer(ram_write_addr))) <= tx_data_200;
+        end if;
+        next_ram_dout <= ram(to_integer(ram_read_addr));
+        ram_dout <= next_ram_dout;
+      end if;
+    end process;
+
+--RAM read pointer
+  THE_READ_CNT : process(CLK_200)
+    begin
+      if rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          ram_read_addr <= (others => '0');
+        elsif ram_read = '1' then
+          ram_read_addr <= ram_read_addr + to_unsigned(1,1);
+        end if;
+      end if;
+    end process;
+
+--RAM write pointer
+  THE_WRITE_CNT : process(CLK_200)
+    begin
+      if rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          ram_write_addr <= (others => '0');
+        elsif ram_write = '1' then
+          ram_write_addr <= ram_write_addr + to_unsigned(1,1);
+        end if;
+      end if;
+    end process;
+
+--RAM fill level counter
+  THE_FILL_CNT : process(CLK_200)
+    begin
+      if rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          ram_fill_level <= (others => '0');
+        else
+          ram_fill_level <= last_ram_write_addr - ram_read_addr;
+        end if;
+      end if;
+    end process;
+
+--RAM empty
+  ram_empty <= '1' when (last_ram_write_addr = ram_read_addr) or RESET_IN = '1' else '0';
+  ram_afull <= '1' when ram_fill_level >= 4 else '0';
+
+  last_ram_write_addr <= ram_write_addr when rising_edge(CLK_200);
+
+----------------------------------------------------------------------
+-- TX control state machine
+----------------------------------------------------------------------
+
+  THE_DATA_CONTROL_FSM : process(CLK_200, RESET_IN)
+    begin
+      if rising_edge(CLK_200) then
+        TX_K_OUT               <= '0';
+        TX_CD_OUT              <= '0';
+        debug_sending_dlm      <= '0';
+        debug_sending_rst      <= '0';
+        first_idle             <= '1';
+        case current_state is
+          when SEND_IDLE_L =>
+            TX_DATA_OUT        <= K_IDLE;
+            TX_K_OUT           <= '1';
+            if WORD_SYNC_IN = '1' then
+              current_state      <= SEND_IDLE_H;
+            else
+              current_state      <= SEND_IDLE_L;
+            end if;
+            first_idle         <= first_idle;
+
+          when SEND_IDLE_H =>
+            if rx_allow_qtx = '1' or toggle_idle = '1' then
+              TX_DATA_OUT        <= D_IDLE1;
+              toggle_idle        <= rx_allow_qtx;
+            else
+              TX_DATA_OUT        <= D_IDLE0;
+              toggle_idle        <= '1';
+            end if;
+            TX_CD_OUT            <= first_idle;
+            first_idle           <= '0';
+
+          when SEND_DATA_L =>
+            TX_DATA_OUT        <= ram_dout(7 downto 0);
+            load_sop           <= ram_dout(16);
+            load_eop           <= ram_dout(17);
+            current_state      <= SEND_DATA_H;
+
+          when SEND_DATA_H =>
+            TX_DATA_OUT        <= ram_dout(15 downto 8);
+
+          when SEND_DLM_L =>
+            TX_DATA_OUT        <= K_DLM;
+            TX_K_OUT           <= '1';
+            current_state      <= SEND_DLM_H;
+            debug_sending_dlm  <= '1';
+
+          when SEND_DLM_H =>
+            TX_DATA_OUT        <= SEND_DLM_WORD;
+
+          when SEND_RESET =>
+            TX_DATA_OUT        <= K_RST;
+            TX_K_OUT           <= '1';
+            debug_sending_rst  <= '1';
+            if send_link_reset_qtx = '0' then
+              current_state    <= SEND_IDLE_L;
+            end if;
+
+          when others =>
+            current_state      <= SEND_IDLE_L;
+        end case;
+
+        if  current_state = SEND_IDLE_H  or
+            current_state = SEND_DATA_H  or
+            current_state = SEND_DLM_H then
+          if tx_allow_qtx = '0' then
+            current_state     <= SEND_IDLE_L;
+          elsif send_link_reset_qtx = '1' then
+            current_state     <= SEND_RESET;
+            debug_sending_rst <= '1';
+          elsif send_dlm_i = '1' then
+            current_state     <= SEND_DLM_L;
+          elsif ram_empty = '0' then
+            current_state     <= SEND_DATA_L;
+          else
+            current_state     <= SEND_IDLE_L;
+          end if;
+
+        end if;
+      end if;
+      --async because of oreg.
+      if  (current_state = SEND_IDLE_H or current_state = SEND_DATA_H or current_state = SEND_DLM_H) 
+            and ram_empty = '0' and tx_allow_qtx = '1' and send_link_reset_qtx = '0' 
+            and send_dlm_i = '0' then  --TODO: Sync this signal?
+        ram_read <= '1';
+      else 
+        ram_read <= '0';
+      end if;
+      if RESET_IN = '1' then
+        ram_read <= '0';
+      end if;
+    end process;
+
+----------------------------------------------------------------------
+--
+----------------------------------------------------------------------
+
+  txallow_sync  : signal_sync port map(RESET => '0',CLK0 => CLK_200, CLK1 => CLK_200,
+                                          D_IN(0)  => TX_ALLOW_IN, 
+                                          D_OUT(0) => tx_allow_qtx);
+  rxallow_sync  : signal_sync port map(RESET => '0',CLK0 => CLK_200, CLK1 => CLK_200,
+                                          D_IN(0)  => RX_ALLOW_IN, 
+                                          D_OUT(0) => rx_allow_qtx);
+  sendres_sync  : signal_sync port map(RESET => '0',CLK0 => CLK_200, CLK1 => CLK_200,
+                                          D_IN(0)  => SEND_LINK_RESET_IN, 
+                                          D_OUT(0) => send_link_reset_qtx);
+  txallow_sync2 : signal_sync port map(RESET => '0',CLK0 => CLK_100, CLK1 => CLK_100,
+                                          D_IN(0)  => tx_allow_qtx, 
+                                          D_OUT(0) => tx_allow_q);
+
+  send_dlm_in_i <= SEND_DLM;
+
+--Send DLM message
+  THE_STORE_DLM_PROC : process(CLK_200, RESET_IN)
+    begin
+      if RESET_IN = '1' then
+        send_dlm_i           <= '0';
+      elsif rising_edge(CLK_200) then
+        if tx_allow_qtx = '0' then
+          send_dlm_i         <= '0';
+        elsif send_dlm_in_i = '1' then
+          send_dlm_i         <= '1';
+        elsif current_state = SEND_DLM_L then
+          send_dlm_i         <= '0';
+        end if;
+      end if;
+    end process;
+
+----------------------------------------------------------------------
+-- Debug
+----------------------------------------------------------------------
+  DEBUG_OUT(31) <= debug_sending_dlm when rising_edge(CLK_200);
+  DEBUG_OUT(30) <= send_dlm_i;
+  DEBUG_OUT(29) <= debug_sending_rst when rising_edge(CLK_200);
+  DEBUG_OUT(28 downto 0) <= (others => '0');
+
+  process(CLK_100)
+    begin
+      if rising_edge(CLK_100) then
+--        STAT_REG_OUT <= (others => '0');
+        STAT_REG_OUT(3 downto 0)   <= state_bits;
+        STAT_REG_OUT(7 downto 4)   <= (others => '0');
+        STAT_REG_OUT(15 downto 8)  <= std_logic_vector(ram_read_addr);
+        STAT_REG_OUT(17)           <= ram_empty;
+        STAT_REG_OUT(18)           <= tx_allow_qtx;
+        STAT_REG_OUT(19)           <= TX_ALLOW_IN;
+        STAT_REG_OUT(21 downto 20) <= (others => '0');
+        STAT_REG_OUT(22)           <= load_eop;
+        STAT_REG_OUT(23)           <= send_dlm_i;
+        STAT_REG_OUT(26 downto 24) <= (others => '0');
+        STAT_REG_OUT(27)           <= ct_fifo_afull;
+        STAT_REG_OUT(28)           <= ct_fifo_read;
+        STAT_REG_OUT(29)           <= ct_fifo_write;
+        STAT_REG_OUT(30)           <= RESET_IN;
+        STAT_REG_OUT(31)           <= '0';
+      end if;
+    end process;
+
+state_bits <= x"0" when current_state = SEND_IDLE_L else
+              x"1" when current_state = SEND_IDLE_H else
+              x"2" when current_state = SEND_DATA_L else
+              x"3" when current_state = SEND_DATA_H else
+              x"4" when current_state = SEND_DLM_L else
+              x"5" when current_state = SEND_DLM_H else
+              x"c" when current_state = SEND_RESET else
+              x"F";
+
+end architecture;
diff --git a/media_interfaces/sync/tx_reset_fsm_RS.vhd b/media_interfaces/sync/tx_reset_fsm_RS.vhd
new file mode 100644 (file)
index 0000000..79e2559
--- /dev/null
@@ -0,0 +1,184 @@
+--Media interface TX state machine
+
+LIBRARY IEEE;
+USE IEEE.std_logic_1164.ALL;
+USE IEEE.numeric_std.all;
+
+entity tx_reset_fsm_RS is
+port (
+  RST_N                : in std_logic;
+  TX_REFCLK            : in std_logic;   
+  TX_PLL_LOL_QD_S      : in std_logic;
+  RX_RESET_FINISHED_IN : in std_logic;
+  RST_QD_C             : out std_logic;
+  TX_PCS_RST_CH_C      : out std_logic;
+  NORMAL_OPERATION_OUT : out std_logic;
+  STATE_OUT            : out std_logic_vector(3 downto 0)
+  );
+end entity;
+                                                                                              
+architecture tx_reset_fsm_arch of tx_reset_fsm_RS is
+
+constant count_index : integer := 19; -- end of timer2
+
+type statetype is ( QUAD_RESET, WAIT_FOR_TIMER1, CHECK_PLOL, WAIT_FOR_TIMER2, NORMAL, WAIT_FOR_RX );
+
+signal cs : statetype;  -- current state of lsm
+signal ns : statetype;  -- next state of lsm
+                                                                                              
+signal tx_pll_lol_qd_s_int  : std_logic;
+signal tx_pcs_rst_ch_c_int  : std_logic;
+signal rst_qd_c_int         : std_logic;
+                                                                                              
+signal reset_timer1         : std_logic;
+signal reset_timer2         : std_logic;
+                                                                                              
+signal counter1             : unsigned(2 downto 0);
+signal timer1               : std_logic;
+                                                                                              
+signal counter2             : unsigned(19 downto 0);
+signal timer2               : std_logic;
+                                                                                              
+begin
+                                                                                              
+sync_sfp_sigs : entity work.signal_sync port map(RESET => '0',CLK0 => TX_REFCLK, CLK1 => TX_REFCLK,
+                                        D_IN(0)  => TX_PLL_LOL_QD_S, 
+                                        D_OUT(0) => tx_pll_lol_qd_s_int);
+
+
+--TIMER1 = 20ns;
+--Fastest REFLCK =312 MHZ, or 3 ns. We need 8 REFCLK cycles or 4 REFCLKDIV2 cycles
+-- A 2 bit counter ([1:0]) counts 4 cycles, so a 3 bit ([2:0]) counter will do if we set TIMER1 = bit[2]
+                                                                                              
+-- Timer 1                                                                                            
+THE_TIMER1_PROC: process( TX_REFCLK )
+begin
+  if rising_edge(TX_REFCLK) then
+    if reset_timer1 = '1' then
+      counter1 <= (others => '0');
+      timer1 <= '0';
+    else
+      if counter1(2) = '1' then
+        timer1 <= '1';
+      else
+        timer1 <='0';
+        counter1 <= counter1 + 1 ;
+      end if;
+    end if;
+  end if;
+end process THE_TIMER1_PROC;                                                                                              
+                                                                                              
+--TIMER2 = 1,400,000 UI;
+--WORST CASE CYCLES is with smallest multipier factor.
+-- This would be with X8 clock multiplier in DIV2 mode
+-- IN this casse, 1 UI = 2/8 REFCLK  CYCLES = 1/8 REFCLKDIV2 CYCLES
+-- SO 1,400,000 UI =1,400,000/8 = 175,000 REFCLKDIV2 CYCLES
+-- An 18 bit counter ([17:0]) counts 262144 cycles, so a 19 bit ([18:0]) counter will do if we set TIMER2 = bit[18]
+                                                                                                                                                                 
+THE_TIMER2_PROC: process( TX_REFCLK )
+begin
+  if rising_edge(TX_REFCLK) then
+    if reset_timer2 = '1' then
+      counter2 <= (others => '0');
+      timer2 <= '0';
+    else
+      if counter2(count_index) = '1' then
+        timer2 <='1';
+      else
+        timer2 <='0';
+        counter2 <= counter2 + 1 ;
+      end if;
+    end if;
+  end if;
+end process THE_TIMER2_PROC;
+
+-- State machine clocked process
+THE_FSM_PROC: process( TX_REFCLK, RST_N )
+begin
+  if RST_N = '0' then
+    cs <= QUAD_RESET;
+    TX_PCS_RST_CH_C <= '1';
+    RST_QD_C <= '1';
+  else 
+    if rising_edge(TX_REFCLK) then
+      cs <= ns;
+      TX_PCS_RST_CH_C <= tx_pcs_rst_ch_c_int;
+      RST_QD_C <= rst_qd_c_int;
+    end if;
+  end if;
+end process THE_FSM_PROC;
+
+THE_FSM_DECODE_PROC: process( cs, timer1, timer2, tx_pll_lol_qd_s_int, RX_RESET_FINISHED_IN )
+begin
+  reset_timer1 <= '0';
+  reset_timer2 <= '0';
+  rst_qd_c_int <= '0';
+  tx_pcs_rst_ch_c_int <= '0';
+  STATE_OUT <= x"F";
+  NORMAL_OPERATION_OUT <= '0';
+
+  case cs is
+                                                                                              
+    when QUAD_RESET   =>
+      STATE_OUT <= x"1";
+      tx_pcs_rst_ch_c_int <= '1';
+      rst_qd_c_int <= '1';
+      reset_timer1 <= '1';
+      ns <= WAIT_FOR_TIMER1;
+                                                                                              
+    when WAIT_FOR_TIMER1 =>
+      STATE_OUT <= x"2";
+      tx_pcs_rst_ch_c_int <= '1';
+      rst_qd_c_int <= '1';
+      if timer1 = '1' then
+        ns <= CHECK_PLOL;
+      else
+        ns <= WAIT_FOR_TIMER1;
+      end if;
+                                                                                              
+    when CHECK_PLOL   =>
+      STATE_OUT <= x"3";
+      tx_pcs_rst_ch_c_int <= '1';
+      --rst_qd_c_int <= '0';
+      reset_timer2 <= '1';
+      ns <= WAIT_FOR_TIMER2;
+                                                                                              
+    when WAIT_FOR_TIMER2 =>
+      STATE_OUT <= x"4";
+      tx_pcs_rst_ch_c_int <= '1';
+      --rst_qd_c_int <= '0';
+      if timer2 = '1' then
+        if tx_pll_lol_qd_s_int = '1' then
+          ns <= QUAD_RESET;
+        else
+          ns <= WAIT_FOR_RX;
+        end if;
+      else
+        ns <= WAIT_FOR_TIMER2;
+      end if;
+            
+    when WAIT_FOR_RX =>
+      if RX_RESET_FINISHED_IN = '1' then
+        ns <= NORMAL;
+      else
+        ns <= WAIT_FOR_RX;
+      end if;
+                                                                                  
+    when NORMAL =>
+      STATE_OUT <= x"5";
+      tx_pcs_rst_ch_c_int <= '0';
+      rst_qd_c_int <= '0';
+      if tx_pll_lol_qd_s_int = '1' then
+        ns <= QUAD_RESET;
+      else
+        NORMAL_OPERATION_OUT <= '1';
+        ns <= NORMAL;
+      end if;
+                                                                                              
+    when others =>
+       ns <=    QUAD_RESET;
+                                                                                              
+  end case;                                                                                
+end process THE_FSM_DECODE_PROC;
+                                                                                              
+end architecture;