diff --git a/litex_boards/platforms/antmicro_sdi_mipi_video_converter.py b/litex_boards/platforms/antmicro_sdi_mipi_video_converter.py new file mode 100644 index 0000000..05c3f06 --- /dev/null +++ b/litex_boards/platforms/antmicro_sdi_mipi_video_converter.py @@ -0,0 +1,235 @@ +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: BSD-2-Clause + +from litex.build.generic_platform import * +from litex.build.lattice import LatticePlatform +from litex.build.lattice.programmer import LatticeProgrammer +from litex.build.lattice.programmer import EcpprogProgrammer + +# IOs ---------------------------------------------------------------------------------------------- + +_io = [ + ("clk12", 0, Pins("G15"), IOStandard("LVCMOS33")), + + ("serial", 0, + Subsignal("tx", Pins("J12"), IOStandard("LVCMOS33")), + Subsignal("rx", Pins("J11"), IOStandard("LVCMOS33")), + ), + + # Section 7.3 General Purpose LEDs + ("user_led", 0, Pins("E15"), IOStandard("LVCMOS33")), + ("user_led", 1, Pins("E16"), IOStandard("LVCMOS33")), + + # Section 7.1 DIP Switch + ("user_dip_btn", 0, Pins("F15"), IOStandard("LVCMOS33")), + ("user_dip_btn", 1, Pins("H10"), IOStandard("LVCMOS33")), + + + # Section 6.3.1. SPI Configuration + ("spiflash", 0, + Subsignal("cs_n", Pins("C15")), + Subsignal("clk", Pins("C16")), + Subsignal("mosi", Pins("C14")), + Subsignal("miso", Pins("D16")), + IOStandard("LVCMOS33") + ) +] + + +# Connectors --------------------------------------------------------------------------------------- + +_connectors = [] + +# Test and Demo ------------------------------------------------------------------------------------ + + +# Platform ----------------------------------------------------------------------------------------- + +class Platform(LatticePlatform): + default_clk_name = "clk12" + default_clk_period = 1e9/12e6 + + def __init__(self, device="LIFCL-40-9BG400C", toolchain="radiant", **kwargs): + # Accept "LIFCL" for backwards compatibility. + # LIFCL just means Crosslink-NX so we can expect every + # Crosslink-NX Evaluation Board to have a LIFCL part. + if device == "LIFCL": + device == "LIFCL-40-9BG400C" + assert device in ["LIFCL-40-9BG256C", "LIFCL-40-9BG400C", "LIFCL-40-8BG400CES", "LIFCL-40-8BG400CES2", "LIFCL-40-8BG400C"] + LatticePlatform.__init__(self, device, _io, _connectors, toolchain=toolchain, **kwargs) + + def create_programmer(self, mode="direct", prog="radiant"): + assert mode in ["direct", "flash"] + assert prog in ["radiant", "ecpprog"] + + if prog == "ecpprog": + return EcpprogProgrammer() + + xcf_template_direct = """ + + + + + JTAG + + + 1 + Lattice + LIFCL + LIFCL-40 + 0x010f1043 + All + LIFCL-40 + + 8 + 11111111 + 1 + 0 + + {bitstream_file} + N/A + Static Random Access Memory (SRAM) + Fast Configuration + + + + + SEQUENTIAL + ENTIRED CHAIN + No Override + TLR + TLR + + 3 + + + USB2 + FTUSB-0 + + +""" + + xcf_template_flash = """ + + + + + JTAG2SPI + + + 1 + Lattice + LIFCL + LIFCL-40 + All + + 8 + 11111111 + 1 + 0 + + {bitstream_file} + External SPI Flash Memory (SPI FLASH) + Erase,Program,Verify + + + + + 1 + Lattice + LIFCL + LIFCL-40 + 0x010f1043 + All + LIFCL-40 + + 8 + 11111111 + 1 + 0 + + Static Random Access Memory (SRAM) + Refresh Verify ID + + + + + + 1 + Macronix + SPI Serial Flash + MX25L12833F + 0x18 + 8-pin SOP + Erase,Program,Verify + {bitstream_file} + 0x00000000 + 0x000F0000 + 128 + 1016029 + 1 + + + + + + 1 + + {bitstream_file} + + + + + + + + + + + SEQUENTIAL + ENTIRED CHAIN + No Override + TLR + TLR + + + 3 + + + USB2 + FTUSB-0 + Lattice CrossLink-NX Eval Board A Location 0000 Serial FT4J4IK9A + + +""" + + if mode == "direct": + xcf_template = xcf_template_direct + if mode == "flash": + xcf_template = xcf_template_flash + + return LatticeProgrammer(xcf_template) diff --git a/litex_boards/targets/antmicro_sdi_mipi_video_converter.py b/litex_boards/targets/antmicro_sdi_mipi_video_converter.py new file mode 100755 index 0000000..f2d9b7e --- /dev/null +++ b/litex_boards/targets/antmicro_sdi_mipi_video_converter.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 + +# +# This file is part of LiteX-Boards. +# +# Copyright (c) 2023 Antmicro +# SPDX-License-Identifier: BSD-2-Clause + +import os + +from migen import * +from migen.genlib.resetsync import AsyncResetSynchronizer + +import litex_boards.platforms.antmicro_sdi_mipi_video_converter + +from litex.soc.cores.ram import NXLRAM +from litex.soc.cores.clock import NXPLL +from litex.build.generic_platform import * + +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 + +from litex.build.lattice.oxide import oxide_args, oxide_argdict +from litex.build.lattice.radiant import radiant_build_argdict, radiant_build_args + +kB = 1024 +mB = 1024*kB + + +# CRG ---------------------------------------------------------------------------------------------- + +class _CRG(Module): + def __init__(self, platform, sys_clk_freq): + self.clock_domains.cd_por = ClockDomain() + self.clock_domains.cd_sys = ClockDomain() + + # Built in OSC + self.submodules.hf_clk = NXOSCA() + hf_clk_freq = 25e6 + self.hf_clk.create_hf_clk(self.cd_por, hf_clk_freq) + + # Power on reset + por_count = Signal(16, reset=2**16-1) + por_done = Signal() + self.comb += por_done.eq(por_count == 0) + self.sync.por += If(~por_done, por_count.eq(por_count - 1)) + + # PLL + self.submodules.sys_pll = sys_pll = NXPLL(platform=platform, create_output_port_clocks=True) + sys_pll.register_clkin(self.cd_por.clk, hf_clk_freq) + sys_pll.create_clkout(self.cd_sys, sys_clk_freq) + self.specials += AsyncResetSynchronizer(self.cd_sys, ~self.sys_pll.locked | ~por_done) + + +# BaseSoC ------------------------------------------------------------------------------------------ + +class BaseSoC(SoCCore): + mem_map = { + "rom": 0x00000000, + "sram": 0x40000000, + "main_ram": 0x60000000, + "csr": 0xf0000000, + } + + def __init__(self, sys_clk_freq=int(75e6), device="LIFCL-40-9BG256C", toolchain="radiant", with_led_chaser=True, **kwargs): + platform = litex_boards.platforms.antmicro_sdi_mipi_video_converter.Platform( + device=device, toolchain=toolchain) + + # CRG -------------------------------------------------------------------------------------- + self.submodules.crg = _CRG(platform, sys_clk_freq) + + # SoCCore -----------------------------------------_---------------------------------------- + + # Disable Integrated SRAM since we want to instantiate LRAM specifically for it + kwargs["integrated_sram_size"] = 0 + SoCCore.__init__(self, platform, sys_clk_freq, + ident="LiteX SoC on Crosslink-NX Evaluation Board", **kwargs) + + # 128KB LRAM (used as SRAM) --------------------------------------------------------------- + + self.submodules.spram = NXLRAM(32, 64*kB) + self.bus.add_slave("sram", self.spram.bus, SoCRegion(origin=self.mem_map["sram"], size=16*kB)) + + self.submodules.main_ram = NXLRAM(32, 64*kB) + self.bus.add_slave("main_ram", self.main_ram.bus, SoCRegion(origin=self.mem_map["main_ram"], size=64*kB)) + + # Leds ------------------------------------------------------------------------------------- + if with_led_chaser: + self.submodules.leds = LedChaser( + pads=Cat(*[platform.request("user_led", i) for i in range(2)]), + sys_clk_freq=sys_clk_freq) + +# Build -------------------------------------------------------------------------------------------- + + +def main(): + from litex.soc.integration.soc import LiteXSoCArgumentParser + parser = LiteXSoCArgumentParser(description="LiteX SoC on Crosslink-NX Eval Board") + target_group = parser.add_argument_group(title="Target options") + target_group.add_argument("--build", action="store_true", help="Build design.") + target_group.add_argument("--load", action="store_true", help="Load bitstream.") + target_group.add_argument("--toolchain", default="radiant", help="FPGA toolchain (radiant or prjoxide).") + target_group.add_argument("--device", default="LIFCL-40-9BG256C", help="FPGA device (LIFCL-40-9BG400C, LIFCL-40-8BG400CES, or LIFCL-40-8BG400CES2).") + target_group.add_argument("--sys-clk-freq", default=75e6, help="System clock frequency.") + target_group.add_argument("--programmer", default="radiant", help="Programmer (radiant or ecpprog).") + target_group.add_argument("--prog-target", default="direct", help="Programming Target (direct or flash).") + + builder_args(parser) + soc_core_args(parser) + oxide_args(parser) + radiant_build_args(parser) + args = parser.parse_args() + + soc = BaseSoC( + sys_clk_freq=int(float(args.sys_clk_freq)), + device=args.device, + toolchain=args.toolchain, + **soc_core_argdict(args) + ) + + builder = Builder(soc, **builder_argdict(args)) + builder_kargs = oxide_argdict(args) if args.toolchain == "oxide" else radiant_build_argdict(args) + if args.build: + builder.build(**builder_kargs) + + if args.load: + prog = soc.platform.create_programmer(args.prog_target, args.programmer) + if args.programmer == "ecpprog" and args.prog_target == "flash": + prog.flash(address=args.address, + bitstream=builder.get_bitstream_filename(mode="sram")) + else: + if args.programmer == "radiant": + os.system("sudo modprobe -rf ftdi_sio") + + prog.load_bitstream(builder.get_bitstream_filename(mode="sram")) + + if args.programmer == "radiant": + os.system("sudo modprobe ftdi_sio") + + +if __name__ == "__main__": + main()