--- /dev/null
+--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;
+
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+--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;
--- /dev/null
+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;
--- /dev/null
+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;
--- /dev/null
+--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;