diff --git a/litex_boards/platforms/fpgawars_alhambra2.py b/litex_boards/platforms/fpgawars_alhambra2.py new file mode 100644 index 0000000..3aa84f4 --- /dev/null +++ b/litex_boards/platforms/fpgawars_alhambra2.py @@ -0,0 +1,95 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2022 JM Robles +# Copyright (c) 2021 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import * +from litex.build.lattice import LatticePlatform +from litex.build.lattice.programmer import IceStormProgrammer + +_io = [ + + # Clock + ("clk12", 0, Pins("49"), IOStandard("LVCMOS33")), + # Leds + ("user_leds", 0, Pins("45"), IOStandard("LVCMOS33")), + ("user_leds", 1, Pins("44"), IOStandard("LVCMOS33")), + ("user_leds", 2, Pins("43"), IOStandard("LVCMOS33")), + ("user_leds", 3, Pins("42"), IOStandard("LVCMOS33")), + ("user_leds", 4, Pins("41"), IOStandard("LVCMOS33")), + ("user_leds", 5, Pins("39"), IOStandard("LVCMOS33")), + ("user_leds", 6, Pins("38"), IOStandard("LVCMOS33")), + ("user_leds", 7, Pins("37"), IOStandard("LVCMOS33")), + # Switches + ("sw1", 0, Pins("34"), IOStandard("LVCMOS33")), + ("sw2", 0, Pins("33"), IOStandard("LVCMOS33")), + + # Serial + ("serial", 0, + Subsignal("rx", Pins("62"), IOStandard("LVCMOS33")), + Subsignal("tx", Pins("61"), IOStandard("LVCMOS33")), + ), + # SPI + ( + "spiflash", 0, + Subsignal("cs_n", Pins("71")), + Subsignal("clk", Pins("70")), + Subsignal("mosi", Pins("67")), + Subsignal("miso", Pins("68")), + IOStandard("LVCMOS33") + + ), + # ADC + ( + "adc", 0, + Subsignal("int", Pins(90)), + Subsignal("sda", Pins(83)), + Subsignal("scl", Pins(84)), + IOStandard("LVCMOS33") + ) + +] + +_connectors = [ + ("d0", "2"), + ("d1", "1"), + ("d2", "4"), + ("d3", "3"), + ("d4", "8"), + ("d5", "7"), + ("d6", "10"), + ("d7", "9"), + ("d8", "20"), + ("d9", "19"), + ("d10", "22"), + ("d11", "21"), + ("d12", "63"), + ("d13", "64"), + + ("a0", "114"), + ("a1", "115"), + ("a2", "116"), + ("a3", "117"), +] + +# Platform ------------------------------------------------------------------------------- + +class Platform(LatticePlatform): + + default_clk_name = "clk12" + default_clk_period = 1e9/12e6 + + def __init__(self, toolchain="icestorm", **kwargs): + + LatticePlatform.__init__(self, "ice40-hx8k-tq144:4k", _io, _connectors, toolchain=toolchain, **kwargs) + + def create_programmer(self, mode="direct"): + + return IceStormProgrammer() + + def do_finalize(self, fragment): + LatticePlatform.do_finalize(self, fragment) + self.add_period_constraint(self.lookup_request("clk12", loose=True), 1e9/12e6) + diff --git a/litex_boards/targets/fpgawars_alhambra2.py b/litex_boards/targets/fpgawars_alhambra2.py new file mode 100644 index 0000000..ee137a8 --- /dev/null +++ b/litex_boards/targets/fpgawars_alhambra2.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2022 JM Robles +# Copyright (c) 2021 Florent Kermarrec +# SPDX-License-Identifier: BSD-2-Clause + +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer + +from litex_boards.platforms import fpgawars_alhambra2 + +from litex.build.lattice.programmer import IceStormProgrammer +from litex.build.lattice.icestorm import icestorm_args, icestorm_argdict +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 + +kB = 1024 +mB = 1024*kB + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq): + assert sys_clk_freq == 12e6 + self.rst = Signal() + self.clock_domains.cd_sys = ClockDomain() + self.clock_domains.cd_por = ClockDomain() + + sys = platform.request("clk12") + platform.add_period_constraint(sys, 1e9/12e6) + + # Power on reset + por_count = Signal(16, reset=2**16-1) + por_done = Signal() + self.comb += self.cd_por.clk.eq(ClockSignal("sys")) + self.comb += por_done.eq(por_count == 0) + self.sync.por += If(~por_done, por_count.eq(por_count -1)) + + # Sys clk + self.comb += self.cd_sys.clk.eq(sys) + self.specials += AsyncResetSynchronizer(self.cd_sys, ~por_done) + +class BaseSoC(SoCCore): + + def __init__(self, sys_clk_freq=int(12e6), with_led_chaser=True, bios_flash_offset=0x50000, **kwargs): + + platform = fpgawars_alhambra2.Platform() + kwargs["integrated_rom_size"] = 0 + + # SoC + SoCCore.__init__(self, platform, sys_clk_freq, ident='Litex on Alhambra II', **kwargs) + # SPI Flash + from litespi.modules import N25Q032A + from litespi.opcodes import SpiNorFlashOpCodes as Codes + self.add_spi_flash(mode='1x', module=N25Q032A(Codes.READ_1_1_1), with_master=False) + self.bus.add_region("rom", SoCRegion( + origin=self.bus.regions["spiflash"].origin + bios_flash_offset, + size=32*kB, + linker=True + )) + self.cpu.set_reset_address(self.bus.regions["rom"].origin) + + # CRG + self.submodules.crg = _CRG(platform, sys_clk_freq) + + # Leds + if with_led_chaser: + self.submodules.leds = LedChaser(pads=platform.request_all("user_leds"), sys_clk_freq=sys_clk_freq) + + +def main(): + + from litex.soc.integration.soc import LiteXSoCArgumentParser + + parser = LiteXSoCArgumentParser(description="LiteX SoC on Lattice iCE40UP5k EVN breakout board") + target_group = parser.add_argument_group(title="Target options") + target_group.add_argument("--build", action="store_true", help="Build bitstream.") + target_group.add_argument("--sys-clk-freq", default=12e6, help="System clock frequency.") + target_group.add_argument("--toolchain", default="icestorm", help="FPGA toolchain (radiant or prjoxide).") + target_group.add_argument("--bios-flash-offset", default="0x50000", help="BIOS offset in SPI flash") + target_group.add_argument("--flash", action="store_true", help="Flash Bitstream.") + builder_args(parser) + soc_core_args(parser) + icestorm_args(parser) + args = parser.parse_args() + + soc = BaseSoC( + bios_flash_offset = int(args.bios_flash_offset, 0), + sys_clk_freq = int(float(args.sys_clk_freq)), + **soc_core_argdict(args) + ) + builder = Builder(soc, **builder_argdict(args)) + if args.build: + builder.build(**icestorm_argdict(args)) + + if args.flash: + flash(args.bios_flash_offset) + +if __name__ == "__main__": + main()