boards: add new digilent arty
authorFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 26 Nov 2015 17:27:25 +0000 (18:27 +0100)
committerFlorent Kermarrec <florent@enjoy-digital.fr>
Thu, 26 Nov 2015 23:29:30 +0000 (00:29 +0100)
litex/boards/platforms/arty.py [new file with mode: 0644]
litex/boards/targets/arty.py [new file with mode: 0644]

diff --git a/litex/boards/platforms/arty.py b/litex/boards/platforms/arty.py
new file mode 100644 (file)
index 0000000..3f5d09a
--- /dev/null
@@ -0,0 +1,115 @@
+# This file is Copyright (c) 2015 Yann Sionneau <yann@sionneau.net>
+# This file is Copyright (c) 2015 Florent Kermarrec <florent@enjoy-digital.fr>
+# License: BSD
+
+from litex.build.generic_platform import *
+from litex.build.xilinx import XilinxPlatform, XC3SProg, VivadoProgrammer
+
+_io = [
+    ("user_led", 0, Pins("H5"), IOStandard("LVCMOS33")),
+    ("user_led", 1, Pins("J5"), IOStandard("LVCMOS33")),
+    ("user_led", 2, Pins("T9"), IOStandard("LVCMOS33")),
+    ("user_led", 3, Pins("T10"), IOStandard("LVCMOS33")),
+
+    ("rgb_leds", 0,
+        Subsignal("r", Pins("G6 G3 J3 K1")),
+        Subsignal("g", Pins("F6 J4 J2 H6")),
+        Subsignal("b", Pins("E1 G4 H4 K2")),
+        IOStandard("LVCMOS33")
+    ),
+
+    ("user_sw", 0, Pins("A8"), IOStandard("LVCMOS33")),
+    ("user_sw", 1, Pins("C11"), IOStandard("LVCMOS33")),
+    ("user_sw", 2, Pins("C10"), IOStandard("LVCMOS33")),
+    ("user_sw", 3, Pins("A10"), IOStandard("LVCMOS33")),
+
+    ("user_btn", 0, Pins("D9"), IOStandard("LVCMOS33")),
+    ("user_btn", 1, Pins("C9"), IOStandard("LVCMOS33")),
+    ("user_btn", 2, Pins("B9"), IOStandard("LVCMOS33")),
+    ("user_btn", 3, Pins("B8"), IOStandard("LVCMOS33")),
+
+    ("clk100", 0, Pins("E3"), IOStandard("LVCMOS33")),
+
+    ("cpu_reset", 0, Pins("C2"), IOStandard("LVCMOS33")),
+
+    ("serial", 0,
+        Subsignal("tx", Pins("D10")),
+        Subsignal("rx", Pins("A9")),
+        IOStandard("LVCMOS33")),
+
+    ("spiflash", 0,  # clock needs to be accessed through STARTUPE2
+        Subsignal("cs_n", Pins("L13")),
+        Subsignal("dq", Pins("K17", "K18", "L14", "M14")),
+        IOStandard("LVCMOS33")
+    ),
+
+    ("eth_ref_clk", 0, Pins("G18"), IOStandard("LVCMOS33")),
+
+    ("ddram", 0,
+        Subsignal("a", Pins(
+            "R2 M6 N4 T1 N6 R7 V6 U7"),
+            IOStandard("SSTL135")),
+        Subsignal("ba", Pins("R1 P4 P2"), IOStandard("SSTL135")),
+        Subsignal("ras_n", Pins("P3"), IOStandard("SSTL135")),
+        Subsignal("cas_n", Pins("M4"), IOStandard("SSTL135")),
+        Subsignal("we_n", Pins("P5"), IOStandard("SSTL135")),
+        Subsignal("cs_n", Pins("U8"), IOStandard("SSTL135")),
+        Subsignal("dm", Pins("L1"), IOStandard("SSTL135")),
+        Subsignal("dq", Pins(
+            "K5 L3 K3 L6 M3 M1 L4 M2"),
+            IOStandard("SSTL135"),
+            Misc("IN_TERM=UNTUNED_SPLIT_50")),
+        Subsignal("dqs_p", Pins("N2"), IOStandard("DIFF_SSTL135")),
+        Subsignal("dqs_n", Pins("N1"), IOStandard("DIFF_SSTL135")),
+        Subsignal("clk_p", Pins("U9"), IOStandard("DIFF_SSTL135")),
+        Subsignal("clk_n", Pins("V9"), IOStandard("DIFF_SSTL135")),
+        Subsignal("cke", Pins("N5"), IOStandard("SSTL135")),
+        Subsignal("odt", Pins("R5"), IOStandard("SSTL135")),
+        Subsignal("reset_n", Pins("K6"), IOStandard("SSTL135")),
+        Misc("SLEW=FAST"),
+    ),
+
+    ("eth_clocks", 0,
+        Subsignal("tx", Pins("H16")),
+        Subsignal("rx", Pins("F15")),
+        IOStandard("LVCMOS33")
+    ),
+    ("eth", 0,
+        Subsignal("rst_n", Pins("C16")),
+        Subsignal("mdio", Pins("K13")),
+        Subsignal("mdc", Pins("F16")),
+        Subsignal("dv", Pins("G16")),
+        Subsignal("rx_er", Pins("C17")),
+        Subsignal("rx_data", Pins("D18 E17 E18 G17")),
+        Subsignal("tx_en", Pins("H15")),
+        Subsignal("tx_data", Pins("H14 J14 J13 H17")),
+        Subsignal("col", Pins("D17")),
+        Subsignal("crs", Pins("G14")),
+        IOStandard("LVCMOS33")
+    ),
+]
+
+
+class Platform(XilinxPlatform):
+    default_clk_name = "clk100"
+    default_clk_period = 10.0
+
+    def __init__(self, toolchain="vivado", programmer="vivado"):
+        XilinxPlatform.__init__(self, "xc7a35ticsg324-1L", _io,
+                                toolchain=toolchain)
+        self.toolchain.bitstream_commands = \
+            ["set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design]"]
+        self.toolchain.additional_commands = \
+            ["write_cfgmem -force -format bin -interface spix4 -size 16 "
+             "-loadbit \"up 0x0 {build_name}.bit\" -file {build_name}.bin"]
+        self.programmer = programmer
+        self.add_platform_command("set_property INTERNAL_VREF 0.675 [get_iobanks 34]")
+
+    def create_programmer(self):
+        if self.programmer == "xc3sprog":
+            return XC3SProg("nexys4")
+        elif self.programmer == "vivado":
+            return VivadoProgrammer(flash_part="n25q128-3.3v-spi-x1_x2_x4")
+        else:
+            raise ValueError("{} programmer is not supported"
+                             .format(self.programmer))
diff --git a/litex/boards/targets/arty.py b/litex/boards/targets/arty.py
new file mode 100644 (file)
index 0000000..eb07d1a
--- /dev/null
@@ -0,0 +1,132 @@
+#!/usr/bin/env python3
+import argparse
+import os
+
+from litex.gen import *
+from litex.gen.genlib.resetsync import AsyncResetSynchronizer
+
+from litex.boards.platforms import arty
+
+from litex.soc.integration.soc_core import *
+from litex.soc.integration.builder import *
+
+from liteeth.phy.mii import LiteEthPHYMII
+from liteeth.core.mac import LiteEthMAC
+
+class _CRG(Module):
+    def __init__(self, platform):
+        self.clock_domains.cd_sys = ClockDomain()
+        self.clock_domains.cd_eth = ClockDomain(reset_less=True)
+
+        clk100 = platform.request("clk100")
+        rst = platform.request("cpu_reset")
+
+        pll_locked = Signal()
+        pll_fb = Signal()
+        pll_sys = Signal()
+        pll_eth = Signal()
+        self.specials += [
+            Instance("PLLE2_BASE",
+                     p_STARTUP_WAIT="FALSE", o_LOCKED=pll_locked,
+
+                     # VCO @ 800 MHz
+                     p_REF_JITTER1=0.01, p_CLKIN1_PERIOD=10.0,
+                     p_CLKFBOUT_MULT=8, p_DIVCLK_DIVIDE=1,
+                     i_CLKIN1=clk100, i_CLKFBIN=pll_fb, o_CLKFBOUT=pll_fb,
+
+                     # 100 MHz
+                     p_CLKOUT0_DIVIDE=8, p_CLKOUT0_PHASE=0.0,
+                     o_CLKOUT0=pll_sys,
+
+                     # 25 MHz
+                     p_CLKOUT1_DIVIDE=32, p_CLKOUT1_PHASE=0.0,
+                     o_CLKOUT1=pll_eth,
+
+                     # 200 MHz
+                     p_CLKOUT2_DIVIDE=4, p_CLKOUT2_PHASE=0.0,
+                     #o_CLKOUT2=,
+
+                     # 200 MHz
+                     p_CLKOUT3_DIVIDE=4, p_CLKOUT3_PHASE=0.0,
+                     #o_CLKOUT3=,
+
+                     # 200MHz
+                     p_CLKOUT4_DIVIDE=4, p_CLKOUT4_PHASE=0.0,
+                     #o_CLKOUT4=
+            ),
+            Instance("BUFG", i_I=pll_sys, o_O=self.cd_sys.clk),
+            Instance("BUFG", i_I=pll_eth, o_O=self.cd_eth.clk),
+            AsyncResetSynchronizer(self.cd_sys, ~pll_locked | ~rst),
+        ]
+
+
+        self.specials += [
+            Instance("ODDR2", p_DDR_ALIGNMENT="NONE",
+                     p_INIT=0, p_SRTYPE="SYNC",
+                     i_D0=0, i_D1=1, i_S=0, i_R=0, i_CE=1,
+                     i_C0=self.cd_eth.clk, i_C1=~self.cd_eth.clk,
+                     o_Q=platform.request("eth_ref_clk"))
+        ]
+
+
+class BaseSoC(SoCCore):
+    def __init__(self, **kwargs):
+        platform = arty.Platform()
+        SoCCore.__init__(self, platform, clk_freq=100*1000000, **kwargs)
+
+        self.submodules.crg = _CRG(platform)
+
+
+class MiniSoC(BaseSoC):
+    csr_map = {
+        "ethphy": 18,
+        "ethmac": 19
+    }
+    csr_map.update(BaseSoC.csr_map)
+
+    interrupt_map = {
+        "ethmac": 2,
+    }
+    interrupt_map.update(BaseSoC.interrupt_map)
+
+    mem_map = {
+        "ethmac": 0x30000000,  # (shadow @0xb0000000)
+    }
+    mem_map.update(BaseSoC.mem_map)
+
+    def __init__(self, **kwargs):
+        BaseSoC.__init__(self, **kwargs)
+
+        self.submodules.ethphy = LiteEthPHYMII(self.platform.request("eth_clocks"),
+                                               self.platform.request("eth"))
+        self.submodules.ethmac = LiteEthMAC(phy=self.ethphy, dw=32, interface="wishbone")
+        self.add_wb_slave(mem_decoder(self.mem_map["ethmac"]), self.ethmac.bus)
+        self.add_memory_region("ethmac", self.mem_map["ethmac"] | self.shadow_base, 0x2000)
+
+
+def main():
+    parser = argparse.ArgumentParser(description="LiteX SoC port to Arty")
+    builder_args(parser)
+    soc_core_args(parser)
+    parser.add_argument("--with-ethernet", action="store_true",
+                        help="enable Ethernet support")
+    parser.add_argument("--build", action="store_true",
+                        help="build bitstream")
+    parser.add_argument("--load", action="store_true",
+                        help="load bitstream")
+    args = parser.parse_args()
+
+    cls = MiniSoC if args.with_ethernet else BaseSoC
+    soc = cls(**soc_core_argdict(args))
+    builder = Builder(soc, **builder_argdict(args))
+
+    if args.build:
+        builder.build()
+
+    if args.load:
+        prog = soc.platform.create_programmer()
+        prog.load_bitstream(os.path.join(builder.output_dir, "gateware", "top.bit"))
+
+
+if __name__ == "__main__":
+    main()