Using externally generated converter profiles
External device tools are often the source of truth for a converter datapath. pyadi-jif can reuse that information to solve the clocks and FPGA transceiver configuration around the converter, but the import process differs between AD9084 and ADRV9009.
Important
pyadi-jif models and validates clocking and JESD204 constraints. It does not program the converter. Keep the generated device profile with the software or device-tree configuration that loads it into the hardware.
Workflow overview
Generate and validate the device profile in the vendor tool.
Export the profile artifacts.
Transfer the converter sample rates, datapath factors, and JESD204 parameters into pyadi-jif:
AD9084 profiles can be imported directly from the full JSON file.
ADRV9009 TES profiles must currently be mapped to pyadi-jif parameters.
Configure the FPGA board and any external PLL topology.
Solve the pyadi-jif system.
Compare the solved lane rates, reference clocks, SYSREF, and JESD parameters with the generated profile before building or programming the hardware.
AD9084 Apollo profiles
Use the AD9084 (Apollo) Profile Generator supplied with the Apollo plugin for ACE to create and validate the device configuration. The generator’s output directory contains:
a full
.jsonprofile;a
_summary.jsondescription;a
.binprofile for loading into the AD9084.
Pass the full JSON profile to pyadi-jif. Do not pass the summary JSON or binary file. The binary remains the artifact loaded by the device software.
Import and solve
The following example models an AD9084 RX path whose device clock is generated by an ADF4382 and whose SYSREF is generated by an ADF4030:
from pathlib import Path
import adijif
profile_json = Path("profiles/my_ad9084_profile.json")
vcxo = 125_000_000
system = adijif.system(
"ad9084_rx", "hmc7044", "xilinx", vcxo, solver="CPLEX"
)
system.converter.apply_profile_settings(str(profile_json))
system.fpga.setup_by_dev_kit_name("vcu118")
system.converter.clocking_option = "direct"
system.add_pll_inline("adf4382", vcxo, system.converter)
system.add_pll_sysref("adf4030", vcxo, system.converter, system.fpga)
config = system.solve()
print(f"sample rate: {system.converter.sample_clock / 1e9:.6f} GSPS")
print(f"lane rate: {system.converter.bit_clock / 1e9:.6f} Gb/s")
print(
"JESD: "
f"{system.converter.jesd_class}, "
f"M={system.converter.M}, L={system.converter.L}, "
f"S={system.converter.S}, Np={system.converter.Np}"
)
Use "ad9084_tx" for a TX-only model or "ad9084" for the combined RX/TX model. Applying a profile to the combined model configures both system.converter.adc and system.converter.dac.
apply_profile_settings() extracts and applies:
the AD9084 device clock;
RX CDDC and FDDC decimation;
TX CDUC and FDUC interpolation;
sample rates;
JESD204 class and
M,L,S, andNpparameters.
The importer currently validates Apollo profile schema version 9.1.0. A different version raises an error before settings are applied. bypass_version_check=True is available for development, but should only be used after confirming that the exported JSON has a schema compatible with the parser; bypassing the check does not translate a changed schema.
Validate the result
Before using the solved configuration, compare these values with the profile generator:
converter = system.converter
converter._check_clock_relations()
assert converter.bit_clock <= converter.bit_clock_max
assert config["clock"]["output_clocks"]
In particular, check the device clock, baseband sample rate, lane rate, JESD204 class, lane count, converter count, samples per frame, and sample width. A mismatch usually means the wrong JSON artifact or converter direction was selected.
A complete repository example is available in examples/ad9084_rx_ebz_profile.py.
ADRV9009 TES profiles
ADRV9009 profiles are commonly generated with the Transceiver Evaluation Software (TES). pyadi-jif can load a TES profile file directly using the apply_profile_settings method.
Since the TES profile contains RF and digital-filter settings but does not explicitly contain the JESD204 link parameters (M, L, S, Np), you must pass the desired JESD configuration parameters as dictionaries (rx_jesd and tx_jesd for combined, or jesd for individual RX/TX components) when loading the profile.
Values mapped from profile
Applying a profile extracts and maps the following values automatically:
Profile information |
pyadi-jif setting |
|---|---|
RX output rate ( |
|
Product of enabled RX decimation stages ( |
|
TX input rate ( |
|
Product of enabled TX interpolation stages ( |
|
Configure and solve
import adijif
vcxo = 122_880_000
system = adijif.system("adrv9009", "ad9528", "xilinx", vcxo=vcxo)
system.fpga.setup_by_dev_kit_name("zcu102")
system.fpga.force_qpll = True
# Load and configure from external TES profile path
profile_path = "path/to/Tx_BW200_IR245p76_Rx_BW100_OR122p88_ORx_BW200_OR245p76_DC245p76.txt"
system.converter.apply_profile_settings(
profile_path,
rx_jesd={"M": 4, "L": 2, "S": 1, "Np": 16},
tx_jesd={"M": 4, "L": 4, "S": 1, "Np": 16}
)
config = system.solve()
print(f"RX lane rate: {system.converter.adc.bit_clock / 1e9:.6f} Gb/s")
print(f"TX lane rate: {system.converter.dac.bit_clock / 1e9:.6f} Gb/s")
The corresponding repository example, including the mapping from device-tree profile fields to total decimation and interpolation, is examples/adrv9009_pcbz_example.py.
AD9371 profiles
AD9371 profile files from the iio-oscilloscope ad9371_5 profile collection can be loaded directly. The parser requires Mykonos profile version 0 and validates the profile device clock plus the primary RX, observation RX, and TX datapath rate/factor pairs before changing model state. The combined model exposes and solves all three links as adc, obs, and dac.
The files do not carry JESD framing. pyadi-jif therefore uses the ADI Mykonos transport semantics: JESD204B subclass 1, N=14, Np=16, CS=2, S=1, K=32, and an AD9371 lane-rate range of 614.4 Mb/s through 6.144 Gb/s. The three links share one physical SYSREF domain. The Linux JESD-FSM target’s 78.125 kHz maximum pulsed-SYSREF setting is exported as device metadata because AD9528 programs that provider separately from ordinary output-divider clocks.
import adijif
system = adijif.system("ad9371", "ad9528", "xilinx", vcxo=122_880_000)
system.converter.apply_profile_settings(
"profile_TxBW200_ORxBW200_RxBW100.txt",
rx_jesd={"M": 4, "L": 2, "S": 1, "Np": 16},
tx_jesd={"M": 4, "L": 4, "S": 1, "Np": 16},
)
system.fpga.setup_by_dev_kit_name("zc706")
system.fpga.force_qpll = True
config = system.solve()
For this profile, the model applies a 122.88 MHz primary RX rate, a 245.76 MHz TX rate, a 122.88 MHz AD9371 device clock, RX decimation of 10, and TX interpolation of 2. The JESD arguments are explicit because the profile configures the transceiver datapaths but does not encode the FPGA HDL transport framing.
Use adijif.ad9371_rx, adijif.ad9371_obs, or adijif.ad9371_tx for a single direction. A malformed file, a profile for another device, or a profile missing any of the clocks, rx, obs, or tx sections is rejected before model state is changed.
Final consistency checklist
Before carrying the result into HDL, device tree, or board software, verify that the external profile and pyadi-jif agree on:
RX and TX sample rates;
total decimation and interpolation;
JESD204B or JESD204C encoding;
M,L,S, andNpfor every link;lane rates and FPGA transceiver limits;
converter device/reference clocks;
FPGA reference clock;
SYSREF frequency and topology.
The generated device profile and pyadi-jif solution serve different purposes. The profile configures the converter; the pyadi-jif result configures and validates the surrounding clock tree and FPGA interface. Keep both artifacts under version control so the complete hardware configuration remains reproducible.