fix trailing backslash that is confusing editors
[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 SIM_BRAM_CHAINBOOT : integer;
16 BRAM_SIZE : integer;
17 DRAM_SIZE : integer;
18 DRAM_INIT_SIZE : integer;
19 HAS_SPI_FLASH : boolean;
20 SPI_FLASH_OFFSET : integer;
21 HAS_LITEETH : boolean;
22 UART0_IS_16550 : boolean;
23 HAS_UART1 : boolean
24 );
25 port (
26 clk : in std_ulogic;
27 rst : in std_ulogic;
28
29 -- Wishbone ports:
30 wishbone_in : in wb_io_master_out;
31 wishbone_out : out wb_io_slave_out;
32
33 -- System control ports
34 dram_at_0 : out std_ulogic;
35 core_reset : out std_ulogic;
36 soc_reset : out std_ulogic
37 );
38 end entity syscon;
39
40
41 architecture behaviour of syscon is
42 -- Register address bits
43 constant SYS_REG_BITS : positive := 6;
44
45 -- Register addresses (matches wishbone addr downto 3, ie, 8 bytes per reg)
46 constant SYS_REG_SIG : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000000";
47 constant SYS_REG_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000001";
48 constant SYS_REG_BRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000010";
49 constant SYS_REG_DRAMINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000011";
50 constant SYS_REG_CLKINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000100";
51 constant SYS_REG_CTRL : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000101";
52 constant SYS_REG_DRAMINITINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000110";
53 constant SYS_REG_SPIFLASHINFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "000111";
54 constant SYS_REG_UART0_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001000";
55 constant SYS_REG_UART1_INFO : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001001";
56 constant SYS_REG_BRAM_BOOTADDR : std_ulogic_vector(SYS_REG_BITS-1 downto 0) := "001010";
57
58 -- Muxed reg read signal
59 signal reg_out : std_ulogic_vector(63 downto 0);
60
61 -- INFO register bits
62 constant SYS_REG_INFO_HAS_UART : integer := 0; -- Has a UART (always set)
63 constant SYS_REG_INFO_HAS_DRAM : integer := 1; -- Has DRAM
64 constant SYS_REG_INFO_HAS_BRAM : integer := 2; -- Has "main" BRAM
65 constant SYS_REG_INFO_HAS_SPIF : integer := 3; -- Has SPI flash
66 constant SYS_REG_INFO_HAS_LETH : integer := 4; -- Has LiteEth ethernet
67 constant SYS_REG_INFO_HAS_LSYS : integer := 5; -- Has 6-bit address syscon
68 constant SYS_REG_INFO_HAS_URT1 : integer := 6; -- Has second UART
69 constant SYS_REG_INFO_HAS_ARTB : integer := 7; -- Has architected TB frequency
70
71 -- BRAMINFO contains the BRAM size in the bottom 52 bits
72 -- DRAMINFO contains the DRAM size if any in the bottom 52 bits
73 -- (both have reserved top bits for future use)
74 -- CLKINFO contains the CLK frequency is HZ in the bottom 40 bits
75
76 -- CTRL register bits
77 constant SYS_REG_CTRL_BITS : positive := 3;
78 constant SYS_REG_CTRL_DRAM_AT_0 : integer := 0;
79 constant SYS_REG_CTRL_CORE_RESET : integer := 1;
80 constant SYS_REG_CTRL_SOC_RESET : integer := 2;
81
82 -- SPI Info register bits
83 --
84 -- Top 32-bit is flash offset which is the amount of flash
85 -- reserved for the FPGA bitfile if any
86 constant SYS_REG_SPI_INFO_IS_FLASH : integer := 0;
87
88 -- UART0/1 info registers bits
89 --
90 -- 0 ..31 : UART clock freq (in HZ)
91 -- 32 : UART is 16550 (otherwise pp)
92 --
93
94 -- Ctrl register
95 signal reg_ctrl : std_ulogic_vector(SYS_REG_CTRL_BITS-1 downto 0);
96 signal reg_ctrl_out : std_ulogic_vector(63 downto 0);
97
98 -- Others
99 signal reg_info : std_ulogic_vector(63 downto 0);
100 signal reg_braminfo : std_ulogic_vector(63 downto 0);
101 signal reg_draminfo : std_ulogic_vector(63 downto 0);
102 signal reg_dramiinfo : std_ulogic_vector(63 downto 0);
103 signal reg_clkinfo : std_ulogic_vector(63 downto 0);
104 signal reg_spiinfo : std_ulogic_vector(63 downto 0);
105 signal reg_uart0info : std_ulogic_vector(63 downto 0);
106 signal reg_uart1info : std_ulogic_vector(63 downto 0);
107 signal info_has_dram : std_ulogic;
108 signal info_has_bram : std_ulogic;
109 signal info_has_uart : std_ulogic;
110 signal info_has_spif : std_ulogic;
111 signal info_has_leth : std_ulogic;
112 signal info_has_urt1 : std_ulogic;
113 signal info_clk : std_ulogic_vector(39 downto 0);
114 signal info_fl_off : std_ulogic_vector(31 downto 0);
115 signal uinfo_16550 : std_ulogic;
116 signal uinfo_freq : std_ulogic_vector(31 downto 0);
117 signal reg_brambootaddr : std_ulogic_vector(63 downto 0);
118
119 -- Wishbone response latch
120 signal wb_rsp : wb_io_slave_out;
121 begin
122
123 -- Generated output signals
124 dram_at_0 <= '1' when BRAM_SIZE = 0 else reg_ctrl(SYS_REG_CTRL_DRAM_AT_0);
125 soc_reset <= reg_ctrl(SYS_REG_CTRL_SOC_RESET);
126 core_reset <= reg_ctrl(SYS_REG_CTRL_CORE_RESET);
127
128 -- Info register is hard wired
129 info_has_uart <= '1' when HAS_UART else '0';
130 info_has_dram <= '1' when HAS_DRAM else '0';
131 info_has_bram <= '1' when BRAM_SIZE /= 0 else '0';
132 info_has_spif <= '1' when HAS_SPI_FLASH else '0';
133 info_has_leth <= '1' when HAS_LITEETH else '0';
134 info_has_urt1 <= '1' when HAS_UART1 else '0';
135 info_clk <= std_ulogic_vector(to_unsigned(CLK_FREQ, 40));
136 reg_info <= (SYS_REG_INFO_HAS_UART => info_has_uart,
137 SYS_REG_INFO_HAS_DRAM => info_has_dram,
138 SYS_REG_INFO_HAS_BRAM => info_has_bram,
139 SYS_REG_INFO_HAS_SPIF => info_has_spif,
140 SYS_REG_INFO_HAS_LETH => info_has_leth,
141 SYS_REG_INFO_HAS_LSYS => '1',
142 SYS_REG_INFO_HAS_URT1 => info_has_urt1,
143 others => '0');
144
145 reg_brambootaddr <= std_ulogic_vector(to_unsigned(SIM_BRAM_CHAINBOOT, 64));
146 reg_braminfo <= x"000" & std_ulogic_vector(to_unsigned(BRAM_SIZE, 52));
147 reg_draminfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_SIZE, 52)) when HAS_DRAM
148 else (others => '0');
149 reg_dramiinfo <= x"000" & std_ulogic_vector(to_unsigned(DRAM_INIT_SIZE, 52)) when HAS_DRAM
150 else (others => '0');
151 reg_clkinfo <= (39 downto 0 => info_clk,
152 others => '0');
153 info_fl_off <= std_ulogic_vector(to_unsigned(SPI_FLASH_OFFSET, 32));
154 reg_spiinfo <= (31 downto 0 => info_fl_off,
155 others => '0');
156
157 -- Control register read composition
158 reg_ctrl_out <= (63 downto SYS_REG_CTRL_BITS => '0',
159 SYS_REG_CTRL_BITS-1 downto 0 => reg_ctrl);
160
161 -- UART info registers read composition
162 uinfo_16550 <= '1' when UART0_IS_16550 else '0';
163 uinfo_freq <= std_ulogic_vector(to_unsigned(CLK_FREQ, 32));
164 reg_uart0info <= (32 => uinfo_16550,
165 31 downto 0 => uinfo_freq,
166 others => '0');
167 reg_uart1info <= (32 => '1',
168 31 downto 0 => uinfo_freq,
169 others => '0');
170
171 -- Wishbone response
172 wb_rsp.ack <= wishbone_in.cyc and wishbone_in.stb;
173 with wishbone_in.adr(SYS_REG_BITS+2 downto 3) select reg_out <=
174 SIG_VALUE when SYS_REG_SIG,
175 reg_info when SYS_REG_INFO,
176 reg_braminfo when SYS_REG_BRAMINFO,
177 reg_draminfo when SYS_REG_DRAMINFO,
178 reg_dramiinfo when SYS_REG_DRAMINITINFO,
179 reg_clkinfo when SYS_REG_CLKINFO,
180 reg_ctrl_out when SYS_REG_CTRL,
181 reg_spiinfo when SYS_REG_SPIFLASHINFO,
182 reg_uart0info when SYS_REG_UART0_INFO,
183 reg_uart1info when SYS_REG_UART1_INFO,
184 reg_brambootaddr when SYS_REG_BRAM_BOOTADDR,
185 (others => '0') when others;
186 wb_rsp.dat <= reg_out(63 downto 32) when wishbone_in.adr(2) = '1' else
187 reg_out(31 downto 0);
188 wb_rsp.stall <= '0';
189
190 -- Wishbone response latch
191 regs_read: process(clk)
192 begin
193 if rising_edge(clk) then
194 -- Send response from latch
195 wishbone_out <= wb_rsp;
196 end if;
197 end process;
198
199 -- Register writes
200 regs_write: process(clk)
201 begin
202 if rising_edge(clk) then
203 if (rst) then
204 reg_ctrl <= (others => '0');
205 else
206 if wishbone_in.cyc and wishbone_in.stb and wishbone_in.we then
207 -- Change this if CTRL ever has more than 32 bits
208 if wishbone_in.adr(SYS_REG_BITS+2 downto 3) = SYS_REG_CTRL and
209 wishbone_in.adr(2) = '0' then
210 reg_ctrl(SYS_REG_CTRL_BITS-1 downto 0) <=
211 wishbone_in.dat(SYS_REG_CTRL_BITS-1 downto 0);
212 end if;
213 end if;
214
215 -- Reset auto-clear
216 if reg_ctrl(SYS_REG_CTRL_SOC_RESET) = '1' then
217 reg_ctrl(SYS_REG_CTRL_SOC_RESET) <= '0';
218 end if;
219 if reg_ctrl(SYS_REG_CTRL_CORE_RESET) = '1' then
220 reg_ctrl(SYS_REG_CTRL_CORE_RESET) <= '0';
221 end if;
222
223 -- If BRAM doesn't exist, force DRAM at 0
224 if BRAM_SIZE = 0 then
225 reg_ctrl(SYS_REG_CTRL_DRAM_AT_0) <= '1';
226 end if;
227 end if;
228 end if;
229 end process;
230
231 end architecture behaviour;