Add initial Arctic Tern support
[microwatt.git] / fpga / top-rcs-arctic-tern-bmc-card.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library work;
6 use work.wishbone_types.all;
7
8 entity toplevel is
9 generic (
10 MEMORY_SIZE : integer := 16384;
11 RAM_INIT_FILE : string := "firmware.hex";
12 RESET_LOW : boolean := true;
13 CLK_INPUT : positive := 125000000;
14 CLK_FREQUENCY : positive := 48000000;
15 HAS_FPU : boolean := true;
16 HAS_BTC : boolean := false;
17 USE_LITEDRAM : boolean := true;
18 NO_BRAM : boolean := true;
19 SCLK_STARTUPE2 : boolean := false;
20 SPI_FLASH_OFFSET : integer := 4194304;
21 SPI_FLASH_DEF_CKDV : natural := 1;
22 SPI_FLASH_DEF_QUAD : boolean := true;
23 LOG_LENGTH : natural := 0;
24 USE_LITEETH : boolean := true;
25 UART_IS_16550 : boolean := true;
26 HAS_UART1 : boolean := false;
27 ICACHE_NUM_LINES : natural := 64
28 );
29 port(
30 ext_clk : in std_ulogic;
31 ext_rst_n : in std_ulogic;
32
33 -- UART0 signals:
34 uart0_txd : out std_ulogic;
35 uart0_rxd : in std_ulogic;
36
37 -- SPI
38 spi_flash_cs_n : out std_ulogic;
39 spi_flash_mosi : inout std_ulogic;
40 spi_flash_miso : inout std_ulogic;
41 spi_flash_wp_n : inout std_ulogic;
42 spi_flash_hold_n : inout std_ulogic;
43
44 -- Ethernet
45 eth_clocks_tx : out std_ulogic;
46 eth_clocks_rx : in std_ulogic;
47 eth_mdio : inout std_ulogic;
48 eth_mdc : out std_ulogic;
49 eth_rx_ctl : in std_ulogic;
50 eth_rx_data : in std_ulogic_vector(3 downto 0);
51 eth_tx_ctl : out std_ulogic;
52 eth_tx_data : out std_ulogic_vector(3 downto 0);
53
54 -- DRAM wires
55 ddram_a : out std_ulogic_vector(13 downto 0);
56 ddram_ba : out std_ulogic_vector(2 downto 0);
57 ddram_ras_n : out std_ulogic;
58 ddram_cas_n : out std_ulogic;
59 ddram_we_n : out std_ulogic;
60 ddram_cs_n : out std_ulogic;
61 ddram_dm : out std_ulogic_vector(3 downto 0);
62 ddram_dq : inout std_ulogic_vector(31 downto 0);
63 ddram_dqs_p : inout std_ulogic_vector(3 downto 0);
64 ddram_clk_p : out std_ulogic_vector(1 downto 0);
65 -- only the positive differential pin is instantiated
66 --ddram_dqs_n : inout std_ulogic_vector(3 downto 0);
67 --ddram_clk_n : out std_ulogic_vector(1 downto 0);
68 ddram_cke : out std_ulogic;
69 ddram_odt : out std_ulogic;
70 ddram_reset_n : out std_ulogic
71 );
72 end entity toplevel;
73
74 architecture behaviour of toplevel is
75
76 -- Reset signals:
77 signal soc_rst : std_ulogic;
78 signal pll_rst : std_ulogic;
79
80 -- Internal clock signals:
81 signal system_clk : std_ulogic;
82 signal system_clk_locked : std_ulogic;
83
84 -- External IOs from the SoC
85 signal wb_ext_io_in : wb_io_master_out;
86 signal wb_ext_io_out : wb_io_slave_out;
87 signal wb_ext_is_dram_csr : std_ulogic;
88 signal wb_ext_is_dram_init : std_ulogic;
89 signal wb_ext_is_eth : std_ulogic;
90
91 -- DRAM main data wishbone connection
92 signal wb_dram_in : wishbone_master_out;
93 signal wb_dram_out : wishbone_slave_out;
94
95 -- DRAM control wishbone connection
96 signal wb_dram_ctrl_out : wb_io_slave_out := wb_io_slave_out_init;
97
98 -- LiteEth connection
99 signal ext_irq_eth : std_ulogic;
100 signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init;
101
102 -- Control/status
103 signal core_alt_reset : std_ulogic;
104
105 -- SPI flash
106 signal spi_sck : std_ulogic;
107 signal spi_cs_n : std_ulogic;
108 signal spi_sdat_o : std_ulogic_vector(3 downto 0);
109 signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
110 signal spi_sdat_i : std_ulogic_vector(3 downto 0);
111
112 -- Fixup various memory sizes based on generics
113 function get_bram_size return natural is
114 begin
115 if USE_LITEDRAM and NO_BRAM then
116 return 0;
117 else
118 return MEMORY_SIZE;
119 end if;
120 end function;
121
122 function get_payload_size return natural is
123 begin
124 if USE_LITEDRAM and NO_BRAM then
125 return MEMORY_SIZE;
126 else
127 return 0;
128 end if;
129 end function;
130
131 constant BRAM_SIZE : natural := get_bram_size;
132 constant PAYLOAD_SIZE : natural := get_payload_size;
133
134 COMPONENT USRMCLK
135 PORT(
136 USRMCLKI : IN STD_ULOGIC;
137 USRMCLKTS : IN STD_ULOGIC
138 );
139 END COMPONENT;
140 attribute syn_noprune: boolean ;
141 attribute syn_noprune of USRMCLK: component is true;
142
143 begin
144
145 -- Main SoC
146 soc0: entity work.soc
147 generic map(
148 MEMORY_SIZE => BRAM_SIZE,
149 RAM_INIT_FILE => RAM_INIT_FILE,
150 SIM => false,
151 CLK_FREQ => CLK_FREQUENCY,
152 HAS_FPU => HAS_FPU,
153 HAS_BTC => HAS_BTC,
154 HAS_DRAM => USE_LITEDRAM,
155 DRAM_SIZE => 256 * 1024 * 1024,
156 DRAM_INIT_SIZE => PAYLOAD_SIZE,
157 HAS_SPI_FLASH => true,
158 SPI_FLASH_DLINES => 4,
159 SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
160 SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
161 SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
162 LOG_LENGTH => LOG_LENGTH,
163 UART0_IS_16550 => UART_IS_16550,
164 HAS_UART1 => HAS_UART1,
165 ICACHE_NUM_LINES => ICACHE_NUM_LINES
166 )
167 port map (
168 -- System signals
169 system_clk => system_clk,
170 rst => soc_rst,
171
172 -- UART signals
173 uart0_txd => uart0_txd,
174 uart0_rxd => uart0_rxd,
175
176 -- SPI signals
177 spi_flash_sck => spi_sck,
178 spi_flash_cs_n => spi_cs_n,
179 spi_flash_sdat_o => spi_sdat_o,
180 spi_flash_sdat_oe => spi_sdat_oe,
181 spi_flash_sdat_i => spi_sdat_i,
182
183 -- DRAM wishbone
184 wb_dram_in => wb_dram_in,
185 wb_dram_out => wb_dram_out,
186
187 -- External interrupts
188 ext_irq_eth => ext_irq_eth,
189
190 -- IO wishbone
191 wb_ext_io_in => wb_ext_io_in,
192 wb_ext_io_out => wb_ext_io_out,
193 wb_ext_is_dram_csr => wb_ext_is_dram_csr,
194 wb_ext_is_dram_init => wb_ext_is_dram_init,
195 wb_ext_is_eth => wb_ext_is_eth,
196
197 alt_reset => core_alt_reset
198 );
199
200 -- SPI Flash
201 --
202 spi_flash_cs_n <= spi_cs_n;
203 spi_flash_mosi <= spi_sdat_o(0) when spi_sdat_oe(0) = '1' else 'Z';
204 spi_flash_miso <= spi_sdat_o(1) when spi_sdat_oe(1) = '1' else 'Z';
205 spi_flash_wp_n <= spi_sdat_o(2) when spi_sdat_oe(2) = '1' else 'Z';
206 spi_flash_hold_n <= spi_sdat_o(3) when spi_sdat_oe(3) = '1' else 'Z';
207 spi_sdat_i(0) <= spi_flash_mosi;
208 spi_sdat_i(1) <= spi_flash_miso;
209 spi_sdat_i(2) <= spi_flash_wp_n;
210 spi_sdat_i(3) <= spi_flash_hold_n;
211
212 uclk: USRMCLK port map (
213 USRMCLKI => spi_sck,
214 USRMCLKTS => '0'
215 );
216
217 nodram: if not USE_LITEDRAM generate
218 signal ddram_clk_dummy : std_ulogic;
219 begin
220 reset_controller: entity work.soc_reset
221 generic map(
222 RESET_LOW => RESET_LOW
223 )
224 port map(
225 ext_clk => ext_clk,
226 pll_clk => system_clk,
227 pll_locked_in => system_clk_locked,
228 ext_rst_in => ext_rst_n,
229 pll_rst_out => pll_rst,
230 rst_out => soc_rst
231 );
232
233 clkgen: entity work.clock_generator
234 generic map(
235 CLK_INPUT_HZ => CLK_INPUT,
236 CLK_OUTPUT_HZ => CLK_FREQUENCY
237 )
238 port map(
239 ext_clk => ext_clk,
240 pll_rst_in => pll_rst,
241 pll_clk_out => system_clk,
242 pll_locked_out => system_clk_locked
243 );
244
245 core_alt_reset <= '0';
246
247 end generate;
248
249 has_dram: if USE_LITEDRAM generate
250 signal dram_init_done : std_ulogic;
251 signal dram_init_error : std_ulogic;
252 signal dram_sys_rst : std_ulogic;
253 signal rst_gen_rst : std_ulogic;
254 begin
255
256 -- Eventually dig out the frequency from
257 -- litesdram generate.py sys_clk_freq
258 -- but for now, assert it's 48Mhz for Arctic Tern
259 assert CLK_FREQUENCY = 48000000;
260
261 reset_controller: entity work.soc_reset
262 generic map(
263 RESET_LOW => RESET_LOW,
264 PLL_RESET_BITS => 18,
265 SOC_RESET_BITS => 1
266 )
267 port map(
268 ext_clk => ext_clk,
269 pll_clk => system_clk,
270 pll_locked_in => system_clk_locked,
271 ext_rst_in => ext_rst_n,
272 pll_rst_out => pll_rst,
273 rst_out => rst_gen_rst
274 );
275
276 -- Generate SoC reset
277 soc_rst_gen: process(system_clk)
278 begin
279 if ext_rst_n = '0' then
280 soc_rst <= '1';
281 elsif rising_edge(system_clk) then
282 soc_rst <= dram_sys_rst or not system_clk_locked;
283 end if;
284 end process;
285
286 dram: entity work.litedram_wrapper
287 generic map(
288 DRAM_ABITS => 24,
289 DRAM_ALINES => 14,
290 DRAM_DLINES => 32,
291 DRAM_CKLINES => 2,
292 DRAM_PORT_WIDTH => 128,
293 NUM_LINES => 8, -- reduce from default of 64 to make smaller/timing
294 PAYLOAD_FILE => RAM_INIT_FILE,
295 PAYLOAD_SIZE => PAYLOAD_SIZE
296 )
297 port map(
298 clk_in => ext_clk,
299 rst => pll_rst,
300 system_clk => system_clk,
301 system_reset => dram_sys_rst,
302 core_alt_reset => core_alt_reset,
303 pll_locked => system_clk_locked,
304
305 wb_in => wb_dram_in,
306 wb_out => wb_dram_out,
307 wb_ctrl_in => wb_ext_io_in,
308 wb_ctrl_out => wb_dram_ctrl_out,
309 wb_ctrl_is_csr => wb_ext_is_dram_csr,
310 wb_ctrl_is_init => wb_ext_is_dram_init,
311
312 init_done => dram_init_done,
313 init_error => dram_init_error,
314
315 ddram_a => ddram_a,
316 ddram_ba => ddram_ba,
317 ddram_ras_n => ddram_ras_n,
318 ddram_cas_n => ddram_cas_n,
319 ddram_we_n => ddram_we_n,
320 ddram_cs_n => ddram_cs_n,
321 ddram_dm => ddram_dm,
322 ddram_dq => ddram_dq,
323 ddram_dqs_p => ddram_dqs_p,
324 ddram_clk_p => ddram_clk_p,
325 -- only the positive differential pin is instantiated
326 --ddram_dqs_n => ddram_dqs_n,
327 --ddram_clk_n => ddram_clk_n,
328 ddram_cke => ddram_cke,
329 ddram_odt => ddram_odt,
330
331 ddram_reset_n => ddram_reset_n
332 );
333
334 end generate;
335
336 has_liteeth : if USE_LITEETH generate
337
338 component liteeth_core port (
339 sys_clock : in std_ulogic;
340 sys_reset : in std_ulogic;
341 rgmii_eth_clocks_tx : out std_ulogic;
342 rgmii_eth_clocks_rx : in std_ulogic;
343 rgmii_eth_mdio : inout std_ulogic;
344 rgmii_eth_mdc : out std_ulogic;
345 rgmii_eth_rx_ctl : in std_ulogic;
346 rgmii_eth_rx_data : in std_ulogic_vector(3 downto 0);
347 rgmii_eth_tx_ctl : out std_ulogic;
348 rgmii_eth_tx_data : out std_ulogic_vector(3 downto 0);
349 wishbone_adr : in std_ulogic_vector(29 downto 0);
350 wishbone_dat_w : in std_ulogic_vector(31 downto 0);
351 wishbone_dat_r : out std_ulogic_vector(31 downto 0);
352 wishbone_sel : in std_ulogic_vector(3 downto 0);
353 wishbone_cyc : in std_ulogic;
354 wishbone_stb : in std_ulogic;
355 wishbone_ack : out std_ulogic;
356 wishbone_we : in std_ulogic;
357 wishbone_cti : in std_ulogic_vector(2 downto 0);
358 wishbone_bte : in std_ulogic_vector(1 downto 0);
359 wishbone_err : out std_ulogic;
360 interrupt : out std_ulogic
361 );
362 end component;
363
364 signal wb_eth_cyc : std_ulogic;
365 signal wb_eth_adr : std_ulogic_vector(29 downto 0);
366
367 begin
368 liteeth : liteeth_core
369 port map(
370 sys_clock => system_clk,
371 sys_reset => soc_rst,
372 rgmii_eth_clocks_tx => eth_clocks_tx,
373 rgmii_eth_clocks_rx => eth_clocks_rx,
374 rgmii_eth_mdio => eth_mdio,
375 rgmii_eth_mdc => eth_mdc,
376 rgmii_eth_rx_ctl => eth_rx_ctl,
377 rgmii_eth_rx_data => eth_rx_data,
378 rgmii_eth_tx_ctl => eth_tx_ctl,
379 rgmii_eth_tx_data => eth_tx_data,
380 wishbone_adr => wb_eth_adr,
381 wishbone_dat_w => wb_ext_io_in.dat,
382 wishbone_dat_r => wb_eth_out.dat,
383 wishbone_sel => wb_ext_io_in.sel,
384 wishbone_cyc => wb_eth_cyc,
385 wishbone_stb => wb_ext_io_in.stb,
386 wishbone_ack => wb_eth_out.ack,
387 wishbone_we => wb_ext_io_in.we,
388 wishbone_cti => "000",
389 wishbone_bte => "00",
390 wishbone_err => open,
391 interrupt => ext_irq_eth
392 );
393
394 -- Gate cyc with "chip select" from soc
395 wb_eth_cyc <= wb_ext_io_in.cyc and wb_ext_is_eth;
396
397 -- Remove top address bits as liteeth decoder doesn't know about them
398 wb_eth_adr <= x"000" & "000" & wb_ext_io_in.adr(14 downto 0);
399
400 -- LiteETH isn't pipelined
401 wb_eth_out.stall <= not wb_eth_out.ack;
402
403 end generate;
404
405 no_liteeth : if not USE_LITEETH generate
406 ext_irq_eth <= '0';
407 end generate;
408
409 -- Mux WB response on the IO bus
410 wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else
411 wb_dram_ctrl_out;
412
413 end architecture behaviour;