From 7d382cc09cd115a30d51178d5b817e2b83d7cc1b Mon Sep 17 00:00:00 2001 From: Michael Boehmer Date: Mon, 15 Nov 2021 14:15:23 +0100 Subject: [PATCH] first DLM operation included, state of code is approx. 04/2020 --- media_interfaces/med_ecp3_sfp_sync_RS.vhd | 304 +++++++++++++ media_interfaces/sync/med_sync_control_RS.vhd | 403 ++++++++++++++++++ media_interfaces/sync/med_sync_define_RS.vhd | 122 ++++++ media_interfaces/sync/rx_control_RS.vhd | 285 +++++++++++++ media_interfaces/sync/rx_reset_fsm_RS.vhd | 188 ++++++++ media_interfaces/sync/sci_reader_RS.vhd | 153 +++++++ media_interfaces/sync/tx_control_RS.vhd | 363 ++++++++++++++++ media_interfaces/sync/tx_reset_fsm_RS.vhd | 184 ++++++++ 8 files changed, 2002 insertions(+) create mode 100644 media_interfaces/med_ecp3_sfp_sync_RS.vhd create mode 100644 media_interfaces/sync/med_sync_control_RS.vhd create mode 100644 media_interfaces/sync/med_sync_define_RS.vhd create mode 100644 media_interfaces/sync/rx_control_RS.vhd create mode 100644 media_interfaces/sync/rx_reset_fsm_RS.vhd create mode 100644 media_interfaces/sync/sci_reader_RS.vhd create mode 100644 media_interfaces/sync/tx_control_RS.vhd create mode 100644 media_interfaces/sync/tx_reset_fsm_RS.vhd diff --git a/media_interfaces/med_ecp3_sfp_sync_RS.vhd b/media_interfaces/med_ecp3_sfp_sync_RS.vhd new file mode 100644 index 0000000..c576d59 --- /dev/null +++ b/media_interfaces/med_ecp3_sfp_sync_RS.vhd @@ -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 index 0000000..350389f --- /dev/null +++ b/media_interfaces/sync/med_sync_control_RS.vhd @@ -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 index 0000000..c9e7720 --- /dev/null +++ b/media_interfaces/sync/med_sync_define_RS.vhd @@ -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 index 0000000..4120d4a --- /dev/null +++ b/media_interfaces/sync/rx_control_RS.vhd @@ -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 index 0000000..aa06bb5 --- /dev/null +++ b/media_interfaces/sync/rx_reset_fsm_RS.vhd @@ -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 index 0000000..20721d7 --- /dev/null +++ b/media_interfaces/sync/sci_reader_RS.vhd @@ -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 index 0000000..fd8831c --- /dev/null +++ b/media_interfaces/sync/tx_control_RS.vhd @@ -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 index 0000000..79e2559 --- /dev/null +++ b/media_interfaces/sync/tx_reset_fsm_RS.vhd @@ -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; -- 2.43.0