|
|
|
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;
|