diff --git a/litex_boards/platforms/efinix_xyloni_dev_kit.py b/litex_boards/platforms/efinix_xyloni_dev_kit.py new file mode 100644 index 0000000..86ddad6 --- /dev/null +++ b/litex_boards/platforms/efinix_xyloni_dev_kit.py @@ -0,0 +1,103 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2021 Franck Jullien +# Copyright (c) 2021 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import * +from litex.build.efinix.platform import EfinixPlatform +from litex.build.efinix import EfinixProgrammer + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + # Clk 33.333MHz Oscillator + ("clk33", 0, Pins("C3"), IOStandard("3.3_V_LVTTL_/_LVCMOS")), # net PLL_IN + + # SPIFlash (W25Q128JVSIM) + ("spiflash", 0, + Subsignal("cs_n", Pins("J4")), # net SPI_SS + Subsignal("clk", Pins("H4")), # net SPI_SCLK + Subsignal("mosi", Pins("F4")), # net SPI_MOSI + Subsignal("miso", Pins("H3")), # net SPI_MISO + #Subsignal("wp", Pins("")), + #Subsignal("hold", Pins("")), + IOStandard("3.3_V_LVTTL_/_LVCMOS") + ), + + ("spiflash2x", 0, + Subsignal("cs_n", Pins("J4")), # net SPI_SS + Subsignal("clk", Pins("H4")), # net SPI_SCLK + Subsignal("dq", Pins("F4 H3")), # DI DO nets SPI_MOSI, SPI_MISO + #Subsignal("wp", Pins("")), + #Subsignal("hold", Pins("")), + IOStandard("3.3_V_LVTTL_/_LVCMOS") + ), + + # SDCard + ("spisdcard", 0, + # all 4 SPI signals below have 10k pullup on dev board + Subsignal("clk", Pins("J2")), # net SD_SCLK + Subsignal("cs_n", Pins("G5")), # net SD_CS + Subsignal("mosi", Pins("G4")), # net SD_DI + Subsignal("miso", Pins("J3")), # net SD_DO + Subsignal("det", Pins("G3")), # net CD2 + Misc("SLEW=FAST"), + IOStandard("3.3_V_LVTTL_/_LVCMOS") + ), + + # Leds # nets LED1-4 + ("user_led", 0, Pins("B3"), IOStandard( + "3.3_V_LVTTL_/_LVCMOS"), Misc("DRIVE_STRENGTH=3")), + ("user_led", 1, Pins("J6"), IOStandard( + "3.3_V_LVTTL_/_LVCMOS"), Misc("DRIVE_STRENGTH=3")), + ("user_led", 2, Pins("D7"), IOStandard( + "3.3_V_LVTTL_/_LVCMOS"), Misc("DRIVE_STRENGTH=3")), + ("user_led", 3, Pins("D8"), IOStandard( + "3.3_V_LVTTL_/_LVCMOS"), Misc("DRIVE_STRENGTH=3")), + + # Buttons nets BTN1-2 + ("user_btn", 0, Pins("C5"), IOStandard( + "3.3_V_LVTTL_/_LVCMOS"), Misc("WEAK_PULLUP")), + ("user_btn", 1, Pins("C9"), IOStandard( + "3.3_V_LVTTL_/_LVCMOS"), Misc("WEAK_PULLUP")), + + # Serial / PMOD USB-UART on PMOD E. + ("serial", 0, + Subsignal("tx", Pins("F3")), # net TXD + Subsignal("rx", Pins("H2")), # net RXD + IOStandard("3.3_V_LVTTL_/_LVCMOS") + ), +] + +# Connectors --------------------------------------------------------------------------------------- + +_connectors = [ + # Wacky PMOD pinout misunderstood by others too + # resulting in this order: GPIOL_12,14,16,19,13,15,17,18 + ("pmod", "G1 E2 C2 D3 F1 E1 D2 E3"), + # GPIOR_020..28, 30..32, 34..36 + ("j1", "F8 E7 F7 E6 F6 F5 G9 H9 J9 J8 G8 H8 J7 G6 H6"), + # GPIOR_19..10, 08..05, 03, 01, 00 + ("j2", "E8 D9 D8 D7 C9 B9 D6 C8 B8 A9 A8 C7 C6 B6 A6 B5 A5"), +] + +# Platform ----------------------------------------------------------------------------------------- + + +class Platform(EfinixPlatform): + default_clk_name = "clk33" + default_clk_period = 1e9/33.333e6 + + def __init__(self): + EfinixPlatform.__init__(self, "T8F81C2", _io, + _connectors, toolchain="efinity") + + def create_programmer(self): + return EfinixProgrammer() + + def do_finalize(self, fragment): + EfinixPlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request( + "clk33", loose=True), 1e9/33.333e6) diff --git a/litex_boards/targets/efinix_xyloni_dev_kit.py b/litex_boards/targets/efinix_xyloni_dev_kit.py new file mode 100755 index 0000000..ed4fb8f --- /dev/null +++ b/litex_boards/targets/efinix_xyloni_dev_kit.py @@ -0,0 +1,148 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2021 Franck Jullien +# Copyright (c) 2021 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +import argparse + +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer + +from litex_boards.platforms import efinix_xyloni_dev_kit + +from litex.soc.cores.clock import * +from litex.soc.integration.soc_core import * +from litex.soc.integration.soc import SoCRegion +from litex.soc.integration.builder import * +from litex.soc.cores.led import LedChaser + +# CRG ---------------------------------------------------------------------------------------------- + + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq): + self.clock_domains.cd_sys = ClockDomain() + + # # # + + clk33 = platform.request("clk33") + rst_n = platform.request("user_btn", 0) + + if sys_clk_freq == int(33.333e6): + self.comb += self.cd_sys.clk.eq(clk33) + self.specials += AsyncResetSynchronizer(self.cd_sys, ~rst_n) + else: + # PLL TODO: V1 simple pll not supported in infrastructure yet + self.submodules.pll = pll = TRIONPLL(platform) + self.comb += pll.reset.eq(~rst_n) + pll.register_clkin(clk33, 33.333e6) + pll.create_clkout(self.cd_sys, sys_clk_freq, with_reset=True) + +# BaseSoC ------------------------------------------------------------------------------------------ + + +class BaseSoC(SoCCore): + mem_map = {**{"sram": 0x01000000}, **{"spiflash": 0x80000000}} + + def __init__(self, sys_clk_freq, bios_flash_offset, with_uartbone=False, with_spi_flash=False, with_led_chaser=True, **kwargs): + platform = efinix_xyloni_dev_kit.Platform() + + # SoCCore ---------------------------------------------------------------------------------- + kwargs["integrated_sram_size"] = 0xC00 + # kwargs["integrated_rom_size"] = 0x6000 # doesn't fit + kwargs["integrated_rom_size"] = 0 + + # Set CPU variant / reset address + if with_spi_flash: + kwargs["cpu_reset_address"] = self.mem_map["spiflash"] + \ + bios_flash_offset + + # Can probably only support minimal variant of vexriscv + if kwargs.get("cpu_type", "vexriscv") == "vexriscv": + kwargs["cpu_variant"] = "minimal" + + SoCCore.__init__(self, platform, sys_clk_freq, + ident="LiteX SoC on Efinix Xyloni Dev Kit", + ident_version=True, + integrated_rom_no_we=True, # FIXME: Avoid this. + integrated_sram_no_we=True, # FIXME: Avoid this. + integrated_main_ram_no_we=True, # FIXME: Avoid this. + **kwargs) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq) + + # SPI Flash -------------------------------------------------------------------------------- + if with_spi_flash: + from litespi.modules import W25Q128JV + from litespi.opcodes import SpiNorFlashOpCodes as Codes + self.add_spi_flash(mode="1x", module=W25Q128JV( + Codes.READ_1_1_1), with_master=True) + + # Add ROM linker region -------------------------------------------------------------------- + self.bus.add_region("rom", SoCRegion( + origin=self.mem_map["spiflash"] + bios_flash_offset, + size=32*1024, + linker=True) + ) + + # UartBone --------------------------------------------------------------------------------- + if with_uartbone: + self.add_uartbone("serial", baudrate=1e6) + + # 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 Efinix Xyloni Dev Kit") + parser.add_argument("--build", action="store_true", help="Build bitstream") + parser.add_argument("--load", action="store_true", help="Load bitstream") + parser.add_argument("--flash", action="store_true", help="Flash Bitstream") + # TODO: try a differnet frequency when PLL is supported + parser.add_argument("--sys-clk-freq", default=33.333e6, + help="System clock frequency (default: 33.333MHz)") + parser.add_argument("--with-uartbone", action="store_true", + help="Enable Uartbone support") + parser.add_argument("--with-spi-flash", action="store_true", + help="Enable SPI Flash (MMAPed)") + parser.add_argument("--bios-flash-offset", default=0x40000, + help="BIOS offset in SPI Flash (default: 0x40000)") + + builder_args(parser) + soc_core_args(parser) + args = parser.parse_args() + + soc = BaseSoC( + int(float(args.sys_clk_freq)), + bios_flash_offset=args.bios_flash_offset, + with_uartbone=args.with_uartbone, + with_spi_flash=args.with_spi_flash, + **soc_core_argdict(args)) + 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, f"outflow/{soc.build_name}.bit")) + + if args.flash: + from litex.build.openfpgaloader import OpenFPGALoader + prog = OpenFPGALoader("xyloni_spi") + prog.flash(0, os.path.join(builder.gateware_dir, + f"outflow/{soc.build_name}.hex")) + + +if __name__ == "__main__": + main() diff --git a/test/test_targets.py b/test/test_targets.py index 89c00ca..2ca005b 100644 --- a/test/test_targets.py +++ b/test/test_targets.py @@ -19,12 +19,14 @@ class TestTargets(unittest.TestCase): "quicklogic_quickfeather", # Reason: No default clock. "efinix_trion_t120_bga576_dev_kit", # Reason: Require Efinity toolchain. "efinix_trion_t20_bga256_dev_kit", # Reason: Require Efinity toolchain. + "efinix_xyloni_dev_kit", # Reason: Require Efinity toolchain. ] excluded_targets = [ "simple", # Reason: Generic target. "quicklogic_quickfeather", # Reason: No default clock. "efinix_trion_t120_bga576_dev_kit", # Reason: Require Efinity toolchain. "efinix_trion_t20_bga256_dev_kit", # Reason: Require Efinity toolchain. + "efinix_xyloni_dev_kit", # Reason: Require Efinity toolchain. ] # Build simple design for all platforms.