diff --git a/.gitignore b/.gitignore index ef6d2ac..963297e 100644 --- a/.gitignore +++ b/.gitignore @@ -91,3 +91,6 @@ ENV/ # Rope project settings .ropeproject + +# VS Code project setting +.vscode \ No newline at end of file diff --git a/README.md b/README.md index f83e035..166f3c4 100644 --- a/README.md +++ b/README.md @@ -127,6 +127,7 @@ The Colorlight5A is a very nice board to start with, cheap, powerful, easy to us | Arty(A7) | Xilinx Artix7 | XC7A35T | 100MHz | FTDI | 16-bit 256MB DDR3 | No | 100Mbps MII | 16MB QSPI | No | | ArtyS7 | Xilinx Spartan7 | XC7S50 | 100MHz | FTDI | 16-bit 256MB DDR3 | No | No | 16MB QSPI | No | | Avalanche | Microsemi PolarFire | MPF300TS | 100MHz | IOs | 16-bit 256MB DDR3 | No | 1Gbps RGMII* | 8MB QSPI* | No | +| Basys3 | Xilinx Artix7 | XC7A35T | 100MHz | FTDI | No | No | No | 4MB QSPI | No | | C10LPRefKit | Intel Cyclone10 | 10CL055 | 50MHz | FTDI | 16-bit 32MB SDR | No | 100Mbps MII | 16MB QSPI | No | | CYC1000 | Intel Cyclone10 | 10CL025 | 50MHz | FTDI | 16-bit 64MB SDR | No | No | 16MB QSPI* | No | | De0Nano | Intel Cyclone4 | EP4CE22F | 50MHz | FTDI | 16-bit 32MB SDR | No | No | No | No | diff --git a/litex_boards/platforms/digilent_basys3.py b/litex_boards/platforms/digilent_basys3.py new file mode 100644 index 0000000..12249c9 --- /dev/null +++ b/litex_boards/platforms/digilent_basys3.py @@ -0,0 +1,132 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2020-2021 Xuanyu Hu +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import * +from litex.build.xilinx import XilinxPlatform, VivadoProgrammer +from litex.build.openocd import OpenOCD + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + # Clk / Rst + ("clk100", 0, Pins("W3"), IOStandard("LVCMOS33")), + + # Leds + ("user_led", 0, Pins("U16"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("E19"), IOStandard("LVCMOS33")), + ("user_led", 2, Pins("U19"), IOStandard("LVCMOS33")), + ("user_led", 3, Pins("V19"), IOStandard("LVCMOS33")), + ("user_led", 4, Pins("W18"), IOStandard("LVCMOS33")), + ("user_led", 5, Pins("U15"), IOStandard("LVCMOS33")), + ("user_led", 6, Pins("U14"), IOStandard("LVCMOS33")), + ("user_led", 7, Pins("V14"), IOStandard("LVCMOS33")), + ("user_led", 8, Pins("V13"), IOStandard("LVCMOS33")), + ("user_led", 9, Pins("V3"), IOStandard("LVCMOS33")), + ("user_led", 10, Pins("W3"), IOStandard("LVCMOS33")), + ("user_led", 11, Pins("U3"), IOStandard("LVCMOS33")), + ("user_led", 12, Pins("P3"), IOStandard("LVCMOS33")), + ("user_led", 13, Pins("N3"), IOStandard("LVCMOS33")), + ("user_led", 14, Pins("P1"), IOStandard("LVCMOS33")), + ("user_led", 15, Pins("L1"), IOStandard("LVCMOS33")), + + # Switches + ("user_sw", 0, Pins("V17"), IOStandard("LVCMOS33")), + ("user_sw", 1, Pins("V16"), IOStandard("LVCMOS33")), + ("user_sw", 2, Pins("W16"), IOStandard("LVCMOS33")), + ("user_sw", 3, Pins("W17"), IOStandard("LVCMOS33")), + ("user_sw", 4, Pins("W15"), IOStandard("LVCMOS33")), + ("user_sw", 5, Pins("V15"), IOStandard("LVCMOS33")), + ("user_sw", 6, Pins("W14"), IOStandard("LVCMOS33")), + ("user_sw", 7, Pins("W13"), IOStandard("LVCMOS33")), + ("user_sw", 8, Pins("V2"), IOStandard("LVCMOS33")), + ("user_sw", 9, Pins("T3"), IOStandard("LVCMOS33")), + ("user_sw", 10, Pins("T2"), IOStandard("LVCMOS33")), + ("user_sw", 11, Pins("R3"), IOStandard("LVCMOS33")), + ("user_sw", 12, Pins("W2"), IOStandard("LVCMOS33")), + ("user_sw", 13, Pins("U1"), IOStandard("LVCMOS33")), + ("user_sw", 14, Pins("T1"), IOStandard("LVCMOS33")), + ("user_sw", 15, Pins("R2"), IOStandard("LVCMOS33")), + + # Buttons + ("user_btnu", 0, Pins("T18"), IOStandard("LVCMOS33")), + ("user_btnd", 0, Pins("U17"), IOStandard("LVCMOS33")), + ("user_btnl", 0, Pins("W19"), IOStandard("LVCMOS33")), + ("user_btnr", 0, Pins("T17"), IOStandard("LVCMOS33")), + ("user_btnc", 0, Pins("U18"), IOStandard("LVCMOS33")), + + # Serial + ("serial", 0, + Subsignal("tx", Pins("A18")), + Subsignal("rx", Pins("B18")), + IOStandard("LVCMOS33"), + ), + + # VGA + ("vga", 0, + Subsignal("hsync_n", Pins("P19")), + Subsignal("vsync_n", Pins("R18")), + Subsignal("r", Pins("G19 H19 J19 N19")), + Subsignal("g", Pins("J17 H17 G17 D17")), + Subsignal("b", Pins("N18 L18 K18 J18")), + IOStandard("LVCMOS33") + ), + + # USB PS/2 + ("usbhost", 0, + Subsignal("ps2_clk", Pins("B6")), + Subsignal("ps2_data", Pins("A6")), + IOStandard("LVCMOS33")) + +] + +# Connectors --------------------------------------------------------------------------------------- + +_connectors = [ + ("pmoda", "J1 L2 J2 G2 H1 K2 H2 G3"), + ("pmodb", "A14 A16 B15 B16 A15 A17 C15 C16"), + ("pmodc", "K17 M18 N17 P18 L17 M19 P17 R18"), + ("pmodxdac", "J3 L3 M2 N2 K3 M3 M1 N1"), +] + +# PMODS -------------------------------------------------------------------------------------------- + +def sdcard_pmod_io(pmod): + return [ + # SDCard PMOD: + # - https://store.digilentinc.com/pmod-microsd-microsd-card-slot/ + ("spisdcard", 0, + Subsignal("clk", Pins(f"{pmod}:3")), + Subsignal("mosi", Pins(f"{pmod}:1"), Misc("PULLUP True")), + Subsignal("cs_n", Pins(f"{pmod}:0"), Misc("PULLUP True")), + Subsignal("miso", Pins(f"{pmod}:2"), Misc("PULLUP True")), + Misc("SLEW=FAST"), + IOStandard("LVCMOS33"), + ), + ("sdcard", 0, + Subsignal("data", Pins(f"{pmod}:2 {pmod}:4 {pmod}:5 {pmod}:0"), Misc("PULLUP True")), + Subsignal("cmd", Pins(f"{pmod}:1"), Misc("PULLUP True")), + Subsignal("clk", Pins(f"{pmod}:3")), + Subsignal("cd", Pins(f"{pmod}:6")), + Misc("SLEW=FAST"), + IOStandard("LVCMOS33"), + ), + +] +_sdcard_pmod_io = sdcard_pmod_io("pmoda") # SDCARD PMOD on JD. + +class Platform(XilinxPlatform): + default_clk_name = "clk100" + default_clk_period = 1e9/100e6 + + def __init__(self): + XilinxPlatform.__init__(self, "xc7a35t-CPG236-1", _io, _connectors, toolchain="vivado") + + def create_programmer(self): + return OpenOCD("openocd_xc7_ft2232.cfg", "bscan_spi_xc7a35t.bit") + + def do_finalize(self, fragment): + XilinxPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6) diff --git a/litex_boards/targets/digilent_basys3.py b/litex_boards/targets/digilent_basys3.py new file mode 100644 index 0000000..32b6c0c --- /dev/null +++ b/litex_boards/targets/digilent_basys3.py @@ -0,0 +1,116 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2020-2021 Xuanyu Hu +# SPDX-License-Identifier: BSD-2-Clause + +import os +import argparse +from litex.build.xilinx import platform + +from migen import * + +from litex_boards.platforms import basys3 + +from litex.soc.cores.clock import * +from litex.soc.integration.soc import SoCRegion +from litex.soc.integration.soc_core import * +from litex.soc.integration.builder import * +from litex.soc.cores.video import VideoVGAPHY +from litex.soc.cores.led import LedChaser + +from litedram.modules import MT47H64M16 +from litedram.phy import s7ddrphy + +from liteeth.phy.rmii import LiteEthPHYRMII + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq): + self.rst = Signal() + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) + self.clock_domains.cd_sys4x_dqs = ClockDomain(reset_less=True) + self.clock_domains.cd_idelay = ClockDomain() + self.clock_domains.cd_vga = ClockDomain(reset_less=True) + + self.submodules.pll = pll = S7MMCM(speedgrade=-1) + self.comb += pll.reset.eq(~platform.request("user_btnc") | self.rst) + + pll.register_clkin(platform.request("clk100"), 100e6) + pll.create_clkout(self.cd_sys, sys_clk_freq) + pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq) + pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90) + pll.create_clkout(self.cd_idelay, 200e6) + pll.create_clkout(self.cd_vga, 40e6) + platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) + + self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_idelay) + +# BaseSoC ------------------------------------------------------------------------------------------ +class BaseSoC(SoCCore): + def __init__(self, sys_clk_freq=int(75e6), with_video_terminal=False, with_video_framebuffer=False, **kwargs): + platform = basys3.Platform() + + # SoCCore ----------------------------------_----------------------------------------------- + SoCCore.__init__(self, platform, sys_clk_freq, + ident = "LiteX SoC on Basys3", + ident_version = True, + **kwargs) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq) + + if with_video_terminal or with_video_framebuffer: + self.submodules.videophy = VideoVGAPHY(platform.request("vga"), clock_domain="vga") + if with_video_terminal: + self.add_video_terminal(phy=self.videophy, timings="800x600@60Hz", clock_domain="vga") + if with_video_framebuffer: + self.add_video_framebuffer(phy=self.videophy, timings="800x600@60Hz", clock_domain="vga") + + self.submodules.leds = LedChaser( + pads = platform.request_all("user_led"), + sys_clk_freq = sys_clk_freq) + +# Build -------------------------------------------------------------------------------------------- +def main(): + parser = argparse.ArgumentParser(description="LiteX SoC on Basys3") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--sys-clk-freq", default=75e6, help="System clock frequency (default: 75MHz)") + sdopts = parser.add_mutually_exclusive_group() + sdopts.add_argument("--with-spi-sdcard", action="store_true", help="Enable SPI-mode SDCard support") + sdopts.add_argument("--with-sdcard", action="store_true", help="Enable SDCard support") + parser.add_argument("--sdcard-adapter", type=str, help="SDCard PMOD adapter: digilent (default) or numato") + viopts = parser.add_mutually_exclusive_group() + viopts.add_argument("--with-video-terminal", action="store_true", help="Enable Video Terminal (VGA)") + viopts.add_argument("--with-video-framebuffer", action="store_true", help="Enable Video Framebuffer (VGA)") + builder_args(parser) + soc_core_args(parser) + args = parser.parse_args() + + soc = BaseSoC( + sys_clk_freq = int(float(args.sys_clk_freq)), + with_video_terminal = args.with_video_terminal, + with_video_framebuffer = args.with_video_framebuffer, + **soc_core_argdict(args) + ) + soc.platform.add_extension(basys3._sdcard_pmod_io) + if args.with_spi_sdcard: + soc.add_spi_sdcard() + if args.with_sdcard: + soc.add_sdcard() + if args.with_spi_sdcard: + soc.add_spi_sdcard() + if args.with_sdcard: + soc.add_sdcard() + builder = Builder(soc, **builder_argdict(args)) + builder.build(run=args.build) + + if args.load: + prog = soc.platform.create_programmer() + prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".bit")) + +if __name__ == "__main__": + main() diff --git a/test/test_targets.py b/test/test_targets.py index be2a0e2..40e7274 100644 --- a/test/test_targets.py +++ b/test/test_targets.py @@ -43,6 +43,7 @@ class TestTargets(unittest.TestCase): platforms.append("ac701") platforms.append("aller") platforms.append("arty") + platforms.append("basys3") platforms.append("mimas_a7") platforms.append("netv2") platforms.append("nexys4ddr")