---------------------------------------------------------------------------------- -- Company: -- Engineer: -- -- Create Date: 04/19/2020 08:45:28 AM -- Design Name: -- Module Name: TTC_RX_if - Behavioral -- Project Name: -- Target Devices: -- Tool Versions: -- Description: -- -- Dependencies: -- -- Revision: -- Revision 0.01 - File Created -- Additional Comments: -- ---------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_MISC.ALL; -- Uncomment the following library declaration if using -- arithmetic functions with Signed or Unsigned values use IEEE.NUMERIC_STD.ALL; Library xpm; use xpm.vcomponents.all; -- Uncomment the following library declaration if instantiating -- any Xilinx leaf cells in this code. library UNISIM; use UNISIM.VComponents.all; use work.ngFEC_pack.all; USE work.lpgbtfpga_package.all; use work.tcds2_link_pkg.all; use work.tcds2_link_speed_pkg.all; use work.tcds2_streams_pkg.all; entity TTC_if is generic (SIM : boolean := false); Port ( reset : in STD_LOGIC; test : in STD_LOGIC; prbs_reset : in STD_LOGIC; cntr_reset : in STD_LOGIC; loopback : in STD_LOGIC; Si_IN_SEL1 : in STD_LOGIC; ngFEC_rdy : in STD_LOGIC; clk125 : in STD_LOGIC; txrefclk_in : in STD_LOGIC; txrefclk_lock : in STD_LOGIC; rxrefclk_in : in STD_LOGIC; fabric_clk : in STD_LOGIC; fabric_clk_RST : out STD_LOGIC; fabric_clk_out : out std_logic; rx_p : in STD_LOGIC; rx_n : in STD_LOGIC; tx_p : out STD_LOGIC; tx_n : out STD_LOGIC; refclkp_out : out STD_LOGIC; refclkn_out : out STD_LOGIC; ttc2_stat : out std_logic_vector(15 downto 0); -- ttc_rx_err : out std_logic; BCntRes : out std_logic; BC0_missing : out std_logic; WTE : out std_logic; TTC_counter : out std_logic_vector(8 downto 0)); end TTC_if; architecture Behavioral of TTC_if is component ttc_mgt_wrapper generic (SIM : boolean := false); Port ( reset : in STD_LOGIC; rstoneven : in STD_LOGIC; clk125 : in STD_LOGIC; txrefclk_lock : in STD_LOGIC; txrefclk_in : in STD_LOGIC; rxrefclk_in : in STD_LOGIC; rx_data_good : in STD_LOGIC; rxslide : in STD_LOGIC; loopback_in : in std_logic_vector(2 downto 0); Si_IN_SEL1 : in STD_LOGIC; rx_p : in STD_LOGIC; rx_n : in STD_LOGIC; tx_p : out STD_LOGIC; tx_n : out STD_LOGIC; txusrclk_out : out STD_LOGIC; rxusrclk_out : out STD_LOGIC; tx_rdy : out STD_LOGIC; rx_rdy : out STD_LOGIC; mgt_rdy : out STD_LOGIC; refclkp_out : out STD_LOGIC; refclkn_out : out STD_LOGIC; ttc2_stat : out std_logic_vector(15 downto 0); mgt_txdata : in STD_LOGIC_VECTOR (31 downto 0); mgt_rxdata : out STD_LOGIC_VECTOR (31 downto 0)); end component; component upLinkTxDataPath is port ( clk : in std_logic; dataEnable : in std_logic; txDataFrame : in std_logic_vector(229 downto 0); txIC : in std_logic_vector(1 downto 0); txEC : in std_logic_vector(1 downto 0); scramblerBypass : in std_logic; interleaverBypass : in std_logic; fecMode : in std_logic; txDataRate : in std_logic; scramblerReset : in std_logic; upLinkFrame : out std_logic_vector(255 downto 0) ); end component upLinkTxDataPath; component upLinkTxGearBox is generic( WORD_WIDTH : integer := 32; DATA_RATE : integer := 2 ); port ( clock : in std_logic; reset : in std_logic; dataStrobe : in std_logic; dataFrame : in std_logic_vector(255 downto 0); errorFrame : in std_logic_vector(255 downto 0); dataWord : out std_logic_vector(WORD_WIDTH-1 downto 0) ); end component upLinkTxGearBox; constant c_multicyleDelay : integer := 3 ; constant c_clockRatio : integer := 8 ; constant c_mgtWordWidth : integer := 32; constant c_allowedFalseHeader : integer := 5 ; constant c_allowedFalseHeaderOverN : integer := 64; constant c_requiredTrueHeader : integer := 32; constant c_bitslip_mindly : integer := 2 ; constant c_bitslip_waitdly : integer := 40; -- Bitslip expert parameters for fixed latency applications - EBSM constant c_resetOnEven : integer := 1; --! Reset on even bitslip (1: Enabled/ 0: disabled) constant c_resetDuration : integer := 10; --! Reset duration (in clk_freeRunningClk_i periods) constant c_tclink_master_rx_slide_mode : std_logic := '1'; --! PCS signal loopback_in : std_logic_vector(2 downto 0) := "000"; signal txusrclk : std_logic := '0'; signal rxusrclk : std_logic := '0'; signal mgt_rxdata : std_logic_vector(31downto 0); signal mgt_txdata : std_logic_vector(31downto 0); signal rstoneven : std_logic := '0'; signal rx_uplinkRst_n : std_logic := '0'; signal mgt_tx_rdy : std_logic := '0'; signal mgt_rx_rdy : std_logic := '0'; signal mgt_rdy : std_logic := '0'; signal rx_rdy : std_logic := '0'; signal rx_frame_locked_320 : std_logic; signal not_rx_frame_locked_320 : std_logic; signal ttc_rx_err : std_logic; signal ttc_rx_err_cnt: std_logic := '0'; signal QIEreset_cnt : std_logic := '0'; signal EvCntRes_cnt : std_logic := '0'; signal BC0_cnt : std_logic := '0'; signal BC0_late_cnt : std_logic := '0'; signal BC0_onTime_cnt : std_logic := '0'; signal BC0_early_cnt : std_logic := '0'; signal WTE_cnt : std_logic := '0'; signal miss_cnt : unsigned(2 downto 0); signal BC0_missing_i : std_logic; signal WTE_i : std_logic; signal bcnt : unsigned(11 downto 0); signal BCntRes_i : std_logic := '0'; signal EvCntRes : std_logic; signal rxslide : std_logic := '0'; signal clk320 : std_logic := '0'; signal clk_40 : std_logic := '0'; signal rx_strobe : std_logic := '0'; signal rx_data_mgtclk_corrected : std_logic_vector(233 downto 0); --! Flag allowing to know which bit(s) were toggled by the FEC -- TCDS2 TTC2/TTS2 frame signals. signal frame_ttc2 : tcds2_frame_t; signal frame_tts2 : tcds2_frame_t; signal frame_rx : tcds2_frame_t; signal frame_tx : tcds2_frame_t; -- TCDS2 TTC2/TTS2 signals. signal channel0_ttc2 : tcds2_ttc2; signal channel0_tts2 : tcds2_tts2; signal local_ttc : tcds2_ttc2 := C_TCDS2_TTC2_NULL; signal channel1_ttc2 : tcds2_ttc2; signal channel1_tts2 : tcds2_tts2; constant C_PRBS_FRAME_WIDTH : natural := C_TCDS2_FRAME_WIDTH_10G; subtype prbs_frame is std_logic_vector(C_PRBS_FRAME_WIDTH - 1 downto 0); -- The PRBS polynomial. Notation: x^23 + x^18 + 1 (PRBS-23). constant C_PRBS_POLYNOMIAL : std_logic_vector(23 downto 0) := "100001000000000000000001"; -- PRBS generator polynomial seed. constant C_PRBS_SEED : std_logic_vector(C_PRBS_POLYNOMIAL'length - 2 downto 0) := (others => '1'); -- Number of correct received frames for PRBS checker to lock. constant C_PRBS_GOOD_FRAME_TO_LOCK : integer := 15; -- Number of incorrect received frames for PRBS checker to unlock. constant C_PRBS_BAD_FRAME_TO_UNLOCK : integer := 5; signal prbs_rst : std_logic_vector(3 downto 0); -- PRBS generator signals. signal prbsgen_reset : std_logic; -- PRBS generator output data. signal prbsgen_frame : prbs_frame; -- PRBS checker signals. signal prbschk_reset : std_logic; -- PRBS checker input data. signal prbschk_frame : prbs_frame; -- PRBS checker output data. signal prbschk_gen : prbs_frame; signal prbschk_error : std_logic; signal prbschk_locked : std_logic; signal prbschk_unlock_count : std_logic_vector(31 downto 0); signal tx_frame_data : std_logic_vector(255 downto 0); signal tx_div : unsigned(2 downto 0) := "000"; signal tx_strobe : std_logic := '0'; signal tx_reset : std_logic := '0'; begin loopback_in(1) <= loopback; fabric_clk_out <= clk_40; fabric_clk_RST <= not rx_rdy; BCntRes_i <= channel0_ttc2.sync_flags_and_commands(0); EvCntRes <= channel0_ttc2.sync_flags_and_commands(1); process(fabric_clk) begin if(fabric_clk'event and fabric_clk = '1')then BCntRes <= BCntRes_i; BC0_missing <= BC0_missing_i; WTE <= WTE_i; TTC_counter(0) <= prbschk_unlock_count(0); TTC_counter(1) <= ttc_rx_err_cnt; TTC_counter(2) <= QIEreset_cnt; TTC_counter(3) <= EvCntRes_cnt; TTC_counter(4) <= BC0_cnt; TTC_counter(5) <= BC0_late_Cnt; TTC_counter(6) <= BC0_onTime_cnt; TTC_counter(7) <= BC0_early_cnt; TTC_counter(8) <= WTE_cnt; end if; end process; process(clk_40, rx_rdy) begin if(rx_rdy = '0')then bcnt <= x"000"; local_ttc.sync_flags_and_commands(0) <= '0'; elsif(clk_40'event and clk_40 = '1')then if((BCntRes_i = '1' and loopback = '0') or bcnt = x"deb")then bcnt <= x"000"; local_ttc.sync_flags_and_commands(0) <= loopback; else bcnt <= bcnt + 1; local_ttc.sync_flags_and_commands(0) <= '0'; end if; end if; end process; process(clk_40, cntr_reset) begin if(cntr_reset = '1')then ttc_rx_err_cnt <= '0'; QIEreset_cnt <= '0'; EvCntRes_cnt <= '0'; BC0_cnt <= '0'; BC0_late_Cnt <= '0'; BC0_onTime_cnt <= '0'; BC0_early_cnt <= '0'; WTE_cnt <= '0'; elsif(clk_40'event and clk_40 = '1')then if(BCntRes_i = '1')then QIEreset_cnt <= not QIEreset_cnt; end if; if(EvCntRes = '1')then EvCntRes_cnt <= not EvCntRes_cnt; end if; if(bcnt = x"deb" and BCntRes_i = '1')then BC0_onTime_cnt <= not BC0_onTime_cnt; end if; if(bcnt = x"deb" and BCntRes_i = '0')then BC0_late_cnt <= not BC0_late_cnt; end if; if(bcnt /= x"deb" and BCntRes_i = '1')then BC0_early_cnt <= not BC0_early_cnt; end if; if(WTE_i = '1')then WTE_cnt <= not WTE_cnt; end if; if(ttc_rx_err = '1')then ttc_rx_err_cnt <= not ttc_rx_err_cnt; end if; end if; end process; process(clk_40) begin if(clk_40'event and clk_40 = '1')then case channel0_ttc2.sync_flags_and_commands(7 downto 4) is when x"8" | x"6" | x"4" => WTE_i <= '1'; when others => WTE_i <= '0'; end case; if(BC0_missing_i = '1')then miss_cnt <= (others => '0'); elsif(bcnt = x"deb" and BCntRes_i = '0')then miss_cnt <= miss_cnt + 1; end if; if(BCntRes_i = '1')then BC0_missing_i <= '0'; elsif(miss_cnt = "101")then BC0_missing_i <= '1'; end if; end if; end process; clk320 <= rxusrclk; i_mgt_wrapper : ttc_mgt_wrapper generic map (sim => sim) PORT MAP ( reset => reset, rstoneven => rstoneven, clk125 => clk125, txrefclk_lock => txrefclk_lock, txrefclk_in => txrefclk_in, rxrefclk_in => rxrefclk_in, rx_data_good => rx_rdy, rxslide => rxslide, loopback_in => loopback_in, Si_IN_SEL1 => Si_IN_SEL1, rx_p => rx_p, rx_n => rx_n, tx_p => tx_p, tx_n => tx_n, txusrclk_out => txusrclk, rxusrclk_out => rxusrclk, tx_rdy => mgt_tx_rdy, rx_rdy => mgt_rx_rdy, mgt_rdy => mgt_rdy, refclkp_out => refclkp_out, refclkn_out => refclkn_out, ttc2_stat => ttc2_stat, mgt_txdata => mgt_txdata, mgt_rxdata => mgt_rxdata ); ttc_rx_err <= or_reduce(rx_data_mgtclk_corrected); prbs_generator : entity work.prbs_gen generic map ( G_PARAL_FACTOR => C_PRBS_FRAME_WIDTH, G_PRBS_POLYNOMIAL => C_PRBS_POLYNOMIAL ) port map ( clk_i => txusrclk, reset_i => prbsgen_reset, en_i => tx_strobe, seed_i => C_PRBS_SEED, load_i => '0', data_o => prbsgen_frame, data_valid_o => open ); -- PRBS checker. prbs_checker : entity work.prbs_chk generic map ( G_PARAL_FACTOR => C_PRBS_FRAME_WIDTH, G_PRBS_POLYNOMIAL => C_PRBS_POLYNOMIAL, G_GOOD_FRAME_TO_LOCK => C_PRBS_GOOD_FRAME_TO_LOCK, G_BAD_FRAME_TO_UNLOCK => C_PRBS_BAD_FRAME_TO_UNLOCK ) port map ( clk_i => clk_40, reset_i => prbschk_reset, en_i => '1', data_i => prbschk_frame, data_o => prbschk_gen, error_o => prbschk_error, locked_o => prbschk_locked ); -- PRBS checker unlock counter. prbs_chk_unlock_cnt : entity work.unlock_counter generic map ( G_WIDTH => prbschk_unlock_count'length ) port map ( clk => clk_40, rst => prbschk_reset, locked => prbschk_locked, unlock_count => prbschk_unlock_count ); process(clk_40,rx_rdy) begin if(rx_rdy = '0')then prbs_rst <= x"f"; elsif(clk_40'event and clk_40 = '1')then prbs_rst <= prbs_rst(2 downto 0) & '0'; end if; end process; -- In normal operation the PRBS generator and checker are kept -- under reset. In link test mode they can be manually reset if -- needed. prbsgen_reset <= prbs_reset or tx_reset when test = '1' else '1'; prbschk_reset <= prbs_reset or prbs_rst(3) when test = '1' else '1'; -- TTC2. frame_ttc2 <= frame_rx when test = '0' else C_TCDS2_FRAME_NULL; prbschk_frame <= frame_rx when test = '1' else (others => '0'); -- TTS2. frame_tx <= prbsgen_frame when test = '1' else frame_tts2; ------------------------------------------ -- TTC2 frame splitter. ------------------------------------------ ttc2_frame_splitter : entity work.ttc2_frame_splitter generic map ( G_LINK_SPEED => TCDS2_LINK_SPEED_10G ) port map ( frame_i => frame_ttc2, stream0_o => channel0_ttc2, stream1_o => channel1_ttc2, ic_o => open, ec_o => open, lm_o => open ); ------------------------------------------ -- TTS2 frame builder. ------------------------------------------ channel0_tts2 <= unflatten_tts2(flatten_ttc2(local_ttc)) when loopback = '1' else C_TCDS2_TTS2_READY when ngFEC_rdy = '1' else C_TCDS2_TTS2_NULL; channel1_tts2 <= unflatten_tts2(flatten_ttc2(local_ttc)) when loopback = '1' else C_TCDS2_TTS2_READY when ngFEC_rdy = '1' else C_TCDS2_TTS2_NULL; tts2_frame_builder : entity work.tts2_frame_builder generic map ( G_LINK_SPEED => TCDS2_LINK_SPEED_10G ) port map ( stream0_i => channel0_tts2, stream1_i => channel1_tts2, ic_i => C_TCDS2_IC_NULL, ec_i => C_TCDS2_EC_NULL, lm_i => C_TCDS2_LM_NULL, frame_o => frame_tts2 ); cmp_lpgbtfpga_uplink : entity work.lpgbtfpga_uplink_fixed generic map( -- General configuration DATARATE => 2 , FEC => FEC5 , -- Expert parameters c_multicyleDelay => c_multicyleDelay , c_clockRatio => c_clockRatio , c_mgtWordWidth => c_mgtWordWidth , c_allowedFalseHeader => c_allowedFalseHeader , c_allowedFalseHeaderOverN => c_allowedFalseHeaderOverN, c_requiredTrueHeader => c_requiredTrueHeader , c_bitslip_mindly => c_bitslip_mindly , c_bitslip_waitdly => c_bitslip_waitdly ) port map( -- Clock and reset clk_freeRunningClk_i => clk125 , uplinkClk_i => rxusrclk , uplinkClkOutEn_o => rx_strobe, uplinkRst_n_i => rx_uplinkRst_n , -- Input mgt_word_o => mgt_rxdata, -- Data USErData_o => frame_rx(229 downto 0), EcData_o =>frame_rx(231 downto 230), IcData_o => frame_rx(233 downto 232), -- Control bypassInterleaver_i => '0', bypassFECEncoder_i => '0', bypassScrambler_i => '0', -- Transceiver control mgt_bitslipCtrl_o => rxslide, -- Fixed-latency applications rst_mgtctrler_i => reset, --! Rst the "reset on even" controller rst_rstoneven_o => rstoneven, --! Output reset asserted -- Status dataCorrected_o => rx_data_mgtclk_corrected(229 downto 0), IcCorrected_o => rx_data_mgtclk_corrected(233 downto 232), EcCorrected_o => rx_data_mgtclk_corrected(231 downto 230), rdy_o => rx_rdy ); rx_uplinkRst_n_bit_sync_320 : entity work.bit_synchronizer port map ( clk_in => rxusrclk, i_in => mgt_rx_rdy, o_out => rx_uplinkRst_n ); rx_frame_locked_bit_sync_320 : entity work.bit_synchronizer port map ( clk_in => rxusrclk, i_in => rx_rdy, o_out => rx_frame_locked_320 ); not_rx_frame_locked_320 <= not rx_frame_locked_320; bufgce_clk_40_rx : bufgce_div generic map ( BUFGCE_DIVIDE => 8 ) port map ( i => rxusrclk, o => clk_40, ce => rx_frame_locked_320, clr => not_rx_frame_locked_320 ); process(txusrclk) begin if(txusrclk'event and txusrclk = '1')then if(tx_reset = '1')then tx_div <= (others => '0'); else tx_div <= tx_div + 1; end if; if(tx_div = "111")then tx_strobe <= '1'; else tx_strobe <= '0'; end if; end if; end process; tx_reset <= not mgt_tx_rdy; txdatapath_inst : upLinkTxDataPath port map ( clk => txusrclk, dataEnable => tx_strobe, txDataFrame => frame_tx(229 downto 0), txIC => frame_tx(233 downto 232), txEC => frame_tx(231 downto 230), scramblerBypass => '0', interleaverBypass => '0', fecMode => '0', -- FEC5 txDataRate => '1', --10G24 scramblerReset => tx_reset, upLinkFrame => tx_frame_data ); txgearbox_inst : upLinkTxGearBox generic map( WORD_WIDTH => c_mgtWordWidth, DATA_RATE => 2 ) port map ( clock => txusrclk, reset => tx_reset, dataStrobe => tx_strobe, dataFrame => tx_frame_data , errorFrame => (others => '0') , dataWord => mgt_txdata ); end Behavioral;