--- /dev/null
+library ieee;\r
+use ieee.std_logic_1164.all;\r
+use ieee.std_logic_arith.all;\r
+use ieee.std_logic_unsigned.all;\r
+\r
+library work;\r
+\r
+\r
+entity trb_net_reset_handler is\r
+generic(\r
+ RESET_DELAY : std_logic_vector(15 downto 0) := x"1fff"\r
+);\r
+port(\r
+ CLEAR_IN : in std_logic; -- reset input (high active, async)\r
+ CLEAR_N_IN : in std_logic; -- reset input (low active, async)\r
+ CLK_IN : in std_logic; -- raw master clock, NOT from PLL/DLL!\r
+ SYSCLK_IN : in std_logic; -- PLL/DLL remastered clock\r
+ PLL_LOCKED_IN : in std_logic; -- master PLL lock signal (async)\r
+ RESET_IN : in std_logic; -- general reset signal (SYSCLK)\r
+ TRB_RESET_IN : in std_logic; -- TRBnet reset signal (SYSCLK)\r
+ CLEAR_OUT : out std_logic; -- async reset out, USE WITH CARE!\r
+ RESET_OUT : out std_logic; -- synchronous reset out (SYSCLK)\r
+ DEBUG_OUT : out std_logic_vector(15 downto 0)\r
+);\r
+end;\r
+\r
+-- This reset handler tries to generate a stable synchronous reset\r
+-- for FPGA fabric. It waits for the system clock PLL to lock, reacts\r
+-- on two external asynchronous resets, and also allows to reset the\r
+-- FPGA by sending a synchronous TRBnet reset pulse.\r
+-- It is not recommended to reset the system clock PLL/DLL with\r
+-- any of the reset signals generated here. It may deadlock.\r
+\r
+architecture behavioral of trb_net_reset_handler is\r
+\r
+-- normal signals\r
+signal async_sampler : std_logic_vector(7 downto 0); -- input shift register\r
+signal comb_async_pulse : std_logic;\r
+signal async_pulse : std_logic;\r
+signal reset_cnt : std_logic_vector(15 downto 0) := x"0000";\r
+signal debug : std_logic_vector(15 downto 0);\r
+signal reset : std_logic; -- DO NOT USE THIS SIGNAL!\r
+\r
+signal reset_buffer : std_logic; -- DO NOT USE THIS SIGNAL!\r
+signal trb_reset_buffer : std_logic; -- DO NOT USE THIS SIGNAL!\r
+signal reset_pulse : std_logic_vector(1 downto 0) := b"00";\r
+signal trb_reset_pulse : std_logic_vector(1 downto 0) := b"00";\r
+signal comb_async_rst : std_logic;\r
+signal final_reset : std_logic_vector(1 downto 0) := b"11"; -- DO NOT USE THIS SIGNAL!\r
+\r
+attribute syn_preserve : boolean;\r
+attribute syn_preserve of async_sampler : signal is true;\r
+attribute syn_preserve of async_pulse : signal is true;\r
+attribute syn_preserve of reset : signal is true;\r
+attribute syn_preserve of reset_cnt : signal is true;\r
+attribute syn_preserve of comb_async_rst : signal is true;\r
+\r
+begin\r
+\r
+----------------------------------------------------------------\r
+-- Combine all async reset sources: CLR, /CLR, PLL_LOCK\r
+----------------------------------------------------------------\r
+comb_async_rst <= not clear_in and clear_n_in and pll_locked_in;\r
+\r
+----------------------------------------------------------------\r
+-- sample the async reset line and react only on a long pulse\r
+----------------------------------------------------------------\r
+THE_ASYNC_SAMPLER_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ async_sampler(7 downto 0) <= async_sampler(6 downto 0) & comb_async_rst;\r
+ async_pulse <= comb_async_pulse;\r
+ end if;\r
+end process THE_ASYNC_SAMPLER_PROC;\r
+\r
+-- first two registers are clock domain transfer registers!\r
+comb_async_pulse <= '1' when ( async_sampler(7 downto 2) = b"0000_00" ) else '0';\r
+\r
+----------------------------------------------------------------\r
+-- Sync the signals from SYSCLK to raw clock domain and back\r
+----------------------------------------------------------------\r
+THE_SYNC_PROC: process( sysclk_in )\r
+begin\r
+ if( rising_edge(sysclk_in) ) then\r
+ reset_buffer <= reset_in; -- not really needed, but relaxes timing\r
+ trb_reset_buffer <= trb_reset_in; -- not really needed, but relaxes timing\r
+ final_reset <= final_reset(0) & reset;\r
+ end if;\r
+end process THE_SYNC_PROC;\r
+\r
+THE_CROSSING_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ reset_pulse <= reset_pulse(0) & reset_buffer;\r
+ trb_reset_pulse <= trb_reset_pulse(0) & trb_reset_buffer;\r
+ end if;\r
+end process THE_CROSSING_PROC;\r
+\r
+----------------------------------------------------------------\r
+-- one global reset counter\r
+----------------------------------------------------------------\r
+THE_GLOBAL_RESET_PROC: process( clk_in )\r
+begin\r
+ if( rising_edge(clk_in) ) then\r
+ if( (async_pulse = '1') or (reset_pulse(1) = '1') or (trb_reset_pulse(1) = '1') ) then\r
+ reset_cnt <= (others => '0');\r
+ reset <= '1';\r
+ else\r
+ reset_cnt <= reset_cnt + 1;\r
+ reset <= '1';\r
+ if( reset_cnt = RESET_DELAY ) then\r
+ reset <= '0';\r
+ reset_cnt <= RESET_DELAY;\r
+ end if;\r
+ end if;\r
+ end if;\r
+end process THE_GLOBAL_RESET_PROC;\r
+\r
+\r
+----------------------------------------------------------------\r
+-- Debug signals\r
+----------------------------------------------------------------\r
+debug(15) <= reset;\r
+debug(14) <= '0';\r
+debug(13 downto 12) <= final_reset;\r
+debug(11 downto 0) <= reset_cnt(11 downto 0);\r
+--debug(15) <= comb_async_pulse;\r
+--debug(14 downto 8) <= (others => '0');\r
+--debug(7 downto 0) <= async_sampler;\r
+\r
+----------------------------------------------------------------\r
+-- Output signals\r
+----------------------------------------------------------------\r
+debug_out <= debug;\r
+clear_out <= not comb_async_rst;\r
+reset_out <= final_reset(1);\r
+\r
+end behavioral;\r