Skip to content

PCIe 3.0 (x8 lanes) support for ADRV9009ZU11EG/ADRV2CRR_FMC - #2139

Draft
cristianmihaipopa wants to merge 13 commits into
mainfrom
pcie_xdma_direct_streaming_pr
Draft

PCIe 3.0 (x8 lanes) support for ADRV9009ZU11EG/ADRV2CRR_FMC#2139
cristianmihaipopa wants to merge 13 commits into
mainfrom
pcie_xdma_direct_streaming_pr

Conversation

@cristianmihaipopa

Copy link
Copy Markdown
Collaborator

PR Description

The ADRV9009ZU11EG/ADRV2CRR_FMC design gains a new data offload pipeline, in addition to the NIC enabled by Corundum.

PCIe 3.0 with 8 differential data lanes (8× RX_P/TX_P and 8× RX_N/TX_N) is now supported using the Xilinx XDMA IP, on the ADRV9009ZU11EG/ADRV2CRR_FMC variant only. It cannot be built alongside the Corundum variant in the same HDL design.

The new PCIe design introduces the following changes:

  • The XDMA IP acts as a PCIe transaction-translation bridge between the FPGA and the host PC. By default the XDMA has its own DMA engines; in this design they are disabled and we use our own AXI DMAC engines and connect them directly to the XDMA bridge
  • The base HDL design for ADRV9009ZU11EG/ADRV2CRR_FMC has been significantly changed. The FPGA's DDR4 memory is bypassed entirely: all data coming from the JESD204 IPs is streamed directly into the host PC's memory through the existing AXI DMAC IPs, via the XDMA IP, when the host requests a transaction
  • Many IPs and signals were rerouted from the PS to the XDMA, so the PS gives up most of its control in favor of host control over the IPs. All AXI DMAC and JESD204 IPs are now controlled by the host through the XDMA bridge. The SPI and GPIO signals were rerouted to new AXI SPI and AXI GPIO controllers, which are likewise connected to the XDMA bridge
  • To satisfy the MSI/MSI-X interrupt handling of the XDMA IP, which is essential to the operation of the PCIe bridge, a new custom AXI IP was implemented: library/axi_pcie_intc. It bridges the level-sensitive fabric interrupt lines to the endpoint's usr_irq_req/usr_irq_ack handshake required by PG195 (XDMA XIli), giving each source its own MSI/MSI-X vector
  • New PCIe-related .tcl methods were added to projects/scripts/adi_board.tcl to support future PCIe projects:
    • ad_pcie_interconnect: connects a peripheral's AXI-Lite slave to the XDMA M_AXI_B (BAR0) master through the pcie_ctrl_sc SmartConnect. Creates the SmartConnect on the first call and grows NUM_MI on each subsequent call; detaches the IP from any previous CPU-side wiring, rewires it to pcie_axi_clk, and assigns its address segment within BAR0
    • ad_pcie_saxi_interconnect: connects an AXI master port (DMA data, scatter-gather, or transceiver eye-scan) to the XDMA S_AXI_B slave through the pcie_saxi_sc SmartConnect, so the DMAC writes straight to host RAM. Creates the SmartConnect on the first call and grows NUM_SI afterwards, adding clock slots as new master-side clock domains appear
    • ad_pcie_interrupt: connects a peripheral IRQ line to the axi_pcie_intc controller. Creates the controller on the first call, maps it into the XDMA M_AXI_B space, and grows NUM_VECTORS/xdma_num_usr_irq as more IPs attach. By default each source gets its own vector (SRC_PER_VEC=1), so the host handler needs no dispatch read; an optional argument pins a source to a fixed vector to keep hwirq numbering stable across build variants
  • To provide network access to the PS from the host over PCIe, a bidirectional PS <-> host network link was added using four axi_dmac instances (axi_host_net_tx/rx_dma on the PCIe side, axi_ps_net_tx/rx_dma on the PS side) and two asynchronous AXI-Stream FIFOs bridging the 250 MHz PCIe and 100 MHz PS clock domains. This carries IP traffic (SSH, remote IIO, firmware updates) over the PCIe link without a separate Ethernet cable.
  • Fixes were made to library/axi_dmac to support the network link: a new HAS_AXIS_TKEEP parameter wires m_axis_keep/s_axis_keep to the real byte strobe (previously hardwired to all-ones), dropping DMA_LENGTH_ALIGN to zero so transfer lengths are byte-exact, required for arbitrary-size network packets. This also fixes a zero-width replication bug in the dest_burst_len_data initialization. In addition, axi_dmac_constr.ttcl gains two set_false_path constraints for the CDC synchronizer pairs introduced when scatter-gather mode (DMA_SG_TRANSFER=1) is enabled.

Both the PCIe project implementation (project documentation + README.md) and the custom interrupt controller have been documented. To build the project, run the following in projects/adrv9009zu11eg/adrv2crr_fmc:

make PCIE=1

