From 458dfe01a6707b62679ace51579b2a21caebf67b Mon Sep 17 00:00:00 2001 From: Anton Blanchard Date: Wed, 4 Aug 2021 15:59:43 +1000 Subject: [PATCH] Add liteeth support to Nexys Video Signed-off-by: Anton Blanchard --- fpga/nexys-video.xdc | 89 ++++++++++++++++- fpga/top-nexys-video.vhdl | 169 ++++++++++++++++++++++++++++---- liteeth/gen-src/generate.sh | 2 +- liteeth/gen-src/nexys-video.yml | 15 +++ liteeth/liteeth.core | 2 +- microwatt.core | 9 +- 6 files changed, 259 insertions(+), 27 deletions(-) create mode 100644 liteeth/gen-src/nexys-video.yml diff --git a/fpga/nexys-video.xdc b/fpga/nexys-video.xdc index 4cedfd3..f04c4da 100644 --- a/fpga/nexys-video.xdc +++ b/fpga/nexys-video.xdc @@ -4,7 +4,7 @@ set_property -dict {PACKAGE_PIN R4 IOSTANDARD LVCMOS33} [get_ports ext_clk] -set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS15} [get_ports ext_rst] +set_property -dict {PACKAGE_PIN G4 IOSTANDARD LVCMOS15} [get_ports ext_rst_n] set_property -dict {PACKAGE_PIN AA19 IOSTANDARD LVCMOS33} [get_ports uart_main_tx] set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart_main_rx] @@ -22,8 +22,14 @@ set_property -dict {PACKAGE_PIN V18 IOSTANDARD LVCMOS33} [get_ports uart_main_rx # LEDs ################################################################################ -set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS33 } [get_ports { led0 }]; -set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS33 } [get_ports { led1 }]; +set_property -dict { PACKAGE_PIN T14 IOSTANDARD LVCMOS25 } [get_ports { led0 }]; +set_property -dict { PACKAGE_PIN T15 IOSTANDARD LVCMOS25 } [get_ports { led1 }]; +set_property -dict { PACKAGE_PIN T16 IOSTANDARD LVCMOS25 } [get_ports { led2 }]; +set_property -dict { PACKAGE_PIN U16 IOSTANDARD LVCMOS25 } [get_ports { led3 }]; +set_property -dict { PACKAGE_PIN V15 IOSTANDARD LVCMOS25 } [get_ports { led4 }]; +set_property -dict { PACKAGE_PIN W16 IOSTANDARD LVCMOS25 } [get_ports { led5 }]; +set_property -dict { PACKAGE_PIN W15 IOSTANDARD LVCMOS25 } [get_ports { led6 }]; +set_property -dict { PACKAGE_PIN Y13 IOSTANDARD LVCMOS25 } [get_ports { led7 }]; ################################################################################ # SPI Flash @@ -35,6 +41,75 @@ set_property -dict { PACKAGE_PIN R22 IOSTANDARD LVCMOS33 } [get_ports { spi_flas set_property -dict { PACKAGE_PIN P21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_wp_n }]; set_property -dict { PACKAGE_PIN R21 IOSTANDARD LVCMOS33 } [get_ports { spi_flash_hold_n }]; +################################################################################ +# Ethernet (generated by LiteX) +################################################################################ + +# eth_clocks:0.tx +set_property LOC AA14 [get_ports {eth_clocks_tx}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_clocks_tx}] + +# eth_clocks:0.rx +set_property LOC V13 [get_ports {eth_clocks_rx}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_clocks_rx}] + +# eth:0.rst_n +set_property LOC U7 [get_ports {eth_rst_n}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_rst_n}] +set_property IOSTANDARD LVCMOS33 [get_ports {eth_rst_n}] + +# eth:0.int_n +set_property LOC Y14 [get_ports {eth_int_n}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_int_n}] + +# eth:0.mdio +set_property LOC Y16 [get_ports {eth_mdio}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_mdio}] + +# eth:0.mdc +set_property LOC AA16 [get_ports {eth_mdc}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_mdc}] + +# eth:0.rx_ctl +set_property LOC W10 [get_ports {eth_rx_ctl}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_ctl}] + +# eth:0.rx_data +set_property LOC AB16 [get_ports {eth_rx_data[0]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[0]}] + +# eth:0.rx_data +set_property LOC AA15 [get_ports {eth_rx_data[1]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[1]}] + +# eth:0.rx_data +set_property LOC AB15 [get_ports {eth_rx_data[2]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[2]}] + +# eth:0.rx_data +set_property LOC AB11 [get_ports {eth_rx_data[3]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_rx_data[3]}] + +# eth:0.tx_ctl +set_property LOC V10 [get_ports {eth_tx_ctl}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_ctl}] + +# eth:0.tx_data +set_property LOC Y12 [get_ports {eth_tx_data[0]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[0]}] + +# eth:0.tx_data +set_property LOC W12 [get_ports {eth_tx_data[1]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[1]}] + +# eth:0.tx_data +set_property LOC W11 [get_ports {eth_tx_data[2]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[2]}] + +# eth:0.tx_data +set_property LOC Y11 [get_ports {eth_tx_data[3]}] +set_property IOSTANDARD LVCMOS25 [get_ports {eth_tx_data[3]}] + ################################################################################ # DRAM (generated by LiteX) ################################################################################ @@ -315,10 +390,16 @@ set_property CONFIG_MODE SPIx4 [current_design] create_clock -name sys_clk_pin -period 10.00 [get_ports { ext_clk }]; +create_clock -name eth_clocks_rx -period 8.0 [get_ports { eth_clocks_rx }] + +set_clock_groups -asynchronous -group [get_clocks sys_clk_pin -include_generated_clocks] -group [get_clocks eth_clocks_rx -include_generated_clocks] + ################################################################################ -# False path constraints (from LiteX as they relate to LiteDRAM) +# False path constraints (from LiteX as they relate to LiteDRAM and LiteEth) ################################################################################ +set_false_path -quiet -through [get_nets -hierarchical -filter {mr_ff == TRUE}] + set_false_path -quiet -to [get_pins -filter {REF_PIN_NAME == PRE} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE || ars_ff2 == TRUE}]] set_max_delay 2 -quiet -from [get_pins -filter {REF_PIN_NAME == C} -of_objects [get_cells -hierarchical -filter {ars_ff1 == TRUE}]] -to [get_pins -filter {REF_PIN_NAME == D} -of_objects [get_cells -hierarchical -filter {ars_ff2 == TRUE}]] diff --git a/fpga/top-nexys-video.vhdl b/fpga/top-nexys-video.vhdl index 86bdd11..e99f2c5 100644 --- a/fpga/top-nexys-video.vhdl +++ b/fpga/top-nexys-video.vhdl @@ -23,19 +23,26 @@ entity toplevel is SPI_FLASH_DEF_CKDV : natural := 1; SPI_FLASH_DEF_QUAD : boolean := true; LOG_LENGTH : natural := 2048; - UART_IS_16550 : boolean := true + UART_IS_16550 : boolean := true; + USE_LITEETH : boolean := false ); port( ext_clk : in std_ulogic; - ext_rst : in std_ulogic; + ext_rst_n : in std_ulogic; -- UART0 signals: uart_main_tx : out std_ulogic; uart_main_rx : in std_ulogic; - -- LEDs - led0 : out std_logic; - led1 : out std_logic; + -- LEDs + led0 : out std_ulogic; + led1 : out std_ulogic; + led2 : out std_ulogic; + led3 : out std_ulogic; + led4 : out std_ulogic; + led5 : out std_ulogic; + led6 : out std_ulogic; + led7 : out std_ulogic; -- SPI spi_flash_cs_n : out std_ulogic; @@ -44,6 +51,18 @@ entity toplevel is spi_flash_wp_n : inout std_ulogic; spi_flash_hold_n : inout std_ulogic; + -- Ethernet + eth_clocks_tx : out std_ulogic; + eth_clocks_rx : in std_ulogic; + eth_rst_n : out std_ulogic; + eth_int_n : in std_ulogic; + eth_mdio : inout std_ulogic; + eth_mdc : out std_ulogic; + eth_rx_ctl : in std_ulogic; + eth_rx_data : in std_ulogic_vector(3 downto 0); + eth_tx_ctl : out std_ulogic; + eth_tx_data : out std_ulogic_vector(3 downto 0); + -- DRAM wires ddram_a : out std_logic_vector(14 downto 0); ddram_ba : out std_logic_vector(2 downto 0); @@ -69,18 +88,26 @@ architecture behaviour of toplevel is signal pll_rst : std_ulogic; -- Internal clock signals: - signal system_clk : std_ulogic; + signal system_clk : std_ulogic; signal system_clk_locked : std_ulogic; + -- External IOs from the SoC + signal wb_ext_io_in : wb_io_master_out; + signal wb_ext_io_out : wb_io_slave_out; + signal wb_ext_is_dram_csr : std_ulogic; + signal wb_ext_is_dram_init : std_ulogic; + signal wb_ext_is_eth : std_ulogic; + -- DRAM main data wishbone connection signal wb_dram_in : wishbone_master_out; signal wb_dram_out : wishbone_slave_out; -- DRAM control wishbone connection - signal wb_ext_io_in : wb_io_master_out; - signal wb_ext_io_out : wb_io_slave_out; - signal wb_ext_is_dram_csr : std_ulogic; - signal wb_ext_is_dram_init : std_ulogic; + signal wb_dram_ctrl_out : wb_io_slave_out := wb_io_slave_out_init; + + -- LiteEth connection + signal ext_irq_eth : std_ulogic; + signal wb_eth_out : wb_io_slave_out := wb_io_slave_out_init; -- Control/status signal core_alt_reset : std_ulogic; @@ -134,7 +161,8 @@ begin SPI_FLASH_DEF_CKDV => SPI_FLASH_DEF_CKDV, SPI_FLASH_DEF_QUAD => SPI_FLASH_DEF_QUAD, LOG_LENGTH => LOG_LENGTH, - UART0_IS_16550 => UART_IS_16550 + UART0_IS_16550 => UART_IS_16550, + HAS_LITEETH => USE_LITEETH ) port map ( -- System signals @@ -152,6 +180,9 @@ begin spi_flash_sdat_oe => spi_sdat_oe, spi_flash_sdat_i => spi_sdat_i, + -- External interrupts + ext_irq_eth => ext_irq_eth, + -- DRAM wishbone wb_dram_in => wb_dram_in, wb_dram_out => wb_dram_out, @@ -159,6 +190,7 @@ begin wb_ext_io_out => wb_ext_io_out, wb_ext_is_dram_csr => wb_ext_is_dram_csr, wb_ext_is_dram_init => wb_ext_is_dram_init, + wb_ext_is_eth => wb_ext_is_eth, alt_reset => core_alt_reset ); @@ -198,8 +230,8 @@ begin port map( ext_clk => ext_clk, pll_clk => system_clk, - pll_locked_in => system_clk_locked, - ext_rst_in => ext_rst, + pll_locked_in => system_clk_locked, + ext_rst_in => ext_rst_n, pll_rst_out => pll_rst, rst_out => soc_rst ); @@ -218,6 +250,7 @@ begin led0 <= '1'; led1 <= not soc_rst; + led2 <= '0'; core_alt_reset <= '0'; -- Vivado barfs on those differential signals if left @@ -252,12 +285,22 @@ begin port map( ext_clk => ext_clk, pll_clk => system_clk, - pll_locked_in => '1', - ext_rst_in => ext_rst, + pll_locked_in => '1', + ext_rst_in => ext_rst_n, pll_rst_out => pll_rst, - rst_out => open + rst_out => open ); + -- Generate SoC reset + soc_rst_gen: process(system_clk) + begin + if ext_rst_n = '0' then + soc_rst <= '1'; + elsif rising_edge(system_clk) then + soc_rst <= dram_sys_rst or not system_clk_locked; + end if; + end process; + dram: entity work.litedram_wrapper generic map( DRAM_ABITS => 25, @@ -271,14 +314,14 @@ begin clk_in => ext_clk, rst => pll_rst, system_clk => system_clk, - system_reset => soc_rst, + system_reset => dram_sys_rst, core_alt_reset => core_alt_reset, pll_locked => system_clk_locked, wb_in => wb_dram_in, wb_out => wb_dram_out, wb_ctrl_in => wb_ext_io_in, - wb_ctrl_out => wb_ext_io_out, + wb_ctrl_out => wb_dram_ctrl_out, wb_ctrl_is_csr => wb_ext_is_dram_csr, wb_ctrl_is_init => wb_ext_is_dram_init, @@ -302,8 +345,96 @@ begin ddram_reset_n => ddram_reset_n ); - led0 <= dram_init_done and not dram_init_error; + led0 <= not dram_init_done; led1 <= dram_init_error; -- Make it blink ? + led2 <= dram_init_done and not dram_init_error; end generate; + + has_liteeth : if USE_LITEETH generate + + component liteeth_core port ( + sys_clock : in std_ulogic; + sys_reset : in std_ulogic; + rgmii_eth_clocks_tx : out std_ulogic; + rgmii_eth_clocks_rx : in std_ulogic; + rgmii_eth_rst_n : out std_ulogic; + rgmii_eth_int_n : in std_ulogic; + rgmii_eth_mdio : inout std_ulogic; + rgmii_eth_mdc : out std_ulogic; + rgmii_eth_rx_ctl : in std_ulogic; + rgmii_eth_rx_data : in std_ulogic_vector(3 downto 0); + rgmii_eth_tx_ctl : out std_ulogic; + rgmii_eth_tx_data : out std_ulogic_vector(3 downto 0); + wishbone_adr : in std_ulogic_vector(29 downto 0); + wishbone_dat_w : in std_ulogic_vector(31 downto 0); + wishbone_dat_r : out std_ulogic_vector(31 downto 0); + wishbone_sel : in std_ulogic_vector(3 downto 0); + wishbone_cyc : in std_ulogic; + wishbone_stb : in std_ulogic; + wishbone_ack : out std_ulogic; + wishbone_we : in std_ulogic; + wishbone_cti : in std_ulogic_vector(2 downto 0); + wishbone_bte : in std_ulogic_vector(1 downto 0); + wishbone_err : out std_ulogic; + interrupt : out std_ulogic + ); + end component; + + signal wb_eth_cyc : std_ulogic; + signal wb_eth_adr : std_ulogic_vector(29 downto 0); + + begin + liteeth : liteeth_core + port map( + sys_clock => system_clk, + sys_reset => soc_rst, + rgmii_eth_clocks_tx => eth_clocks_tx, + rgmii_eth_clocks_rx => eth_clocks_rx, + rgmii_eth_rst_n => eth_rst_n, + rgmii_eth_int_n => eth_int_n, + rgmii_eth_mdio => eth_mdio, + rgmii_eth_mdc => eth_mdc, + rgmii_eth_rx_ctl => eth_rx_ctl, + rgmii_eth_rx_data => eth_rx_data, + rgmii_eth_tx_ctl => eth_tx_ctl, + rgmii_eth_tx_data => eth_tx_data, + wishbone_adr => wb_eth_adr, + wishbone_dat_w => wb_ext_io_in.dat, + wishbone_dat_r => wb_eth_out.dat, + wishbone_sel => wb_ext_io_in.sel, + wishbone_cyc => wb_eth_cyc, + wishbone_stb => wb_ext_io_in.stb, + wishbone_ack => wb_eth_out.ack, + wishbone_we => wb_ext_io_in.we, + wishbone_cti => "000", + wishbone_bte => "00", + wishbone_err => open, + interrupt => ext_irq_eth + ); + + -- Gate cyc with "chip select" from soc + wb_eth_cyc <= wb_ext_io_in.cyc and wb_ext_is_eth; + + -- Remove top address bits as liteeth decoder doesn't know about them + wb_eth_adr <= x"000" & "000" & wb_ext_io_in.adr(16 downto 2); + + -- LiteETH isn't pipelined + wb_eth_out.stall <= not wb_eth_out.ack; + + end generate; + + no_liteeth : if not USE_LITEETH generate + ext_irq_eth <= '0'; + end generate; + + -- Mux WB response on the IO bus + wb_ext_io_out <= wb_eth_out when wb_ext_is_eth = '1' else + wb_dram_ctrl_out; + + led4 <= system_clk_locked; + led5 <= '1'; + led6 <= not soc_rst; + led7 <= '0'; + end architecture behaviour; diff --git a/liteeth/gen-src/generate.sh b/liteeth/gen-src/generate.sh index 805e0b8..ba1ba46 100755 --- a/liteeth/gen-src/generate.sh +++ b/liteeth/gen-src/generate.sh @@ -1,6 +1,6 @@ #!/bin/bash -TARGETS=arty +TARGETS="arty nexys-video" ME=$(realpath $0) echo ME=$ME diff --git a/liteeth/gen-src/nexys-video.yml b/liteeth/gen-src/nexys-video.yml new file mode 100644 index 0000000..38a207c --- /dev/null +++ b/liteeth/gen-src/nexys-video.yml @@ -0,0 +1,15 @@ +# This file is Copyright (c) 2020 Florent Kermarrec +# License: BSD + +# PHY ---------------------------------------------------------------------- +phy: LiteEthS7PHYRGMII +vendor: xilinx +# Core --------------------------------------------------------------------- +clk_freq: 125e6 +core: wishbone +endianness: little + +soc: + mem_map: + ethmac: 0x00010000 + csr_data_width: 32 diff --git a/liteeth/liteeth.core b/liteeth/liteeth.core index 6a5c719..0b12428 100644 --- a/liteeth/liteeth.core +++ b/liteeth/liteeth.core @@ -12,4 +12,4 @@ generators: based on the board type. Parameters: - board: The board type (arty) + board: The board type (arty, nexys-video) diff --git a/microwatt.core b/microwatt.core index a21ba3e..41421c3 100644 --- a/microwatt.core +++ b/microwatt.core @@ -228,11 +228,12 @@ targets: nexys_video: default_tool: vivado - filesets: [core, nexys_video, soc, fpga, debug_xilinx, litedram, uart16550, xilinx_specific] + filesets: [core, nexys_video, soc, fpga, debug_xilinx, litedram, liteeth, uart16550, xilinx_specific] parameters: - memory_size - ram_init_file - use_litedram=true + - use_liteeth=true - disable_flatten_core - no_bram - spi_flash_offset=10485760 @@ -240,7 +241,7 @@ targets: - uart_is_16550 - has_fpu - has_btc - generate: [litedram_nexys_video] + generate: [litedram_nexys_video, liteeth_nexys_video] tools: vivado: {part : xc7a200tsbg484-1} toplevel : toplevel @@ -370,6 +371,10 @@ generate: generator: litedram_gen parameters: {board : nexys-video} + liteeth_nexys_video: + generator: liteeth_gen + parameters: {board : nexys-video} + litedram_acorn_cle_215: generator: litedram_gen parameters: {board : acorn-cle-215}