Advertisement
Guest User

litepcie_with_spi_and_gpio_UPDATE

a guest
Nov 10th, 2021
93
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 15.60 KB | None | 0 0
  1. #!/usr/bin/env python3
  2.  
  3. #
  4. # This file is part of LitePCIe.
  5. #
  6. # Copyright (c) 2019-2020 Florent Kermarrec <florent@enjoy-digital.fr>
  7. # Copyright (c) 2020 Antmicro <www.antmicro.com>
  8. # SPDX-License-Identifier: BSD-2-Clause
  9.  
  10. """
  11. LitePCIe standalone core generator
  12.  
  13. LitePCIe aims to be directly used as a python package when the SoC is created using LiteX. However,
  14. for some use cases it could be interesting to generate a standalone verilog file of the core:
  15. - integration of the core in a SoC using a more traditional flow.
  16. - need to version/package the core.
  17. - avoid Migen/LiteX dependencies.
  18. - etc...
  19.  
  20. The standalone core is generated from a YAML configuration file that allows the user to generate
  21. easily a custom configuration of the core.
  22.  
  23. Current version of the generator is limited to:
  24. - Xilinx 7-Series.
  25. - Xilinx Ultrascale.
  26. - Altera Cyclone V.
  27. """
  28.  
  29. import yaml
  30. import argparse
  31. import subprocess
  32.  
  33. from migen import *
  34. from migen.genlib.resetsync import AsyncResetSynchronizer
  35. from migen.genlib.misc import WaitTimer
  36.  
  37. from litex.soc.cores.clock import *
  38. from litex.soc.interconnect.csr import *
  39. from litex.soc.interconnect import wishbone
  40. from litex.soc.interconnect.axi import *
  41. from litex.soc.integration.soc_core import *
  42. from litex.soc.integration.builder import *
  43.  
  44. # PCIe pecific imports
  45. from litepcie.core import LitePCIeEndpoint, LitePCIeMSI, LitePCIeMSIMultiVector, LitePCIeMSIX
  46. from litepcie.frontend.dma import LitePCIeDMA
  47. from litepcie.frontend.wishbone import LitePCIeWishboneMaster, LitePCIeWishboneSlave
  48. from litepcie.frontend.axi import LitePCIeAXISlave
  49. from litepcie.software import generate_litepcie_software_headers
  50.  
  51. # SPI flash specific imports
  52. from litex.soc.cores.gpio import GPIOOut
  53. from litex.soc.cores.spi_flash import S7SPIFlash
  54.  
  55. # ICAP specific imports
  56. from litex.soc.cores.icap import ICAP
  57.  
  58. from litex.build.generic_platform import *
  59.  
  60. # IOs/Interfaces -----------------------------------------------------------------------------------
  61.  
  62. def get_clkin_ios():
  63.     return [
  64.         # clk / rst
  65.         ("clk", 0, Pins(1)),
  66.         ("rst", 0, Pins(1))
  67.     ]
  68.  
  69. def get_clkout_ios():
  70.     return [
  71.         # clk / rst
  72.         ("clk125", 0, Pins(1)),
  73.         ("rst125", 0, Pins(1))
  74.     ]
  75.  
  76. def get_gpios():
  77.     return [
  78.         # GPIO
  79.         ("flash_cs_n", 0,Pins("T19"),IOStandard("LVCMOS33"))
  80.     ]
  81.  
  82. def get_spi_ios():
  83.     return [
  84.         # SPI flash
  85.         ("flash", 0,
  86.             Subsignal("mosi", Pins("P22")),
  87.             Subsignal("miso", Pins("R22")),
  88.             Subsignal("wp",   Pins("P21")),
  89.             Subsignal("hold", Pins("R21")),
  90.             IOStandard("LVCMOS33")
  91.         )
  92.     ]
  93.  
  94.  
  95. def get_pcie_ios(phy_lanes=4):
  96.     return [
  97.         ("pcie", 0,
  98.             Subsignal("rst_n", Pins(1)),
  99.             Subsignal("clk_p", Pins(1)),
  100.             Subsignal("clk_n", Pins(1)),
  101.             Subsignal("rx_p",  Pins(phy_lanes)),
  102.             Subsignal("rx_n",  Pins(phy_lanes)),
  103.             Subsignal("tx_p",  Pins(phy_lanes)),
  104.             Subsignal("tx_n",  Pins(phy_lanes)),
  105.         ),
  106.     ]
  107.  
  108. def get_axi_dma_ios(_id, dw):
  109.     return [
  110.         ("dma{}_writer_axi".format(_id), 0,
  111.             Subsignal("tvalid", Pins(1)),
  112.             Subsignal("tready", Pins(1)),
  113.             Subsignal("tlast",  Pins(1)),
  114.             Subsignal("tdata",  Pins(dw)),
  115.             Subsignal("tuser",  Pins(1)), # first
  116.         ),
  117.         ("dma{}_reader_axi".format(_id), 0,
  118.             Subsignal("tvalid", Pins(1)),
  119.             Subsignal("tready", Pins(1)),
  120.             Subsignal("tlast",  Pins(1)),
  121.             Subsignal("tdata",  Pins(dw)),
  122.             Subsignal("tuser",  Pins(1)), # first
  123.         ),
  124.     ]
  125.  
  126. def get_msi_irqs_ios(width=16):
  127.     return [("msi_irqs", 0, Pins(width))]
  128.  
  129. # CRG ----------------------------------------------------------------------------------------------
  130.  
  131. class LitePCIeCRG(Module):
  132.     def __init__(self, platform, sys_clk_freq, clk_external):
  133.         self.clock_domains.cd_sys = ClockDomain()
  134.  
  135.         # # #
  136.  
  137.         if clk_external:
  138.             platform.add_extension(get_clkin_ios())
  139.             self.comb += self.cd_sys.clk.eq(platform.request("clk"))
  140.             self.specials += AsyncResetSynchronizer(self.cd_sys, platform.request("rst"))
  141.         else:
  142.             platform.add_extension(get_clkout_ios())
  143.             self.comb += self.cd_sys.clk.eq(ClockSignal("pcie"))
  144.             self.comb += self.cd_sys.rst.eq(ResetSignal("pcie"))
  145.             self.comb += platform.request("clk125").eq(ClockSignal("pcie"))
  146.             self.comb += platform.request("rst125").eq(ResetSignal("pcie"))
  147.  
  148. # Core ---------------------------------------------------------------------------------------------
  149.  
  150. class LitePCIeCore(SoCMini):
  151.     SoCMini.mem_map["csr"] = 0x00000000
  152.     SoCMini.csr_map = {
  153.         "ctrl":           0,
  154.         "crg" :           1,
  155.         "pcie_phy":       2,
  156.         "pcie_msi":       3,
  157.         "pcie_msi_table": 4,
  158.     }
  159.     def __init__(self, platform, core_config):
  160.         platform.add_extension(get_pcie_ios(core_config["phy_lanes"]))
  161.         for i in range(core_config["dma_channels"]):
  162.             platform.add_extension(get_axi_dma_ios(i, core_config["phy_data_width"]))
  163.         platform.add_extension(get_msi_irqs_ios(width=core_config["msi_irqs"]))
  164.         sys_clk_freq = float(core_config.get("clk_freq", 125e6))
  165.  
  166.         # SoCMini ----------------------------------------------------------------------------------
  167.         SoCMini.__init__(self, platform, clk_freq=sys_clk_freq,
  168.             csr_data_width = 32,
  169.             csr_ordering   = core_config.get("csr_ordering", "big"),
  170.             ident          = "LitePCIe standalone core",
  171.             ident_version  = True
  172.         )
  173.  
  174.         # CRG --------------------------------------------------------------------------------------
  175.         clk_external = core_config.get("clk_external", False)
  176.         self.submodules.crg = LitePCIeCRG(platform, sys_clk_freq, clk_external)
  177.  
  178.         # PCIe PHY ---------------------------------------------------------------------------------
  179.         self.submodules.pcie_phy = core_config["phy"](platform, platform.request("pcie"),
  180.             pcie_data_width = core_config.get("phy_pcie_data_width", 64),
  181.             data_width      = core_config["phy_data_width"],
  182.             bar0_size       = core_config["phy_bar0_size"])
  183.  
  184.         # PCIe Endpoint ----------------------------------------------------------------------------
  185.         self.submodules.pcie_endpoint = LitePCIeEndpoint(self.pcie_phy,
  186.             endianness           = self.pcie_phy.endianness,
  187.             max_pending_requests = core_config.get("ep_max_pending_requests", 4))
  188.  
  189.         # PCIe Wishbone Master ---------------------------------------------------------------------
  190.         pcie_wishbone_master = LitePCIeWishboneMaster(self.pcie_endpoint,
  191.             qword_aligned = self.pcie_phy.qword_aligned)
  192.         self.submodules += pcie_wishbone_master
  193.         self.add_wb_master(pcie_wishbone_master.wishbone)
  194.  
  195.         # PCIe MMAP Master -------------------------------------------------------------------------
  196.         if core_config.get("mmap", False):
  197.             mmap_base        = core_config["mmap_base"]
  198.             mmap_size        = core_config["mmap_size"]
  199.             mmap_translation = core_config.get("mmap_translation", 0x00000000)
  200.             wb = wishbone.Interface(data_width=32)
  201.             self.mem_map["mmap"] = mmap_base
  202.             self.add_wb_slave(mmap_base, wb, mmap_size)
  203.             self.add_memory_region("mmap", mmap_base, mmap_size, type="io")
  204.             axi = AXILiteInterface(data_width=32, address_width=32)
  205.             wb2axi = Wishbone2AXILite(wb, axi, base_address=-mmap_translation)
  206.             self.submodules += wb2axi
  207.             platform.add_extension(axi.get_ios("mmap_axi_lite"))
  208.             axi_pads = platform.request("mmap_axi_lite")
  209.             self.comb += axi.connect_to_pads(axi_pads, mode="master")
  210.  
  211.         # PCIe MMAP Slave --------------------------------------------------------------------------
  212.         if core_config.get("mmap_slave", False):
  213.             # AXI-Full
  214.             if core_config.get("mmap_slave_axi_full", False):
  215.                 pcie_axi_slave = LitePCIeAXISlave(self.pcie_endpoint, data_width=128)
  216.                 self.submodules += pcie_axi_slave
  217.                 platform.add_extension(pcie_axi_slave.axi.get_ios("mmap_slave_axi"))
  218.                 axi_pads = platform.request("mmap_slave_axi")
  219.                 self.comb += pcie_axi_slave.axi.connect_to_pads(axi_pads, mode="slave")
  220.             # AXI-Lite
  221.             else:
  222.                 platform.add_extension(axi.get_ios("mmap_slave_axi_lite"))
  223.                 axi_pads = platform.request("mmap_slave_axi_lite")
  224.                 wb = wishbone.Interface(data_width=32)
  225.                 axi = AXILiteInterface(data_width=32, address_width=32)
  226.                 self.comb += axi.connect_to_pads(axi_pads, mode="slave")
  227.                 axi2wb = AXILite2Wishbone(axi, wb)
  228.                 self.submodules += axi2wb
  229.                 pcie_wishbone_slave = LitePCIeWishboneSlave(self.pcie_endpoint,
  230.                     qword_aligned=self.pcie_phy.qword_aligned)
  231.                 self.submodules += pcie_wishbone_slave
  232.                 self.comb += wb.connect(pcie_wishbone_slave.wishbone)
  233.  
  234.         # PCIe DMA ---------------------------------------------------------------------------------
  235.         pcie_dmas = []
  236.         self.add_constant("DMA_CHANNELS", core_config["dma_channels"])
  237.         for i in range(core_config["dma_channels"]):
  238.             pcie_dma = LitePCIeDMA(self.pcie_phy, self.pcie_endpoint,
  239.                 with_buffering    = core_config["dma_buffering"] != 0,
  240.                 buffering_depth   = core_config["dma_buffering"],
  241.                 with_loopback     = core_config["dma_loopback"],
  242.                 with_synchronizer = core_config["dma_synchronizer"],
  243.                 with_monitor      = core_config["dma_monitor"])
  244.             pcie_dma = stream.BufferizeEndpoints({"sink"   : stream.DIR_SINK})(pcie_dma)
  245.             pcie_dma = stream.BufferizeEndpoints({"source" : stream.DIR_SOURCE})(pcie_dma)
  246.             setattr(self.submodules, "pcie_dma" + str(i), pcie_dma)
  247.             self.add_csr("pcie_dma{}".format(i))
  248.             dma_writer_ios = platform.request("dma{}_writer_axi".format(i))
  249.             dma_reader_ios = platform.request("dma{}_reader_axi".format(i))
  250.             self.comb += [
  251.                 # Writer IOs
  252.                 pcie_dma.sink.valid.eq(dma_writer_ios.tvalid),
  253.                 dma_writer_ios.tready.eq(pcie_dma.sink.ready),
  254.                 pcie_dma.sink.last.eq(dma_writer_ios.tlast),
  255.                 pcie_dma.sink.data.eq(dma_writer_ios.tdata),
  256.                 pcie_dma.sink.first.eq(dma_writer_ios.tuser),
  257.  
  258.                 # Reader IOs
  259.                 dma_reader_ios.tvalid.eq(pcie_dma.source.valid),
  260.                 pcie_dma.source.ready.eq(dma_reader_ios.tready),
  261.                 dma_reader_ios.tlast.eq(pcie_dma.source.last),
  262.                 dma_reader_ios.tdata.eq(pcie_dma.source.data),
  263.                 dma_reader_ios.tuser.eq(pcie_dma.source.first),
  264.             ]
  265.  
  266.         # PCIe MSI ---------------------------------------------------------------------------------
  267.         if core_config.get("msi_x", False):
  268.             assert core_config["msi_irqs"] <= 32
  269.             self.submodules.pcie_msi = LitePCIeMSIX(self.pcie_endpoint, width=64)
  270.             self.comb += self.pcie_msi.irqs[32:32+core_config["msi_irqs"]].eq(platform.request("msi_irqs"))
  271.         else:
  272.             assert core_config["msi_irqs"] <= 16
  273.             if core_config.get("msi_multivector", False):
  274.                 self.submodules.pcie_msi = LitePCIeMSIMultiVector(width=32)
  275.             else:
  276.                 self.submodules.pcie_msi = LitePCIeMSI(width=32)
  277.             self.comb += self.pcie_msi.source.connect(self.pcie_phy.msi)
  278.             self.comb += self.pcie_msi.irqs[16:16+core_config["msi_irqs"]].eq(platform.request("msi_irqs"))
  279.         self.interrupts = {}
  280.         for i in range(core_config["dma_channels"]):
  281.             self.interrupts["pcie_dma" + str(i) + "_writer"] = getattr(self, "pcie_dma" + str(i)).writer.irq
  282.             self.interrupts["pcie_dma" + str(i) + "_reader"] = getattr(self, "pcie_dma" + str(i)).reader.irq
  283.         for i, (k, v) in enumerate(sorted(self.interrupts.items())):
  284.             self.comb += self.pcie_msi.irqs[i].eq(v)
  285.             self.add_constant(k.upper() + "_INTERRUPT", i)
  286.         assert len(self.interrupts.keys()) <= 16
  287.  
  288.         # Flash (For SPIFlash update over PCIe). FIXME: Should probably be updated to use SpiFlashSingle/SpiFlashDualQuad (so MMAPed and do the update with bit-bangin>
  289.         platform.add_extension(get_gpios())
  290.         self.submodules.flash_cs_n = GPIOOut(platform.request("flash_cs_n"))
  291.         platform.add_extension(get_spi_ios())
  292.         self.submodules.flash      = S7SPIFlash(platform.request("flash"), sys_clk_freq, 25e6)
  293.  
  294.     def generate_documentation(self, build_name, **kwargs):
  295.         from litex.soc.doc import generate_docs
  296.         generate_docs(self, "documentation".format(build_name),
  297.             project_name = "LitePCIe standalone core",
  298.             author       = "Enjoy-Digital")
  299.         os.system("sphinx-build -M html documentation/ documentation/_build".format(build_name, build_name))
  300.  
  301. # Build --------------------------------------------------------------------------------------------
  302.  
  303. def main():
  304.     parser = argparse.ArgumentParser(description="LitePCIe standalone core generator")
  305.     parser.add_argument("config", help="YAML config file")
  306.     parser.add_argument("--doc",  action="store_true", help="Build documentation")
  307.     args = parser.parse_args()
  308.     core_config = yaml.load(open(args.config).read(), Loader=yaml.Loader)
  309.  
  310.     # Convert YAML elements to Python/LiteX --------------------------------------------------------
  311.     for k, v in core_config.items():
  312.         replaces = {"False": False, "True": True, "None": None}
  313.         for r in replaces.keys():
  314.             if v == r:
  315.                 core_config[k] = replaces[r]
  316.  
  317.     # Generate core --------------------------------------------------------------------------------
  318.     if core_config["phy"]  == "C5PCIEPHY":
  319.         from litex.build.altera import AlteraPlatform
  320.         from litepcie.phy.c5pciephy import C5PCIEPHY
  321.         platform = AlteraPlatform("", io=[])
  322.         core_config["phy"] = C5PCIEPHY
  323.     elif core_config["phy"] == "S7PCIEPHY":
  324.         from litex.build.xilinx import XilinxPlatform
  325.         from litepcie.phy.s7pciephy import S7PCIEPHY
  326.         platform = XilinxPlatform(core_config["phy_device"], io=[], toolchain="vivado")
  327.         core_config["phy"] = S7PCIEPHY
  328.     elif core_config["phy"] == "USPCIEPHY":
  329.         from litex.build.xilinx import XilinxPlatform
  330.         from litepcie.phy.uspciephy import USPCIEPHY
  331.         platform = XilinxPlatform(core_config["phy_device"], io=[], toolchain="vivado")
  332.         core_config["phy"] = USPCIEPHY
  333.     elif core_config["phy"] == "USPPCIEPHY":
  334.         from litex.build.xilinx import XilinxPlatform
  335.         from litepcie.phy.usppciephy import USPPCIEPHY
  336.         platform = XilinxPlatform(core_config["phy_device"], io=[], toolchain="vivado")
  337.         core_config["phy"] = USPPCIEPHY
  338.     else:
  339.         raise ValueError("Unsupported PCIe PHY: {}".format(core_config["phy"]))
  340.     soc      = LitePCIeCore(platform, core_config)
  341.     builder  = Builder(soc, output_dir="build", compile_gateware=False)
  342.     builder.build(build_name="litepcie_core", regular_comb=True)
  343.     generate_litepcie_software_headers(soc, "./")
  344.  
  345.     if args.doc:
  346.         soc.generate_documentation("litepcie_core")
  347.  
  348. if __name__ == "__main__":
  349.     main()
  350.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement