From: Manuel Penschuck Date: Fri, 13 Jun 2014 07:25:03 +0000 (+0200) Subject: Synthesisable with new CBMNet, however initialisation of link fails X-Git-Url: https://jspc29.x-matter.uni-frankfurt.de/git/?a=commitdiff_plain;h=71f9dfdd7a8d6a56db98d029138ff2c6da7fa8b9;p=trb3.git Synthesisable with new CBMNet, however initialisation of link fails --- diff --git a/cbmnet/code/cbmnet_interface_pkg.vhd b/cbmnet/code/cbmnet_interface_pkg.vhd index 5ec8f55..7931d1f 100644 --- a/cbmnet/code/cbmnet_interface_pkg.vhd +++ b/cbmnet/code/cbmnet_interface_pkg.vhd @@ -22,61 +22,77 @@ package cbmnet_interface_pkg is constant CBMNET_READY_CHAR1 : std_logic_vector(7 downto 0) := K287; constant CBMNET_ALIGN_CHAR : std_logic_vector(7 downto 0) := K285; - component gtp_rx_ready_module is + component cn_rx_pcs_wrapper is generic ( - READY_CHAR0 : std_logic_vector(7 downto 0) := K284; - READY_CHAR1 : std_logic_vector(7 downto 0) := K287; - ALIGN_CHAR : std_logic_vector(7 downto 0) := K285; - DATAWIDTH : integer := 16; - WORDS : integer := 2; --DATAWIDTH/8; + SIMULATION : integer range 0 to 1 := 0; + READY_CHAR0 : std_logic_vector(7 downto 0) := K284; + READY_CHAR1 : std_logic_vector(7 downto 0) := K287; + ALIGN_CHAR : std_logic_vector(7 downto 0) := K285; + + USE_BS : integer range 0 to 1 := 1; -- Use barrel-shifter, otherwise reset rx CDR + SYNC_SIGNALS : integer range 0 to 1 := 1; -- Sync input signals to rx clock domain + INCL_8B10B_DEC : integer range 0 to 1 := 1 ); - port ( - clk : in std_logic; - res_n : in std_logic; - ready_MGT2RM : in std_logic; - rxdata_in : in std_logic_vector((WORDS*10)-1 downto 0); - - tx_ready : in std_logic; - tx_almost_ready : in std_logic; - - ready_RM2LP : out std_logic; - almost_ready_OUT : out std_logic; - rxdata_out : out std_logic_vector((DATAWIDTH-1) downto 0); - charisk_out : out std_logic_vector((WORDS-1) downto 0); - see_ready0 : out std_logic; - saw_ready1 : out std_logic; - valid_char : out std_logic; - reset_rx : out std_logic + port ( + rx_clk : in std_logic; + res_n_rx : in std_logic; + rxpcs_reinit : in std_logic; -- Reinit RXPCS + rxdata_in : in std_logic_vector(19 downto 0); + reset_rx_cdr : out std_logic; -- Reset RX CDR to align + rxpcs_almost_ready : out std_logic; -- Ready1 detected, only waiting for break + rxpcs_ready : out std_logic; -- RXPCS initialization done + see_reinit : out std_logic; -- Initialization pattern detected although ready + bs_position : out std_logic_vector(4 downto 0); -- Number of bit-shifts necessary for word-alignment + rxdata_out : out std_logic_vector(17 downto 0); + ebtb_detect : out std_logic; -- Depends on the FSM state, alignment done + + --diagnostics + ebtb_code_err_cntr_clr : in std_logic; + ebtb_disp_err_cntr_clr : in std_logic; + ebtb_code_err_cntr : out std_logic_vector(15 downto 0); -- Counts for code errors if ebtb_detect is true + ebtb_disp_err_cntr : out std_logic_vector(15 downto 0); -- Counts for disparity errors if ebtb_detect is true + ebtb_code_err_cntr_flag : out std_logic; + ebtb_disp_err_cntr_flag : out std_logic ); end component; - component gtp_tx_ready_module is + + component cn_tx_pcs_wrapper is generic ( --- READY_CHAR0 : std_logic_vector(7 downto 0) := K284; --- READY_CHAR1 : std_logic_vector(7 downto 0) := K287; --- ALIGN_CHAR : std_logic_vector(7 downto 0) := K285; - DATAWIDTH : integer := 16; - WORDS :integer := 2 --DATAWIDTH/8; + READY_CHAR0 : std_logic_vector( 7 downto 0) := K284; + READY_CHAR1 : std_logic_vector( 7 downto 0) := K287; + ALIGN_CHAR : std_logic_vector( 7 downto 0) := K285; + PMA_INIT_CHAR : std_logic_vector(19 downto 0) := x"aaaaa"; + + REVERSE_OUTPUT : integer range 0 to 1 := 1; + LINK_MASTER : integer range 0 to 1 := 1; + SYNC_SIGNALS : integer range 0 to 1 := 1; + + INCL_8B10B_ENC : integer range 0 to 1 := 1 ); port ( - clk : in std_logic; - res_n : in std_logic; - restart_link : in std_logic; - ready_MGT2RM : in std_logic; - txdata_in : in std_logic_vector((DATAWIDTH-1) downto 0); - txcharisk_in : in std_logic_vector((WORDS-1) downto 0); - - see_ready0 : in std_logic; - saw_ready1 : in std_logic; - valid_char : in std_logic; - rx_rm_ready : in std_logic; - - ready_RM2LP : out std_logic; - txdata_out : out std_logic_vector((WORDS*9)-1 downto 0); - almost_ready : out std_logic; - gt11_reinit : out std_logic + tx_clk : in std_logic; + res_n_tx : in std_logic; + pcs_restart : in std_logic; -- restart pcs layer + pma_ready : in std_logic; + ebtb_detect : in std_logic; -- alignment done and valid 8b10b stream detected + see_reinit : in std_logic; + rxpcs_almost_ready : in std_logic; + txdata_in : in std_logic_vector(17 downto 0); + + txpcs_ready : out std_logic; + link_lost : out std_logic; + reset_out : out std_logic; + rxpcs_reinit : out std_logic; -- Reinit the RXPCS FSM + txdata_out : out std_logic_vector(17 downto 0); -- tx data to transceiver + txdata_out_coded : out std_logic_vector(19 downto 0); -- tx data to transceiver already 8b10b coded + + --diagnostics + pcs_startup_cntr_clr : in std_logic; + pcs_startup_cntr : out std_logic_vector(15 downto 0); -- Counts for link startups + pcs_startup_cntr_flag : out std_logic ); end component; @@ -123,7 +139,51 @@ package cbmnet_interface_pkg is link_activeovr : in std_logic; -- Overrides; set 0 by default link_readyovr : in std_logic; - SERDES_ready : in std_logic -- signalize when PHY ready + SERDES_ready : in std_logic; -- signalize when PHY ready + + -- diagnostics Lane0 + crc_error_cntr_flag_0 : out std_logic; + retrans_cntr_flag_0 : out std_logic; + retrans_error_cntr_flag_0 : out std_logic; + crc_error_cntr_0 : out std_logic_vector(15 downto 0); + retrans_cntr_0 : out std_logic_vector(15 downto 0); + retrans_error_cntr_0 : out std_logic_vector(15 downto 0); + crc_error_cntr_clr_0 : in std_logic; + retrans_cntr_clr_0 : in std_logic; + retrans_error_cntr_clr_0 : in std_logic; + + -- diagnostics Lane1 + crc_error_cntr_flag_1 : out std_logic; + retrans_cntr_flag_1 : out std_logic; + retrans_error_cntr_flag_1 : out std_logic; + crc_error_cntr_1 : out std_logic_vector(15 downto 0); + retrans_cntr_1 : out std_logic_vector(15 downto 0); + retrans_error_cntr_1 : out std_logic_vector(15 downto 0); + crc_error_cntr_clr_1 : in std_logic; + retrans_cntr_clr_1 : in std_logic; + retrans_error_cntr_clr_1 : in std_logic; + + -- diagnostics Lane2 + crc_error_cntr_flag_2 : out std_logic; + retrans_cntr_flag_2 : out std_logic; + retrans_error_cntr_flag_2 : out std_logic; + crc_error_cntr_2 : out std_logic_vector(15 downto 0); + retrans_cntr_2 : out std_logic_vector(15 downto 0); + retrans_error_cntr_2 : out std_logic_vector(15 downto 0); + crc_error_cntr_clr_2 : in std_logic; + retrans_cntr_clr_2 : in std_logic; + retrans_error_cntr_clr_2 : in std_logic; + + -- diagnostics Lane3 + crc_error_cntr_flag_3 : out std_logic; + retrans_cntr_flag_3 : out std_logic; + retrans_error_cntr_flag_3 : out std_logic; + crc_error_cntr_3 : out std_logic_vector(15 downto 0); + retrans_cntr_3 : out std_logic_vector(15 downto 0); + retrans_error_cntr_3 : out std_logic_vector(15 downto 0); + crc_error_cntr_clr_3 : in std_logic; + retrans_cntr_clr_3 : in std_logic; + retrans_error_cntr_clr_3 : in std_logic ); end component; diff --git a/cbmnet/code/cbmnet_phy_ecp3.vhd b/cbmnet/code/cbmnet_phy_ecp3.vhd index 346ea87..b08328b 100755 --- a/cbmnet/code/cbmnet_phy_ecp3.vhd +++ b/cbmnet/code/cbmnet_phy_ecp3.vhd @@ -1,671 +1,724 @@ ---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 + +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 tx_gear_ready_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; + + signal rm_rx_data_buf_i : std_logic_vector(17 downto 0); + + signal rm_rx_ebtb_code_err_cntr_clr_i : std_logic; + signal rm_rx_ebtb_disp_err_cntr_clr_i : std_logic; + signal rm_rx_ebtb_code_err_cntr_i : std_logic_vector(15 downto 0); + signal rm_rx_ebtb_disp_err_cntr_i : std_logic_vector(15 downto 0); + signal rm_rx_ebtb_code_err_cntr_flag_i : std_logic; + signal rm_rx_ebtb_disp_err_cntr_flag_i : std_logic; + + signal rm_tx_to_rx_reinit_i : std_logic; + + signal rm_rx_see_reinit : std_logic; + signal rm_rx_ebtb_detect_i : std_logic; + signal rm_tx_link_lost_i : std_logic; + + signal rm_tx_pcs_startup_cntr_clr : std_logic; + signal rm_tx_pcs_startup_cntr : std_logic_vector(15 downto 0); -- Counts for link startups + signal rm_tx_pcs_startup_cntr_flag : std_logic; + + signal rm_rx_rxpcs_ready_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; signal low_level_tx_see_dlm0_125 : std_logic; - 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); +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; + variable data_buf_v : std_logic_vector(8 downto 0); + begin + wait until rising_edge(rclk_250_i); + + if state_v = '0' then + rx_data_debug_i(7 downto 0) <= data_buf_v(7 downto 0); + rx_data_debug_i(16) <= data_buf_v(8); + else + rx_data_debug_i(15 downto 8) <= data_buf_v(7 downto 0); + rx_data_debug_i(17) <= data_buf_v(8); + end if; + + data_buf_v := data_buf_v; + 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 + + TX_READY_OUT => tx_gear_ready_i, + + 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: cn_rx_pcs_wrapper + generic map ( + SIMULATION => 0, + USE_BS => 0, + SYNC_SIGNALS => 1, + INCL_8B10B_DEC => 0 + ) + port map ( + rx_clk => clk_125_i, -- in std_logic; + res_n_rx => gear_to_rm_n_rst_i, -- in std_logic; + rxpcs_reinit => rm_tx_to_rx_reinit_i, -- in std_logic; -- Reinit RXPCS + rxdata_in(17 downto 0) => rx_data_i, + rxdata_in(19 downto 18) => "00", + reset_rx_cdr => rm_rx_to_gear_reset_i, -- out std_logic; -- Reset RX CDR to align + rxpcs_almost_ready => rm_rx_almost_ready_i, -- out std_logic; -- Ready1 detected, only waiting for break + rxpcs_ready => rm_rx_rxpcs_ready_i, -- out std_logic; -- RXPCS initialization done + see_reinit => rm_rx_see_reinit, -- out std_logic; -- Initialization pattern detected although ready + bs_position => open, -- out std_logic_vector(4 downto 0); -- Number of bit-shifts necessary for word-alignment + rxdata_out => rm_rx_data_buf_i, -- out std_logic_vector(17 downto 0); + ebtb_detect => rm_rx_ebtb_detect_i, -- out std_logic; -- Depends on the FSM state, alignment done + + --diagnostics + ebtb_code_err_cntr_clr => rm_rx_ebtb_code_err_cntr_clr_i, -- in std_logic; + ebtb_disp_err_cntr_clr => rm_rx_ebtb_disp_err_cntr_clr_i, -- in std_logic; + 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 + 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 + ebtb_code_err_cntr_flag => rm_rx_ebtb_code_err_cntr_flag_i,-- out std_logic; + ebtb_disp_err_cntr_flag => rm_rx_ebtb_disp_err_cntr_flag_i -- out std_logic + ); + + PHY_RXDATA_OUT <= rm_rx_data_buf_i(15 downto 0); + PHY_RXDATA_K_OUT <= rm_rx_data_buf_i(1 downto 0); + gear_to_rm_n_rst_i <= not gear_to_rm_rst_i when rising_edge(clk_125_i); + + + THE_TX_READY: cn_tx_pcs_wrapper + generic map ( +-- READY_CHAR0 => , --std_logic_vector( 7 downto 0) := K284; +-- READY_CHAR1 => , --std_logic_vector( 7 downto 0) := K287; +-- ALIGN_CHAR => , --std_logic_vector( 7 downto 0) := K285; +-- PMA_INIT_CHAR => , --std_logic_vector(19 downto 0) := x"aaaaa"; + + REVERSE_OUTPUT => 0, --integer range 0 to 1 := 1; + LINK_MASTER => 0, --integer range 0 to 1 := 1; + SYNC_SIGNALS => 1, --integer range 0 to 1 := 1; + + INCL_8B10B_ENC => 0 --integer range 0 to 1 := 1 + ) port map ( + tx_clk => clk_125_i, --in std_logic; + res_n_tx => tx_rst_fsm_ready_buf_i, --in std_logic; + pcs_restart => CTRL_OP(14), --in std_logic; -- restart pcs layer + pma_ready => tx_gear_ready_i, --in std_logic; + ebtb_detect => rm_rx_ebtb_detect_i, --in std_logic; -- alignment done and valid 8b10b stream detected + see_reinit => rm_rx_see_reinit, --in std_logic; + rxpcs_almost_ready => rm_rx_almost_ready_i, --in std_logic; + txdata_in(15 downto 0) => PHY_TXDATA_IN, --in std_logic_vector(17 downto 0); + txdata_in(17 downto 16)=> PHY_TXDATA_K_IN, + + txpcs_ready => rm_tx_ready_i, --out std_logic; + link_lost => rm_tx_link_lost_i, --out std_logic; + reset_out => open, --out std_logic; + rxpcs_reinit => rm_tx_to_rx_reinit_i, --out std_logic; -- Reinit the RXPCS FSM + txdata_out => tx_data_i, --out std_logic_vector(17 downto 0); -- tx data to transceiver + txdata_out_coded => open, --out std_logic_vector(19 downto 0); -- tx data to transceiver already 8b10b coded + + --diagnostics + pcs_startup_cntr_clr => rm_tx_pcs_startup_cntr_clr, --in std_logic; + pcs_startup_cntr => rm_tx_pcs_startup_cntr, --out std_logic_vector(15 downto 0); -- Counts for link startups + pcs_startup_cntr_flag => rm_tx_pcs_startup_cntr_flag --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_rxpcs_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; end process; PROC_SENSE_DLMS: process begin @@ -676,46 +729,46 @@ begin elsif rx_data_i(17) = '1' and rx_data_i(15 downto 8) = K277 then stat_dlm_counter_i <= stat_dlm_counter_i + TO_UNSIGNED(1,1); end if; - 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); - 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; + +-- 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_rxpcs_ready_i & rm_rx_see_reinit & rm_rx_ebtb_detect_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_dlm_counter_i(15 downto 0); + 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); + --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 architecture; \ No newline at end of file diff --git a/cbmnet/code/cbmnet_phy_pkg.vhd b/cbmnet/code/cbmnet_phy_pkg.vhd index c3ee736..27df297 100644 --- a/cbmnet/code/cbmnet_phy_pkg.vhd +++ b/cbmnet/code/cbmnet_phy_pkg.vhd @@ -92,6 +92,8 @@ package cbmnet_phy_pkg is DATA_IN : in std_logic_vector(17 downto 0); DATA_OUT : out std_logic_vector(8 downto 0); + + TX_READY_OUT: out std_logic; DEBUG_OUT : out std_logic_vector(31 downto 0) ); diff --git a/cbmnet/code/cbmnet_phy_tx_gear.vhd b/cbmnet/code/cbmnet_phy_tx_gear.vhd index 9969670..13cd151 100644 --- a/cbmnet/code/cbmnet_phy_tx_gear.vhd +++ b/cbmnet/code/cbmnet_phy_tx_gear.vhd @@ -25,6 +25,8 @@ entity CBMNET_PHY_TX_GEAR is DATA_IN : in std_logic_vector(17 downto 0); DATA_OUT : out std_logic_vector(8 downto 0); + TX_READY_OUT: out std_logic; + DEBUG_OUT : out std_logic_vector(31 downto 0) ); end entity; @@ -73,6 +75,8 @@ begin end case; end process; + TX_READY_OUT <= not RESET_IN; + process is begin wait until rising_edge(CLK_125_IN); diff --git a/cbmnet/test/flash b/cbmnet/test/flash index a48b6cc..f0e21a4 100755 --- a/cbmnet/test/flash +++ b/cbmnet/test/flash @@ -16,7 +16,7 @@ if ($flash_master) { if ($flash_slave) { print "Flash SLAVE\n"; system "trbcmd s 0x72000002e2eb4628 0x02 0x8001"; - system "trbflash -y program 0x8001 workdir_slave/trb3_periph_cbmnet.bit"; + system "trbflash -y program 0x8001 workdir/trb3_periph_cbmnet.bit"; system "rebootfpga.sh 0x8001"; } else { print "Skip SLAVE\n"; diff --git a/cbmnet/test/info.pl b/cbmnet/test/info.pl index 17c8943..a3e25c6 100755 --- a/cbmnet/test/info.pl +++ b/cbmnet/test/info.pl @@ -95,23 +95,60 @@ for my $line (@lines) { my @names = paddListR (map {$_->[0]} @defs); +sub show8b10b { + my $data = shift; + my $k = shift; + + if ($k) { + my %codes = ( + 28, "K.28.0", + 60, "K.28.1", + 92, "K.28.2", + 124, "K.28.3", + 156, "K.28.4", + 188, "K.28.5", + 220, "K.28.6", + 252, "K.28.7", + 247, "K.23.7", + 251, "K.27.7", + 253, "K.29.7", + 254, "K.30.7"); + + return $codes{$data}; + } else { + return sprintf("D.%02d.%d", $data & 0x1f, ($data >> 5) & 0x7); + } +} + +sub show8b10bWord { + my $data = shift; + return + show8b10b( ($data >> 8) & 0xff, ($data >> 17) & 1 ) . " " . + show8b10b( ($data >> 0) & 0xff, ($data >> 16) & 1 ); +} + my @old_results; +my $first_one = 1; while (1) { my @results = (); - for my $i (0 .. 1) { + for my $i (1 .. 1) { my $reg = readRegs 0x8000 + $i, 8; my @slices = (); for my $def (@defs) { my $idx = $def->[1]; my $len = $def->[2]; - push @slices, sprintf($len == 1 ? "%x" : "0x%0" . (ceil($len / 4.0)) . "x", ($reg >> $idx) & ((1 << $len) - 1)); + my $text = sprintf($len == 1 ? "%x" : "0x%0" . (ceil(($len+3) / 4.0)) . "x", ($reg >> $idx) & ((1 << $len) - 1)); + if ($len == 18) { + $text .= " " . show8b10bWord(($reg >> $idx) & ((1 << $len) - 1)); + } + push @slices, $text; } push @results, [paddListL @slices]; } - + for my $idx (0..$#names) { my $line = $names[$idx] . " | "; @@ -133,5 +170,6 @@ while (1) { sleep 1; - print chr(27) . "[1;1H" ; -} \ No newline at end of file +print $first_one ? `reset` : chr(27) . "[1;1H"; +$first_one = 0; +} diff --git a/cbmnet/trb3_periph_cbmnet.p2t b/cbmnet/trb3_periph_cbmnet.p2t index 42de4f4..b7ad87c 100755 --- a/cbmnet/trb3_periph_cbmnet.p2t +++ b/cbmnet/trb3_periph_cbmnet.p2t @@ -1,14 +1,14 @@ #-t is seed -w --i 15 --l 5 +#-i 1 +#-l 5 #-n 1 -y #-s 12 -t 3 -c 1 #-e 2 -#-m nodelist.txt +-m nodelist.txt # -w # -i 6 # -l 5 diff --git a/cbmnet/trb3_periph_cbmnet.prj b/cbmnet/trb3_periph_cbmnet.prj index fc75d2e..f6ad15a 100644 --- a/cbmnet/trb3_periph_cbmnet.prj +++ b/cbmnet/trb3_periph_cbmnet.prj @@ -9,9 +9,11 @@ add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/rams/ram_1w2r_1c.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/rams/ram_2rw_1c.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/rams/ram_2rw_2c.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/rams/ram_1w1r_1c_enable.v" + add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fast_fifo/fast_fifo.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fast_fifo/fifo_ram.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fast_fifo/fifo_reg.v" + add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fwft_fifo_spec/spec_fwft_fifo.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fwft_fifo_spec/spec_standard_fifo.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fwft_fifo_spec/empty_logic_spec_so.v" @@ -19,11 +21,27 @@ add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fwft_fifo_spec/empty_ add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fwft_fifo_spec/full_logic_spec_si.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fwft_fifo_spec/full_logic_wo_spec.v" add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/fwft_fifo_spec/full_logic_spec_si_all.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_init/async_input_sync.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_init/gtp_rx_ready_module.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_init/gtp_rx_rm_fsm.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_init/gtp_tx_ready_module.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_init/gtp_tx_rm_fsm.v" + +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/async_fifo.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/async_standard_fifo.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/sync_r2w.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/sync_w2r.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/sync_w2r_hs.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/empty_logic.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/full_logic.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/empty_logic_spec_shift_out.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/empty_logic_spec_shift_out_1_inc.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/full_logic_spec_shift_in.v" +add_file -verilog "./cbmnet/cores/CBMnet/cores_fpga/common/async_fifo/full_logic_spec_shift_in_1_inc.v" + +add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/pcs_init/cn_barrel_shifter.v" +add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/pcs_init/cn_rx_pcs_init_fsm.v" +add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/pcs_init/cn_rx_pcs_wrapper.v" +add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/pcs_init/cn_tx_pcs_init_fsm.v" +add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/pcs_init/cn_tx_pcs_wrapper.v" +add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/pcs_init/cn_async_input_sync.v" + + add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/LP/lp_top.v" add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/LP/lp_arbiter_fsm.v" add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/LP/lp_crc_generator.v" @@ -46,11 +64,9 @@ add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/LP/lp_send_buffer.v" add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/LP/lp_send_fsm.v" add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/LP/lp_tx_slave_top.v" add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/LP/lp_tx_top.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_tester/lt_send_fsm.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_tester/lt_random_stopper.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_tester/link_tester_be.v" -add_file -verilog "./cbmnet/cores/CBMnet/building_blocks/link_tester/link_tester_fe.v" + add_file -vhdl -lib work "./version.vhd" + add_file -vhdl -lib work "../../trbnet/trb_net_std.vhd" add_file -vhdl -lib work "../../trbnet/basics/pulse_sync.vhd" add_file -vhdl -lib work "../../trbnet/basics/state_sync.vhd" diff --git a/cbmnet/trb3_periph_cbmnet.vhd b/cbmnet/trb3_periph_cbmnet.vhd index e5acc21..6105663 100755 --- a/cbmnet/trb3_periph_cbmnet.vhd +++ b/cbmnet/trb3_periph_cbmnet.vhd @@ -309,9 +309,58 @@ architecture trb3_periph_arch of trb3_periph_cbmnet is signal send_num_pack_counter_i : unsigned(15 downto 0); + signal send_enabled_i : std_logic := '0'; + signal dlm_counter_i : unsigned(31 downto 0); signal dlm_glob_counter_i : unsigned(31 downto 0); + + -- diagnostics Lane0 + signal cbm_crc_error_cntr_flag_0 : std_logic; + signal cbm_retrans_cntr_flag_0 : std_logic; + signal cbm_retrans_error_cntr_flag_0 : std_logic; + signal cbm_crc_error_cntr_0 : std_logic_vector(15 downto 0); + signal cbm_retrans_cntr_0 : std_logic_vector(15 downto 0); + signal cbm_retrans_error_cntr_0 : std_logic_vector(15 downto 0); + signal cbm_crc_error_cntr_clr_0 : std_logic; + signal cbm_retrans_cntr_clr_0 : std_logic; + signal cbm_retrans_error_cntr_clr_0 : std_logic; + + -- diagnostics Lane1 + signal cbm_crc_error_cntr_flag_1 : std_logic; + signal cbm_retrans_cntr_flag_1 : std_logic; + signal cbm_retrans_error_cntr_flag_1 : std_logic; + signal cbm_crc_error_cntr_1 : std_logic_vector(15 downto 0); + signal cbm_retrans_cntr_1 : std_logic_vector(15 downto 0); + signal cbm_retrans_error_cntr_1 : std_logic_vector(15 downto 0); + signal cbm_crc_error_cntr_clr_1 : std_logic; + signal cbm_retrans_cntr_clr_1 : std_logic; + signal cbm_retrans_error_cntr_clr_1 : std_logic; + + -- diagnostics Lane2 + signal cbm_crc_error_cntr_flag_2 : std_logic; + signal cbm_retrans_cntr_flag_2 : std_logic; + signal cbm_retrans_error_cntr_flag_2 : std_logic; + signal cbm_crc_error_cntr_2 : std_logic_vector(15 downto 0); + signal cbm_retrans_cntr_2 : std_logic_vector(15 downto 0); + signal cbm_retrans_error_cntr_2 : std_logic_vector(15 downto 0); + signal cbm_crc_error_cntr_clr_2 : std_logic; + signal cbm_retrans_cntr_clr_2 : std_logic; + signal cbm_retrans_error_cntr_clr_2 : std_logic; + + -- diagnostics Lane3 + signal cbm_crc_error_cntr_flag_3 : std_logic; + signal cbm_retrans_cntr_flag_3 : std_logic; + signal cbm_retrans_error_cntr_flag_3 : std_logic; + signal cbm_crc_error_cntr_3 : std_logic_vector(15 downto 0); + signal cbm_retrans_cntr_3 : std_logic_vector(15 downto 0); + signal cbm_retrans_error_cntr_3 : std_logic_vector(15 downto 0); + signal cbm_crc_error_cntr_clr_3 : std_logic; + signal cbm_retrans_cntr_clr_3 : std_logic; + signal cbm_retrans_error_cntr_clr_3 : std_logic; + + signal cbm_debug_overrides_i : std_logic_vector(1 downto 0) := "00"; + begin clk_125_i <= CLK_GPLL_LEFT; @@ -393,8 +442,8 @@ begin -- Phy data_from_link => cbm_data_from_link, data2link => cbm_data2link, - link_activeovr => '0', - link_readyovr => '0', + link_activeovr => cbm_debug_overrides_i(0), + link_readyovr => cbm_debug_overrides_i(1), SERDES_ready => cbm_SERDES_ready, -- CBMNet Interface @@ -423,11 +472,68 @@ begin ctrl_rec => cbm_ctrl_rec, ctrl_rec_start => cbm_ctrl_rec_start, ctrl_rec_end => cbm_ctrl_rec_end, - ctrl_rec_stop => cbm_ctrl_rec_stop + ctrl_rec_stop => cbm_ctrl_rec_stop, + + -- diagnostics Lane0 + crc_error_cntr_flag_0 => cbm_crc_error_cntr_flag_0, -- out std_logic; + retrans_cntr_flag_0 => cbm_retrans_cntr_flag_0, -- out std_logic; + retrans_error_cntr_flag_0 => cbm_retrans_error_cntr_flag_0, -- out std_logic; + crc_error_cntr_0 => cbm_crc_error_cntr_0, -- out std_logic_vector(15 downto 0); + retrans_cntr_0 => cbm_retrans_cntr_0, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_0 => cbm_retrans_error_cntr_0, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_0 => cbm_crc_error_cntr_clr_0, -- in std_logic; + retrans_cntr_clr_0 => cbm_retrans_cntr_clr_0, -- in std_logic; + retrans_error_cntr_clr_0 => cbm_retrans_error_cntr_clr_0, -- in std_logic; + + -- diagnostics Lane1 + crc_error_cntr_flag_1 => cbm_crc_error_cntr_flag_1, -- out std_logic; + retrans_cntr_flag_1 => cbm_retrans_cntr_flag_1, -- out std_logic; + retrans_error_cntr_flag_1 => cbm_retrans_error_cntr_flag_1, -- out std_logic; + crc_error_cntr_1 => cbm_crc_error_cntr_1, -- out std_logic_vector(15 downto 0); + retrans_cntr_1 => cbm_retrans_cntr_1, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_1 => cbm_retrans_error_cntr_1, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_1 => cbm_crc_error_cntr_clr_1, -- in std_logic; + retrans_cntr_clr_1 => cbm_retrans_cntr_clr_1, -- in std_logic; + retrans_error_cntr_clr_1 => cbm_retrans_error_cntr_clr_1, -- in std_logic; + + -- diagnostics Lane2 + crc_error_cntr_flag_2 => cbm_crc_error_cntr_flag_2, -- out std_logic; + retrans_cntr_flag_2 => cbm_retrans_cntr_flag_2, -- out std_logic; + retrans_error_cntr_flag_2 => cbm_retrans_error_cntr_flag_2, -- out std_logic; + crc_error_cntr_2 => cbm_crc_error_cntr_2, -- out std_logic_vector(15 downto 0); + retrans_cntr_2 => cbm_retrans_cntr_2, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_2 => cbm_retrans_error_cntr_2, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_2 => cbm_crc_error_cntr_clr_2, -- in std_logic; + retrans_cntr_clr_2 => cbm_retrans_cntr_clr_2, -- in std_logic; + retrans_error_cntr_clr_2 => cbm_retrans_error_cntr_clr_2, -- in std_logic; + + -- diagnostics Lane3 + crc_error_cntr_flag_3 => cbm_crc_error_cntr_flag_3, -- out std_logic; + retrans_cntr_flag_3 => cbm_retrans_cntr_flag_3, -- out std_logic; + retrans_error_cntr_flag_3 => cbm_retrans_error_cntr_flag_3, -- out std_logic; + crc_error_cntr_3 => cbm_crc_error_cntr_3, -- out std_logic_vector(15 downto 0); + retrans_cntr_3 => cbm_retrans_cntr_3, -- out std_logic_vector(15 downto 0); + retrans_error_cntr_3 => cbm_retrans_error_cntr_3, -- out std_logic_vector(15 downto 0); + crc_error_cntr_clr_3 => cbm_crc_error_cntr_clr_3, -- in std_logic; + retrans_cntr_clr_3 => cbm_retrans_cntr_clr_3, -- in std_logic; + retrans_error_cntr_clr_3 => cbm_retrans_error_cntr_clr_3 -- in std_logic + ); cbm_res_n <= not rreset_i; - + + cbm_crc_error_cntr_clr_0 <= reset_i; + cbm_retrans_cntr_clr_0 <= reset_i; + cbm_retrans_error_cntr_clr_0 <= reset_i; + cbm_crc_error_cntr_clr_1 <= reset_i; + cbm_retrans_cntr_clr_1 <= reset_i; + cbm_retrans_error_cntr_clr_1 <= reset_i; + cbm_crc_error_cntr_clr_2 <= reset_i; + cbm_retrans_cntr_clr_2 <= reset_i; + cbm_retrans_error_cntr_clr_2 <= reset_i; + cbm_crc_error_cntr_clr_3 <= reset_i; + cbm_retrans_cntr_clr_3 <= reset_i; + cbm_retrans_error_cntr_clr_3 <= reset_i; PROC_DATA_SEND: process begin wait until rising_edge(rclk_125_i); @@ -444,31 +550,32 @@ begin cbm_data2send_start <= "0"; cbm_data2send_end <= "0"; - - case(send_fsm_i) is - when IDLE => - if cbm_link_active='1' and cbm_data2send_stop = "0" then - send_fsm_i <= WAITc; - send_wait_counter_i <= (others => '0'); - send_num_pack_counter_i <= send_num_pack_counter_i + TO_UNSIGNED(1, 1); - end if; - - when WAITc => - if send_wait_counter_i(send_pack_counter_i'HIGH) = '1' then - send_fsm_i <= SEND; - cbm_data2send_start <= "1"; - end if; - - when SEND => - if send_wait_counter_i(send_pack_counter_i'HIGH) = '1' then - cbm_data2send_end <= "1"; - send_fsm_i <= IDLE; - end if; - end case; - - if reset_i = '1' then + + if reset_i = '1' or send_enabled_i = '0' then send_fsm_i <= IDLE; send_num_pack_counter_i <= (others => '0'); + + else + case(send_fsm_i) is + when IDLE => + if cbm_link_active='1' and cbm_data2send_stop = "0" then + send_fsm_i <= WAITc; + send_wait_counter_i <= (others => '0'); + send_num_pack_counter_i <= send_num_pack_counter_i + TO_UNSIGNED(1, 1); + end if; + + when WAITc => + if send_wait_counter_i(send_pack_counter_i'HIGH) = '1' then + send_fsm_i <= SEND; + cbm_data2send_start <= "1"; + end if; + + when SEND => + if send_wait_counter_i(send_pack_counter_i'HIGH) = '1' then + cbm_data2send_end <= "1"; + send_fsm_i <= IDLE; + end if; + end case; end if; end process; @@ -502,7 +609,6 @@ begin address := to_integer(unsigned(debug_addr)); debug_data_out <= x"00000000"; - debug_ack <= '0'; debug_ack <= debug_read_en or debug_write_en; case address is @@ -528,9 +634,20 @@ begin when 16#12# => debug_data_out <= STD_LOGIC_VECTOR(dlm_counter_i); when 16#13# => debug_data_out <= STD_LOGIC_VECTOR(dlm_glob_counter_i); - when 16#14# => - debug_data_out(19 downto 16) <= "00" & cbm_data2send_stop & cbm_link_active; + when 16#14# => + debug_data_out(21 downto 20) <= cbm_debug_overrides_i; + debug_data_out(19 downto 16) <= "0" & send_enabled_i & cbm_data2send_stop & cbm_link_active; debug_data_out(15 downto 0) <= STD_LOGIC_VECTOR(send_num_pack_counter_i); + + + when 16#15# => debug_data_out(15 downto 0) <= cbm_crc_error_cntr_0; + when 16#16# => debug_data_out <= cbm_retrans_error_cntr_0 & cbm_retrans_cntr_0; + when 16#17# => debug_data_out(15 downto 0) <= cbm_crc_error_cntr_1; + when 16#18# => debug_data_out <= cbm_retrans_error_cntr_1 & cbm_retrans_cntr_1; + when 16#19# => debug_data_out(15 downto 0) <= cbm_crc_error_cntr_2; + when 16#1a# => debug_data_out <= cbm_retrans_error_cntr_2 & cbm_retrans_cntr_2; + when 16#1b# => debug_data_out(15 downto 0) <= cbm_crc_error_cntr_3; + when 16#1c# => debug_data_out <= cbm_retrans_error_cntr_3 & cbm_retrans_cntr_3; when others => debug_ack <= '0'; end case; @@ -541,6 +658,10 @@ begin when 16#4# => phy_ctrl_debug(31 downto 0) <= debug_data_in; when 16#5# => phy_ctrl_debug(63 downto 32) <= debug_data_in; + when 16#14# => + send_enabled_i <= debug_data_in(18); + cbm_debug_overrides_i <= debug_data_in(21 downto 20); + -- when 16#11# => link_tester_ctrl <= debug_data_in; when others => debug_ack <= '0'; end case; diff --git a/cbmnet/trb3_periph_cbmnet_constraints.lpf b/cbmnet/trb3_periph_cbmnet_constraints.lpf index 381c50a..8c7b738 100644 --- a/cbmnet/trb3_periph_cbmnet_constraints.lpf +++ b/cbmnet/trb3_periph_cbmnet_constraints.lpf @@ -8,21 +8,14 @@ SYSCONFIG MCCLK_FREQ = 20; -# FREQUENCY PORT CLK_PCLK_RIGHT 200 MHz; -# FREQUENCY PORT CLK_PCLK_LEFT 200 MHz; - - FREQUENCY PORT CLK_GPLL_RIGHT 200 MHz; - FREQUENCY PORT CLK_GPLL_LEFT 125 MHz; - - FREQUENCY NET "THE_CBM_PHY/CLK_TX_FULL_I" 250 MHz; +# FREQUENCY NET "THE_CBM_PHY/CLK_TX_FULL_I" 250 MHz; FREQUENCY NET "THE_CBM_PHY/RCLK_250_I" 250 MHz; #Change the next two lines to the clk_fast signal of the ADC # USE PRIMARY2EDGE NET "THE_MAIN_PLL/PLLInst_0"; # USE PRIMARY NET "THE_MAIN_PLL/PLLInst_0"; -# USE PRIMARY NET "CLK_PCLK_LEFT"; -# USE PRIMARY NET "CLK_PCLK_LEFT_c"; - + +USE PRIMARY NET "CLK_GPLL_LEFT"; # USE PRIMARY NET "THE_CBM_PHY/RCLK_250_I"; # USE SECONDARY NET "THE_CBM_PHY/CLK_TX_FULL_I";