Add liteeth support to Nexys Video
authorAnton Blanchard <anton@linux.ibm.com>
Wed, 4 Aug 2021 05:59:43 +0000 (15:59 +1000)
committerAnton Blanchard <anton@ozlabs.org>
Mon, 9 Aug 2021 11:21:04 +0000 (21:21 +1000)
Signed-off-by: Anton Blanchard <anton@linux.ibm.com>
fpga/nexys-video.xdc
fpga/top-nexys-video.vhdl
liteeth/gen-src/generate.sh
liteeth/gen-src/nexys-video.yml [new file with mode: 0644]
liteeth/liteeth.core
microwatt.core

index 4cedfd31361cb345a45d7a4b829c1eabfc51c830..f04c4daa2649be2a0103febac8856e9e2e4faced 100644 (file)
@@ -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}]]
index 86bdd1199133af22d4224e242654ee0ce52cdaad..e99f2c55588e0a8069b3192fbe65385bd5bf09b6 100644 (file)
@@ -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;
index 805e0b86fef94cd3b080c06e70f5948e7be00809..ba1ba46d088deceb3875174e00121dd15a2f0cde 100755 (executable)
@@ -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 (file)
index 0000000..38a207c
--- /dev/null
@@ -0,0 +1,15 @@
+# This file is Copyright (c) 2020 Florent Kermarrec <florent@enjoy-digital.fr>
+# License: BSD
+
+# PHY ----------------------------------------------------------------------
+phy:        LiteEthS7PHYRGMII
+vendor:     xilinx
+# Core ---------------------------------------------------------------------
+clk_freq:   125e6
+core:       wishbone
+endianness: little
+
+soc:
+    mem_map:
+        ethmac: 0x00010000
+    csr_data_width: 32
index 6a5c719b714911eed40543378a4a28cab3df5ee5..0b12428f6eebaa2e43ef17629c5b24d5853c0104 100644 (file)
@@ -12,4 +12,4 @@ generators:
       based on the board type.
 
       Parameters:
-        board: The board type (arty)
+        board: The board type (arty, nexys-video)
index a21ba3e8422006845d32ec82a6b2ca25a591e8c7..41421c396bc66034df5ddfaba9bf8aa1722db96b 100644 (file)
@@ -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}