#!/usr/bin/env python3 # This file is Copyright (c) 2018-2019 Rohit Singh # This file is Copyright (c) 2019 Florent Kermarrec # License: BSD import os import argparse import sys from migen import * from migen.genlib.misc import WaitTimer from litex.build import tools from litex_boards.platforms import nereid from litex.soc.interconnect.csr import * from litex.soc.integration.soc_core import * from litex.soc.integration.soc_sdram import * from litex.soc.integration.builder import * from litex.soc.integration.export import * from litex.soc.cores.clock import * from litex.soc.cores.dna import DNA from litex.soc.cores.xadc import XADC from litex.soc.cores.icap import ICAP from litedram.modules import MT8KTF51264 from litedram.phy import s7ddrphy from litepcie.phy.s7pciephy import S7PCIEPHY from litepcie.core import LitePCIeEndpoint, LitePCIeMSI from litepcie.frontend.dma import LitePCIeDMA from litepcie.frontend.wishbone import LitePCIeWishboneBridge # CRG ---------------------------------------------------------------------------------------------- class CRG(Module, AutoCSR): def __init__(self, platform, sys_clk_freq): self.rst = CSR() self.clock_domains.cd_sys = ClockDomain() self.clock_domains.cd_sys4x = ClockDomain(reset_less=True) self.clock_domains.cd_clk200 = ClockDomain() # Clk/Rst clk100 = platform.request("clk100") # Delay software reset by 10us to ensure write has been acked on PCIe. rst_delay = WaitTimer(int(10e-6*sys_clk_freq)) self.submodules += rst_delay self.sync += If(self.rst.re, rst_delay.wait.eq(1)) # PLL self.submodules.pll = pll = S7PLL() self.comb += pll.reset.eq(rst_delay.done) pll.register_clkin(clk100, 100e6) pll.create_clkout(self.cd_sys, sys_clk_freq) pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq) pll.create_clkout(self.cd_clk200, 200e6) self.submodules.idelayctrl = S7IDELAYCTRL(self.cd_clk200) # PCIeSoC ----------------------------------------------------------------------------------------- class PCIeSoC(SoCCore): def __init__(self, platform, **kwargs): sys_clk_freq = int(100e6) # SoCCore ---------------------------------------------------------------------------------- SoCCore.__init__(self, platform, sys_clk_freq, ident = "LiteX SoC on Nereid", ident_version = True, **kwargs) # CRG -------------------------------------------------------------------------------------- self.submodules.crg = CRG(platform, sys_clk_freq) self.add_csr("crg") # DNA -------------------------------------------------------------------------------------- self.submodules.dna = DNA() self.dna.add_timing_constraints(platform, sys_clk_freq, self.crg.cd_sys.clk) self.add_csr("dna") # XADC ------------------------------------------------------------------------------------- self.submodules.xadc = XADC() self.add_csr("xadc") # ICAP ------------------------------------------------------------------------------------- self.submodules.icap = ICAP(platform) self.icap.add_timing_constraints(platform, sys_clk_freq, self.crg.cd_sys.clk) self.add_csr("icap") # DDR3 SDRAM ------------------------------------------------------------------------------- if not self.integrated_main_ram_size: self.submodules.ddrphy = s7ddrphy.K7DDRPHY(platform.request("ddram"), memtype = "DDR3", nphases = 4, sys_clk_freq = sys_clk_freq, iodelay_clk_freq = 200e6) self.add_csr("ddrphy") self.add_sdram("sdram", phy = self.ddrphy, module = MT8KTF51264(sys_clk_freq, "1:4", speedgrade="800"), 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 ) # PCIe ------------------------------------------------------------------------------------- # PHY self.submodules.pcie_phy = S7PCIEPHY(platform, platform.request("pcie_x4"), data_width = 128, bar0_size = 0x20000) self.pcie_phy.add_timing_constraints(platform) 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") # DMA1 self.submodules.pcie_dma1 = LitePCIeDMA(self.pcie_phy, self.pcie_endpoint, with_buffering = True, buffering_depth=1024, with_loopback = True) self.add_csr("pcie_dma1") self.add_constant("DMA_CHANNELS", 2) # 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, "PCIE_DMA1_WRITER": self.pcie_dma1.writer.irq, "PCIE_DMA1_READER": self.pcie_dma1.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) def generate_software_headers(self): csr_header = get_csr_header(self.csr_regions, self.constants, with_access_functions=False) tools.write_to_file("csr.h", csr_header) soc_header = get_soc_header(self.constants, with_access_functions=False) tools.write_to_file("soc.h", soc_header) mem_header = get_mem_header(self.mem_regions) tools.write_to_file("mem.h", mem_header) # Build -------------------------------------------------------------------------------------------- def main(): parser = argparse.ArgumentParser(description="LiteX SoC on Nereid") parser.add_argument("--build", action="store_true", help="Build bitstream") parser.add_argument("--load", action="store_true", help="Load bitstream") builder_args(parser) soc_sdram_args(parser) args = parser.parse_args() # Enforce arguments args.uart_name = "crossover" args.csr_data_width = 32 platform = nereid.Platform() soc = PCIeSoC(platform, **soc_sdram_argdict(args)) builder = Builder(soc, **builder_argdict(args)) vns = builder.build(run=args.build) soc.generate_software_headers() if args.load: prog = soc.platform.create_programmer() prog.load_bitstream(os.path.join(builder.gateware_dir, "top.bit")) if __name__ == "__main__": main()