Merge pull request #235 from paulusmack/master
[microwatt.git] / fpga / top-arty.vhdl
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4
5 library unisim;
6 use unisim.vcomponents.all;
7
8 library work;
9 use work.wishbone_types.all;
10
11 entity toplevel is
12 generic (
13 MEMORY_SIZE : integer := 16384;
14 RAM_INIT_FILE : string := "firmware.hex";
15 RESET_LOW : boolean := true;
16 CLK_FREQUENCY : positive := 100000000;
17 USE_LITEDRAM : boolean := false;
18 NO_BRAM : boolean := false;
19 DISABLE_FLATTEN_CORE : boolean := false;
20 SCLK_STARTUPE2 : boolean := false;
21 SPI_FLASH_OFFSET : integer := 4194304;
22 SPI_FLASH_DEF_CKDV : natural := 1;
23 SPI_FLASH_DEF_QUAD : boolean := true;
24 LOG_LENGTH : natural := 512;
25 USE_LITEETH : boolean := false;
26 UART_IS_16550 : boolean := false;
27 HAS_UART1 : boolean := true
28 );
29 port(
30 ext_clk : in std_ulogic;
31 ext_rst_n : in std_ulogic;
32
33 -- UART0 signals:
34 uart_main_tx : out std_ulogic;
35 uart_main_rx : in std_ulogic;
36
37 -- UART1 signals:
38 uart_pmod_tx : out std_ulogic;
39 uart_pmod_rx : in std_ulogic;
40 uart_pmod_cts_n : in std_ulogic;
41 uart_pmod_rts_n : out std_ulogic;
42
43 -- LEDs
44 led0_b : out std_ulogic;
45 led0_g : out std_ulogic;
46 led0_r : out std_ulogic;
47 led4 : out std_ulogic;
48 led5 : out std_ulogic;
49 led6 : out std_ulogic;
50 led7 : out std_ulogic;
51
52 -- SPI
53 spi_flash_cs_n : out std_ulogic;
54 spi_flash_clk : out std_ulogic;
55 spi_flash_mosi : inout std_ulogic;
56 spi_flash_miso : inout std_ulogic;
57 spi_flash_wp_n : inout std_ulogic;
58 spi_flash_hold_n : inout std_ulogic;
59
60 -- Ethernet
61 eth_ref_clk : out std_ulogic;
62 eth_clocks_tx : in std_ulogic;
63 eth_clocks_rx : in std_ulogic;
64 eth_rst_n : out std_ulogic;
65 eth_mdio : inout std_ulogic;
66 eth_mdc : out std_ulogic;
67 eth_rx_dv : in std_ulogic;
68 eth_rx_er : in std_ulogic;
69 eth_rx_data : in std_ulogic_vector(3 downto 0);
70 eth_tx_en : out std_ulogic;
71 eth_tx_data : out std_ulogic_vector(3 downto 0);
72 eth_col : in std_ulogic;
73 eth_crs : in std_ulogic;
74
75 -- DRAM wires
76 ddram_a : out std_ulogic_vector(13 downto 0);
77 ddram_ba : out std_ulogic_vector(2 downto 0);
78 ddram_ras_n : out std_ulogic;
79 ddram_cas_n : out std_ulogic;
80 ddram_we_n : out std_ulogic;
81 ddram_cs_n : out std_ulogic;
82 ddram_dm : out std_ulogic_vector(1 downto 0);
83 ddram_dq : inout std_ulogic_vector(15 downto 0);
84 ddram_dqs_p : inout std_ulogic_vector(1 downto 0);
85 ddram_dqs_n : inout std_ulogic_vector(1 downto 0);
86 ddram_clk_p : out std_ulogic;
87 ddram_clk_n : out std_ulogic;
88 ddram_cke : out std_ulogic;
89 ddram_odt : out std_ulogic;
90 ddram_reset_n : out std_ulogic
91 );
92 end entity toplevel;
93
94 architecture behaviour of toplevel is
95
96 -- Reset signals:
97 signal soc_rst : std_ulogic;
98 signal pll_rst : std_ulogic;
99
100 -- Internal clock signals:
101 signal system_clk : std_ulogic;
102 signal system_clk_locked : std_ulogic;
103 signal eth_clk_locked : std_ulogic;
104
105 -- External IOs from the SoC
106 signal wb_ext_io_in : wb_io_master_out;
107 signal wb_ext_io_out : wb_io_slave_out;
108 signal wb_ext_is_dram_csr : std_ulogic;
109 signal wb_ext_is_dram_init : std_ulogic;
110 signal wb_ext_is_eth : std_ulogic;
111
112 -- DRAM main data wishbone connection
113 signal wb_dram_in : wishbone_master_out;
114 signal wb_dram_out : wishbone_slave_out;
115
116 -- DRAM control wishbone connection
117 signal wb_dram_ctrl_out : wb_io_slave_out := wb_io_slave_out_init;
118
119 -- LiteEth connection
120 signal ext_irq_eth : std_ulogic;
121 signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init;
122
123 -- Control/status
124 signal core_alt_reset : std_ulogic;
125
126 -- Status LED
127 signal led0_b_pwm : std_ulogic;
128 signal led0_r_pwm : std_ulogic;
129 signal led0_g_pwm : std_ulogic;
130
131 -- Dumb PWM for the LEDs, those RGB LEDs are too bright otherwise
132 signal pwm_counter : std_ulogic_vector(8 downto 0);
133
134 -- SPI flash
135 signal spi_sck : std_ulogic;
136 signal spi_cs_n : std_ulogic;
137 signal spi_sdat_o : std_ulogic_vector(3 downto 0);
138 signal spi_sdat_oe : std_ulogic_vector(3 downto 0);
139 signal spi_sdat_i : std_ulogic_vector(3 downto 0);
140
141 -- Fixup various memory sizes based on generics
142 function get_bram_size return natural is
143 begin
144 if USE_LITEDRAM and NO_BRAM then
145 return 0;
146 else
147 return MEMORY_SIZE;
148 end if;
149 end function;
150
151 function get_payload_size return natural is
152 begin
153 if USE_LITEDRAM and NO_BRAM then
154 return MEMORY_SIZE;
155 else
156 return 0;
157 end if;
158 end function;
159
160 constant BRAM_SIZE : natural := get_bram_size;
161 constant PAYLOAD_SIZE : natural := get_payload_size;
162 begin
163
164 -- Main SoC
165 soc0: entity work.soc
166 generic map(
167 MEMORY_SIZE => BRAM_SIZE,
168 RAM_INIT_FILE => RAM_INIT_FILE,
169 SIM => false,
170 CLK_FREQ => CLK_FREQUENCY,
171 HAS_DRAM => USE_LITEDRAM,
172 DRAM_SIZE => 256 * 1024 * 1024,
173 DRAM_INIT_SIZE => PAYLOAD_SIZE,
174 DISABLE_FLATTEN_CORE => DISABLE_FLATTEN_CORE,
175 HAS_SPI_FLASH => true,
176 SPI_FLASH_DLINES => 4,
177 SPI_FLASH_OFFSET => SPI_FLASH_OFFSET,
178 SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV,
179 SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD,
180 LOG_LENGTH => LOG_LENGTH,
181 HAS_LITEETH => USE_LITEETH,
182 UART0_IS_16550 => UART_IS_16550,
183 HAS_UART1 => HAS_UART1
184 )
185 port map (
186 -- System signals
187 system_clk => system_clk,
188 rst => soc_rst,
189
190 -- UART signals
191 uart0_txd => uart_main_tx,
192 uart0_rxd => uart_main_rx,
193
194 -- UART1 signals
195 uart1_txd => uart_pmod_tx,
196 uart1_rxd => uart_pmod_rx,
197
198 -- SPI signals
199 spi_flash_sck => spi_sck,
200 spi_flash_cs_n => spi_cs_n,
201 spi_flash_sdat_o => spi_sdat_o,
202 spi_flash_sdat_oe => spi_sdat_oe,
203 spi_flash_sdat_i => spi_sdat_i,
204
205 -- External interrupts
206 ext_irq_eth => ext_irq_eth,
207
208 -- DRAM wishbone
209 wb_dram_in => wb_dram_in,
210 wb_dram_out => wb_dram_out,
211 wb_ext_io_in => wb_ext_io_in,
212 wb_ext_io_out => wb_ext_io_out,
213 wb_ext_is_dram_csr => wb_ext_is_dram_csr,
214 wb_ext_is_dram_init => wb_ext_is_dram_init,
215 wb_ext_is_eth => wb_ext_is_eth,
216 alt_reset => core_alt_reset
217 );
218
219 uart_pmod_rts_n <= '0';
220
221 -- SPI Flash
222 --
223 -- Note: Unlike many other boards, the SPI flash on the Arty has
224 -- an actual pin to generate the clock and doesn't require to use
225 -- the STARTUPE2 primitive.
226 --
227 spi_flash_cs_n <= spi_cs_n;
228 spi_flash_mosi <= spi_sdat_o(0) when spi_sdat_oe(0) = '1' else 'Z';
229 spi_flash_miso <= spi_sdat_o(1) when spi_sdat_oe(1) = '1' else 'Z';
230 spi_flash_wp_n <= spi_sdat_o(2) when spi_sdat_oe(2) = '1' else 'Z';
231 spi_flash_hold_n <= spi_sdat_o(3) when spi_sdat_oe(3) = '1' else 'Z';
232 spi_sdat_i(0) <= spi_flash_mosi;
233 spi_sdat_i(1) <= spi_flash_miso;
234 spi_sdat_i(2) <= spi_flash_wp_n;
235 spi_sdat_i(3) <= spi_flash_hold_n;
236
237 spi_sclk_startupe2: if SCLK_STARTUPE2 generate
238 spi_flash_clk <= 'Z';
239
240 STARTUPE2_INST: STARTUPE2
241 port map (
242 CLK => '0',
243 GSR => '0',
244 GTS => '0',
245 KEYCLEARB => '0',
246 PACK => '0',
247 USRCCLKO => spi_sck,
248 USRCCLKTS => '0',
249 USRDONEO => '1',
250 USRDONETS => '0'
251 );
252 end generate;
253
254 spi_direct_sclk: if not SCLK_STARTUPE2 generate
255 spi_flash_clk <= spi_sck;
256 end generate;
257
258 nodram: if not USE_LITEDRAM generate
259 signal ddram_clk_dummy : std_ulogic;
260 begin
261 reset_controller: entity work.soc_reset
262 generic map(
263 RESET_LOW => RESET_LOW
264 )
265 port map(
266 ext_clk => ext_clk,
267 pll_clk => system_clk,
268 pll_locked_in => system_clk_locked and eth_clk_locked,
269 ext_rst_in => ext_rst_n,
270 pll_rst_out => pll_rst,
271 rst_out => soc_rst
272 );
273
274 clkgen: entity work.clock_generator
275 generic map(
276 CLK_INPUT_HZ => 100000000,
277 CLK_OUTPUT_HZ => CLK_FREQUENCY
278 )
279 port map(
280 ext_clk => ext_clk,
281 pll_rst_in => pll_rst,
282 pll_clk_out => system_clk,
283 pll_locked_out => system_clk_locked
284 );
285
286 led0_b_pwm <= '1';
287 led0_r_pwm <= '1';
288 led0_g_pwm <= '0';
289 core_alt_reset <= '0';
290
291 -- Vivado barfs on those differential signals if left
292 -- unconnected. So instanciate a diff. buffer and feed
293 -- it a constant '0'.
294 dummy_dram_clk: OBUFDS
295 port map (
296 O => ddram_clk_p,
297 OB => ddram_clk_n,
298 I => ddram_clk_dummy
299 );
300 ddram_clk_dummy <= '0';
301
302 end generate;
303
304 has_dram: if USE_LITEDRAM generate
305 signal dram_init_done : std_ulogic;
306 signal dram_init_error : std_ulogic;
307 signal dram_sys_rst : std_ulogic;
308 signal rst_gen_rst : std_ulogic;
309 begin
310
311 -- Eventually dig out the frequency from the generator
312 -- but for now, assert it's 100Mhz
313 assert CLK_FREQUENCY = 100000000;
314
315 reset_controller: entity work.soc_reset
316 generic map(
317 RESET_LOW => RESET_LOW,
318 PLL_RESET_BITS => 18,
319 SOC_RESET_BITS => 1
320 )
321 port map(
322 ext_clk => ext_clk,
323 pll_clk => system_clk,
324 pll_locked_in => eth_clk_locked,
325 ext_rst_in => ext_rst_n,
326 pll_rst_out => pll_rst,
327 rst_out => rst_gen_rst
328 );
329
330 -- Generate SoC reset
331 soc_rst_gen: process(system_clk)
332 begin
333 if ext_rst_n = '0' then
334 soc_rst <= '1';
335 elsif rising_edge(system_clk) then
336 soc_rst <= dram_sys_rst or not eth_clk_locked or not system_clk_locked;
337 end if;
338 end process;
339
340 dram: entity work.litedram_wrapper
341 generic map(
342 DRAM_ABITS => 24,
343 DRAM_ALINES => 14,
344 DRAM_DLINES => 16,
345 DRAM_PORT_WIDTH => 128,
346 PAYLOAD_FILE => RAM_INIT_FILE,
347 PAYLOAD_SIZE => PAYLOAD_SIZE
348 )
349 port map(
350 clk_in => ext_clk,
351 rst => pll_rst,
352 system_clk => system_clk,
353 system_reset => dram_sys_rst,
354 core_alt_reset => core_alt_reset,
355 pll_locked => system_clk_locked,
356
357 wb_in => wb_dram_in,
358 wb_out => wb_dram_out,
359 wb_ctrl_in => wb_ext_io_in,
360 wb_ctrl_out => wb_dram_ctrl_out,
361 wb_ctrl_is_csr => wb_ext_is_dram_csr,
362 wb_ctrl_is_init => wb_ext_is_dram_init,
363
364 init_done => dram_init_done,
365 init_error => dram_init_error,
366
367 ddram_a => ddram_a,
368 ddram_ba => ddram_ba,
369 ddram_ras_n => ddram_ras_n,
370 ddram_cas_n => ddram_cas_n,
371 ddram_we_n => ddram_we_n,
372 ddram_cs_n => ddram_cs_n,
373 ddram_dm => ddram_dm,
374 ddram_dq => ddram_dq,
375 ddram_dqs_p => ddram_dqs_p,
376 ddram_dqs_n => ddram_dqs_n,
377 ddram_clk_p => ddram_clk_p,
378 ddram_clk_n => ddram_clk_n,
379 ddram_cke => ddram_cke,
380 ddram_odt => ddram_odt,
381 ddram_reset_n => ddram_reset_n
382 );
383
384 led0_b_pwm <= not dram_init_done;
385 led0_r_pwm <= dram_init_error;
386 led0_g_pwm <= dram_init_done and not dram_init_error;
387
388 end generate;
389
390 has_liteeth : if USE_LITEETH generate
391
392 component liteeth_core port (
393 sys_clock : in std_ulogic;
394 sys_reset : in std_ulogic;
395 mii_eth_clocks_tx : in std_ulogic;
396 mii_eth_clocks_rx : in std_ulogic;
397 mii_eth_rst_n : out std_ulogic;
398 mii_eth_mdio : in std_ulogic;
399 mii_eth_mdc : out std_ulogic;
400 mii_eth_rx_dv : in std_ulogic;
401 mii_eth_rx_er : in std_ulogic;
402 mii_eth_rx_data : in std_ulogic_vector(3 downto 0);
403 mii_eth_tx_en : out std_ulogic;
404 mii_eth_tx_data : out std_ulogic_vector(3 downto 0);
405 mii_eth_col : in std_ulogic;
406 mii_eth_crs : in std_ulogic;
407 wishbone_adr : in std_ulogic_vector(29 downto 0);
408 wishbone_dat_w : in std_ulogic_vector(31 downto 0);
409 wishbone_dat_r : out std_ulogic_vector(31 downto 0);
410 wishbone_sel : in std_ulogic_vector(3 downto 0);
411 wishbone_cyc : in std_ulogic;
412 wishbone_stb : in std_ulogic;
413 wishbone_ack : out std_ulogic;
414 wishbone_we : in std_ulogic;
415 wishbone_cti : in std_ulogic_vector(2 downto 0);
416 wishbone_bte : in std_ulogic_vector(1 downto 0);
417 wishbone_err : out std_ulogic;
418 interrupt : out std_ulogic
419 );
420 end component;
421
422 signal wb_eth_cyc : std_ulogic;
423 signal wb_eth_adr : std_ulogic_vector(29 downto 0);
424
425 -- Change this to use a PLL instead of a BUFR to generate the 25Mhz
426 -- reference clock to the PHY.
427 constant USE_PLL : boolean := false;
428 begin
429 eth_use_pll: if USE_PLL generate
430 signal eth_clk_25 : std_ulogic;
431 signal eth_clkfb : std_ulogic;
432 begin
433 pll_eth : PLLE2_BASE
434 generic map (
435 BANDWIDTH => "OPTIMIZED",
436 CLKFBOUT_MULT => 16,
437 CLKIN1_PERIOD => 10.0,
438 CLKOUT0_DIVIDE => 64,
439 DIVCLK_DIVIDE => 1,
440 STARTUP_WAIT => "FALSE")
441 port map (
442 CLKOUT0 => eth_clk_25,
443 CLKOUT1 => open,
444 CLKOUT2 => open,
445 CLKOUT3 => open,
446 CLKOUT4 => open,
447 CLKOUT5 => open,
448 CLKFBOUT => eth_clkfb,
449 LOCKED => eth_clk_locked,
450 CLKIN1 => ext_clk,
451 PWRDWN => '0',
452 RST => pll_rst,
453 CLKFBIN => eth_clkfb);
454
455 eth_clk_buf: BUFG
456 port map (
457 I => eth_clk_25,
458 O => eth_ref_clk
459 );
460 end generate;
461
462 eth_use_bufr: if not USE_PLL generate
463 eth_clk_div: BUFR
464 generic map (
465 BUFR_DIVIDE => "4"
466 )
467 port map (
468 I => system_clk,
469 O => eth_ref_clk,
470 CE => '1',
471 CLR => '0'
472 );
473 eth_clk_locked <= '1';
474 end generate;
475
476 liteeth : liteeth_core
477 port map(
478 sys_clock => system_clk,
479 sys_reset => soc_rst,
480 mii_eth_clocks_tx => eth_clocks_tx,
481 mii_eth_clocks_rx => eth_clocks_rx,
482 mii_eth_rst_n => eth_rst_n,
483 mii_eth_mdio => eth_mdio,
484 mii_eth_mdc => eth_mdc,
485 mii_eth_rx_dv => eth_rx_dv,
486 mii_eth_rx_er => eth_rx_er,
487 mii_eth_rx_data => eth_rx_data,
488 mii_eth_tx_en => eth_tx_en,
489 mii_eth_tx_data => eth_tx_data,
490 mii_eth_col => eth_col,
491 mii_eth_crs => eth_crs,
492 wishbone_adr => wb_eth_adr,
493 wishbone_dat_w => wb_ext_io_in.dat,
494 wishbone_dat_r => wb_eth_out.dat,
495 wishbone_sel => wb_ext_io_in.sel,
496 wishbone_cyc => wb_eth_cyc,
497 wishbone_stb => wb_ext_io_in.stb,
498 wishbone_ack => wb_eth_out.ack,
499 wishbone_we => wb_ext_io_in.we,
500 wishbone_cti => "000",
501 wishbone_bte => "00",
502 wishbone_err => open,
503 interrupt => ext_irq_eth
504 );
505
506 -- Gate cyc with "chip select" from soc
507 wb_eth_cyc <= wb_ext_io_in.cyc and wb_ext_is_eth;
508
509 -- Remove top address bits as liteeth decoder doesn't know about them
510 wb_eth_adr <= x"000" & "000" & wb_ext_io_in.adr(16 downto 2);
511
512 -- LiteETH isn't pipelined
513 wb_eth_out.stall <= not wb_eth_out.ack;
514
515 end generate;
516
517 no_liteeth : if not USE_LITEETH generate
518 eth_clk_locked <= '1';
519 ext_irq_eth <= '0';
520 end generate;
521
522 -- Mux WB response on the IO bus
523 wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else wb_dram_ctrl_out;
524
525 leds_pwm : process(system_clk)
526 begin
527 if rising_edge(system_clk) then
528 pwm_counter <= std_ulogic_vector(signed(pwm_counter) + 1);
529 if pwm_counter(8 downto 4) = "00000" then
530 led0_b <= led0_b_pwm;
531 led0_r <= led0_r_pwm;
532 led0_g <= led0_g_pwm;
533 else
534 led0_b <= '0';
535 led0_r <= '0';
536 led0_g <= '0';
537 end if;
538 end if;
539 end process;
540
541 led4 <= system_clk_locked;
542 led5 <= eth_clk_locked;
543 led6 <= not soc_rst;
544 led7 <= not spi_flash_cs_n;
545
546 end architecture behaviour;