Source code for jitxexamples.jumpstart_kits.js1_stackup_components.versal_fpga.bundles
"""Versal GTM transceiver bundle and its structural pin grouping.
Bundle shape
Follows the JITX Versal protocol-bundle convention: a GT quad is four
``LanePair`` lanes plus two reference-clock diff pairs.
On the VP1002 in NFVI1369 each GTM bank (202-207) carries exactly
4 x (RXP/RXN + TXP/TXN) lanes and 2 x REFCLKP/REFCLKN pairs — see the
per-bank rows of the AMD package pinout file (``xcvp1002nfvi1369pkg.txt``)
and AM013 (v1.9) "GTM Transceiver Pins".
Naming
``LanePair`` keeps the upper-case ``TX``/``RX`` sub-port style of
``jitx.common``; ``DiffPair`` uses lower-case ``p``/``n`` (the Python
convention). Consumers therefore write ``quad.L[0].TX.p``.
``GTMQuadPins``
The structural grouping the generated :class:`~.xcvp1002.XCVP1002`
component exposes for each GTM bank so the circuit wrapper can wire a
:class:`GTMQuad` bundle without composing attribute names at runtime.
(Wrapper code in the wild often resolves pins via ``getattr`` name
composition; this repo's conventions forbid that — every reference in
a ``GTMQuadPins`` is an explicit attribute of the generated component.)
"""
from collections.abc import Sequence
from dataclasses import dataclass
from jitx.common import LanePair
from jitx.net import DiffPair, Port
LANES_PER_QUAD = 4
REFCLKS_PER_QUAD = 2
[docs]
class GTMQuad(Port):
"""Versal GTM transceiver quad: 4 lanes + 2 reference clocks."""
L: Sequence[LanePair]
REFCLK: Sequence[DiffPair]
def __init__(self):
self.L = tuple(LanePair() for _ in range(LANES_PER_QUAD))
self.REFCLK = tuple(DiffPair() for _ in range(REFCLKS_PER_QUAD))
[docs]
@dataclass(frozen=True)
class GTMQuadPins:
"""Component pins of one GTM bank, in lane / refclk index order."""
rxp: tuple[Port, ...]
rxn: tuple[Port, ...]
txp: tuple[Port, ...]
txn: tuple[Port, ...]
refclkp: tuple[Port, ...]
refclkn: tuple[Port, ...]
def __post_init__(self) -> None:
lanes = {
"rxp": self.rxp,
"rxn": self.rxn,
"txp": self.txp,
"txn": self.txn,
}
for name, pins in lanes.items():
if len(pins) != LANES_PER_QUAD:
raise ValueError(f"{name} must have {LANES_PER_QUAD} pins")
refclks = {"refclkp": self.refclkp, "refclkn": self.refclkn}
for name, pins in refclks.items():
if len(pins) != REFCLKS_PER_QUAD:
raise ValueError(f"{name} must have {REFCLKS_PER_QUAD} pins")