From 713ae531f66507b2bce36d85d8d314b938c09b0c Mon Sep 17 00:00:00 2001 From: Primesh Date: Mon, 3 Jan 2022 16:31:13 -0500 Subject: [PATCH] Add Spartan Edge Accelerator support --- .../platforms/spartan_edge_accelerator.py | 130 ++++++++++++++++ .../targets/spartan_edge_accelerator.py | 144 ++++++++++++++++++ 2 files changed, 274 insertions(+) create mode 100644 litex_boards/platforms/spartan_edge_accelerator.py create mode 100755 litex_boards/targets/spartan_edge_accelerator.py diff --git a/litex_boards/platforms/spartan_edge_accelerator.py b/litex_boards/platforms/spartan_edge_accelerator.py new file mode 100644 index 0000000..7c615b8 --- /dev/null +++ b/litex_boards/platforms/spartan_edge_accelerator.py @@ -0,0 +1,130 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2022 Primesh Pinto +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import * +from litex.build.xilinx import XilinxPlatform +from litex.build.openocd import OpenOCD + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + # Clk / Rst + ("clk100", 0, Pins("H4"), IOStandard("LVCMOS33")), + ("cpu_reset", 0, Pins("D14"), IOStandard("LVCMOS33")), #Reset is active low + + + # Leds - Board has 2 + ("user_led", 0, Pins("J1"), IOStandard("LVCMOS33")), #green + ("user_led", 1, Pins("A13"), IOStandard("LVCMOS33")), #red + + + # Mini HDMI Interface + ("hdmi", 0, + Subsignal("clk_p", Pins("G4"),IOStandard("LVCMOS33")), + Subsignal("clk_n", Pins("F4"),IOStandard("LVCMOS33")), + Subsignal("data0_p", Pins("G1"),IOStandard("LVCMOS33")), + Subsignal("data0_n", Pins("F1"),IOStandard("LVCMOS33")), + Subsignal("data1_p", Pins("E2"),IOStandard("LVCMOS33")), + Subsignal("data1_n", Pins("D2"),IOStandard("LVCMOS33")), + Subsignal("data2_p", Pins("D1"),IOStandard("LVCMOS33")), + Subsignal("data2_n", Pins("C1"),IOStandard("LVCMOS33")), + Subsignal("scl", Pins("F3"),IOStandard("LVCMOS33")), + Subsignal("sda", Pins("F2"),IOStandard("LVCMOS33")), + Subsignal("hpd", Pins("D4"),IOStandard("LVCMOS33")), + Subsignal("cec", Pins("E4"),IOStandard("LVCMOS33")) + ), + + + #Interface to 2 RGB SK6805 LEDs + ("rgb", 0, Pins("N11"),IOStandard("LVCMOS33")), + + + # Buttons + ("user_btn", 0, Pins("C3"), IOStandard("LVCMOS33")), + ("user_btn", 1, Pins("M4"), IOStandard("LVCMOS33")), + + + # MIPI pins not tested + ("camera", 0, + Subsignal("clkp", Pins("G11"), IOStandard("MIPI_DPHY")), + Subsignal("clkn", Pins("F11"), IOStandard("LVCMOS12H")), + Subsignal("dp", Pins("J11 P10"), IOStandard("MIPI_DPHY")), + Subsignal("dn", Pins("J12 P11"), IOStandard("LVCMOS12H")), + ), + +] + +# Connectors --------------------------------------------------------------------------------------- + +_connectors = [ + ("j10", { + "j10_0" : "N14", + "j10_1" : "M14", + "j10_2" : "C4", + "j10_3" : "B13", + "j10_4" : "N10", + "j10_5" : "M10", + "j10_6" : "B14", + "j10_7" : "D3", + "j10_8" : "P5", + "j10_9" : "E11" + } + ), + + ("digital_d2",{ + "d2_0" : "A10", + "d2_1" : "B6" + }), + + ("i2c", "P12 P13"), #SCL, SDA + + + ("ar_io", { + # Outer Digital Header + "d0" : "A12", + "d1" : "C12", + "d2" : "A10", + "d3" : "B6", + "d4" : "A5", + "d5" : "B5", + "d6" : "A4", + "d7" : "A3", + "d8" : "B3", + "d9" : "A2", + "d10" : "B2", + "d11" : "B1", + "d12" : "H1", + "d13" : "H2", + + + # Outer Analog Header as Digital IO + "a0" : "F5", + "a1" : "D8", + "a2" : "C7", + "a3" : "E7", + "a4" : "D7", + "a5" : "D5", + + } ) + +] + + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(XilinxPlatform): + + def __init__(self, toolchain="vivado"): + XilinxPlatform.__init__(self, "xc7s15-ftgb196", _io, _connectors, toolchain=toolchain) + + + #Image needs to manually copy to SD card in the Spartan Edge Accelerator + def do_finalize(self, fragment): + default_clk_period = 1e9/100e6 + default_clk_name = "clk100" + XilinxPlatform.do_finalize(self, fragment) + from litex.build.xilinx import symbiflow + self.add_period_constraint(self.lookup_request(default_clk_name, loose=True), default_clk_period ) diff --git a/litex_boards/targets/spartan_edge_accelerator.py b/litex_boards/targets/spartan_edge_accelerator.py new file mode 100755 index 0000000..f151e39 --- /dev/null +++ b/litex_boards/targets/spartan_edge_accelerator.py @@ -0,0 +1,144 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2022 Primesh Pinto +# SPDX-License-Identifier: BSD-2-Clause + +import os +import argparse + +from migen import * +from litex.build.generic_platform import * +from litex_boards.platforms import spartan_edge_accelerator +from litex.build.xilinx.vivado import vivado_build_args, vivado_build_argdict +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.led import LedChaser,WS2812 +from litex.soc.cores.video import * + +#Serial Port IO ----------------------------------------------------------------------------------- + # Serial port use the Pin 0 and 1 of the 10 pin connector togather with Ground +_serial_io= [("serial", 0, + Subsignal("tx", Pins("j10:j10_0")), + Subsignal("rx", Pins("j10:j10_1")), + IOStandard("LVCMOS33") + ), +] + + + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq, with_video_pll): + clk100 = platform.request("clk100") + rst_n = platform.request("cpu_reset") + self.rst = Signal() + + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_hdmi = ClockDomain() + self.clock_domains.cd_hdmi5x = ClockDomain() + + self.submodules.pll = pll = S7PLL(speedgrade=-1) + self.comb += pll.reset.eq(~rst_n | self.rst) + pll.register_clkin(clk100, sys_clk_freq) + pll.create_clkout(self.cd_sys, sys_clk_freq) + + if with_video_pll: + self.submodules.video_pll = video_pll = S7PLL(speedgrade=-1) #S7MMCM(speedgrade=-1) + video_pll.reset.eq(~rst_n | self.rst) + video_pll.register_clkin(clk100, 100e6) + video_pll.create_clkout(self.cd_hdmi, 25e6) + video_pll.create_clkout(self.cd_hdmi5x, 5*25e6) + + +# BaseSoC ------------------------------------------------------------------------------------------ + +class BaseSoC(SoCCore): + + def __init__(self, toolchain="vivado", sys_clk_freq=int(100e6), + ident_version=True, with_led_chaser=True, with_jtagbone=False,with_video_terminal=True, + with_neopixel=False, **kwargs): + platform = spartan_edge_accelerator.Platform(toolchain=toolchain) + platform.add_extension(_serial_io) + + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, sys_clk_freq, + ident = "LiteX SoC on Sipeed Spartan Edge Accelerator", + ident_version = ident_version, + **kwargs) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq,with_video_pll=with_video_terminal) + + + # Jtagbone --------------------------------------------------------------------------------- + if with_jtagbone: + self.add_jtagbone() + + + # Leds ------------------------------------------------------------------------------------- + if with_led_chaser: + self.submodules.leds = LedChaser( + pads = platform.request_all("user_led"), + sys_clk_freq = sys_clk_freq) + + # Video ------------------------------------------------------------------------------------ + if with_video_terminal: + self.submodules.videophy = VideoHDMIPHY(platform.request("hdmi"), clock_domain="hdmi") + self.add_video_colorbars(phy=self.videophy, timings="640x480@75Hz", clock_domain="hdmi") + #self.add_video_terminal(phy=self.videophy, timings="640x480@75Hz", clock_domain="hdmi") #Fixme Not enough BRAM + + # Neopixel --------------------------------------------------------------------------------- + # To test Nexpixel by "litex> mem_write 0x01000000 0x00100000" + if with_neopixel: + self.submodules.ws2812 = WS2812(platform.request("rgb"), nleds=2, sys_clk_freq=sys_clk_freq) + self.bus.add_slave(name="ws2812", slave=self.ws2812.bus, + region=SoCRegion( + origin = 0x0100_0000, + size = 2*4, + )) + + +# Build -------------------------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser(description="LiteX SoC on Spartan Edge Accelerator") + parser.add_argument("--toolchain", default="vivado", help="Toolchain use to build (default: vivado)") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--sys-clk-freq", default=100e6, help="System clock frequency (default: 100MHz)") + parser.add_argument("--no-ident-version", action="store_false", help="Disable build time output") + parser.add_argument("--with-jtagbone", action="store_true", help="Enable Jtagbone support") + parser.add_argument("--with-video-terminal", action="store_true", help="Enable Video Colorbars (HDMI)") + parser.add_argument("--with-neopixel", action="store_true", help="Enable onboard two Neopixels") + + builder_args(parser) + soc_core_args(parser) + vivado_build_args(parser) + args = parser.parse_args() + + + + soc = BaseSoC( + + toolchain = args.toolchain, + sys_clk_freq = int(float(args.sys_clk_freq)), + ident_version = args.no_ident_version, + with_jtagbone = args.with_jtagbone, + with_video_terminal= args.with_video_terminal, + with_neopixel = args.with_neopixel, + **soc_core_argdict(args) + ) + + builder = Builder(soc, **builder_argdict(args)) + builder_kwargs = vivado_build_argdict(args) if args.toolchain == "vivado" else {} + builder.build(**builder_kwargs, run=args.build) + + + +if __name__ == "__main__": + main()