PR Type

  • Bug fix (change that fixes an issue)
  • New feature (change that adds new functionality)
  • Breaking change (has dependencies in other repos or will cause CI to fail)
  • Documentation

PR Checklist

  • I have followed the code style guidelines
  • I have performed a self-review of changes
  • I have compiled all hdl projects and libraries affected by this PR
  • I have tested in hardware affected projects, at least on relevant boards
  • I have commented my code, at least hard-to-understand parts
  • I have signed off all commits from this PR
  • I have updated the documentation (wiki pages, ReadMe files, Copyright etc)
  • I have not introduced new Warnings/Critical Warnings on compilation
  • I have added new hdl testbenches or updated existing ones

rodrigo455 and others added 9 commits August 18, 2026 17:12
The ttcl covers `i_sync_status_src`, `i_sync_control_src`,
`i_sync_status_dest`, `i_sync_control_dest`, and `i_sync_sg_enable`,
but it was missing `i_sync_control_sg` and `i_sync_status_sg` in
`axi_dmac_reset_manager`. Two `set_false_path` entries were added to the
existing `async_req_sg && sg_enabled` block, mirroring the shape of the
src/dest equivalents.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
The state machine gives a rewind request priority over accepting a new
descriptor, but req_ready is registered off the previous cycle's nx_state
and so would still complete the handshake. Accepting a descriptor in the
same cycle the rewind is taken toggles cur_transfer_id before
STATE_REWIND_ID gets to compare it, which makes the single-bit id alias the
rewound segment with the one two ahead of it: transfer_id_match then reports
a match that isn't, the burst ID is rolled back over segments that were
never replayed, and the channel deadlocks with the data mover holding a
descriptor it can never get a burst ID for.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
- This is an utility IP and can be used with both the XDMA
and QDMA IPs (used in the PL PCIe implementations) when
they are configured to work with MSI/MSI-X interrupts
- The XDMA/QDMA IPs, when have configured MSI/MSI-X interrupts,
required a certain amount of time to pass while a requested is
consumed after acknowledgmenet by the IP; if the tmining it's
not respected, future interrupts might get missed and not
treated
- The XDMA has a dedicated port called 'usr_irq_ack[]' which
it's used for the acknowledgmenet of the current interrupt;
this signal stays high until the interrupt it's handled completly;
when this happens, only then, a new interrupt it's sent to
the XDMA from this custom irq. controller
- The module signals of the IP are:
	- AXI interface specific signals
        - 16 input interrupts (MSI/MSI-X vectors)
        - usr_irq_req[] output, goes into the usr_irq_req port
        of the XDMA, represents the current untreated interrupts
        - usr_irq_ack[] input, is driven by the usr_irq_ack port
        of the XDMA
- The IP has configurable number of vectors (interrupts) and a
configurable number of lines/interrupts (interrupt, which is a
vector, can have multiple bits, each bit represents a line)

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Signed-off-by: Cristian Mihai Popa <cristianmihai.popa@analog.com>
- Add ad_pcie_interconnect, ad_pcie_saxi_interconnect and ad_pcie_interrupt;
those will be used to build designs on top of a PCIe AXI bridge
- In the development process, there're were a lot of redundant
connections and IP declarations, thus, the necessity of creating
some procedures, which were made to also be used for the future PCIe
projects;
- The three procedures:
	- ad_pcie_interconnect: Connects a peripheral's AXI slave
        to the XDMA M_AXI_B port through pcie_ctrl_sc
        (SmartConnect, created on first call, auto-grows NUM_MI).
        Detaches the IP from its previous CPU-side wiring (intf
        net, address segments, clock/reset), rewires to
        pcie_axi_clk, and assigns the address segment within
        BAR0. Handles hierarchical cells by descending to the
        leaf IP for address resolution.
        - ad_pcie_saxi_interconnect: Connects an AXI master (DMA
        data, SG descriptors, eye-scan) to the XDMA S_AXI_B port
        through pcie_saxi_sc (SmartConnect, created on first
        call, auto-grows NUM_SI). Handles multi-clock topologies
        by finding or creating aclk slots. Derives the segment
        offset and range from the XDMA's axibar_0 /
        axibar_highaddr_0 configuration, with validation for
        power-of-two alignment and address width bounds. Clamps
        the range for narrow masters (e.g. 32-bit xcvr m_axi).
        - ad_pcie_interrupt: Connects a peripheral IRQ to the
        axi_pcie_intc controller (created on first call, mapped
        into M_AXI_B via ad_pcie_interconnect). Each source gets
        its own MSI/MSI-X vector by default (SRC_PER_VEC=1),
        auto-grows NUM_VECTORS and the XDMA's xdma_num_usr_irq.
        Supports pinned index allocation for stable hwirq
        numbering across build variants, and optional source
        grouping for designs exceeding 16 sources.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Signed-off-by: Cristian Mihai Popa <cristianmihai.popa@analog.com>
