Merge pull request #273 from antonblanchard/wishbone-checking
[microwatt.git] / fpga / soc_reset.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 entity soc_reset is
6 generic (
7 PLL_RESET_BITS : integer := 5;
8 SOC_RESET_BITS : integer := 5;
9 RESET_LOW : boolean := true
10 );
11 port (
12 ext_clk : in std_ulogic;
13 pll_clk : in std_ulogic;
14
15 pll_locked_in : in std_ulogic;
16 ext_rst_in : in std_ulogic;
17
18 pll_rst_out : out std_ulogic;
19 rst_out : out std_ulogic
20 );
21 end soc_reset;
22
23 architecture rtl of soc_reset is
24 signal ext_rst0_n : std_ulogic;
25 signal ext_rst1_n : std_ulogic := '0';
26 signal ext_rst2_n : std_ulogic := '0';
27 signal rst0_n : std_ulogic;
28 signal rst1_n : std_ulogic := '0';
29 signal rst2_n : std_ulogic := '0';
30 signal pll_rst_cnt : std_ulogic_vector(PLL_RESET_BITS downto 0) := (others => '0');
31 signal soc_rst_cnt : std_ulogic_vector(SOC_RESET_BITS downto 0) := (others => '0');
32 begin
33 ext_rst0_n <= ext_rst_in when RESET_LOW else not ext_rst_in;
34 rst0_n <= ext_rst0_n and pll_locked_in and not pll_rst_out;
35
36 -- PLL reset is active high
37 pll_rst_out <= not pll_rst_cnt(pll_rst_cnt'left);
38 -- Pass active high reset around
39 rst_out <= not soc_rst_cnt(soc_rst_cnt'left);
40
41 -- Wait for external clock to become stable before starting the PLL
42 -- By the time the FPGA has been loaded the clock should be well and
43 -- truly stable, but lets give it a few cycles to be sure.
44 --
45 -- [BenH] Some designs seem to require a lot more..
46 pll_reset_0 : process(ext_clk)
47 begin
48 if (rising_edge(ext_clk)) then
49 ext_rst1_n <= ext_rst0_n;
50 ext_rst2_n <= ext_rst1_n;
51 if (ext_rst2_n = '0') then
52 pll_rst_cnt <= (others => '0');
53 elsif (pll_rst_cnt(pll_rst_cnt'left) = '0') then
54 pll_rst_cnt <= std_ulogic_vector(unsigned(pll_rst_cnt) + 1);
55 end if;
56 end if;
57 end process;
58
59 -- Once our clock is stable and the external reset button isn't being
60 -- pressed, assert the SOC reset for long enough for the CPU pipeline
61 -- to clear completely.
62 soc_reset_0 : process(pll_clk)
63 begin
64 if (rising_edge(pll_clk)) then
65 rst1_n <= rst0_n;
66 rst2_n <= rst1_n;
67 if (rst2_n = '0') then
68 soc_rst_cnt <= (others => '0');
69 elsif (soc_rst_cnt(soc_rst_cnt'left) = '0') then
70 soc_rst_cnt <= std_ulogic_vector(unsigned(soc_rst_cnt) + 1);
71 end if;
72 end if;
73 end process;
74 end rtl;