---Media interface for Lattice ECP3 using PCS at 2.5GHz
-
-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;
-use work.cbmnet_interface_pkg.all;
-use work.cbmnet_phy_pkg.all;
-
-entity cbmnet_phy_ecp3 is
- generic(
- IS_SYNC_SLAVE : integer := c_NO; --select slave mode
- IS_SIMULATED : integer := c_NO;
- INCL_DEBUG_AIDS : integer := c_YES
- );
- port(
- CLK : in std_logic; -- *internal* 125 MHz reference clock
- RESET : in std_logic; -- synchronous reset
- CLEAR : in std_logic; -- asynchronous reset
-
- --Internal Connection TX
- PHY_TXDATA_IN : in std_logic_vector(15 downto 0);
- PHY_TXDATA_K_IN : in std_logic_vector( 1 downto 0);
-
- --Internal Connection RX
- PHY_RXDATA_OUT : out std_logic_vector(15 downto 0) := (others => '0');
- PHY_RXDATA_K_OUT : out std_logic_vector( 1 downto 0) := (others => '0');
-
- CLK_RX_HALF_OUT : out std_logic := '0'; -- recovered 125 MHz
- CLK_RX_FULL_OUT : out std_logic := '0'; -- recovered 250 MHz
- CLK_RX_RESET_OUT : out std_logic := '1';
-
- LINK_ACTIVE_OUT : out std_logic; -- link is active and can send and receive data
- SERDES_ready : out std_logic;
-
- --SFP Connection
- SD_RXD_P_IN : in std_logic := '0';
- SD_RXD_N_IN : in std_logic := '0';
- SD_TXD_P_OUT : out std_logic := '0';
- SD_TXD_N_OUT : out std_logic := '0';
-
- SD_PRSNT_N_IN : in std_logic; -- SFP Present ('0' = SFP in place,entity '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
-
- LED_RX_OUT : out std_logic;
- LED_TX_OUT : out std_logic;
- LED_OK_OUT : out std_logic;
-
- -- Status and control port
- STAT_OP : out std_logic_vector ( 15 downto 0) := (others => '0');
- CTRL_OP : in std_logic_vector ( 15 downto 0) := (others => '0');
- DEBUG_OUT : out std_logic_vector (255 downto 0) := (others => '0')
- );
-end entity;
-
-architecture cbmnet_phy_ecp3_arch of cbmnet_phy_ecp3 is
- -- Placer Directives
- attribute HGROUP : string;
- -- for whole architecture
- attribute HGROUP of cbmnet_phy_ecp3_arch : architecture is "cbmnet_phy_group";
-
- attribute syn_hier: string;
- attribute syn_hier of cbmnet_phy_ecp3_arch : architecture is "hard";
-
-
- attribute syn_sharing : string;
- attribute syn_sharing of cbmnet_phy_ecp3_arch : architecture is "off";
-
- constant WA_FIXATION : integer := c_YES;
-
--- Clocks and global resets
- signal clk_125_local : std_logic; -- local 125 MHz reference clock driven by clock generators
- signal clk_125_i : std_logic; -- in FEE mode, driven by recovered clock, in Master mode, driven by local clock
- signal rclk_250_i : std_logic; -- recovered word clock
- signal rclk_125_i : std_logic; -- rclk_250_i divided by two. aligned s.t. the rising edge corresponds to the lower received word
- signal clk_tx_full_i : std_logic; -- 250 MHz clock generated by the serdes's TX-PLL
-
- signal clk_tx_half_i : std_logic; -- 250 MHz clock generated by the serdes's TX-PLL
-
- signal rst_i : std_logic; -- High-active reset driven by external logic
- signal rst_n_i : std_logic; -- Low-active version of rst_i
-
- signal clk_serdes_rx_ref : std_logic;
- signal clk_serdes_tx_ref : std_logic;
-
--- SERDES/PCS
- -- status
- signal rx_los_low_i : std_logic;
- signal rx_cdr_lol_i : std_logic;
- signal tx_pll_lol_i : std_logic;
- signal lsm_status_i : std_logic;
-
- signal rx_dec_error_i: std_logic;
- signal rx_error_delay : std_logic_vector(3 downto 0); -- shift register to detect a "stable error condition"
-
- -- resets
- signal rst_qd_i : std_logic;
- signal serdes_rst_qd_i : std_logic;
-
- signal tx_serdes_rst_i : std_logic;
- signal tx_pcs_rst_i : std_logic;
-
- signal rx_serdes_rst_i : std_logic;
- signal rx_pcs_rst_i : std_logic;
-
- -- data
- signal tx_data_to_serdes_i : std_logic_vector( 8 downto 0); -- received by SERDES
- signal rx_data_from_serdes_i : std_logic_vector( 8 downto 0); -- received by SERDES
-
- -- status & control interface (and obtained info)
- signal sci_ch_i : std_logic_vector(3 downto 0);
- signal sci_qd_i : std_logic;
- signal sci_reg_i : std_logic;
- signal sci_addr_i : std_logic_vector(8 downto 0);
- signal sci_data_in_i : std_logic_vector(7 downto 0) := (others => '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 sci_write_shift_i : std_logic_vector(2 downto 0);
- signal sci_read_shift_i : std_logic_vector(2 downto 0);
-
- signal wa_position_i : std_logic_vector(15 downto 0) := x"FFFF";
- signal barrel_shifter_misaligned_i: std_logic;
-
--- RESET FSM
- signal rx_rst_fsm_state_i : std_logic_vector(3 downto 0);
- signal tx_rst_fsm_state_i : std_logic_vector(3 downto 0);
- signal tx_rst_fsm_ready_i : std_logic;
- signal tx_rst_fsm_ready_buf_i : std_logic;
-
- signal byte_alignment_to_fsm_i : std_logic;
- signal word_alignment_to_fsm_i : std_logic;
-
- signal rx_rst_fsm_ready_i : std_logic;
-
- signal serdes_ready_i : std_logic;
-
--- SCI Logic to obtain the barrel shifter position
- type sci_ctrl is (IDLE, GET_WA, GET_WA_WAIT, GET_WA_WAIT2, GET_WA_FINISH);
- signal sci_state : sci_ctrl;
- signal sci_timer : unsigned( 7 downto 0) := (others => '0');
- signal start_timer : unsigned(18 downto 0) := (others => '0');
-
--- GEAR
- signal gear_to_fsm_rst_i : std_logic;
- signal gear_to_rm_rst_i : std_logic; -- gear keeps CBMNet ready manager reset until gear locked successfully
- signal gear_to_rm_n_rst_i : std_logic; -- inverted version of above
-
- signal rx_data_from_gear_i : std_logic_vector(17 downto 0); -- 16(+2) bit word generated by gear
-
- signal rx_data_i : std_logic_vector(17 downto 0); -- in the front end this signal is identical to rx_data_from_gear_i
- -- otherwise a clock domain crossing from rclk_125_i to clk_125_local is
- -- necessary. this signal will not exhibit a deterministic latency !!!!!!
- -- (however, this is no problem, as the clock master will not receive DLMs)
-
- signal rx_data_debug_i : std_logic_vector(17 downto 0);
-
- signal tx_data_i : std_logic_vector(17 downto 0); -- 16(+2) bit word generated fed to gear
- signal tx_gear_reset_i : std_logic;
- signal tx_gear_allow_relock_i : std_logic;
-
-
- signal rx_gear_debug_i : std_logic_vector(31 downto 0);
- signal tx_gear_debug_i : std_logic_vector(31 downto 0);
-
--- CBMNet Ready Managers
- signal rm_rx_ready_i : std_logic;
- signal rm_rx_almost_ready_i : std_logic;
- signal rm_rx_status_for_tx_i : std_logic;
- signal rm_rx_see_ready0_i : std_logic;
- signal rm_rx_saw_ready1_i : std_logic;
- signal rm_rx_valid_char_i : std_logic;
-
- signal rm_tx_ready_i : std_logic;
- signal rm_tx_almost_ready_i : std_logic;
-
- signal rm_rx_to_gear_reset_i : std_logic;
-
--- LEDs
- signal led_ok_i : std_logic;
- signal led_tx_i, last_led_tx_i : std_logic;
- signal led_rx_i, last_led_rx_i : std_logic;
- signal led_timer_i : unsigned(20 downto 0);
-
--- Stats
- signal stat_reconnect_counter_i : unsigned(15 downto 0); -- counts the number of RX-serdes resets since last external reset
- signal stat_last_reconnect_duration_i : unsigned(31 downto 0);
-
- signal stat_wa_int_i : std_logic_vector(15 downto 0) := (others => '0');
-
- signal tx_data_debug_i : std_logic_vector(17 downto 0);
- signal tx_data_debug_state_i : std_logic;
-
- signal low_level_rx_see_dlm0 : std_logic;
- signal low_level_tx_see_dlm0 : std_logic;
+--Media interface for Lattice ECP3 using PCS at 2.5GHz\r
+\r
+LIBRARY IEEE;\r
+USE IEEE.std_logic_1164.ALL;\r
+USE IEEE.numeric_std.all;\r
+\r
+library work;\r
+use work.trb_net_std.all;\r
+use work.trb_net_components.all;\r
+use work.med_sync_define.all;\r
+use work.cbmnet_interface_pkg.all;\r
+use work.cbmnet_phy_pkg.all;\r
+\r
+entity cbmnet_phy_ecp3 is\r
+ generic(\r
+ IS_SYNC_SLAVE : integer := c_NO; --select slave mode\r
+ IS_SIMULATED : integer := c_NO;\r
+ INCL_DEBUG_AIDS : integer := c_YES\r
+ );\r
+ port(\r
+ CLK : in std_logic; -- *internal* 125 MHz reference clock\r
+ RESET : in std_logic; -- synchronous reset\r
+ CLEAR : in std_logic; -- asynchronous reset\r
+\r
+ --Internal Connection TX\r
+ PHY_TXDATA_IN : in std_logic_vector(15 downto 0);\r
+ PHY_TXDATA_K_IN : in std_logic_vector( 1 downto 0);\r
+\r
+ --Internal Connection RX\r
+ PHY_RXDATA_OUT : out std_logic_vector(15 downto 0) := (others => '0');\r
+ PHY_RXDATA_K_OUT : out std_logic_vector( 1 downto 0) := (others => '0');\r
+\r
+ CLK_RX_HALF_OUT : out std_logic := '0'; -- recovered 125 MHz\r
+ CLK_RX_FULL_OUT : out std_logic := '0'; -- recovered 250 MHz\r
+ CLK_RX_RESET_OUT : out std_logic := '1';\r
+\r
+ LINK_ACTIVE_OUT : out std_logic; -- link is active and can send and receive data\r
+ SERDES_ready : out std_logic;\r
+\r
+ --SFP Connection\r
+ SD_RXD_P_IN : in std_logic := '0';\r
+ SD_RXD_N_IN : in std_logic := '0';\r
+ SD_TXD_P_OUT : out std_logic := '0';\r
+ SD_TXD_N_OUT : out std_logic := '0';\r
+\r
+ SD_PRSNT_N_IN : in std_logic; -- SFP Present ('0' = SFP in place,entity '1' = no SFP mounted)\r
+ SD_LOS_IN : in std_logic; -- SFP Loss Of Signal ('0' = OK, '1' = no signal)\r
+ SD_TXDIS_OUT : out std_logic := '0'; -- SFP disable\r
+\r
+ LED_RX_OUT : out std_logic;\r
+ LED_TX_OUT : out std_logic;\r
+ LED_OK_OUT : out std_logic;\r
+ \r
+ -- Status and control port\r
+ STAT_OP : out std_logic_vector ( 15 downto 0) := (others => '0');\r
+ CTRL_OP : in std_logic_vector ( 15 downto 0) := (others => '0');\r
+ DEBUG_OUT : out std_logic_vector (255 downto 0) := (others => '0')\r
+ );\r
+end entity;\r
+\r
+architecture cbmnet_phy_ecp3_arch of cbmnet_phy_ecp3 is\r
+ -- Placer Directives\r
+ attribute HGROUP : string;\r
+ -- for whole architecture\r
+ attribute HGROUP of cbmnet_phy_ecp3_arch : architecture is "cbmnet_phy_group";\r
+ \r
+ attribute syn_hier: string;\r
+ attribute syn_hier of cbmnet_phy_ecp3_arch : architecture is "hard"; \r
+ \r
+ \r
+ attribute syn_sharing : string;\r
+ attribute syn_sharing of cbmnet_phy_ecp3_arch : architecture is "off";\r
+\r
+ constant WA_FIXATION : integer := c_YES;\r
+\r
+-- Clocks and global resets \r
+ signal clk_125_local : std_logic; -- local 125 MHz reference clock driven by clock generators\r
+ signal clk_125_i : std_logic; -- in FEE mode, driven by recovered clock, in Master mode, driven by local clock\r
+ signal rclk_250_i : std_logic; -- recovered word clock\r
+ signal rclk_125_i : std_logic; -- rclk_250_i divided by two. aligned s.t. the rising edge corresponds to the lower received word\r
+ signal clk_tx_full_i : std_logic; -- 250 MHz clock generated by the serdes's TX-PLL\r
+\r
+ signal clk_tx_half_i : std_logic; -- 250 MHz clock generated by the serdes's TX-PLL\r
+ \r
+ signal rst_i : std_logic; -- High-active reset driven by external logic\r
+ signal rst_n_i : std_logic; -- Low-active version of rst_i\r
+\r
+ signal clk_serdes_rx_ref : std_logic;\r
+ signal clk_serdes_tx_ref : std_logic;\r
+ \r
+-- SERDES/PCS \r
+ -- status\r
+ signal rx_los_low_i : std_logic;\r
+ signal rx_cdr_lol_i : std_logic;\r
+ signal tx_pll_lol_i : std_logic;\r
+ signal lsm_status_i : std_logic;\r
+\r
+ signal rx_dec_error_i: std_logic;\r
+ signal rx_error_delay : std_logic_vector(3 downto 0); -- shift register to detect a "stable error condition"\r
+ \r
+ -- resets\r
+ signal rst_qd_i : std_logic;\r
+ signal serdes_rst_qd_i : std_logic;\r
+ \r
+ signal tx_serdes_rst_i : std_logic;\r
+ signal tx_pcs_rst_i : std_logic;\r
+ \r
+ signal rx_serdes_rst_i : std_logic;\r
+ signal rx_pcs_rst_i : std_logic;\r
+\r
+ -- data\r
+ signal tx_data_to_serdes_i : std_logic_vector( 8 downto 0); -- received by SERDES\r
+ signal rx_data_from_serdes_i : std_logic_vector( 8 downto 0); -- received by SERDES\r
+\r
+ -- status & control interface (and obtained info)\r
+ signal sci_ch_i : std_logic_vector(3 downto 0);\r
+ signal sci_qd_i : std_logic;\r
+ signal sci_reg_i : std_logic;\r
+ signal sci_addr_i : std_logic_vector(8 downto 0);\r
+ signal sci_data_in_i : std_logic_vector(7 downto 0) := (others => '0');\r
+ signal sci_data_out_i : std_logic_vector(7 downto 0);\r
+ signal sci_read_i : std_logic;\r
+ signal sci_write_i : std_logic;\r
+ signal sci_write_shift_i : std_logic_vector(2 downto 0);\r
+ signal sci_read_shift_i : std_logic_vector(2 downto 0);\r
+\r
+ signal wa_position_i : std_logic_vector(15 downto 0) := x"FFFF";\r
+ signal barrel_shifter_misaligned_i: std_logic;\r
+ \r
+-- RESET FSM \r
+ signal rx_rst_fsm_state_i : std_logic_vector(3 downto 0);\r
+ signal tx_rst_fsm_state_i : std_logic_vector(3 downto 0);\r
+ signal tx_rst_fsm_ready_i : std_logic;\r
+ signal tx_rst_fsm_ready_buf_i : std_logic;\r
+ \r
+ signal byte_alignment_to_fsm_i : std_logic;\r
+ signal word_alignment_to_fsm_i : std_logic;\r
+\r
+ signal rx_rst_fsm_ready_i : std_logic;\r
+ \r
+ signal serdes_ready_i : std_logic;\r
+ \r
+-- SCI Logic to obtain the barrel shifter position\r
+ type sci_ctrl is (IDLE, GET_WA, GET_WA_WAIT, GET_WA_WAIT2, GET_WA_FINISH);\r
+ signal sci_state : sci_ctrl;\r
+ signal sci_timer : unsigned( 7 downto 0) := (others => '0');\r
+ signal start_timer : unsigned(18 downto 0) := (others => '0');\r
+ \r
+-- GEAR\r
+ signal gear_to_fsm_rst_i : std_logic;\r
+ signal gear_to_rm_rst_i : std_logic; -- gear keeps CBMNet ready manager reset until gear locked successfully\r
+ signal gear_to_rm_n_rst_i : std_logic; -- inverted version of above\r
+\r
+ signal rx_data_from_gear_i : std_logic_vector(17 downto 0); -- 16(+2) bit word generated by gear\r
+ \r
+ signal rx_data_i : std_logic_vector(17 downto 0); -- in the front end this signal is identical to rx_data_from_gear_i\r
+ -- otherwise a clock domain crossing from rclk_125_i to clk_125_local is\r
+ -- necessary. this signal will not exhibit a deterministic latency !!!!!!\r
+ -- (however, this is no problem, as the clock master will not receive DLMs)\r
+\r
+ signal rx_data_debug_i : std_logic_vector(17 downto 0); \r
+ \r
+ signal tx_data_i : std_logic_vector(17 downto 0); -- 16(+2) bit word generated fed to gear\r
+ signal tx_gear_reset_i : std_logic;\r
+ signal tx_gear_allow_relock_i : std_logic;\r
+ \r
+ signal tx_gear_ready_i : std_logic;\r
+ \r
+ signal rx_gear_debug_i : std_logic_vector(31 downto 0);\r
+ signal tx_gear_debug_i : std_logic_vector(31 downto 0);\r
+ \r
+-- CBMNet Ready Managers\r
+ signal rm_rx_ready_i : std_logic;\r
+ signal rm_rx_almost_ready_i : std_logic;\r
+ signal rm_rx_status_for_tx_i : std_logic;\r
+ signal rm_rx_see_ready0_i : std_logic;\r
+ signal rm_rx_saw_ready1_i : std_logic;\r
+ signal rm_rx_valid_char_i : std_logic;\r
+ \r
+ signal rm_tx_ready_i : std_logic;\r
+ signal rm_tx_almost_ready_i : std_logic;\r
+ \r
+ signal rm_rx_to_gear_reset_i : std_logic;\r
+ \r
+ signal rm_rx_data_buf_i : std_logic_vector(17 downto 0);\r
+ \r
+ signal rm_rx_ebtb_code_err_cntr_clr_i : std_logic;\r
+ signal rm_rx_ebtb_disp_err_cntr_clr_i : std_logic;\r
+ signal rm_rx_ebtb_code_err_cntr_i : std_logic_vector(15 downto 0);\r
+ signal rm_rx_ebtb_disp_err_cntr_i : std_logic_vector(15 downto 0);\r
+ signal rm_rx_ebtb_code_err_cntr_flag_i : std_logic;\r
+ signal rm_rx_ebtb_disp_err_cntr_flag_i : std_logic;\r
+ \r
+ signal rm_tx_to_rx_reinit_i : std_logic;\r
+ \r
+ signal rm_rx_see_reinit : std_logic;\r
+ signal rm_rx_ebtb_detect_i : std_logic;\r
+ signal rm_tx_link_lost_i : std_logic;\r
+ \r
+ signal rm_tx_pcs_startup_cntr_clr : std_logic;\r
+ signal rm_tx_pcs_startup_cntr : std_logic_vector(15 downto 0); -- Counts for link startups\r
+ signal rm_tx_pcs_startup_cntr_flag : std_logic; \r
+ \r
+ signal rm_rx_rxpcs_ready_i : std_logic;\r
+\r
+-- LEDs\r
+ signal led_ok_i : std_logic;\r
+ signal led_tx_i, last_led_tx_i : std_logic;\r
+ signal led_rx_i, last_led_rx_i : std_logic;\r
+ signal led_timer_i : unsigned(20 downto 0);\r
+\r
+-- Stats\r
+ signal stat_reconnect_counter_i : unsigned(15 downto 0); -- counts the number of RX-serdes resets since last external reset\r
+ signal stat_last_reconnect_duration_i : unsigned(31 downto 0);\r
+ \r
+ signal stat_wa_int_i : std_logic_vector(15 downto 0) := (others => '0');\r
+ \r
+ signal tx_data_debug_i : std_logic_vector(17 downto 0);\r
+ signal tx_data_debug_state_i : std_logic;\r
+ \r
+ signal low_level_rx_see_dlm0 : std_logic;\r
+ signal low_level_tx_see_dlm0 : std_logic;\r
signal low_level_tx_see_dlm0_125 : std_logic;\r
\r
- signal stat_dlm_counter_i : unsigned(15 downto 0);
-begin
- clk_125_local <= CLK;
- CLK_RX_HALF_OUT <= rclk_125_i when IS_SYNC_SLAVE = c_YES or 1=1 else clk_tx_half_i;
- CLK_RX_FULL_OUT <= rclk_250_i;
-
- SD_TXDIS_OUT <= '0';
-
- rst_i <= (CLEAR or CTRL_OP(0));
- rst_n_i <= not rst_i;
-
- gen_slave_clock : if IS_SYNC_SLAVE = c_YES generate
- clk_125_i <= rclk_125_i;
- clk_serdes_rx_ref <= clk_125_local;
- clk_serdes_tx_ref <= rclk_125_i;
- end generate;
-
- gen_master_clock : if IS_SYNC_SLAVE = c_NO generate
- clk_125_i <= clk_tx_half_i;
- clk_serdes_rx_ref <= clk_tx_half_i;
- clk_serdes_tx_ref <= clk_125_local;
- end generate;
-
- -------------------------------------------------
- -- Serdes
- -------------------------------------------------
- THE_SERDES : cbmnet_sfp1
- port map(
- -- SERIAL DATA PORTS
- hdinp_ch0 => SD_RXD_P_IN,
- hdinn_ch0 => SD_RXD_N_IN,
- hdoutp_ch0 => SD_TXD_P_OUT,
- hdoutn_ch0 => SD_TXD_N_OUT,
-
- -- CLOCKS
- rx_full_clk_ch0 => rclk_250_i,
- rx_half_clk_ch0 => open, -- recovered (and correctly aligned) 125 MHz clock is generated by gear
-
- tx_full_clk_ch0 => clk_tx_full_i,
- tx_half_clk_ch0 => open,
-
- fpga_rxrefclk_ch0 => clk_serdes_rx_ref,
- fpga_txrefclk => clk_serdes_tx_ref,
- txiclk_ch0 => clk_tx_full_i,
-
- -- RESETS
- rst_qd_c => rst_qd_i,
- serdes_rst_qd_c => serdes_rst_qd_i, -- always 0
- tx_serdes_rst_c => tx_serdes_rst_i, -- always 0
- rx_serdes_rst_ch0_c => rx_serdes_rst_i,
- tx_pcs_rst_ch0_c => tx_pcs_rst_i,
- rx_pcs_rst_ch0_c => rx_pcs_rst_i,
-
- tx_pwrup_ch0_c => '1',
- rx_pwrup_ch0_c => '1',
-
- -- TX DATA PORT
- txdata_ch0 => tx_data_to_serdes_i(7 downto 0),
- tx_k_ch0 => tx_data_to_serdes_i(8),
-
- tx_force_disp_ch0 => '0',
- tx_disp_sel_ch0 => '0',
- tx_div2_mode_ch0_c => '0',
-
- -- RX DATA PORT
- rxdata_ch0 => rx_data_from_serdes_i(7 downto 0),
- rx_k_ch0 => rx_data_from_serdes_i(8),
-
- rx_disp_err_ch0 => open,
- rx_cv_err_ch0 => rx_dec_error_i,
- rx_div2_mode_ch0_c => '0',
-
- -- LOOPBACK
- sb_felb_ch0_c => '0',
- sb_felb_rst_ch0_c => '0',
-
- -- STATUS
- tx_pll_lol_qd_s => tx_pll_lol_i,
- rx_los_low_ch0_s => rx_los_low_i,
- rx_cdr_lol_ch0_s => rx_cdr_lol_i,
- lsm_status_ch0_s => lsm_status_i,
-
- SCI_WRDATA => sci_data_in_i,
- SCI_RDDATA => sci_data_out_i,
- SCI_ADDR => sci_addr_i(5 downto 0),
- SCI_SEL_QUAD => sci_qd_i,
- SCI_SEL_CH0 => sci_ch_i(0),
- SCI_RD => sci_read_i,
- SCI_WRN => sci_write_i
- );
-
- tx_serdes_rst_i <= '0'; --no function
- serdes_rst_qd_i <= '0'; --included in rst_qd_i
-
- -------------------------------------------------
- -- Reset FSM & Link states
- -------------------------------------------------
- THE_RX_FSM : cbmnet_phy_ecp3_rx_reset_fsm
- generic map (
- IS_SIMULATED => IS_SIMULATED
- )
- port map(
- RST_N => rst_n_i,
- RX_REFCLK => clk_125_local,
- TX_PLL_LOL_QD_S => tx_pll_lol_i,
- RX_CDR_LOL_CH_S => rx_cdr_lol_i,
- RX_LOS_LOW_CH_S => rx_los_low_i,
-
- RM_RESET_IN => CTRL_OP(4), --rx_reset_from_rm_i,
- PROPER_BYTE_ALIGN_IN=> byte_alignment_to_fsm_i,
- PROPER_WORD_ALIGN_IN=> word_alignment_to_fsm_i,
-
- RX_SERDES_RST_CH_C => rx_serdes_rst_i,
- RX_PCS_RST_CH_C => rx_pcs_rst_i,
- STATE_OUT => rx_rst_fsm_state_i
- );
- byte_alignment_to_fsm_i <= (not barrel_shifter_misaligned_i) or CTRL_OP(3);
- word_alignment_to_fsm_i <= not (gear_to_fsm_rst_i or AND_ALL(rx_error_delay));
- rx_error_delay <= rx_error_delay(rx_error_delay'high - 1 downto 0) & rx_dec_error_i when rising_edge(clk_125_local);
-
-
- THE_TX_FSM : cbmnet_phy_ecp3_tx_reset_fsm
- generic map (
- IS_SIMULATED => IS_SIMULATED
- )
- port map(
- RST_N => rst_n_i,
- TX_REFCLK => clk_125_local,
- TX_PLL_LOL_QD_S => tx_pll_lol_i,
- RST_QD_C => rst_qd_i,
- TX_PCS_RST_CH_C => tx_pcs_rst_i,
- STATE_OUT => tx_rst_fsm_state_i
- );
-
- proc_rst_fsms_ready: process is begin
- wait until rising_edge(clk_125_local);
- rx_rst_fsm_ready_i <= '0';
- if rx_rst_fsm_state_i = x"6" then
- rx_rst_fsm_ready_i <= '1';
- end if;
-
- tx_rst_fsm_ready_i <= '0';
- if tx_rst_fsm_state_i = x"5" then
- tx_rst_fsm_ready_i <= '1';
- end if;
- end process;
-
- THE_RX_GEAR: CBMNET_PHY_RX_GEAR
- generic map (
- IS_SYNC_SLAVE => IS_SYNC_SLAVE
- ) port map (
- -- SERDES PORT
- CLK_250_IN => rclk_250_i, -- in std_logic;
- PCS_READY_IN => rx_rst_fsm_ready_i, -- in std_logic;
- SERDES_RESET_OUT=> gear_to_fsm_rst_i, -- out std_logic;
- DATA_IN => rx_data_from_serdes_i, -- in std_logic_vector( 8 downto 0);
-
- -- RM PORT
- RM_RESET_IN => rm_rx_to_gear_reset_i, -- in std_logic;
- CLK_125_OUT => rclk_125_i, -- out std_logic;
- RESET_OUT => gear_to_rm_rst_i, -- out std_logic;
- DATA_OUT => rx_data_from_gear_i, -- out std_logic_vector(17 downto 0)
-
- DEBUG_OUT => rx_gear_debug_i
- );
-
- process is
- variable state_v : std_logic;
- begin
- wait until rising_edge(rclk_250_i);
-
- if state_v = '0' then
- rx_data_debug_i(7 downto 0) <= rx_data_from_serdes_i(7 downto 0);
- rx_data_debug_i(16) <= rx_data_from_serdes_i(8);
- else
- rx_data_debug_i(15 downto 8) <= rx_data_from_serdes_i(7 downto 0);
- rx_data_debug_i(17) <= rx_data_from_serdes_i(8);
- end if;
-
- state_v := not state_v;
- end process;
-
- rx_data_i <= rx_data_from_gear_i when rising_edge(clk_125_local) or (IS_SYNC_SLAVE = c_YES);
-
- THE_TX_GEAR: CBMNET_PHY_TX_GEAR
- generic map (IS_SYNC_SLAVE => IS_SYNC_SLAVE)
- port map (
- CLK_250_IN => clk_tx_full_i, -- in std_logic;
- CLK_125_IN => clk_serdes_tx_ref, -- in std_logic;
- CLK_125_OUT => clk_tx_half_i,
-
- RESET_IN => tx_gear_reset_i, -- in std_logic;
- ALLOW_RELOCK_IN => tx_gear_allow_relock_i, -- in std_logic
-
- DATA_IN => tx_data_i, -- in std_logic_vector(17 downto 0)
-
- DATA_OUT => tx_data_to_serdes_i -- out std_logic_vector(8 downto 0);
- );
- tx_gear_reset_i <= not tx_rst_fsm_ready_i;
- tx_gear_allow_relock_i <= ((not tx_rst_fsm_ready_i) and not CTRL_OP(1)) or CTRL_OP(2);
-
- process is
- begin
- wait until rising_edge(clk_tx_full_i);
-
- tx_data_debug_state_i <= not tx_data_debug_state_i;
-
- if tx_data_debug_state_i = '1' then
- tx_data_debug_i(7 downto 0) <= tx_data_to_serdes_i(7 downto 0);
- tx_data_debug_i(16) <= tx_data_to_serdes_i(8);
-
- else
- tx_data_debug_i(15 downto 8) <= tx_data_to_serdes_i(7 downto 0);
- tx_data_debug_i(17) <= tx_data_to_serdes_i(8);
-
- end if;
- end process;
-
- -------------------------------------------------
- -- CBMNet Ready Modules
- -------------------------------------------------
- THE_RX_READY: gtp_rx_ready_module
- generic map (INCL_8B10B_DEC => c_No)
- port map (
- clk => clk_125_i,
- res_n => gear_to_rm_n_rst_i,
- ready_MGT2RM => '1',
-
- rxdata_in(17 downto 0) => rx_data_i,
- rxdata_in(19 downto 18) => "00",
- tx_ready => rm_tx_ready_i,
- tx_almost_ready => rm_tx_almost_ready_i,
-
- ready_RM2LP => rm_rx_ready_i,
-
- rxdata_out => PHY_RXDATA_OUT,
- charisk_out => PHY_RXDATA_K_OUT,
-
- almost_ready_OUT => rm_rx_almost_ready_i,
- see_ready0 => rm_rx_see_ready0_i,
- saw_ready1 => rm_rx_saw_ready1_i,
- valid_char => rm_rx_valid_char_i,
-
- reset_rx => rm_rx_to_gear_reset_i
- );
- gear_to_rm_n_rst_i <= not gear_to_rm_rst_i when rising_edge(clk_125_i);
-
- THE_TX_READY: gtp_tx_ready_module
- port map (
- clk => clk_125_i, -- : in std_logic;
- res_n => tx_rst_fsm_ready_buf_i, -- : in std_logic;
- restart_link => CTRL_OP(14), -- : in std_logic;
- ready_MGT2RM => '1', -- : in std_logic;
- txdata_in => PHY_TXDATA_IN , -- : in std_logic_vector((DATAWIDTH-1) downto 0);
- txcharisk_in => PHY_TXDATA_K_IN, -- : in std_logic_vector((WORDS-1) downto 0);
-
- see_ready0 => rm_rx_see_ready0_i, -- : in std_logic;
- saw_ready1 => rm_rx_saw_ready1_i, -- : in std_logic;
- valid_char => rm_rx_valid_char_i, -- : in std_logic;
- rx_rm_ready => rm_rx_status_for_tx_i, -- : in std_logic;
-
- ready_RM2LP => rm_tx_ready_i, -- : out std_logic;
- txdata_out => tx_data_i, -- : out std_logic_vector((WORDS*9)-1 downto 0);
- almost_ready => rm_tx_almost_ready_i, -- : out std_logic;
- gt11_reinit => open -- : out std_logic
- );
- rm_rx_status_for_tx_i <= rm_rx_almost_ready_i or rm_rx_ready_i;
-
- -- clock domain crossing from clk_125_local to clk_125_i
- PROC_SYNC_FSM_READY: process is begin
- wait until rising_edge(clk_125_i);
-
- if IS_SYNC_SLAVE = c_YES then
- tx_rst_fsm_ready_buf_i <= tx_rst_fsm_ready_i and not gear_to_rm_rst_i;
-
- else
- tx_rst_fsm_ready_buf_i <= tx_rst_fsm_ready_i;
-
- end if;
- end process;
-
- serdes_ready_i <= rm_tx_ready_i and rm_rx_ready_i when rising_edge(clk_125_i);
- led_ok_i <= serdes_ready_i;
- SERDES_ready <= serdes_ready_i;
-
- -------------------------------------------------
- -- SCI
- -------------------------------------------------
- -- gives access to serdes config port from slow control and reads word alignment every ~ 40 us
- -- upon retrival the barrel shifter is checked and - if necessary - a serdes reset is issued
- PROC_SCI_CTRL: process
- variable cnt : integer range 0 to 4 := 0;
- begin
- wait until rising_edge(clk_125_local);
-
- case sci_state is
- when IDLE =>
- sci_ch_i <= x"0";
- sci_qd_i <= '0';
- sci_reg_i <= '0';
- sci_read_i <= '0';
- sci_write_i <= '0';
- sci_timer <= sci_timer + 1;
- if sci_timer(sci_timer'left) = '1' then
- sci_timer <= (others => '0');
- sci_state <= GET_WA;
- end if;
-
- when GET_WA =>
- if cnt = 4 then
- cnt := 0;
- sci_state <= IDLE;
-
- else
- sci_state <= GET_WA_WAIT;
- sci_addr_i <= '0' & x"22";
- sci_ch_i <= x"0";
- sci_ch_i(cnt) <= '1';
- sci_read_i <= '1';
- end if;
-
- when GET_WA_WAIT =>
- sci_state <= GET_WA_WAIT2;
-
- when GET_WA_WAIT2 =>
- sci_state <= GET_WA_FINISH;
-
- when GET_WA_FINISH =>
- wa_position_i(cnt*4+3 downto cnt*4) <= sci_data_out_i(3 downto 0);
- sci_state <= GET_WA;
- cnt := cnt + 1;
-
- end case;
- end process;
-
- process is begin
- wait until rising_edge(clk_125_local);
- barrel_shifter_misaligned_i <= '0';
- if lsm_status_i = '1' and wa_position_i(3 downto 0) /= x"0" then
- barrel_shifter_misaligned_i <= '1';
- end if;
- end process;
-
-
- -- RX/TX leds are on as soon as the correspondent pll is locked and data
- -- other than the idle word is transmitted
- PROC_LEDS: process is
- begin
- wait until rising_edge(CLK);
-
- led_rx_i <= not gear_to_rm_rst_i;
- led_tx_i <= tx_rst_fsm_ready_i;
-
- if (led_timer_i(20) = '1') or (rx_data_i(17 downto 16) = "10" and rx_data_i(15 downto 0) = x"fcce") then
- led_rx_i <= '0';
- end if;
-
- if (led_timer_i(20) = '1') or (tx_data_i(17 downto 16) = "10" and tx_data_i(15 downto 0) = x"fcce") then
- led_tx_i <= '0';
- end if;
-
- led_timer_i <= led_timer_i + 1 ;
- if led_timer_i(20) = '1' then
- led_timer_i <= (others => '0');
- last_led_rx_i <= led_rx_i ;
- last_led_tx_i <= led_tx_i;
- end if;
- end process;
-
- LED_OK_OUT <= led_ok_i;
- LED_RX_OUT <= led_rx_i;
- LED_TX_OUT <= led_tx_i;
-
- -- Produce 1us reset pulse for external logic
- PROC_CLK_RESET: process is
- variable counter : unsigned(8 downto 0) := (others => '0');
- begin
- wait until rising_edge(rclk_125_i);
- CLK_RX_RESET_OUT <= '1';
-
- if serdes_ready_i = '0' then
- counter := (others => '0');
-
- elsif counter(counter'high) = '0' then
- counter := counter + 1;
-
- else
- CLK_RX_RESET_OUT <= '0';
-
- end if;
- end process;
-
-
- GEN_DEBUG: if INCL_DEBUG_AIDS = c_YES generate
- proc_stat: process is
- variable last_rx_serdes_rst_i : std_logic;
- begin
- wait until rising_edge(clk_125_local);
-
- if rst_n_i = '0' then
- stat_reconnect_counter_i <= (others => '0');
- stat_last_reconnect_duration_i <= (others => '0');
- stat_wa_int_i <= (others => '0');
- else
- if rx_serdes_rst_i = '1' and last_rx_serdes_rst_i = '0' then
- stat_reconnect_counter_i <= stat_reconnect_counter_i + TO_UNSIGNED(1,1);
- end if;
-
- if serdes_ready_i = '0' then
- stat_last_reconnect_duration_i <= stat_last_reconnect_duration_i + TO_UNSIGNED(1,1);
- end if;
-
- stat_wa_int_i <= stat_wa_int_i or wa_position_i;
- end if;
-
- last_rx_serdes_rst_i := rx_serdes_rst_i;
- end process;
-
- PROC_SENSE_RX_DLM0: process is
- variable detected_first_word_v : std_logic := '0';
- begin
- wait until rising_edge(rclk_250_i);
- low_level_rx_see_dlm0 <= '0';
-
- if detected_first_word_v = '0' then
- if rx_data_from_serdes_i = "1" & x"fb" then
- detected_first_word_v := '1';
- end if;
-
- else
- detected_first_word_v := '0';
- if rx_data_from_serdes_i = "001101010" then
- low_level_rx_see_dlm0 <= '1';
- end if;
-
- end if;
- end process;
-
- PROC_SENSE_TX_DLM0: process is
- variable detected_first_word_v : std_logic := '0';
- begin
- wait until rising_edge(clk_tx_full_i);
- low_level_tx_see_dlm0 <= '0';
-
- if detected_first_word_v = '0' then
- if tx_data_to_serdes_i = "1" & x"fb" then
- detected_first_word_v := '1';
- end if;
-
- else
- detected_first_word_v := '0';
- if tx_data_to_serdes_i = "001101010" then
- low_level_tx_see_dlm0 <= '1';
- end if;
-
- end if;
- end process;
-
- PROC_SENSE_TX_DLM125: process is
- begin
- wait until rising_edge(clk_125_i);
-
- low_level_tx_see_dlm0_125 <= '0';
- if tx_data_i = "10" & x"fb6a" then
- low_level_tx_see_dlm0_125 <= '1';
- end if;
+ signal stat_dlm_counter_i : unsigned(15 downto 0);\r
+begin\r
+ clk_125_local <= CLK;\r
+ CLK_RX_HALF_OUT <= rclk_125_i when IS_SYNC_SLAVE = c_YES or 1=1 else clk_tx_half_i;\r
+ CLK_RX_FULL_OUT <= rclk_250_i;\r
+\r
+ SD_TXDIS_OUT <= '0';\r
+\r
+ rst_i <= (CLEAR or CTRL_OP(0));\r
+ rst_n_i <= not rst_i;\r
+\r
+ gen_slave_clock : if IS_SYNC_SLAVE = c_YES generate\r
+ clk_125_i <= rclk_125_i;\r
+ clk_serdes_rx_ref <= clk_125_local;\r
+ clk_serdes_tx_ref <= rclk_125_i;\r
+ end generate;\r
+\r
+ gen_master_clock : if IS_SYNC_SLAVE = c_NO generate\r
+ clk_125_i <= clk_tx_half_i; \r
+ clk_serdes_rx_ref <= clk_tx_half_i;\r
+ clk_serdes_tx_ref <= clk_125_local;\r
+ end generate;\r
+\r
+ ------------------------------------------------- \r
+ -- Serdes\r
+ ------------------------------------------------- \r
+ THE_SERDES : cbmnet_sfp1\r
+ port map(\r
+ -- SERIAL DATA PORTS\r
+ hdinp_ch0 => SD_RXD_P_IN,\r
+ hdinn_ch0 => SD_RXD_N_IN,\r
+ hdoutp_ch0 => SD_TXD_P_OUT,\r
+ hdoutn_ch0 => SD_TXD_N_OUT,\r
+ \r
+ -- CLOCKS\r
+ rx_full_clk_ch0 => rclk_250_i,\r
+ rx_half_clk_ch0 => open, -- recovered (and correctly aligned) 125 MHz clock is generated by gear\r
+ \r
+ tx_full_clk_ch0 => clk_tx_full_i,\r
+ tx_half_clk_ch0 => open,\r
+ \r
+ fpga_rxrefclk_ch0 => clk_serdes_rx_ref,\r
+ fpga_txrefclk => clk_serdes_tx_ref,\r
+ txiclk_ch0 => clk_tx_full_i,\r
+\r
+ -- RESETS\r
+ rst_qd_c => rst_qd_i,\r
+ serdes_rst_qd_c => serdes_rst_qd_i, -- always 0\r
+ tx_serdes_rst_c => tx_serdes_rst_i, -- always 0\r
+ rx_serdes_rst_ch0_c => rx_serdes_rst_i,\r
+ tx_pcs_rst_ch0_c => tx_pcs_rst_i,\r
+ rx_pcs_rst_ch0_c => rx_pcs_rst_i,\r
+\r
+ tx_pwrup_ch0_c => '1',\r
+ rx_pwrup_ch0_c => '1',\r
+ \r
+ -- TX DATA PORT \r
+ txdata_ch0 => tx_data_to_serdes_i(7 downto 0),\r
+ tx_k_ch0 => tx_data_to_serdes_i(8),\r
+\r
+ tx_force_disp_ch0 => '0',\r
+ tx_disp_sel_ch0 => '0',\r
+ tx_div2_mode_ch0_c => '0',\r
+ \r
+ -- RX DATA PORT\r
+ rxdata_ch0 => rx_data_from_serdes_i(7 downto 0),\r
+ rx_k_ch0 => rx_data_from_serdes_i(8),\r
+\r
+ rx_disp_err_ch0 => open,\r
+ rx_cv_err_ch0 => rx_dec_error_i,\r
+ rx_div2_mode_ch0_c => '0',\r
+ \r
+ -- LOOPBACK\r
+ sb_felb_ch0_c => '0',\r
+ sb_felb_rst_ch0_c => '0',\r
+\r
+ -- STATUS\r
+ tx_pll_lol_qd_s => tx_pll_lol_i,\r
+ rx_los_low_ch0_s => rx_los_low_i,\r
+ rx_cdr_lol_ch0_s => rx_cdr_lol_i,\r
+ lsm_status_ch0_s => lsm_status_i,\r
+ \r
+ SCI_WRDATA => sci_data_in_i,\r
+ SCI_RDDATA => sci_data_out_i,\r
+ SCI_ADDR => sci_addr_i(5 downto 0),\r
+ SCI_SEL_QUAD => sci_qd_i,\r
+ SCI_SEL_CH0 => sci_ch_i(0),\r
+ SCI_RD => sci_read_i,\r
+ SCI_WRN => sci_write_i\r
+ );\r
+\r
+ tx_serdes_rst_i <= '0'; --no function\r
+ serdes_rst_qd_i <= '0'; --included in rst_qd_i\r
+ \r
+ ------------------------------------------------- \r
+ -- Reset FSM & Link states\r
+ ------------------------------------------------- \r
+ THE_RX_FSM : cbmnet_phy_ecp3_rx_reset_fsm\r
+ generic map (\r
+ IS_SIMULATED => IS_SIMULATED\r
+ )\r
+ port map(\r
+ RST_N => rst_n_i,\r
+ RX_REFCLK => clk_125_local,\r
+ TX_PLL_LOL_QD_S => tx_pll_lol_i,\r
+ RX_CDR_LOL_CH_S => rx_cdr_lol_i,\r
+ RX_LOS_LOW_CH_S => rx_los_low_i,\r
+ \r
+ RM_RESET_IN => CTRL_OP(4), --rx_reset_from_rm_i,\r
+ PROPER_BYTE_ALIGN_IN=> byte_alignment_to_fsm_i,\r
+ PROPER_WORD_ALIGN_IN=> word_alignment_to_fsm_i,\r
+ \r
+ RX_SERDES_RST_CH_C => rx_serdes_rst_i,\r
+ RX_PCS_RST_CH_C => rx_pcs_rst_i,\r
+ STATE_OUT => rx_rst_fsm_state_i\r
+ );\r
+ byte_alignment_to_fsm_i <= (not barrel_shifter_misaligned_i) or CTRL_OP(3);\r
+ word_alignment_to_fsm_i <= not (gear_to_fsm_rst_i or AND_ALL(rx_error_delay));\r
+ rx_error_delay <= rx_error_delay(rx_error_delay'high - 1 downto 0) & rx_dec_error_i when rising_edge(clk_125_local);\r
+ \r
+ \r
+ THE_TX_FSM : cbmnet_phy_ecp3_tx_reset_fsm\r
+ generic map (\r
+ IS_SIMULATED => IS_SIMULATED\r
+ )\r
+ port map(\r
+ RST_N => rst_n_i,\r
+ TX_REFCLK => clk_125_local,\r
+ TX_PLL_LOL_QD_S => tx_pll_lol_i,\r
+ RST_QD_C => rst_qd_i,\r
+ TX_PCS_RST_CH_C => tx_pcs_rst_i,\r
+ STATE_OUT => tx_rst_fsm_state_i\r
+ );\r
+ \r
+ proc_rst_fsms_ready: process is begin\r
+ wait until rising_edge(clk_125_local);\r
+ rx_rst_fsm_ready_i <= '0';\r
+ if rx_rst_fsm_state_i = x"6" then\r
+ rx_rst_fsm_ready_i <= '1';\r
+ end if;\r
+\r
+ tx_rst_fsm_ready_i <= '0';\r
+ if tx_rst_fsm_state_i = x"5" then\r
+ tx_rst_fsm_ready_i <= '1';\r
+ end if;\r
+ end process;\r
+ \r
+ THE_RX_GEAR: CBMNET_PHY_RX_GEAR \r
+ generic map (\r
+ IS_SYNC_SLAVE => IS_SYNC_SLAVE\r
+ ) port map (\r
+ -- SERDES PORT\r
+ CLK_250_IN => rclk_250_i, -- in std_logic;\r
+ PCS_READY_IN => rx_rst_fsm_ready_i, -- in std_logic;\r
+ SERDES_RESET_OUT=> gear_to_fsm_rst_i, -- out std_logic;\r
+ DATA_IN => rx_data_from_serdes_i, -- in std_logic_vector( 8 downto 0);\r
+\r
+ -- RM PORT\r
+ RM_RESET_IN => rm_rx_to_gear_reset_i, -- in std_logic;\r
+ CLK_125_OUT => rclk_125_i, -- out std_logic;\r
+ RESET_OUT => gear_to_rm_rst_i, -- out std_logic;\r
+ DATA_OUT => rx_data_from_gear_i, -- out std_logic_vector(17 downto 0)\r
+ \r
+ DEBUG_OUT => rx_gear_debug_i\r
+ );\r
+ \r
+ process is \r
+ variable state_v : std_logic;\r
+ variable data_buf_v : std_logic_vector(8 downto 0);\r
+ begin\r
+ wait until rising_edge(rclk_250_i);\r
+ \r
+ if state_v = '0' then\r
+ rx_data_debug_i(7 downto 0) <= data_buf_v(7 downto 0);\r
+ rx_data_debug_i(16) <= data_buf_v(8);\r
+ else\r
+ rx_data_debug_i(15 downto 8) <= data_buf_v(7 downto 0);\r
+ rx_data_debug_i(17) <= data_buf_v(8);\r
+ end if;\r
+ \r
+ data_buf_v := data_buf_v;\r
+ state_v := not state_v;\r
+ end process;\r
+ \r
+ rx_data_i <= rx_data_from_gear_i when rising_edge(clk_125_local) or (IS_SYNC_SLAVE = c_YES);\r
+ \r
+ THE_TX_GEAR: CBMNET_PHY_TX_GEAR\r
+ generic map (IS_SYNC_SLAVE => IS_SYNC_SLAVE)\r
+ port map (\r
+ CLK_250_IN => clk_tx_full_i, -- in std_logic;\r
+ CLK_125_IN => clk_serdes_tx_ref, -- in std_logic;\r
+ CLK_125_OUT => clk_tx_half_i,\r
+ \r
+ RESET_IN => tx_gear_reset_i, -- in std_logic;\r
+ ALLOW_RELOCK_IN => tx_gear_allow_relock_i, -- in std_logic\r
+ \r
+ TX_READY_OUT => tx_gear_ready_i,\r
+ \r
+ DATA_IN => tx_data_i, -- in std_logic_vector(17 downto 0)\r
+ \r
+ DATA_OUT => tx_data_to_serdes_i -- out std_logic_vector(8 downto 0);\r
+ );\r
+ tx_gear_reset_i <= not tx_rst_fsm_ready_i;\r
+ tx_gear_allow_relock_i <= ((not tx_rst_fsm_ready_i) and not CTRL_OP(1)) or CTRL_OP(2);\r
+ \r
+ process is\r
+ begin\r
+ wait until rising_edge(clk_tx_full_i);\r
+ \r
+ tx_data_debug_state_i <= not tx_data_debug_state_i;\r
+ \r
+ if tx_data_debug_state_i = '1' then\r
+ tx_data_debug_i(7 downto 0) <= tx_data_to_serdes_i(7 downto 0);\r
+ tx_data_debug_i(16) <= tx_data_to_serdes_i(8);\r
+ \r
+ else\r
+ tx_data_debug_i(15 downto 8) <= tx_data_to_serdes_i(7 downto 0);\r
+ tx_data_debug_i(17) <= tx_data_to_serdes_i(8);\r
+ \r
+ end if;\r
+ end process;\r
+ \r
+ ------------------------------------------------- \r
+ -- CBMNet Ready Modules\r
+ ------------------------------------------------- \r
+ THE_RX_READY: cn_rx_pcs_wrapper\r
+ generic map (\r
+ SIMULATION => 0,\r
+ USE_BS => 0,\r
+ SYNC_SIGNALS => 1,\r
+ INCL_8B10B_DEC => 0\r
+ )\r
+ port map ( \r
+ rx_clk => clk_125_i, -- in std_logic;\r
+ res_n_rx => gear_to_rm_n_rst_i, -- in std_logic;\r
+ rxpcs_reinit => rm_tx_to_rx_reinit_i, -- in std_logic; -- Reinit RXPCS \r
+ rxdata_in(17 downto 0) => rx_data_i,\r
+ rxdata_in(19 downto 18) => "00",\r
+ reset_rx_cdr => rm_rx_to_gear_reset_i, -- out std_logic; -- Reset RX CDR to align\r
+ rxpcs_almost_ready => rm_rx_almost_ready_i, -- out std_logic; -- Ready1 detected, only waiting for break\r
+ rxpcs_ready => rm_rx_rxpcs_ready_i, -- out std_logic; -- RXPCS initialization done\r
+ see_reinit => rm_rx_see_reinit, -- out std_logic; -- Initialization pattern detected although ready\r
+ bs_position => open, -- out std_logic_vector(4 downto 0); -- Number of bit-shifts necessary for word-alignment\r
+ rxdata_out => rm_rx_data_buf_i, -- out std_logic_vector(17 downto 0);\r
+ ebtb_detect => rm_rx_ebtb_detect_i, -- out std_logic; -- Depends on the FSM state, alignment done\r
+ \r
+ --diagnostics\r
+ ebtb_code_err_cntr_clr => rm_rx_ebtb_code_err_cntr_clr_i, -- in std_logic;\r
+ ebtb_disp_err_cntr_clr => rm_rx_ebtb_disp_err_cntr_clr_i, -- in std_logic;\r
+ ebtb_code_err_cntr => rm_rx_ebtb_code_err_cntr_i, -- out std_logic_vector(15 downto 0); -- Counts for code errors if ebtb_detect is true\r
+ ebtb_disp_err_cntr => rm_rx_ebtb_disp_err_cntr_i, -- out std_logic_vector(15 downto 0); -- Counts for disparity errors if ebtb_detect is true\r
+ ebtb_code_err_cntr_flag => rm_rx_ebtb_code_err_cntr_flag_i,-- out std_logic;\r
+ ebtb_disp_err_cntr_flag => rm_rx_ebtb_disp_err_cntr_flag_i -- out std_logic\r
+ );\r
+\r
+ PHY_RXDATA_OUT <= rm_rx_data_buf_i(15 downto 0);\r
+ PHY_RXDATA_K_OUT <= rm_rx_data_buf_i(1 downto 0);\r
+ gear_to_rm_n_rst_i <= not gear_to_rm_rst_i when rising_edge(clk_125_i);\r
+ \r
+ \r
+ THE_TX_READY: cn_tx_pcs_wrapper \r
+ generic map (\r
+-- READY_CHAR0 => , --std_logic_vector( 7 downto 0) := K284;\r
+-- READY_CHAR1 => , --std_logic_vector( 7 downto 0) := K287;\r
+-- ALIGN_CHAR => , --std_logic_vector( 7 downto 0) := K285;\r
+-- PMA_INIT_CHAR => , --std_logic_vector(19 downto 0) := x"aaaaa";\r
+ \r
+ REVERSE_OUTPUT => 0, --integer range 0 to 1 := 1;\r
+ LINK_MASTER => 0, --integer range 0 to 1 := 1;\r
+ SYNC_SIGNALS => 1, --integer range 0 to 1 := 1;\r
+\r
+ INCL_8B10B_ENC => 0 --integer range 0 to 1 := 1\r
+ ) port map (\r
+ tx_clk => clk_125_i, --in std_logic;\r
+ res_n_tx => tx_rst_fsm_ready_buf_i, --in std_logic;\r
+ pcs_restart => CTRL_OP(14), --in std_logic; -- restart pcs layer\r
+ pma_ready => tx_gear_ready_i, --in std_logic;\r
+ ebtb_detect => rm_rx_ebtb_detect_i, --in std_logic; -- alignment done and valid 8b10b stream detected\r
+ see_reinit => rm_rx_see_reinit, --in std_logic;\r
+ rxpcs_almost_ready => rm_rx_almost_ready_i, --in std_logic;\r
+ txdata_in(15 downto 0) => PHY_TXDATA_IN, --in std_logic_vector(17 downto 0);\r
+ txdata_in(17 downto 16)=> PHY_TXDATA_K_IN,\r
+ \r
+ txpcs_ready => rm_tx_ready_i, --out std_logic;\r
+ link_lost => rm_tx_link_lost_i, --out std_logic;\r
+ reset_out => open, --out std_logic;\r
+ rxpcs_reinit => rm_tx_to_rx_reinit_i, --out std_logic; -- Reinit the RXPCS FSM\r
+ txdata_out => tx_data_i, --out std_logic_vector(17 downto 0); -- tx data to transceiver\r
+ txdata_out_coded => open, --out std_logic_vector(19 downto 0); -- tx data to transceiver already 8b10b coded\r
+ \r
+ --diagnostics\r
+ pcs_startup_cntr_clr => rm_tx_pcs_startup_cntr_clr, --in std_logic;\r
+ pcs_startup_cntr => rm_tx_pcs_startup_cntr, --out std_logic_vector(15 downto 0); -- Counts for link startups\r
+ pcs_startup_cntr_flag => rm_tx_pcs_startup_cntr_flag --out std_logic;\r
+ );\r
+\r
+ \r
+ rm_rx_status_for_tx_i <= rm_rx_almost_ready_i or rm_rx_ready_i;\r
+ \r
+ -- clock domain crossing from clk_125_local to clk_125_i\r
+ PROC_SYNC_FSM_READY: process is begin\r
+ wait until rising_edge(clk_125_i);\r
+ \r
+ if IS_SYNC_SLAVE = c_YES then\r
+ tx_rst_fsm_ready_buf_i <= tx_rst_fsm_ready_i and not gear_to_rm_rst_i;\r
+ \r
+ else\r
+ tx_rst_fsm_ready_buf_i <= tx_rst_fsm_ready_i;\r
+ \r
+ end if;\r
+ end process;\r
+ \r
+ serdes_ready_i <= rm_tx_ready_i and rm_rx_rxpcs_ready_i when rising_edge(clk_125_i);\r
+ led_ok_i <= serdes_ready_i;\r
+ SERDES_ready <= serdes_ready_i;\r
+ \r
+ ------------------------------------------------- \r
+ -- SCI\r
+ ------------------------------------------------- \r
+ -- gives access to serdes config port from slow control and reads word alignment every ~ 40 us\r
+ -- upon retrival the barrel shifter is checked and - if necessary - a serdes reset is issued\r
+ PROC_SCI_CTRL: process \r
+ variable cnt : integer range 0 to 4 := 0;\r
+ begin\r
+ wait until rising_edge(clk_125_local);\r
+ \r
+ case sci_state is\r
+ when IDLE =>\r
+ sci_ch_i <= x"0";\r
+ sci_qd_i <= '0';\r
+ sci_reg_i <= '0';\r
+ sci_read_i <= '0';\r
+ sci_write_i <= '0';\r
+ sci_timer <= sci_timer + 1;\r
+ if sci_timer(sci_timer'left) = '1' then\r
+ sci_timer <= (others => '0');\r
+ sci_state <= GET_WA;\r
+ end if; \r
+\r
+ when GET_WA =>\r
+ if cnt = 4 then\r
+ cnt := 0;\r
+ sci_state <= IDLE;\r
+ \r
+ else\r
+ sci_state <= GET_WA_WAIT;\r
+ sci_addr_i <= '0' & x"22";\r
+ sci_ch_i <= x"0";\r
+ sci_ch_i(cnt) <= '1';\r
+ sci_read_i <= '1';\r
+ end if;\r
+ \r
+ when GET_WA_WAIT =>\r
+ sci_state <= GET_WA_WAIT2;\r
+ \r
+ when GET_WA_WAIT2 =>\r
+ sci_state <= GET_WA_FINISH;\r
+ \r
+ when GET_WA_FINISH =>\r
+ wa_position_i(cnt*4+3 downto cnt*4) <= sci_data_out_i(3 downto 0);\r
+ sci_state <= GET_WA; \r
+ cnt := cnt + 1;\r
+ \r
+ end case;\r
+ end process;\r
+ \r
+ process is begin\r
+ wait until rising_edge(clk_125_local);\r
+ barrel_shifter_misaligned_i <= '0';\r
+ if lsm_status_i = '1' and wa_position_i(3 downto 0) /= x"0" then\r
+ barrel_shifter_misaligned_i <= '1';\r
+ end if;\r
+ end process;\r
+ \r
+ \r
+ -- RX/TX leds are on as soon as the correspondent pll is locked and data\r
+ -- other than the idle word is transmitted\r
+ PROC_LEDS: process is\r
+ begin\r
+ wait until rising_edge(CLK);\r
+\r
+ led_rx_i <= not gear_to_rm_rst_i;\r
+ led_tx_i <= tx_rst_fsm_ready_i;\r
+ \r
+ if (led_timer_i(20) = '1') or (rx_data_i(17 downto 16) = "10" and rx_data_i(15 downto 0) = x"fcce") then\r
+ led_rx_i <= '0';\r
+ end if;\r
+ \r
+ if (led_timer_i(20) = '1') or (tx_data_i(17 downto 16) = "10" and tx_data_i(15 downto 0) = x"fcce") then\r
+ led_tx_i <= '0';\r
+ end if;\r
+\r
+ led_timer_i <= led_timer_i + 1 ;\r
+ if led_timer_i(20) = '1' then\r
+ led_timer_i <= (others => '0');\r
+ last_led_rx_i <= led_rx_i ;\r
+ last_led_tx_i <= led_tx_i;\r
+ end if; \r
+ end process;\r
+ \r
+ LED_OK_OUT <= led_ok_i;\r
+ LED_RX_OUT <= led_rx_i;\r
+ LED_TX_OUT <= led_tx_i;\r
+ \r
+ -- Produce 1us reset pulse for external logic\r
+ PROC_CLK_RESET: process is\r
+ variable counter : unsigned(8 downto 0) := (others => '0');\r
+ begin\r
+ wait until rising_edge(rclk_125_i);\r
+ CLK_RX_RESET_OUT <= '1';\r
+ \r
+ if serdes_ready_i = '0' then\r
+ counter := (others => '0');\r
+ \r
+ elsif counter(counter'high) = '0' then\r
+ counter := counter + 1;\r
+ \r
+ else\r
+ CLK_RX_RESET_OUT <= '0';\r
+ \r
+ end if;\r
+ end process;\r
+\r
+ \r
+ GEN_DEBUG: if INCL_DEBUG_AIDS = c_YES generate\r
+ proc_stat: process is\r
+ variable last_rx_serdes_rst_i : std_logic;\r
+ begin\r
+ wait until rising_edge(clk_125_local);\r
+ \r
+ if rst_n_i = '0' then\r
+ stat_reconnect_counter_i <= (others => '0');\r
+ stat_last_reconnect_duration_i <= (others => '0');\r
+ stat_wa_int_i <= (others => '0');\r
+ else\r
+ if rx_serdes_rst_i = '1' and last_rx_serdes_rst_i = '0' then\r
+ stat_reconnect_counter_i <= stat_reconnect_counter_i + TO_UNSIGNED(1,1);\r
+ end if;\r
+ \r
+ if serdes_ready_i = '0' then\r
+ stat_last_reconnect_duration_i <= stat_last_reconnect_duration_i + TO_UNSIGNED(1,1);\r
+ end if;\r
+ \r
+ stat_wa_int_i <= stat_wa_int_i or wa_position_i;\r
+ end if;\r
+ \r
+ last_rx_serdes_rst_i := rx_serdes_rst_i;\r
+ end process;\r
+ \r
+ PROC_SENSE_RX_DLM0: process is \r
+ variable detected_first_word_v : std_logic := '0';\r
+ begin\r
+ wait until rising_edge(rclk_250_i);\r
+ low_level_rx_see_dlm0 <= '0';\r
+ \r
+ if detected_first_word_v = '0' then\r
+ if rx_data_from_serdes_i = "1" & x"fb" then\r
+ detected_first_word_v := '1';\r
+ end if;\r
+ \r
+ else\r
+ detected_first_word_v := '0';\r
+ if rx_data_from_serdes_i = "001101010" then\r
+ low_level_rx_see_dlm0 <= '1';\r
+ end if;\r
+ \r
+ end if;\r
+ end process;\r
+ \r
+ PROC_SENSE_TX_DLM0: process is \r
+ variable detected_first_word_v : std_logic := '0';\r
+ begin\r
+ wait until rising_edge(clk_tx_full_i);\r
+ low_level_tx_see_dlm0 <= '0';\r
+ \r
+ if detected_first_word_v = '0' then\r
+ if tx_data_to_serdes_i = "1" & x"fb" then\r
+ detected_first_word_v := '1';\r
+ end if;\r
+ \r
+ else\r
+ detected_first_word_v := '0';\r
+ if tx_data_to_serdes_i = "001101010" then\r
+ low_level_tx_see_dlm0 <= '1';\r
+ end if;\r
+ \r
+ end if;\r
+ end process;\r
+ \r
+ PROC_SENSE_TX_DLM125: process is\r
+ begin\r
+ wait until rising_edge(clk_125_i);\r
+ \r
+ low_level_tx_see_dlm0_125 <= '0';\r
+ if tx_data_i = "10" & x"fb6a" then\r
+ low_level_tx_see_dlm0_125 <= '1';\r
+ end if;\r
end process;\r
\r
PROC_SENSE_DLMS: process begin\r
elsif rx_data_i(17) = '1' and rx_data_i(15 downto 8) = K277 then\r
stat_dlm_counter_i <= stat_dlm_counter_i + TO_UNSIGNED(1,1);\r
end if;\r
- end process;
-
--- DEBUG_OUT_BEGIN
- DEBUG_OUT(19 downto 0) <= "00" & tx_data_i(17 downto 0);
-
- DEBUG_OUT(23 downto 20) <= "0" & tx_pll_lol_i & rx_los_low_i & rx_cdr_lol_i;
-
- DEBUG_OUT(27 downto 24) <= gear_to_fsm_rst_i & barrel_shifter_misaligned_i & SD_PRSNT_N_IN & SD_LOS_IN;
- DEBUG_OUT(31 downto 28) <= rst_qd_i & rx_serdes_rst_i & tx_pcs_rst_i & rx_pcs_rst_i;
-
- DEBUG_OUT( 51 downto 32) <= "00" & rx_data_i(17 downto 0);
- DEBUG_OUT( 59 downto 52) <= rx_rst_fsm_state_i(3 downto 0) & tx_rst_fsm_state_i(3 downto 0);
-
- DEBUG_OUT( 63 downto 60) <= serdes_ready_i & rm_rx_ready_i & rm_tx_ready_i & rm_tx_almost_ready_i;
-
- DEBUG_OUT( 79 downto 64) <= rx_gear_debug_i(15 downto 0);
- DEBUG_OUT( 95 downto 80) <= tx_gear_debug_i(15 downto 0);
-
- DEBUG_OUT( 99 downto 96) <= rm_rx_almost_ready_i & rm_rx_see_ready0_i & rm_rx_saw_ready1_i & rm_rx_valid_char_i;
- DEBUG_OUT(103 downto 100) <= wa_position_i(3 downto 0);
- DEBUG_OUT(107 downto 104) <= "00" & rm_rx_to_gear_reset_i & gear_to_rm_rst_i;
-
- DEBUG_OUT(127 downto 108) <= "00" & tx_data_debug_i(17 downto 0);
- DEBUG_OUT(147 downto 128) <= "00" & rx_data_debug_i(17 downto 0) when rising_edge(clk_125_local);
- DEBUG_OUT(179 downto 148) <= stat_last_reconnect_duration_i(31 downto 0);
- DEBUG_OUT(195 downto 180) <= stat_reconnect_counter_i(15 downto 0);
- DEBUG_OUT(211 downto 196) <= stat_wa_int_i(15 downto 0);\r
- DEBUG_OUT(227 downto 212) <= stat_dlm_counter_i(15 downto 0);
- --DEBUG_OUT(255 downto 170) <= (others => '0');
-
--- DEBUG_OUT_END
-
- -- STAT_OP REGISTER
- STAT_OP(6 downto 0) <= tx_data_to_serdes_i(6 downto 0);
- STAT_OP( 7) <= low_level_rx_see_dlm0;
- STAT_OP( 8) <= clk_125_local;
- STAT_OP( 9) <= rclk_250_i;
- STAT_OP(10) <= rclk_125_i;
- STAT_OP(11) <= clk_tx_full_i;
- STAT_OP(12) <= clk_tx_half_i;
- STAT_OP(13) <= low_level_tx_see_dlm0;
- end generate;
+ end process;\r
+\r
+-- DEBUG_OUT_BEGIN \r
+ DEBUG_OUT(19 downto 0) <= "00" & tx_data_i(17 downto 0);\r
+ \r
+ DEBUG_OUT(23 downto 20) <= "0" & tx_pll_lol_i & rx_los_low_i & rx_cdr_lol_i;\r
+\r
+ DEBUG_OUT(27 downto 24) <= gear_to_fsm_rst_i & barrel_shifter_misaligned_i & SD_PRSNT_N_IN & SD_LOS_IN;\r
+ DEBUG_OUT(31 downto 28) <= rst_qd_i & rx_serdes_rst_i & tx_pcs_rst_i & rx_pcs_rst_i;\r
+ \r
+ DEBUG_OUT( 51 downto 32) <= "00" & rx_data_i(17 downto 0);\r
+ DEBUG_OUT( 59 downto 52) <= rx_rst_fsm_state_i(3 downto 0) & tx_rst_fsm_state_i(3 downto 0);\r
+ \r
+ DEBUG_OUT( 63 downto 60) <= serdes_ready_i & rm_rx_ready_i & rm_tx_ready_i & rm_tx_almost_ready_i;\r
+ \r
+ DEBUG_OUT( 79 downto 64) <= rx_gear_debug_i(15 downto 0);\r
+ DEBUG_OUT( 95 downto 80) <= tx_gear_debug_i(15 downto 0);\r
+ \r
+ DEBUG_OUT( 99 downto 96) <= rm_rx_almost_ready_i & rm_rx_rxpcs_ready_i & rm_rx_see_reinit & rm_rx_ebtb_detect_i;\r
+ DEBUG_OUT(103 downto 100) <= wa_position_i(3 downto 0);\r
+ DEBUG_OUT(107 downto 104) <= "00" & rm_rx_to_gear_reset_i & gear_to_rm_rst_i;\r
+ \r
+ DEBUG_OUT(127 downto 108) <= "00" & tx_data_debug_i(17 downto 0);\r
+ DEBUG_OUT(147 downto 128) <= "00" & rx_data_debug_i(17 downto 0) when rising_edge(clk_125_local);\r
+ DEBUG_OUT(179 downto 148) <= stat_last_reconnect_duration_i(31 downto 0);\r
+ DEBUG_OUT(195 downto 180) <= stat_reconnect_counter_i(15 downto 0);\r
+ DEBUG_OUT(211 downto 196) <= stat_dlm_counter_i(15 downto 0);\r
+ DEBUG_OUT(243 downto 212) <= rm_rx_ebtb_code_err_cntr_i(15 downto 0) & rm_rx_ebtb_disp_err_cntr_i(15 downto 0);\r
+ --DEBUG_OUT(255 downto 170) <= (others => '0');\r
+ \r
+-- DEBUG_OUT_END\r
+\r
+ -- STAT_OP REGISTER\r
+ STAT_OP(6 downto 0) <= tx_data_to_serdes_i(6 downto 0);\r
+ STAT_OP( 7) <= low_level_rx_see_dlm0;\r
+ STAT_OP( 8) <= clk_125_local;\r
+ STAT_OP( 9) <= rclk_250_i;\r
+ STAT_OP(10) <= rclk_125_i;\r
+ STAT_OP(11) <= clk_tx_full_i;\r
+ STAT_OP(12) <= clk_tx_half_i;\r
+ STAT_OP(13) <= low_level_tx_see_dlm0;\r
+ end generate;\r
end architecture;
\ No newline at end of file