- Added support for PCIe 3.0 (x8) on ADRV9009ZU11EG/ADRV2CRR
- Added PCIe constraints file, BD file and a separate system_top file
- Modified the Makefile, system_project and system_bd files
accordignly to support a new build mode, for PCIe:
		make PCIE=1
- PCIe is enabled by the Xilinx XDMA IP, which is configured in AXI Bridge
mode, meaning it doesn't use its own incorporated DMAs, it just acts like
a PCIe transactions translator between the already present DMAs and the
PCIe root complex (present on the Host PC); bassically, streams data
straight to the connected Host PC when requested
- XDMA in AXI Bridge mode it's directly connected to the already present
DMAs, so the DMAs write directly in Host PC's memory, thus generated data
is bypassing entirely the ADRV9009ZU11EG's DDR4 physical memory
- The base ADRV9009ZU11EG/ADRV2CRR design suffered major changes, as many
routes were dropped out; the PS doesn't have much controll over the IPs,
as all of them (JESD204B IPs, DMAs etc.) were routed the XDMA bridge;
also MIO/EMIO connections were dropped out and routed to the XDMA bridge
- In this implementation, the recently added ad_pcie_* procs are used to
migrate the project so that the entire RF datapath is set to be PCIE
controlled using XDMA in AXI Bridge mode, allowing to leverage our DMAC
blocks and control hardware from host drivers.
- Add external AXI SPI controller connected to the XDMA
	- Drop binary-encoded chip-select done by the base design
- Add 2 external AXI GPIO controller connected to the XDMA
	- To fulfill the great number of GPIO signals from the design,
	slice and concat IPs were used;
	- The GPIO signals are split between 2 AXI GPIO controllers
	(one in dual mode, the other one in single mode);
- Applicable interrupts are connected the PCIE AXI Bridge via the
recently added axi_pcie_intc custom interrupt controller, which
handles the XDMA MSI/MSI-X interupts accordignly

Signed-off-by: Cristian Mihai Popa <cristianmihai.popa@analog.com>
Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Add HAS_AXIS_TKEEP, which lets a stream destination/source emit/consume
a real TKEEP and accept byte-granular transfer lengths.

axi_dmac_burst_memory already derives a trailing byte strobe, and
request_arb already carries it as dest_strb. It was dropped on the last
hop because dest_axi_stream had no port for it, so m_axis_keep was
hardwired to all-ones. Wire it through, unconditionally: without the
parameter the strobe's sub-beat bits stay pinned at all-ones and the
result is identical to the old hardwire. So HAS_AXIS_TKEEP only relaxes
DMA_LENGTH_ALIGN, which is enough to make the length byte-exact.

Also fix a zero-width replication in the dest_burst_len_data
initializer, illegal whenever DMA_LENGTH_ALIGN is 0 - already reachable
for MM->MM, before this change.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
Add a bidirectional network data path between the host PC and the
Zynq PS over the PCIe link, enabling IP connectivity without a
separate Ethernet cable.

Four axi_dmac instances (host TX/RX + PS TX/RX) connected through
two async AXI-Stream FIFOs for clock domain crossing (250 MHz PCIe
↔ 100 MHz PS). Host-side DMACs are mapped into M_AXI_B/S_AXI_B;
PS-side DMACs use HPC0/HPC1 via the CPU interconnect.

All DMACs use 64-bit data width with HAS_AXIS_TKEEP=1 for
byte-exact transfer lengths, required for network packet framing.

Signed-off-by: Rodrigo Alencar <rodrigo.alencar@analog.com>
- Updated the HDL documentation for ADRV9009ZU11EG where the
new design for PCIe has been described in detail (new diagrams
& PCIe related changes)
- Also updated projects/adrv9009zu11eg/adrv2crr_fmc/README.md
file to reflect the changes

Signed-off-by: Cristian Mihai Popa <cristianmihai.popa@analog.com>
- In order to satisfy the handling of MSI/MSI-X interrupts of the XDMA IP,
used for the PCIe implementation on ADRV9009ZU11EG/ADRV2CRR, a custom
IP has been implemented
- This is the documentation page for the hdl/library/axi_pcie_intc IP

Signed-off-by: Cristian Mihai Popa <cristianmihai.popa@analog.com>
@cristianmihaipopa
cristianmihaipopa force-pushed the pcie_xdma_direct_streaming_pr branch from 2d75831 to 83958a9 Compare September 8, 2026 12:45
@cristianmihaipopa

Copy link
Copy Markdown
Collaborator Author

V1: Fixed check_guideline script highlighted issues (comments, copyright years, indentation).

@cristianmihaipopa

cristianmihaipopa commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator Author

V2:

  • GPIO[31:0] were rerouted back to the PS. Previously, they were routed to the XDMA bridge. These GPIOs are carrier specific (HMC7044 carrier, leds, buttons etc.), no need for them to be controlled from the Host.
  • removed axi_gpio2, now we use only axi_gpio1, in dual mode
  • moved axi_spi from address 0x84040000 to 0x84030000 (old address of axi_gpio2)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants