--- /dev/null
+# 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))
--- /dev/null
+#!/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()