Data Flow
Three independent flows cross the design. Each has a documented entry point and a documented synchroniser at every clock-domain boundary.
PGP RX Path (Optical → Host DMA)
QSFP RX (serial)
│
▼
surf.Pgp4GtyUs (GTY + PGP4 core) <-- pgpClk
│
▼ per-VC AXI-Stream
PgpLaneRx <-- pgpClk
│ ┌── rxlinkReady blowoff filter
│ ├── per-VC URAM FIFO (4×4 k deep, 64-bit)
│ └── surf.AxiStreamMux (burst arbitration, 128-word)
▼
surf.AxiStreamFifoV2 (async) pgpClk → dmaClk
│
▼ dmaIbMasters
<Board>Core (axi-pcie-core)
│
▼ PCIe DMA write
Host memory
With an optional DDR/HBM buffer (MigDmaBuffer / HbmDmaBuffer
from axi-pcie-core):
PgpLaneRx → buffIbMasters → MigDmaBuffer → DDR/HBM → back to dmaIbMasters
The DDR/HBM buffer enables event-triggered readout — frames sit in on-board memory until the host issues a read request via descriptor.
PGP TX Path (Host DMA → Optical)
Host memory
│
▼ PCIe DMA read
<Board>Core (axi-pcie-core)
│ dmaObMasters
▼
PgpLaneTx <-- dmaClk
│ ├── AxiStreamFlush (flushEn = NOT linkReady)
│ └── surf.AxiStreamFifoV2 (async + resize)
▼ dmaClk → pgpClk
surf.SsiInsertSof <-- pgpClk
│
▼
surf.AxiStreamDeMux (route by tDest → VC)
│
▼
surf.Pgp4GtyUs (GTY + PGP4 core)
│
▼
QSFP TX (serial)
The flush logic on link-down ensures that frames sourced from the host
do not stall the entire DMA path when the optical link goes down — they
are dropped in the AxiStreamFlush block until linkReady returns.
AXI-Lite Register Path (Software → Firmware Registers)
Python: rogue.hardware.axi.AxiMemMap('/dev/datadev_0')
│ PCIe BAR0 reads/writes
▼
<Board>Core (axi-pcie-core)
│ AXI4 → AXI-Lite (AxiPcieReg)
▼
appReadMaster / appWriteMaster <-- appClk
│
▼
Top-level AxiLiteCrossbar (in <Target>.vhd)
│
├── 0x00100000 MigDmaBuffer (optional)
├── 0x002–0x004…00000 Utility A/B/C
└── 0x00800000 Hardware (PgpLaneWrapper)
│
▼ per-lane crossbar (stride 0x10000)
Lane[0..7]
│
▼ per-lane internal crossbar
├── 0x0000 GT core
├── 0x1000 PGP monitor
├── 0x2000 Ctrl
├── 0x3000 TX stream monitor
└── 0x4000 RX stream monitor
The full per-lane register layout is in AXI-Lite Address Map.
Back-Pressure Path (DMA Pause → PGP Pause)
axi-pcie-core’s DMA engine asserts dmaBuffGrpPause when host-side
DMA buffers fill up. pgp-pcie-apps propagates that signal back into
two places:
Into
PgpLaneRx.disableSel— synchronised topgpClk, blocks ingress on the affected VCs to stop new frames being absorbed.Into
pgpTxIn.locData(0)— synchronised, signals the remote end of the PGP link to pause via the PGP4 in-band flow-control channel.
This is the canonical SLAC two-sided back-pressure model: stop ingress locally and ask the upstream sender to slow down.
State
There is no shared global RTL state. Every block holds only its own
local state, and inter-block signalling is exclusively through
AXI-Stream / AXI-Lite / well-documented sideband signals like
dmaBuffGrpPause.