syscon: Add syscon registers
[microwatt.git] / syscon.vhdl
1 -- syscon module, a bunch of misc global system control MMIO registers
2 library ieee;
3 use ieee.std_logic_1164.all;
4 use ieee.numeric_std.all;
5
6 library work;
7 use work.wishbone_types.all;
8
9 entity syscon is
10 generic (
11 SIG_VALUE : std_ulogic_vector(63 downto 0) := x"f00daa5500010001";
12 CLK_FREQ : integer;
13 HAS_UART : boolean;
14 HAS_DRAM : boolean;
15 BRAM_SIZE : integer;
16 DRAM_SIZE : integer
17 );
18 port (
19 clk : in std_ulogic;
20 rst : in std_ulogic;
21
22 -- Wishbone ports:
23 wishbone_in : in wishbone_master_out;
24 wishbone_out : out wishbone_slave_out;
25
26 -- System control ports
27 dram_at_0 : out std_ulogic;
28 core_reset : out std_ulogic;
29 soc_reset : out std_ulogic
30 );
31 end entity syscon;
32
33
34 architecture behaviour of syscon is
35 -- Register address bits
36 constant SYS_REG_BITS : positive := 3;
37
38 -- Register addresses (matches wishbone addr downto 3, ie, 8 bytes per reg)
39 constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000";
40 constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001";
41 constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "010";
42 constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "011";
43 constant SYS_REG_CLKINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "100";
44 constant SYS_REG_CTRL : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "101";
45
46 -- INFO register bits
47 constant SYS_REG_INFO_HAS_UART : integer := 0;
48 constant SYS_REG_INFO_HAS_DRAM : integer := 1;
49
50 -- BRAMINFO contains the BRAM size in the bottom 52 bits
51 -- DRAMINFO contains the DRAM size if any in the bottom 52 bits
52 -- (both have reserved top bits for future use)
53 -- CLKINFO contains the CLK frequency is HZ in the bottom 40 bits
54
55 -- CTRL register bits
56 constant SYS_REG_CTRL_BITS : positive := 3;
57 constant SYS_REG_CTRL_DRAM_AT_0 : integer := 0;
58 constant SYS_REG_CTRL_CORE_RESET : integer := 1;
59 constant SYS_REG_CTRL_SOC_RESET : integer := 2;
60
61 -- Ctrl register
62 signal reg_ctrl : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0);
63 signal reg_ctrl_out : std_ulogic_vector(63 downto 0);
64
65 -- Others
66 signal reg_info : std_ulogic_vector(63 downto 0);
67 signal reg_braminfo : std_ulogic_vector(63 downto 0);
68 signal reg_draminfo : std_ulogic_vector(63 downto 0);
69 signal reg_clkinfo : std_ulogic_vector(63 downto 0);
70 signal info_has_dram : std_ulogic;
71 signal info_has_uart : std_ulogic;
72 signal info_clk : std_ulogic_vector(39 downto 0);
73 begin
74
75 -- Generated output signals
76 dram_at_0 <= reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
77 soc_reset <= reg_ctrl(SYS_REG_CTRL_SOC_RESET);
78 core_reset <= reg_ctrl(SYS_REG_CTRL_CORE_RESET);
79
80 -- All register accesses are single cycle
81 wishbone_out.ack <= wishbone_in.cyc and wishbone_in.stb;
82 wishbone_out.stall <= '0';
83
84 -- Info register is hard wired
85 info_has_uart <= '1' when HAS_UART else '0';
86 info_has_dram <= '1' when HAS_DRAM else '0';
87 info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
88 reg_info <= (0 => info_has_uart,
89 1 => info_has_dram,
90 others => '0');
91 reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52));
92 reg_draminfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_SIZE, 52)) when HAS_DRAM
93 else (others => '0');
94 reg_clkinfo <= (39 downto 0 => info_clk,
95 others => '0');
96
97 -- Control register read composition
98 reg_ctrl_out <= (63 downto SYS_REG_CTRL_BITS => '0',
99 SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);
100
101 -- Register read mux
102 with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select wishbone_out.dat <=
103 SIG_VALUE when SYS_REG_SIG,
104 reg_info when SYS_REG_INFO,
105 reg_braminfo when SYS_REG_BRAMINFO,
106 reg_draminfo when SYS_REG_DRAMINFO,
107 reg_clkinfo when SYS_REG_CLKINFO,
108 reg_ctrl_out when SYS_REG_CTRL,
109 (others => '0') when others;
110
111 -- Register writes
112 regs_write: process(clk)
113 begin
114 if rising_edge(clk) then
115 if (rst) then
116 reg_ctrl <= (others => '0');
117 else
118 if wishbone_in.cyc and wishbone_in.stb and wishbone_in.we then
119 if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL then
120 reg_ctrl(SYS_REG_CTRL_BITS-1 downto 0) <=
121 wishbone_in.dat(SYS_REG_CTRL_BITS-1 downto 0);
122 end if;
123 end if;
124
125 -- Reset auto-clear
126 if reg_ctrl(SYS_REG_CTRL_SOC_RESET) = '1' then
127 reg_ctrl(SYS_REG_CTRL_SOC_RESET) <= '0';
128 end if;
129 if reg_ctrl(SYS_REG_CTRL_CORE_RESET) = '1' then
130 reg_ctrl(SYS_REG_CTRL_CORE_RESET) <= '0';
131 end if;
132 end if;
133 end if;
134 end process;
135
136 end architecture behaviour;