From 1c87c391c42ef56ac916fa285a6e6bc3dd2f716b Mon Sep 17 00:00:00 2001 From: Derek Mulcahy Date: Tue, 14 Dec 2021 16:00:42 -0500 Subject: [PATCH 1/5] Initial release for Snickerdoodle --- litex_boards/platforms/snickerdoodle.py | 73 +++++++++++++ litex_boards/targets/snickerdoodle.py | 133 ++++++++++++++++++++++++ 2 files changed, 206 insertions(+) create mode 100644 litex_boards/platforms/snickerdoodle.py create mode 100755 litex_boards/targets/snickerdoodle.py diff --git a/litex_boards/platforms/snickerdoodle.py b/litex_boards/platforms/snickerdoodle.py new file mode 100644 index 0000000..99bd6e6 --- /dev/null +++ b/litex_boards/platforms/snickerdoodle.py @@ -0,0 +1,73 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2019-2020 Florent Kermarrec +# Copyright (c) 2021 Derek Mulcahy , +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import * +from litex.build.xilinx import XilinxPlatform, VivadoProgrammer + + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ +] + +_ps7_io = [ + # PS7 + ("ps7_clk", 0, Pins(1)), + ("ps7_porb", 0, Pins(1)), + ("ps7_srstb", 0, Pins(1)), + ("ps7_mio", 0, Pins(54)), + ("ps7_ddram", 0, + Subsignal("addr", Pins(15)), + Subsignal("ba", Pins(3)), + Subsignal("cas_n", Pins(1)), + Subsignal("ck_n", Pins(1)), + Subsignal("ck_p", Pins(1)), + Subsignal("cke", Pins(1)), + Subsignal("cs_n", Pins(1)), + Subsignal("dm", Pins(4)), + Subsignal("dq", Pins(32)), + Subsignal("dqs_n", Pins(4)), + Subsignal("dqs_p", Pins(4)), + Subsignal("odt", Pins(1)), + Subsignal("ras_n", Pins(1)), + Subsignal("reset_n", Pins(1)), + Subsignal("we_n", Pins(1)), + Subsignal("vrn", Pins(1)), + Subsignal("vrp", Pins(1)), + ), +] + +# Connectors --------------------------------------------------------------------------------------- + +_connectors = [ + ("ja1", "- - - G14 E18 D20 E19 D19 - - F16 B20 F17 C20 - - E17 A20 D18 B19 - - F19 G20 F20 G19 - - J20 G18 H20 G17 - - J18 H17 H18 H16 - -"), + ("ja2", "- - - J15 L14 J16 L15 K16 - - M14 G15 M15 H15 - - N15 J14 N16 K14 - - L19 J19 L20 K19 - - M17 M20 M18 M19 - - L16 K18 L17 K17 - -"), + ("jb1", "- - - T19 T11 U12 T10 T12 - - P14 W13 R14 V12 - - U13 T14 V13 T14 - - T16 Y17 U17 Y16 - - W14 W15 Y14 V15 - - U14 U19 U15 U18 - -"), + ("jb2", "- - - R19 N17 P16 P18 P15 - - T17 R17 R18 R16 - - V17 W19 V18 W18 - - T20 W16 U20 V16 - - V20 Y19 W20 Y18 - - N20 P19 P20 N18 - -"), + ("jc1", "- - - V5 U7 U10 V7 T9 - - T5 Y13 U5 Y12 - - V11 W6 V10 V6 - - V8 Y11 W8 W11 - - U9 W9 U8 W10 - - Y9 Y6 Y8 Y7 - -"), + # ("xadc", "N15 L14 K16 K14 N16 L15 J16 J14"), + # ("mrcc", "H17 H16 K18 K17 U19 U18 P19 N18 Y6 Y7"), + # ("srcc", "J18 H18 L16 L17 U14 U15 N20 P20 Y9 Y8"), +] + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(XilinxPlatform): + # The clock speed depends on the PS7 PLL configuration for the FCLK_CLK0 signal. + default_clk_name = "clk100" + default_clk_period = 1e9/100e6 + + def __init__(self): + XilinxPlatform.__init__(self, "xc7z010-clg400-1", _io, _connectors, toolchain="vivado") + self.add_extension(_ps7_io) + + def create_programmer(self): + return VivadoProgrammer(flash_part="n25q128a") + + 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/snickerdoodle.py b/litex_boards/targets/snickerdoodle.py new file mode 100755 index 0000000..dc86632 --- /dev/null +++ b/litex_boards/targets/snickerdoodle.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2019-2020 Florent Kermarrec , +# Copyright (c) 2021 Derek Mulcahy , +# SPDX-License-Identifier: BSD-2-Clause + +import os +import argparse + +from migen import * + +from litex_boards.platforms import snickerdoodle +from litex.build.xilinx.vivado import vivado_build_args, vivado_build_argdict + +from litex.soc.interconnect import axi +from litex.soc.interconnect import wishbone + +from litex.soc.cores.clock import * +from litex.soc.integration.soc_core import * +from litex.soc.integration.builder import * + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq, use_ps7_clk=True): + self.rst = Signal() + self.clock_domains.cd_sys = ClockDomain() + + # # # + + if use_ps7_clk: + assert sys_clk_freq == 100e6 + self.comb += ClockSignal("sys").eq(ClockSignal("ps7")) + self.comb += ResetSignal("sys").eq(ResetSignal("ps7") | self.rst) + else: + raise NotImplementedError + +# BaseSoC ------------------------------------------------------------------------------------------ + +def load_ps7(soc, xci_file): + odir = os.path.join("build", "snickerdoodle", "gateware", "xci") + os.makedirs(odir, exist_ok=True) + file = "snickerdoodle_ps7.xci" + dst = os.path.join(odir, file) + if xci_file is None: + src = "https://technicaltoys-support.s3.amazonaws.com/xci/" + file + os.system("wget " + src + " -O " + dst) + else: + os.system("cp -p " + xci_file + " " + dst) + soc.cpu.set_ps7_xci(dst) + +def blinky(soc, platform): + from litex.build.generic_platform import Pins, IOStandard + platform.add_extension([("blinky_led", 0, Pins("ja1:3"), IOStandard("LVCMOS33"))]) + led = platform.request("blinky_led") + soc.submodules.blinky = blinky = Module() + counter = Signal(27) + blinky.comb += led.eq(counter[counter.nbits-1]) + blinky.sync += counter.eq(counter + 1) + +class BaseSoC(SoCCore): + + def __init__(self, sys_clk_freq=int(100e6), + with_blinky = False, + blinky_led = "ja1:3", + xci_file = None, + **kwargs): + + platform = snickerdoodle.Platform() + + kwargs["with_uart"] = False + kwargs["cpu_type"] = "zynq7000" + + # SoCCore ---------------------------------------------------------------------------------- + SoCCore.__init__(self, platform, sys_clk_freq, + ident = "Snickerdoodle", + ident_version = True, + **kwargs) + + # Zynq7000 Integration --------------------------------------------------------------------- + if kwargs.get("cpu_type", None) == "zynq7000": + load_ps7(self, xci_file) + + # Connect AXI GP0 to the SoC with base address of 0x43c00000 (default one) + wb_gp0 = wishbone.Interface() + self.submodules += axi.AXI2Wishbone( + axi = self.cpu.add_axi_gp_master(), + wishbone = wb_gp0, + base_address = 0x43c00000) + self.add_wb_master(wb_gp0) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq) + + platform.add_platform_command("set_property BITSTREAM.GENERAL.COMPRESS True [current_design]") + + if with_blinky: + blinky(self, platform) + +# Build -------------------------------------------------------------------------------------------- + +def main(): + parser = argparse.ArgumentParser(description="LiteX SoC on Snickerdoodle") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--with-blinky", action="store_true", help="Enable Blinky") + parser.add_argument("--blinky-led", default="ja1:3", help="Blinky LED") + parser.add_argument("--xci-file", help="XCI for PS7 configuration") + parser.add_argument("--target", help="Programmer target") + builder_args(parser) + soc_core_args(parser) + vivado_build_args(parser) + args = parser.parse_args() + + soc = BaseSoC( + with_blinky = args.with_blinky, + blinky_led = args.blinky_led, + xci_file = args.xci_file, + **soc_core_argdict(args) + ) + builder = Builder(soc, **builder_argdict(args)) + builder.build(**vivado_build_argdict(args), run=args.build) + + if args.load: + prog = soc.platform.create_programmer() + bitstream = os.path.join(builder.gateware_dir, soc.build_name + ".bit") + prog.load_bitstream(bitstream, target=args.target, device=1) + +if __name__ == "__main__": + main() From 15ea01197db81ff9a485fea54695287f119c02a2 Mon Sep 17 00:00:00 2001 From: Derek Mulcahy Date: Mon, 20 Dec 2021 21:12:46 -0500 Subject: [PATCH 2/5] Added placeholder clk/led/uart. --- litex_boards/platforms/snickerdoodle.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/litex_boards/platforms/snickerdoodle.py b/litex_boards/platforms/snickerdoodle.py index 99bd6e6..3e550a2 100644 --- a/litex_boards/platforms/snickerdoodle.py +++ b/litex_boards/platforms/snickerdoodle.py @@ -8,13 +8,22 @@ from litex.build.generic_platform import * from litex.build.xilinx import XilinxPlatform, VivadoProgrammer - # IOs ---------------------------------------------------------------------------------------------- _io = [ -] + # Clk / Rst - A placeholder for an external clock + ("clk100", 0, Pins("H16"), IOStandard("LVCMOS33")), + + # Leds - A placeholder for an external LED + ("user_led", 0, Pins("G14"), IOStandard("LVCMOS33")), + + # UART - A placeholder for an external UART + ("serial", 0, + Subsignal("tx", Pins("D19")), + Subsignal("rx", Pins("D20")), + IOStandard("LVCMOS33"), + ), -_ps7_io = [ # PS7 ("ps7_clk", 0, Pins(1)), ("ps7_porb", 0, Pins(1)), @@ -59,15 +68,16 @@ _connectors = [ class Platform(XilinxPlatform): # The clock speed depends on the PS7 PLL configuration for the FCLK_CLK0 signal. default_clk_name = "clk100" - default_clk_period = 1e9/100e6 + default_clk_freq = 100e6 def __init__(self): XilinxPlatform.__init__(self, "xc7z010-clg400-1", _io, _connectors, toolchain="vivado") - self.add_extension(_ps7_io) + self.default_clk_period = 1e9 / self.default_clk_freq def create_programmer(self): return VivadoProgrammer(flash_part="n25q128a") def do_finalize(self, fragment): XilinxPlatform.do_finalize(self, fragment) - self.add_period_constraint(self.lookup_request("clk100", loose=True), 1e9/100e6) + self.add_period_constraint(self.lookup_request(self.default_clk_name, loose=True), + self.default_clk_period) From 81404ff185dadf9dd646d7ccade646135b9ecad3 Mon Sep 17 00:00:00 2001 From: Derek Mulcahy Date: Mon, 20 Dec 2021 21:14:18 -0500 Subject: [PATCH 3/5] Improved PS7 support. Configured external clock. --- litex_boards/targets/snickerdoodle.py | 116 ++++++++++++++++---------- 1 file changed, 71 insertions(+), 45 deletions(-) diff --git a/litex_boards/targets/snickerdoodle.py b/litex_boards/targets/snickerdoodle.py index dc86632..10f7348 100755 --- a/litex_boards/targets/snickerdoodle.py +++ b/litex_boards/targets/snickerdoodle.py @@ -22,23 +22,9 @@ from litex.soc.cores.clock import * from litex.soc.integration.soc_core import * from litex.soc.integration.builder import * -# CRG ---------------------------------------------------------------------------------------------- +from litex.build.generic_platform import Pins, IOStandard, Subsignal -class _CRG(Module): - def __init__(self, platform, sys_clk_freq, use_ps7_clk=True): - self.rst = Signal() - self.clock_domains.cd_sys = ClockDomain() - - # # # - - if use_ps7_clk: - assert sys_clk_freq == 100e6 - self.comb += ClockSignal("sys").eq(ClockSignal("ps7")) - self.comb += ResetSignal("sys").eq(ResetSignal("ps7") | self.rst) - else: - raise NotImplementedError - -# BaseSoC ------------------------------------------------------------------------------------------ +# UTILS --------------------------------------------------------------------------------------------- def load_ps7(soc, xci_file): odir = os.path.join("build", "snickerdoodle", "gateware", "xci") @@ -52,31 +38,61 @@ def load_ps7(soc, xci_file): os.system("cp -p " + xci_file + " " + dst) soc.cpu.set_ps7_xci(dst) -def blinky(soc, platform): - from litex.build.generic_platform import Pins, IOStandard - platform.add_extension([("blinky_led", 0, Pins("ja1:3"), IOStandard("LVCMOS33"))]) - led = platform.request("blinky_led") - soc.submodules.blinky = blinky = Module() - counter = Signal(27) - blinky.comb += led.eq(counter[counter.nbits-1]) - blinky.sync += counter.eq(counter + 1) +class Blinky(Module): + def __init__(self, led, sys_clk_freq, period=1e0): + counter = Signal(max=int(period * sys_clk_freq)) + self.comb += led.eq(counter[counter.nbits-1]) + self.sync += counter.eq(counter + 1) + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq, use_ps7_clk=False, ext_freq=10e6): + self.rst = Signal() + self.clock_domains.cd_sys = ClockDomain() + + # # # + + if use_ps7_clk: + assert sys_clk_freq == 100e6 + self.comb += ClockSignal("sys").eq(ClockSignal("ps7")) + self.comb += ResetSignal("sys").eq(ResetSignal("ps7") | self.rst) + else: + self.submodules.pll = pll = S7MMCM(speedgrade=-1) + self.comb += pll.reset.eq(self.rst) + pll.register_clkin(platform.request(platform.default_clk_name), + platform.default_clk_freq) + pll.create_clkout(self.cd_sys, sys_clk_freq) + # Ignore sys_clk to pll.clkin path created by SoC's rst. + platform.add_false_path_constraints(self.cd_sys.clk, pll.clkin) + +# BaseSoC ------------------------------------------------------------------------------------------ class BaseSoC(SoCCore): - def __init__(self, sys_clk_freq=int(100e6), - with_blinky = False, - blinky_led = "ja1:3", - xci_file = None, - **kwargs): + def __init__(self, + sys_clk_freq = int(100e6), + ext_clk_freq = None, + with_blinky = True, + xci_file = None, + **kwargs): platform = snickerdoodle.Platform() - kwargs["with_uart"] = False - kwargs["cpu_type"] = "zynq7000" + if ext_clk_freq: + platform.default_clk_freq = ext_clk_freq + platform.default_clk_period = 1e9 / ext_clk_freq + + if kwargs.get("cpu_type", None) == "zynq7000": + kwargs['integrated_sram_size'] = 0 + kwargs['with_uart'] = False + self.mem_map = { + 'csr': 0x4000_0000, # Zynq GP0 default + } # SoCCore ---------------------------------------------------------------------------------- SoCCore.__init__(self, platform, sys_clk_freq, - ident = "Snickerdoodle", + ident = "LiteX SoC on Snickerdoodle", ident_version = True, **kwargs) @@ -89,36 +105,46 @@ class BaseSoC(SoCCore): self.submodules += axi.AXI2Wishbone( axi = self.cpu.add_axi_gp_master(), wishbone = wb_gp0, - base_address = 0x43c00000) + base_address = self.mem_map['csr']) self.add_wb_master(wb_gp0) + use_ps7_clk = True + else: + use_ps7_clk = False + # CRG -------------------------------------------------------------------------------------- - self.submodules.crg = _CRG(platform, sys_clk_freq) + self.submodules.crg = _CRG(platform, sys_clk_freq, use_ps7_clk) platform.add_platform_command("set_property BITSTREAM.GENERAL.COMPRESS True [current_design]") if with_blinky: - blinky(self, platform) + self.submodules.blinky = Blinky( + led = platform.request("user_led"), + sys_clk_freq = sys_clk_freq, + period = 1 + ) # Build -------------------------------------------------------------------------------------------- def main(): parser = argparse.ArgumentParser(description="LiteX SoC on Snickerdoodle") - parser.add_argument("--build", action="store_true", help="Build bitstream") - parser.add_argument("--load", action="store_true", help="Load bitstream") - parser.add_argument("--with-blinky", action="store_true", help="Enable Blinky") - parser.add_argument("--blinky-led", default="ja1:3", help="Blinky LED") - parser.add_argument("--xci-file", help="XCI for PS7 configuration") - parser.add_argument("--target", help="Programmer target") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--with-blinky", default=True, action="store_true", help="Enable Blinky") + parser.add_argument("--ext-clk-freq", default=10e6, type=float, help="External Clock Frequency") + parser.add_argument("--sys-clk-freq", default=100e6, type=float, help="System clock frequency") + parser.add_argument("--xci-file", help="XCI file for PS7 configuration") + parser.add_argument("--target", help="Vivado programmer target") builder_args(parser) soc_core_args(parser) vivado_build_args(parser) args = parser.parse_args() soc = BaseSoC( - with_blinky = args.with_blinky, - blinky_led = args.blinky_led, - xci_file = args.xci_file, + sys_clk_freq = args.sys_clk_freq, + ext_clk_freq = args.ext_clk_freq, + with_blinky = args.with_blinky, + xci_file = args.xci_file, **soc_core_argdict(args) ) builder = Builder(soc, **builder_argdict(args)) @@ -126,7 +152,7 @@ def main(): if args.load: prog = soc.platform.create_programmer() - bitstream = os.path.join(builder.gateware_dir, soc.build_name + ".bit") + bitstream = os.path.join(builder.gateware_dir, soc.build_name + soc.platform.bitstream_ext) prog.load_bitstream(bitstream, target=args.target, device=1) if __name__ == "__main__": From 154cb672dad735f5535600df2b259ffa19939a02 Mon Sep 17 00:00:00 2001 From: Derek Mulcahy Date: Mon, 20 Dec 2021 21:42:21 -0500 Subject: [PATCH 4/5] Removed unused ext_freq parameter. --- litex_boards/targets/snickerdoodle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/litex_boards/targets/snickerdoodle.py b/litex_boards/targets/snickerdoodle.py index 10f7348..a09fc82 100755 --- a/litex_boards/targets/snickerdoodle.py +++ b/litex_boards/targets/snickerdoodle.py @@ -47,7 +47,7 @@ class Blinky(Module): # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): - def __init__(self, platform, sys_clk_freq, use_ps7_clk=False, ext_freq=10e6): + def __init__(self, platform, sys_clk_freq, use_ps7_clk=False): self.rst = Signal() self.clock_domains.cd_sys = ClockDomain() From a118a0e4991af8ddc086293a6953650c6a1203af Mon Sep 17 00:00:00 2001 From: Derek Mulcahy Date: Fri, 24 Dec 2021 22:14:18 -0500 Subject: [PATCH 5/5] Replaced Blinky with LedChaser. --- litex_boards/targets/snickerdoodle.py | 30 +++++++++------------------ 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/litex_boards/targets/snickerdoodle.py b/litex_boards/targets/snickerdoodle.py index a09fc82..ba484c3 100755 --- a/litex_boards/targets/snickerdoodle.py +++ b/litex_boards/targets/snickerdoodle.py @@ -21,8 +21,7 @@ from litex.soc.interconnect import wishbone from litex.soc.cores.clock import * from litex.soc.integration.soc_core import * from litex.soc.integration.builder import * - -from litex.build.generic_platform import Pins, IOStandard, Subsignal +from litex.soc.cores.led import LedChaser # UTILS --------------------------------------------------------------------------------------------- @@ -38,12 +37,6 @@ def load_ps7(soc, xci_file): os.system("cp -p " + xci_file + " " + dst) soc.cpu.set_ps7_xci(dst) -class Blinky(Module): - def __init__(self, led, sys_clk_freq, period=1e0): - counter = Signal(max=int(period * sys_clk_freq)) - self.comb += led.eq(counter[counter.nbits-1]) - self.sync += counter.eq(counter + 1) - # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): @@ -71,10 +64,10 @@ class _CRG(Module): class BaseSoC(SoCCore): def __init__(self, - sys_clk_freq = int(100e6), - ext_clk_freq = None, - with_blinky = True, - xci_file = None, + sys_clk_freq = int(100e6), + ext_clk_freq = None, + with_led_chaser = True, + xci_file = None, **kwargs): platform = snickerdoodle.Platform() @@ -117,12 +110,11 @@ class BaseSoC(SoCCore): platform.add_platform_command("set_property BITSTREAM.GENERAL.COMPRESS True [current_design]") - if with_blinky: - self.submodules.blinky = Blinky( - led = platform.request("user_led"), - sys_clk_freq = sys_clk_freq, - period = 1 - ) + # Leds ------------------------------------------------------------------------------------- + if with_led_chaser: + self.submodules.leds = LedChaser( + pads = platform.request_all("user_led"), + sys_clk_freq = sys_clk_freq) # Build -------------------------------------------------------------------------------------------- @@ -130,7 +122,6 @@ def main(): parser = argparse.ArgumentParser(description="LiteX SoC on Snickerdoodle") parser.add_argument("--build", action="store_true", help="Build bitstream") parser.add_argument("--load", action="store_true", help="Load bitstream") - parser.add_argument("--with-blinky", default=True, action="store_true", help="Enable Blinky") parser.add_argument("--ext-clk-freq", default=10e6, type=float, help="External Clock Frequency") parser.add_argument("--sys-clk-freq", default=100e6, type=float, help="System clock frequency") parser.add_argument("--xci-file", help="XCI file for PS7 configuration") @@ -143,7 +134,6 @@ def main(): soc = BaseSoC( sys_clk_freq = args.sys_clk_freq, ext_clk_freq = args.ext_clk_freq, - with_blinky = args.with_blinky, xci_file = args.xci_file, **soc_core_argdict(args) )