Merge pull request #191 from ozbenh/litedram
[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 DRAM_INIT_SIZE : integer
18 );
19 port (
20 clk : in std_ulogic;
21 rst : in std_ulogic;
22
23 -- Wishbone ports:
24 wishbone_in : in wb_io_master_out;
25 wishbone_out : out wb_io_slave_out;
26
27 -- System control ports
28 dram_at_0 : out std_ulogic;
29 core_reset : out std_ulogic;
30 soc_reset : out std_ulogic
31 );
32 end entity syscon;
33
34
35 architecture behaviour of syscon is
36 -- Register address bits
37 constant SYS_REG_BITS : positive := 3;
38
39 -- Register addresses (matches wishbone addr downto 3, ie, 8 bytes per reg)
40 constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000";
41 constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001";
42 constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "010";
43 constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "011";
44 constant SYS_REG_CLKINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "100";
45 constant SYS_REG_CTRL : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "101";
46 constant SYS_REG_DRAMINITINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "110";
47
48 -- Muxed reg read signal
49 signal reg_out : std_ulogic_vector(63 downto 0);
50
51 -- INFO register bits
52 constant SYS_REG_INFO_HAS_UART : integer := 0;
53 constant SYS_REG_INFO_HAS_DRAM : integer := 1;
54 constant SYS_REG_INFO_HAS_BRAM : integer := 2;
55
56 -- BRAMINFO contains the BRAM size in the bottom 52 bits
57 -- DRAMINFO contains the DRAM size if any in the bottom 52 bits
58 -- (both have reserved top bits for future use)
59 -- CLKINFO contains the CLK frequency is HZ in the bottom 40 bits
60
61 -- CTRL register bits
62 constant SYS_REG_CTRL_BITS : positive := 3;
63 constant SYS_REG_CTRL_DRAM_AT_0 : integer := 0;
64 constant SYS_REG_CTRL_CORE_RESET : integer := 1;
65 constant SYS_REG_CTRL_SOC_RESET : integer := 2;
66
67 -- Ctrl register
68 signal reg_ctrl : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0);
69 signal reg_ctrl_out : std_ulogic_vector(63 downto 0);
70
71 -- Others
72 signal reg_info : std_ulogic_vector(63 downto 0);
73 signal reg_braminfo : std_ulogic_vector(63 downto 0);
74 signal reg_draminfo : std_ulogic_vector(63 downto 0);
75 signal reg_dramiinfo : std_ulogic_vector(63 downto 0);
76 signal reg_clkinfo : std_ulogic_vector(63 downto 0);
77 signal info_has_dram : std_ulogic;
78 signal info_has_bram : std_ulogic;
79 signal info_has_uart : std_ulogic;
80 signal info_clk : std_ulogic_vector(39 downto 0);
81 begin
82
83 -- Generated output signals
84 dram_at_0 <= '1' when BRAM_SIZE = 0 else reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
85 soc_reset <= reg_ctrl(SYS_REG_CTRL_SOC_RESET);
86 core_reset <= reg_ctrl(SYS_REG_CTRL_CORE_RESET);
87
88 -- All register accesses are single cycle
89 wishbone_out.ack <= wishbone_in.cyc and wishbone_in.stb;
90 wishbone_out.stall <= '0';
91
92 -- Info register is hard wired
93 info_has_uart <= '1' when HAS_UART else '0';
94 info_has_dram <= '1' when HAS_DRAM else '0';
95 info_has_bram <= '1' when BRAM_SIZE /= 0 else '0';
96 info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
97 reg_info <= (0 => info_has_uart,
98 1 => info_has_dram,
99 2 => info_has_bram,
100 others => '0');
101 reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52));
102 reg_draminfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_SIZE, 52)) when HAS_DRAM
103 else (others => '0');
104 reg_dramiinfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_INIT_SIZE, 52)) when HAS_DRAM
105 else (others => '0');
106 reg_clkinfo <= (39 downto 0 => info_clk,
107 others => '0');
108
109 -- Control register read composition
110 reg_ctrl_out <= (63 downto SYS_REG_CTRL_BITS => '0',
111 SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);
112
113 -- Register read mux
114 with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select reg_out <=
115 SIG_VALUE when SYS_REG_SIG,
116 reg_info when SYS_REG_INFO,
117 reg_braminfo when SYS_REG_BRAMINFO,
118 reg_draminfo when SYS_REG_DRAMINFO,
119 reg_dramiinfo when SYS_REG_DRAMINITINFO,
120 reg_clkinfo when SYS_REG_CLKINFO,
121 reg_ctrl_out when SYS_REG_CTRL,
122 (others => '0') when others;
123 wishbone_out.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
124 reg_out(31 downto 0);
125
126 -- Register writes
127 regs_write: process(clk)
128 begin
129 if rising_edge(clk) then
130 if (rst) then
131 reg_ctrl <= (others => '0');
132 else
133 if wishbone_in.cyc and wishbone_in.stb and wishbone_in.we then
134 -- Change this if CTRL ever has more than 32 bits
135 if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL and
136 wishbone_in.adr(2) = '0' then
137 reg_ctrl(SYS_REG_CTRL_BITS-1 downto 0) <=
138 wishbone_in.dat(SYS_REG_CTRL_BITS-1 downto 0);
139 end if;
140 end if;
141
142 -- Reset auto-clear
143 if reg_ctrl(SYS_REG_CTRL_SOC_RESET) = '1' then
144 reg_ctrl(SYS_REG_CTRL_SOC_RESET) <= '0';
145 end if;
146 if reg_ctrl(SYS_REG_CTRL_CORE_RESET) = '1' then
147 reg_ctrl(SYS_REG_CTRL_CORE_RESET) <= '0';
148 end if;
149
150 -- If BRAM doesn't exist, force DRAM at 0
151 if BRAM_SIZE = 0 then
152 reg_ctrl(SYS_REG_CTRL_DRAM_AT_0) <= '1';
153 end if;
154 end if;
155 end if;
156 end process;
157
158 end architecture behaviour;