#!/usr/bin/env python3 # This file is Copyright (c) 2020 Florent Kermarrec # License: BSD # Build/Use ---------------------------------------------------------------------------------------- # Build/Load bitstream: # ./acorn_cle_215.py --build # ./acorn_cle_215.py --load (or --flash) # # Get Linux driver/utilities from: # https://github.com/enjoy-digital/litex_playground/tree/master/004_litepcie_aller_test/software # Copy generated csr.h/soc.h/mem.h to software/kernel. # #.Build the kernel and load it: # cd software/kernel # make # sudo ./init.sh # # Test userspace utilities: # cd software/user # make # ./litepcie_util info # ./litepcie_util scratch_test # ./litepcie_util dma_test # ./litepcie_util uart_test 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 acorn_cle_215 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 litex.soc.cores.led import LedChaser from litedram.modules import MT41K512M16 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_sys4x_dqs = ClockDomain(reset_less=True) self.clock_domains.cd_clk200 = ClockDomain() # Clk/Rst clk200 = platform.request("clk200") # 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(clk200, 200e6) pll.create_clkout(self.cd_sys, sys_clk_freq) pll.create_clkout(self.cd_sys4x, 4*sys_clk_freq) pll.create_clkout(self.cd_sys4x_dqs, 4*sys_clk_freq, phase=90) 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 Acorn CLE 215+", 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.A7DDRPHY(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 = MT41K512M16(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 ) # 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") self.comb += platform.request("pcie_clkreq_n").eq(0) # 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) # Leds ------------------------------------------------------------------------------------- self.submodules.leds = LedChaser( pads = Cat(*[platform.request("user_led", i) for i in range(4)]), sys_clk_freq = sys_clk_freq) self.add_csr("leds") 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 LiteX SoC on Acorn CLE 215+") 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") builder_args(parser) soc_sdram_args(parser) args = parser.parse_args() # Enforce arguments args.uart_name = "crossover" args.csr_data_width = 32 platform = acorn_cle_215.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 args.flash: prog = soc.platform.create_programmer() prog.flash(0, os.path.join(builder.gateware_dir, "top.bin")) if __name__ == "__main__": main()