From a20bf8827793bf2aca69f131b4da2f6f212c4f43 Mon Sep 17 00:00:00 2001 From: Florent Kermarrec Date: Tue, 28 Mar 2023 17:48:51 +0200 Subject: [PATCH] litepcie_gen: Limit IRQ rate to 1MHz on Ultrascale(+) to prevent IRQ stall issue. On Ultrascale(+) IRQ stop being transmitted without this. The issue still need to be closely investigated but this IRQ rate limitation seems to prevent it. Since interface with the PHY will be soon reworked, it's not useful to investigate now, we'll investigate after the rework if the issue is still present. --- litepcie/gen.py | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/litepcie/gen.py b/litepcie/gen.py index 71dfe1d..18b7384 100755 --- a/litepcie/gen.py +++ b/litepcie/gen.py @@ -3,7 +3,7 @@ # # This file is part of LitePCIe. # -# Copyright (c) 2019-2020 Florent Kermarrec +# Copyright (c) 2019-2023 Florent Kermarrec # Copyright (c) 2020 Antmicro # SPDX-License-Identifier: BSD-2-Clause @@ -44,6 +44,11 @@ from litex.soc.integration.soc_core import * from litex.soc.integration.builder import * +from litepcie.phy.c5pciephy import C5PCIEPHY +from litepcie.phy.s7pciephy import S7PCIEPHY +from litepcie.phy.uspciephy import USPCIEPHY +from litepcie.phy.usppciephy import USPPCIEPHY + from litepcie.core import LitePCIeEndpoint, LitePCIeMSI, LitePCIeMSIMultiVector, LitePCIeMSIX from litepcie.frontend.dma import LitePCIeDMA from litepcie.frontend.wishbone import LitePCIeWishboneMaster, LitePCIeWishboneSlave @@ -244,7 +249,6 @@ def __init__(self, platform, core_config): self.comb += wb.connect(pcie_wishbone_slave.wishbone) # PCIe DMA --------------------------------------------------------------------------------- - with_writer = core_config.get("dma_writer", True) with_reader = core_config.get("dma_reader", True) @@ -252,7 +256,6 @@ def __init__(self, platform, core_config): self.add_constant("DMA_CHANNELS", core_config["dma_channels"]) self.add_constant("DMA_ADDR_WIDTH", ep_address_width) for i in range(core_config["dma_channels"]): - pcie_dma = LitePCIeDMA(self.pcie_phy, self.pcie_endpoint, address_width = ep_address_width, with_writer = with_writer, @@ -313,7 +316,13 @@ def __init__(self, platform, core_config): self.pcie_msi = LitePCIeMSIMultiVector(width=32) else: self.pcie_msi = LitePCIeMSI(width=32) - self.comb += self.pcie_msi.source.connect(self.pcie_phy.msi) + # On Ultrascale/Ultrascale+ limit rate of IRQs to 1MHz (to prevent issue with IRQs stalled). + if isinstance(self.pcie_phy, (USPCIEPHY, USPPCIEPHY)): + self.pcie_msi_timer = WaitTimer(int(sys_clk_freq/1e6)) + self.comb += self.pcie_msi_timer.wait.eq(~self.pcie_msi_timer.done) + self.comb += If(self.pcie_msi_timer.done, self.pcie_msi.source.connect(self.pcie_phy.msi)) + else: + self.comb += self.pcie_msi.source.connect(self.pcie_phy.msi) self.comb += self.pcie_msi.irqs[16:16+core_config["msi_irqs"]].eq(platform.request("msi_irqs")) self.interrupts = {} for i in range(core_config["dma_channels"]): @@ -353,22 +362,18 @@ def main(): # Generate core -------------------------------------------------------------------------------- if core_config["phy"] == "C5PCIEPHY": from litex.build.altera import AlteraPlatform - from litepcie.phy.c5pciephy import C5PCIEPHY platform = AlteraPlatform("", io=[]) core_config["phy"] = C5PCIEPHY elif core_config["phy"] == "S7PCIEPHY": from litex.build.xilinx import XilinxPlatform - from litepcie.phy.s7pciephy import S7PCIEPHY platform = XilinxPlatform(core_config["phy_device"], io=[], toolchain="vivado") core_config["phy"] = S7PCIEPHY elif core_config["phy"] == "USPCIEPHY": from litex.build.xilinx import XilinxPlatform - from litepcie.phy.uspciephy import USPCIEPHY platform = XilinxPlatform(core_config["phy_device"], io=[], toolchain="vivado") core_config["phy"] = USPCIEPHY elif core_config["phy"] == "USPPCIEPHY": from litex.build.xilinx import XilinxPlatform - from litepcie.phy.usppciephy import USPPCIEPHY platform = XilinxPlatform(core_config["phy_device"], io=[], toolchain="vivado") core_config["phy"] = USPPCIEPHY else: