#!/usr/bin/env python3 # # This file is part of LiteX-Boards. # # Copyright (c) 2020 Florent Kermarrec # SPDX-License-Identifier: BSD-2-Clause import os import argparse from migen import * from litex_boards.platforms import xcu1525 from litex.soc.cores.clock import * from litex.soc.integration.soc_core import * from litex.soc.integration.soc_sdram import * from litex.soc.integration.builder import * from litex.soc.cores.led import LedChaser from litedram.modules import MT40A512M8 from litedram.phy import usddrphy from litepcie.phy.usppciephy import USPPCIEPHY from litepcie.core import LitePCIeEndpoint, LitePCIeMSI from litepcie.frontend.dma import LitePCIeDMA from litepcie.frontend.wishbone import LitePCIeWishboneBridge from litepcie.software import generate_litepcie_software # CRG ---------------------------------------------------------------------------------------------- class _CRG(Module): def __init__(self, platform, sys_clk_freq): self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) self.clock_domains.cd_pll4x = ClockDomain(reset_less=True) self.clock_domains.cd_clk500 = ClockDomain() # # # self.submodules.pll = pll = USPMMCM(speedgrade=-2) pll.register_clkin(platform.request("clk300"), 300e6) pll.create_clkout(self.cd_pll4x, sys_clk_freq*4, buf=None, with_reset=False) pll.create_clkout(self.cd_clk500, 500e6, with_reset=False) self.specials += [ Instance("BUFGCE_DIV", name="main_bufgce_div", p_BUFGCE_DIVIDE=4, i_CE=1, i_I=self.cd_pll4x.clk, o_O=self.cd_sys.clk), Instance("BUFGCE", name="main_bufgce", i_CE=1, i_I=self.cd_pll4x.clk, o_O=self.cd_sys4x.clk), AsyncResetSynchronizer(self.cd_clk500, ~pll.locked), ] self.submodules.idelayctrl = USPIDELAYCTRL(cd_ref=self.cd_clk500, cd_sys=self.cd_sys) # BaseSoC ------------------------------------------------------------------------------------------ class BaseSoC(SoCCore): def __init__(self, sys_clk_freq=int(125e6), ddram_channel=0, with_pcie=False, **kwargs): platform = xcu1525.Platform() # SoCCore ---------------------------------------------------------------------------------- SoCCore.__init__(self, platform, sys_clk_freq, ident = "LiteX SoC on XCU1525", ident_version = True, **kwargs) # CRG -------------------------------------------------------------------------------------- self.submodules.crg = _CRG(platform, sys_clk_freq) # DDR4 SDRAM ------------------------------------------------------------------------------- if not self.integrated_main_ram_size: self.submodules.ddrphy = usddrphy.USPDDRPHY( pads = platform.request("ddram", ddram_channel), memtype = "DDR4", sys_clk_freq = sys_clk_freq, iodelay_clk_freq = 500e6, cmd_latency = 1) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, module = MT40A512M8(sys_clk_freq, "1:4"), origin = self.mem_map["main_ram"], size = kwargs.get("max_sdram_size", 0x40000000), l2_cache_size = kwargs.get("l2_size", 8192), l2_cache_min_data_width = kwargs.get("min_l2_data_width", 128), l2_cache_reverse = True ) # Workadound for Vivado 2018.2 DRC, can be ignored and probably fixed on newer Vivado versions. platform.add_platform_command("set_property SEVERITY {{Warning}} [get_drc_checks PDCN-2736]") # PCIe ------------------------------------------------------------------------------------- if with_pcie: # PHY self.submodules.pcie_phy = USPPCIEPHY(platform, platform.request("pcie_x4"), data_width = 128, bar0_size = 0x20000) platform.add_false_path_constraints(self.crg.cd_sys.clk, self.pcie_phy.cd_pcie.clk) self.add_csr("pcie_phy") # Endpoint self.submodules.pcie_endpoint = LitePCIeEndpoint(self.pcie_phy, max_pending_requests=8) # Wishbone bridge self.submodules.pcie_bridge = LitePCIeWishboneBridge(self.pcie_endpoint, base_address = self.mem_map["csr"]) self.add_wb_master(self.pcie_bridge.wishbone) # DMA0 self.submodules.pcie_dma0 = LitePCIeDMA(self.pcie_phy, self.pcie_endpoint, with_buffering = True, buffering_depth=1024, with_loopback = True) self.add_csr("pcie_dma0") self.add_constant("DMA_CHANNELS", 1) # MSI self.submodules.pcie_msi = LitePCIeMSI() self.add_csr("pcie_msi") self.comb += self.pcie_msi.source.connect(self.pcie_phy.msi) self.interrupts = { "PCIE_DMA0_WRITER": self.pcie_dma0.writer.irq, "PCIE_DMA0_READER": self.pcie_dma0.reader.irq, } for i, (k, v) in enumerate(sorted(self.interrupts.items())): self.comb += self.pcie_msi.irqs[i].eq(v) self.add_constant(k + "_INTERRUPT", i) # Leds ------------------------------------------------------------------------------------- self.submodules.leds = LedChaser( pads = platform.request_all("user_led"), sys_clk_freq = sys_clk_freq) self.add_csr("leds") # Build -------------------------------------------------------------------------------------------- def main(): parser = argparse.ArgumentParser(description="LiteX SoC on XCU1525") parser.add_argument("--build", action="store_true", help="Build bitstream") parser.add_argument("--ddram-channel", default="0", help="DDRAM channel") parser.add_argument("--with-pcie", action="store_true", help="Enable PCIe support") parser.add_argument("--driver", action="store_true", help="Generate PCIe driver") parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) args = parser.parse_args() # Enforce arguments args.csr_data_width = 32 soc = BaseSoC( ddram_channel = int(args.ddram_channel, 0), with_pcie = args.with_pcie, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) builder.build(run=args.build) if args.driver: generate_litepcie_software(soc, os.path.join(builder.output_dir, "driver")) if args.load: prog = soc.platform.create_programmer() prog.load_bitstream(os.path.join(builder.gateware_dir, soc.build_name + ".bit")) if __name__ == "__main__": main()