You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			75 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			VHDL
		
	
			
		
		
	
	
			75 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			VHDL
		
	
| library ieee;
 | |
| use ieee.std_logic_1164.all;
 | |
| use ieee.numeric_std.all;
 | |
| 
 | |
| entity soc_reset is
 | |
|     generic (
 | |
|         PLL_RESET_BITS   : integer := 5;
 | |
|         SOC_RESET_BITS   : integer := 5;
 | |
|         RESET_LOW        : boolean := true
 | |
|         );
 | |
|     port (
 | |
|         ext_clk       : in std_ulogic;
 | |
|         pll_clk       : in std_ulogic;
 | |
| 
 | |
|         pll_locked_in : in std_ulogic;
 | |
|         ext_rst_in    : in std_ulogic;
 | |
| 
 | |
|         pll_rst_out : out std_ulogic;
 | |
|         rst_out       : out std_ulogic
 | |
|         );
 | |
| end soc_reset;
 | |
| 
 | |
| architecture rtl of soc_reset is
 | |
|     signal ext_rst0_n    : std_ulogic;
 | |
|     signal ext_rst1_n    : std_ulogic := '0';
 | |
|     signal ext_rst2_n    : std_ulogic := '0';
 | |
|     signal rst0_n        : std_ulogic;
 | |
|     signal rst1_n        : std_ulogic := '0';
 | |
|     signal rst2_n        : std_ulogic := '0';
 | |
|     signal pll_rst_cnt   : std_ulogic_vector(PLL_RESET_BITS downto 0) := (others => '0');
 | |
|     signal soc_rst_cnt   : std_ulogic_vector(SOC_RESET_BITS downto 0) := (others => '0');
 | |
| begin
 | |
|     ext_rst0_n <= ext_rst_in when RESET_LOW else not ext_rst_in;
 | |
|     rst0_n <= ext_rst0_n and pll_locked_in and not pll_rst_out;
 | |
| 
 | |
|     -- PLL reset is active high
 | |
|     pll_rst_out <= not pll_rst_cnt(pll_rst_cnt'left);
 | |
|     -- Pass active high reset around
 | |
|     rst_out <= not soc_rst_cnt(soc_rst_cnt'left);
 | |
| 
 | |
|     -- Wait for external clock to become stable before starting the PLL
 | |
|     -- By the time the FPGA has been loaded the clock should be well and
 | |
|     -- truly stable, but lets give it a few cycles to be sure.
 | |
|     --
 | |
|     -- [BenH] Some designs seem to require a lot more..
 | |
|     pll_reset_0 : process(ext_clk)
 | |
|     begin
 | |
|         if (rising_edge(ext_clk)) then
 | |
|             ext_rst1_n <= ext_rst0_n;
 | |
|             ext_rst2_n <= ext_rst1_n;
 | |
|             if (ext_rst2_n = '0') then
 | |
|                 pll_rst_cnt <= (others => '0');
 | |
|             elsif (pll_rst_cnt(pll_rst_cnt'left) = '0') then
 | |
|                 pll_rst_cnt <= std_ulogic_vector(unsigned(pll_rst_cnt) + 1);
 | |
|             end if;
 | |
|         end if;
 | |
|     end process;
 | |
| 
 | |
|     -- Once our clock is stable and the external reset button isn't being
 | |
|     -- pressed, assert the SOC reset for long enough for the CPU pipeline
 | |
|     -- to clear completely.
 | |
|     soc_reset_0 : process(pll_clk)
 | |
|     begin
 | |
|         if (rising_edge(pll_clk)) then
 | |
|             rst1_n <= rst0_n;
 | |
|             rst2_n <= rst1_n;
 | |
|             if (rst2_n = '0') then
 | |
|                 soc_rst_cnt <= (others => '0');
 | |
|             elsif (soc_rst_cnt(soc_rst_cnt'left) = '0') then
 | |
|                 soc_rst_cnt <= std_ulogic_vector(unsigned(soc_rst_cnt) + 1);
 | |
|             end if;
 | |
|         end if;
 | |
|     end process;
 | |
| end rtl;
 |