From 119b0d132306d804b4d270e37c9bcc4f9f5a47d9 Mon Sep 17 00:00:00 2001 From: Michael Boehmer Date: Wed, 22 Dec 2021 09:41:53 +0100 Subject: [PATCH] TRBnet reset works again with link re-establishment --- media_interfaces/med_ecp3_sfp_sync_all_RS.vhd | 30 ++-- special/trb_net_reset_handler.vhd | 145 +++++++++--------- 2 files changed, 90 insertions(+), 85 deletions(-) diff --git a/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd b/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd index b4d30b4..0a8387a 100644 --- a/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd +++ b/media_interfaces/med_ecp3_sfp_sync_all_RS.vhd @@ -46,7 +46,7 @@ entity med_ecp3_sfp_sync_all_RS is TX_CLK_AVAIL_OUT : out std_logic; -- stable RX recovered clock available TX_PCS_RST_IN : in std_logic; -- TX PCS reset signal SYNC_TX_PLL_IN : in std_logic; -- bit0 alignment for TX serializer - LINK_TX_READY_IN : in std_logic; -- + LINK_TX_READY_IN : in std_logic; -- from TX reset generator DESTROY_LINK_IN : in std_logic_vector(3 downto 0); -- hard reset for links --SFP Connection SD_PRSNT_N_IN : in std_logic_vector(3 downto 0); -- SFP Present ('0' = SFP in place, '1' = no SFP mounted) @@ -164,21 +164,25 @@ begin ------------------------------------------------- -- BUG: link_tx_ready(i) for master ports to be included -- BUG: slave ports need also disable with link_tx_ready(i) - SD_TXDIS_OUT(3) <= DESTROY_LINK_IN(3) or (not SLAVE_ACTIVE_IN) when IS_MODE(3) = c_IS_MASTER else - not link_rx_ready_i(3) when IS_MODE(3) = c_IS_SLAVE else - '1' when IS_MODE(3) = c_IS_UNUSED else + SD_TXDIS_OUT(3) <= DESTROY_LINK_IN(3) or (not SLAVE_ACTIVE_IN) or RESET + when IS_MODE(3) = c_IS_MASTER else + not link_rx_ready_i(3) when IS_MODE(3) = c_IS_SLAVE else + '1' when IS_MODE(3) = c_IS_UNUSED else '0'; - SD_TXDIS_OUT(2) <= DESTROY_LINK_IN(2) or (not SLAVE_ACTIVE_IN) when IS_MODE(2) = c_IS_MASTER else - not link_rx_ready_i(2) when IS_MODE(2) = c_IS_SLAVE else - '1' when IS_MODE(2) = c_IS_UNUSED else + SD_TXDIS_OUT(2) <= DESTROY_LINK_IN(2) or (not SLAVE_ACTIVE_IN) or RESET + when IS_MODE(2) = c_IS_MASTER else + not link_rx_ready_i(2) when IS_MODE(2) = c_IS_SLAVE else + '1' when IS_MODE(2) = c_IS_UNUSED else '0'; - SD_TXDIS_OUT(1) <= DESTROY_LINK_IN(1) or (not SLAVE_ACTIVE_IN) when IS_MODE(1) = c_IS_MASTER else - not link_rx_ready_i(1) when IS_MODE(1) = c_IS_SLAVE else - '1' when IS_MODE(1) = c_IS_UNUSED else + SD_TXDIS_OUT(1) <= DESTROY_LINK_IN(1) or (not SLAVE_ACTIVE_IN) or RESET + when IS_MODE(1) = c_IS_MASTER else + not link_rx_ready_i(1) when IS_MODE(1) = c_IS_SLAVE else + '1' when IS_MODE(1) = c_IS_UNUSED else '0'; - SD_TXDIS_OUT(0) <= DESTROY_LINK_IN(0) or (not SLAVE_ACTIVE_IN) when IS_MODE(0) = c_IS_MASTER else - not link_rx_ready_i(0) when IS_MODE(0) = c_IS_SLAVE else - '1' when IS_MODE(0) = c_IS_UNUSED else + SD_TXDIS_OUT(0) <= DESTROY_LINK_IN(0) or (not SLAVE_ACTIVE_IN) or RESET + when IS_MODE(0) = c_IS_MASTER else + not link_rx_ready_i(0) when IS_MODE(0) = c_IS_SLAVE else + '1' when IS_MODE(0) = c_IS_UNUSED else '0'; ------------------------------------------------- diff --git a/special/trb_net_reset_handler.vhd b/special/trb_net_reset_handler.vhd index ed1e3da..c4213e5 100644 --- a/special/trb_net_reset_handler.vhd +++ b/special/trb_net_reset_handler.vhd @@ -30,109 +30,110 @@ end entity; -- It is not recommended to reset the system clock PLL/DLL with -- any of the reset signals generated here. It may deadlock. +-- Usually 200M clock is used, so we have 5ns. To get a suitable time for link reset, +-- more than 16bit counter is needed. +-- With 200MHz and 20bit counter (19 bit effective), we get 2.6ms reset time, which +-- should be sufficient to shut down the TX laser in SFP. + architecture behavioral of trb_net_reset_handler is --- normal signals -signal async_sampler : std_logic_vector(7 downto 0); -- input shift register -signal comb_async_pulse : std_logic; -signal async_pulse : std_logic; -signal reset_cnt : std_logic_vector(15 downto 0) := x"0000"; -signal debug : std_logic_vector(15 downto 0); -signal reset : std_logic; -- DO NOT USE THIS SIGNAL! - -signal reset_buffer : std_logic; -- DO NOT USE THIS SIGNAL! -signal trb_reset_buffer : std_logic; -- DO NOT USE THIS SIGNAL! -signal reset_pulse : std_logic_vector(1 downto 0) := b"00"; -signal trb_reset_pulse : std_logic_vector(1 downto 0) := b"00"; -signal comb_async_rst_n : std_logic; -signal final_reset : std_logic_vector(1 downto 0) := b"11"; -- DO NOT USE THIS SIGNAL! - -attribute syn_preserve : boolean; -attribute syn_preserve of async_sampler : signal is true; -attribute syn_preserve of async_pulse : signal is true; -attribute syn_preserve of reset : signal is true; -attribute syn_preserve of reset_cnt : signal is true; -attribute syn_preserve of comb_async_rst_n : signal is true; - -attribute syn_hier : string; -attribute syn_hier of behavioral : architecture is "firm"; + -- normal signals + signal async_sampler : std_logic_vector(7 downto 0); -- input shift register + signal comb_async_pulse : std_logic; + signal async_pulse : std_logic; + signal reset_cnt : std_logic_vector(20 downto 0) := (others => '0'); + signal debug : std_logic_vector(15 downto 0); + signal reset : std_logic; -- DO NOT USE THIS SIGNAL! + + signal reset_buffer : std_logic; -- DO NOT USE THIS SIGNAL! + signal trb_reset_buffer : std_logic; -- DO NOT USE THIS SIGNAL! + signal reset_pulse : std_logic_vector(1 downto 0) := b"00"; + signal trb_reset_pulse : std_logic_vector(1 downto 0) := b"00"; + signal comb_async_rst_n : std_logic; + signal final_reset : std_logic_vector(1 downto 0) := b"11"; -- DO NOT USE THIS SIGNAL! + + attribute syn_preserve : boolean; + attribute syn_preserve of async_sampler : signal is true; + attribute syn_preserve of async_pulse : signal is true; + attribute syn_preserve of reset : signal is true; + attribute syn_preserve of reset_cnt : signal is true; + attribute syn_preserve of comb_async_rst_n : signal is true; + + attribute syn_hier : string; + attribute syn_hier of behavioral : architecture is "firm"; begin ---------------------------------------------------------------- -- Combine all async reset sources: CLR, /CLR, PLL_LOCK ---------------------------------------------------------------- -comb_async_rst_n <= not clear_in and clear_n_in and pll_locked_in; + comb_async_rst_n <= not clear_in and clear_n_in and pll_locked_in; ---------------------------------------------------------------- -- sample the async reset line and react only on a long pulse ---------------------------------------------------------------- -THE_ASYNC_SAMPLER_PROC: process( clk_in ) -begin - if( rising_edge(clk_in) ) then - async_sampler(7 downto 0) <= async_sampler(6 downto 0) & comb_async_rst_n; - async_pulse <= comb_async_pulse; - end if; -end process THE_ASYNC_SAMPLER_PROC; + THE_ASYNC_SAMPLER_PROC: process( clk_in ) + begin + if( rising_edge(clk_in) ) then + async_sampler(7 downto 0) <= async_sampler(6 downto 0) & comb_async_rst_n; + async_pulse <= comb_async_pulse; + end if; + end process THE_ASYNC_SAMPLER_PROC; -- first two registers are clock domain transfer registers! -comb_async_pulse <= '1' when ( async_sampler(7 downto 2) = b"0000_00" ) else '0'; + comb_async_pulse <= '1' when ( async_sampler(7 downto 2) = b"0000_00" ) else '0'; ---------------------------------------------------------------- -- Sync the signals from SYSCLK to raw clock domain and back ---------------------------------------------------------------- -THE_SYNC_PROC: process( sysclk_in ) -begin - if( rising_edge(sysclk_in) ) then - reset_buffer <= RESET_IN; -- not really needed, but relaxes timing - trb_reset_buffer <= TRB_RESET_IN; -- not really needed, but relaxes timing - final_reset <= final_reset(0) & reset; - end if; -end process THE_SYNC_PROC; - -THE_CROSSING_PROC: process( clk_in ) -begin - if( rising_edge(clk_in) ) then - reset_pulse <= reset_pulse(0) & reset_buffer; - trb_reset_pulse <= trb_reset_pulse(0) & trb_reset_buffer; - end if; -end process THE_CROSSING_PROC; + THE_SYNC_PROC: process( sysclk_in ) + begin + if( rising_edge(sysclk_in) ) then + reset_buffer <= RESET_IN; -- not really needed, but relaxes timing + trb_reset_buffer <= TRB_RESET_IN; -- not really needed, but relaxes timing + final_reset <= final_reset(0) & reset; + end if; + end process THE_SYNC_PROC; + + THE_CROSSING_PROC: process( clk_in ) + begin + if( rising_edge(clk_in) ) then + reset_pulse <= reset_pulse(0) & reset_buffer; + trb_reset_pulse <= trb_reset_pulse(0) & trb_reset_buffer; + end if; + end process THE_CROSSING_PROC; ---------------------------------------------------------------- -- one global reset counter ---------------------------------------------------------------- -THE_GLOBAL_RESET_PROC: process( clk_in ) -begin - if( rising_edge(clk_in) ) then - if( (async_pulse = '1') or (reset_pulse(1) = '1') or (trb_reset_pulse(1) = '1') ) then - reset_cnt <= (others => '0'); - reset <= '1'; - else - reset_cnt <= reset_cnt + 1; - reset <= '1'; - if( reset_cnt = RESET_DELAY ) then - reset <= '0'; - reset_cnt <= RESET_DELAY; + THE_GLOBAL_RESET_PROC: process( clk_in ) + begin + if( rising_edge(clk_in) ) then + if( (async_pulse = '1') or (reset_pulse(1) = '1') or (trb_reset_pulse(1) = '1') ) then + reset_cnt <= (others => '0'); + elsif( reset_cnt(reset_cnt'left) = '0' ) then + reset_cnt <= reset_cnt + 1; end if; end if; - end if; -end process THE_GLOBAL_RESET_PROC; + end process THE_GLOBAL_RESET_PROC; + reset <= not reset_cnt(reset_cnt'left); + ---------------------------------------------------------------- -- Debug signals ---------------------------------------------------------------- -debug(15 downto 11) <= (others => '0'); -debug(10) <= reset; -debug(9) <= '0'; -debug(8 downto 7) <= final_reset; -debug(6) <= async_pulse; -debug(5 downto 0) <= reset_cnt(5 downto 0); + debug(15 downto 11) <= (others => '0'); + debug(10) <= reset; + debug(9) <= '0'; + debug(8 downto 7) <= final_reset; + debug(6) <= async_pulse; + debug(5 downto 0) <= reset_cnt(5 downto 0); ---------------------------------------------------------------- -- Output signals ---------------------------------------------------------------- -DEBUG_OUT <= debug; -CLEAR_OUT <= not comb_async_rst_n; -RESET_OUT <= final_reset(1); + DEBUG_OUT <= debug; + CLEAR_OUT <= not comb_async_rst_n; + RESET_OUT <= final_reset(1); end behavioral; -- 2.43.0