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