diff --git a/litex_boards/platforms/snickerdoodle.py b/litex_boards/platforms/snickerdoodle.py new file mode 100644 index 0000000..3e550a2 --- /dev/null +++ b/litex_boards/platforms/snickerdoodle.py @@ -0,0 +1,83 @@ +# +# 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 = [ + # 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 + ("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_freq = 100e6 + + def __init__(self): + XilinxPlatform.__init__(self, "xc7z010-clg400-1", _io, _connectors, toolchain="vivado") + 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(self.default_clk_name, loose=True), + self.default_clk_period) diff --git a/litex_boards/targets/snickerdoodle.py b/litex_boards/targets/snickerdoodle.py new file mode 100755 index 0000000..ba484c3 --- /dev/null +++ b/litex_boards/targets/snickerdoodle.py @@ -0,0 +1,149 @@ +#!/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 * +from litex.soc.cores.led import LedChaser + +# UTILS --------------------------------------------------------------------------------------------- + +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) + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq, use_ps7_clk=False): + 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), + ext_clk_freq = None, + with_led_chaser = True, + xci_file = None, + **kwargs): + + platform = snickerdoodle.Platform() + + 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 = "LiteX SoC on 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 = 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, use_ps7_clk) + + platform.add_platform_command("set_property BITSTREAM.GENERAL.COMPRESS True [current_design]") + + # Leds ------------------------------------------------------------------------------------- + if with_led_chaser: + 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 Snickerdoodle") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + 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( + sys_clk_freq = args.sys_clk_freq, + ext_clk_freq = args.ext_clk_freq, + 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 + soc.platform.bitstream_ext) + prog.load_bitstream(bitstream, target=args.target, device=1) + +if __name__ == "__main__": + main()