Skip to content

Add MATLAB R2025b and HDL 2026-r1 support - #176

Open
tfcollins wants to merge 6 commits into
masterfrom
feat/r2025b-hdl-2026-r1
Open

Add MATLAB R2025b and HDL 2026-r1 support#176
tfcollins wants to merge 6 commits into
masterfrom
feat/r2025b-hdl-2026-r1

Conversation

@tfcollins

Copy link
Copy Markdown
Collaborator

Summary

  • update the toolbox release contract to MATLAB R2025b, hdl_2026_r1, Vivado 2025.1, and toolbox 25.2.1
  • replace the removed DSP delay dependency with a streaming local delay and update AD9081 numerical spectrum/NCO checks for R2025b
  • adapt ZCU102 HDL Coder insertion to axi_hpm0_lpd_interconnect/M11_AXI and preserve target Tcl globals across HDL library builds
  • derive the required Vivado version from HDL release metadata and refresh CI/Jenkins/docs/board matrices
  • integrate the R2025b ToolboxCommon method-access fix from Fix debug method access for MATLAB R2025b ToolboxCommon#24
  • exclude local MATLAB/BSP/hardware outputs from both source control and generated toolbox packages

Verification

  • MATLAB R2025b Update 5: 55/55 passed
    • 17 AD9081 simulation tests
    • 32 non-hardware constructor tests
    • 4 R2025b delay/PFilter compatibility tests
    • 2 release-contract tests
  • Python Vivado metadata parser: 3/3 passed
  • focused AD9081/ZCU102 HDL Workflow Advisor create-project gate: 1/1 passed with Vivado 2025.1
  • HDLBRANCH=hdl_2026_r1 bash build_bsp.sh: passed
  • generated AnalogDevicesHighSpeedConverterToolbox_v25.2.1.mltbx: 26,642,280 bytes, 3,628 entries; archive inspection found no transient lab/test artifacts
  • git diff --check: passed

Physical AD9081 status

mini2 was acquired and cold-booted repeatedly. The MATLAB hardware runner reached the board, but all five tests were blocked before data-path exercise because the catalog-default 2023_R2_P1 image does not initialize the converter:

  • IIO inventory contains only xilinx-ams and hmc7044
  • HMC7044 PLL2 reports unlocked
  • kernel: ad9081 spi1.0: PLL not locked
  • kernel: ad9081: probe of spi1.0 failed with error -21
  • AXI RX/TX devices remain deferred, so MATLAB reports FindDeviceFail

The labgrid Kuiper downloader currently supports only 2018_R2, 2019_R1, and 2023_R2_P1, so no 2026-r1 boot image is selectable through adi-lg --bootfile. This is recorded as an external hardware/image blocker; no physical pass is claimed.

Update the release contract to MATLAB R2025b, hdl_2026_r1, and Vivado 2025.1. Adapt AD9081 simulation and ZCU102 HDL Coder integration, preserve BSP generation context, add compatibility coverage, and integrate the ToolboxCommon R2025b access fix.
Use current checkout/setup-python actions and constrain Pygments below 2.20 to remain compatible with the documentation stack's pymdown-extensions release.
Install DSP System Toolbox and Fixed-Point Designer for the R2025b PFilter tests, and download the Google Vale style from its current vale-cli repository.
@tfcollins

Copy link
Copy Markdown
Collaborator Author

Final hosted verification for 0b45626fb818bb50c21ebad1edc333c0c8b42e10:

  • Build Toolbox: passed (including Python metadata tests, MATLAB R2025b compatibility tests with DSP System Toolbox + Fixed-Point Designer, and .mltbx generation)
  • Documentation: both push and pull-request jobs passed
  • Vale: passed
  • CodeQL: actions, JavaScript/TypeScript, and Python analyses passed
  • Hosted artifact downloaded from run 30660870184 and inspected: AnalogDevicesHighSpeedConverterToolbox_v25.2.1.mltbx, 47,127,968 bytes, 3,975 archive entries, DelayLine.m present, zero transient lab/test artifacts

The physical mini2 blocker described in the PR remains external and reproducible (ad9081 PLL lock failure on the catalog-default 2023_R2_P1 image); no hardware pass is claimed.

@tfcollins

Copy link
Copy Markdown
Collaborator Author

Additional classification of the earlier managed hardware run (proc_d135fbf9fbc3, MATLAB PID 3032924):

  • adi-lg exited 137 because its child MATLAB process terminated abnormally; this is not a hardware-test pass.
  • MATLAB wrote /home/tcollins/matlab_crash_dump.3032924-1 at 2026-07-31 14:31:34 EDT.
  • The dump identifies a segmentation violation in MATLAB R2025b Update 5 during MCOS/container cleanup and Mlm_MATLAB_fn_impl::unload / engine shutdown.
  • No kernel OOM-killer or process-segfault entry was found for PID 3032924 in the corresponding kernel-journal interval, so exit 137 alone should not be described as evidence of memory exhaustion.
  • Labgrid still performed teardown: powered off mini2 and closed both SSH connections.

This run produced no valid JUnit pass result. The later cold-boot/IIO probes remain the authoritative physical diagnosis: the catalog 2023_R2_P1 image fails AD9081 PLL initialization before MATLAB can exercise the data path.

@tfcollins

tfcollins commented Jul 31, 2026

Copy link
Copy Markdown
Collaborator Author

Additional physical coverage on labgrid DAQ3/VCU118 for head 0b45626fb818bb50c21ebad1edc333c0c8b42e10:

  • Place: nuc (daq3 / vcu118, BootFabric/JTAG)
  • MATLAB: R2025b Update 5 on Nemo
  • Boot: MicroBlaze bitstream/kernel programmed successfully; UART reached shell; DHCP target ip:10.0.0.233
  • IIO preflight: ad9528, buffer-capable axi-ad9152-hpc, and buffer-capable axi-ad9680-hpc present
  • JUnit: 5 tests, 5 passed, 0 failures, 0 errors, 0 skipped
    • RX capture
    • TX DDS → RX, one channel
    • TX DDS → RX, two channels
    • TX DMA → RX, one channel
    • TX DMA → RX, two channels
  • Place released and no reservation/process remains.

Infrastructure findings encountered and isolated before the passing run: Nemo's nuc SSH alias incorrectly targeted the coordinator, bare nuc was not DNS-resolvable for RFC2217, and the coordinator's static NetworkService address (10.0.0.231) was stale versus DHCP (10.0.0.233). The passing orchestration retained the Nemo lease, allowed nuc/tcollins, booted on the exporter where UART resolves locally, and passed the observed DHCP URI to MATLAB. No DAQ3 code change was required.

The AD9081 System objects assumed a fixed 4-coarse / 4-fine NCO datapath
with a contiguous voltage-channel stride. The hdl_2026_r1 m8_l4 reference
design instead presents 2 coarse (CDUC) converters shared across 4 fine
(FDUC) channels, so the previous assumptions broke physical operation on
ZCU102 AD9081-FMCA-EBZ hardware.

Fixes, all verified against physical AD9081 on ZCU102 (labgrid mini2)
with an HDL-2026-compatible kernel/DTB and MATLAB R2025b:

* GetDataPathConfiguration: count unique coarse/fine converter indices
  instead of raw label occurrences. Several fine paths can share one
  coarse converter (FDUC1/2/3 -> CDUC0), which previously inflated the
  coarse count to 4 and produced an invalid attribute map.

* CheckAndUpdateHW/HWFloat/HWBool: resolve the physical voltage channel
  IDs for main_* (coarse) attributes by probing attribute readability at
  write time, and only when connected to hardware. Coarse-capable
  channels are non-contiguous on this datapath, and the previous stride
  assumption wrote main_nco_* to channels that return EINVAL. Resolution
  now runs inside the connected guard so construction no longer probes a
  null device pointer.

* Tx DDR offload: pl_ddr_fifo_enable was removed from the TX DMA device
  in the new HDL datapath. Probe for the debug attribute and skip the
  write when absent so DMA streaming works on both datapath variants.

Adds pure mapper regression tests (no hardware required) to
R2025bCompatibilityTests covering non-contiguous coarse selection,
the too-few-readable error path, and the fully-populated fine case.

Physical result: testAD9081Rx passes end-to-end; all construction and
DMA-setup errors are eliminated. The remaining TX tone-accuracy checks
depend on internal DAC->ADC loopback tone placement in the m8_l4
reference design (the pyadi-dt reference framework observes the same
placement offset and only asserts SNR, not exact frequency); that gap is
datapath behavior, not a toolbox regression.
@tfcollins

Copy link
Copy Markdown
Collaborator Author

AD9081 physical hardware verification — HDL 2026-r1 datapath

Ran the AD9081 System objects against physical AD9081-FMCA-EBZ on ZCU102 (labgrid mini2) using an HDL-2026-compatible kernel/DTB and MATLAB R2025b. This surfaced and fixed three real datapath-assumption bugs; cfd5a6c carries the fixes.

Root causes (m8_l4 reference design)

The hdl_2026_r1 m8_l4 datapath presents 2 coarse (CDUC) converters shared across 4 fine (FDUC) channels, e.g. FDUC1/2/3 -> CDUC0 and FDUC0 -> CDUC3. The previous code assumed a fixed 4-coarse/4-fine layout with a contiguous voltage%d_i stride.

Bug Symptom on hardware Fix
GetDataPathConfiguration counted CDUC label occurrences (→4) not unique converters (→2) wrong num_coarse_attr_channels count distinct converter indices
CheckAndUpdateHW* wrote main_nco_* on non-coarse channels; also probed a null device pointer at construction EINVAL / "not enough channels" at object construction resolve coarse channel IDs by attribute readability, only inside the connected guard
pl_ddr_fifo_enable debug attr removed from TX DMA device ENOENT aborted DMA-data tests probe-and-skip when the attribute is absent

Results

  • testAD9081Rx: PASS end-to-end on physical hardware.
  • Datapath discovery now correct for both directions: cdc=2, fdc=4, dc=8.
  • All construction-time and DMA-setup errors are eliminated — the four TX tests now run to completion.
  • 7/7 offline R2025bCompatibilityTests pass, including 3 new pure-mapper regression tests (non-contiguous coarse selection, too-few-readable error path, fully-populated fine case) that require no hardware and run in hosted CI.

Remaining TX tone-accuracy gap (characterized, not a toolbox regression)

The four TX tests assert the looped-back tone frequency to ±1%. On this bench the internal DAC→ADC loopback tone does not land at the requested frequency:

  • MATLAB: requested 45 MHz DDS tone, RX spectral peak near DC / noise-dominated.
  • The pyadi-dt reference framework on the same board shows the same behavior: it requested a 1 MHz tone and detected the peak at 106 kHz. Its test_dma_loopback "passes" only because it asserts SNR (>10 dB), not exact frequency; AD9081HWTests asserts exact frequency, which is strictly tighter.

This tone-placement offset is therefore a property of the m8_l4 reference datapath's DDS/NCO configuration affecting both frameworks, not a regression introduced by this PR. No hardware pass is claimed for the four TX tone tests; the RX data path is verified passing.

Hardware: AD9081-FMCA-EBZ + ZCU102 @ labgrid mini2; MATLAB R2025b; HDL-2026-compatible boot.

The new AD9081 mapper regression tests called a static method on
adi.AD9081.Base, which forces MATLAB to load the class and its
matlabshared.libiio.base superclass. The hosted Build Toolbox runner has
no libiio hardware support package, so the class fails to parse and the
tests error with MATLAB:class:InvalidSuperClass.

Extract the pure selection logic into a standalone package function
adi.AD9081.selectReadableAttributeChannelIDs (no libiio dependency);
Base retains a thin static forwarder for backward compatibility. The
compatibility tests now call the package function directly, so they run
on any MATLAB install without the libiio support package.
@tfcollins

Copy link
Copy Markdown
Collaborator Author

Correction + refined analysis: TX tone is coherent, but mis-placed in frequency

My earlier comment described the MATLAB RX capture as "noise-dominated." That characterization was imprecise — it came from a raw meanfreq/argmax read that the DC spur skewed. Re-analyzing the same captured buffer with the pyadi-dt reference framework's exact FFT method (Hanning window, 5-bin DC guard, median-noise SNR) shows the opposite:

nfft=32768  fbin=7629 Hz
peak 129700 Hz (0.0 dB), noise floor -25.0 dB, SNR 25.0 dB
VERDICT: TONE (SNR > 10 dB)

So the MATLAB DDS path does deliver a coherent looped-back tone (SNR 25 dB), directly comparable to the reference run on the same board (1 MHz request → 106.8 kHz peak, SNR 22.5 dB).

Precise root cause of the four TX failures

On this m8_l4 datapath the looped-back tone is coherent but does not land at the commanded frequency — in either framework:

Framework Commanded Observed peak SNR Assertion Result
pyadi-dt test_dma_loopback 1 MHz 106.8 kHz 22.5 dB SNR only (>10 dB) passes
MATLAB AD9081HWTests (DDS/data) 45 MHz ~130 kHz 25 dB exact frequency (±1%) fails

The DDS tone routing itself was verified correct offline: MATLAB's DDSSingleTone(f,s,1) writes to altvoltage0/altvoltage2, which on this board are labelled TX1_I_F1/TX1_Q_F1 — exactly the channels pyadi-iio's label-based dds_single_tone targets, with the same I/Q phase convention. NCOs are left at 0 in both frameworks during the DDS test.

Conclusion

This is a datapath/DDS-configuration behavior of the m8_l4 reference design, not a HighSpeedConverterToolbox regression: both frameworks see the identical coherent-but-frequency-compressed tone. The MATLAB tests are simply stricter (exact frequency vs SNR-only) and correctly flag it.

No hardware pass is claimed for the four TX tone tests. Closing the gap would require HDL/driver-side investigation of the DDS-to-DAC frequency mapping on m8_l4 (out of scope for this toolbox PR), not a toolbox code change — and I will not relax the frequency assertion to force green. The three toolbox bugs this PR fixes are independently verified: testAD9081Rx passes on hardware, datapath discovery is correct, and 9/9 offline compatibility tests (incl. 3 new mapper tests) pass in hosted CI.

The R2025b/hdl_2026_r1 migration was verified on AD9081/ZCU102, but the
other targeting platforms (daq2, ad9434, ad9265, ad9783, ad9208, plus
fmcjesdadc1/ad9739a) failed BSP project generation on Vivado 2025.1. Six
distinct issues, all in the toolbox's HDL Coder integration and BSP
staging, were surfaced by running BSPTests (SynthesizeDesign=false) and
fixed. AD9081 was immune because its reference design does not use the
transceiver wizard or the classic CPU interconnect.

Verified end-to-end: daq2/zcu102 rx now completes "Create Project" and
the full IP Core Generation workflow on Vivado 2025.1.

Fixes:

1. build_bsp.sh: stop overwriting the HDL branch's adi_project_xilinx.tcl
   with the stale toolbox fork. Since hdl_2026_r1 the reference designs
   call adi_xcvr_project, defined only in the branch copy; the fork broke
   "Create Project" with 'invalid command name "adi_xcvr_project"'. Keep
   the branch version (it already supports the MATLAB in-memory flow via
   ADI_MATLAB) and add a guard that fails fast if a future branch drops
   the proc.

2. system_project_rxtx.tcl: set ADI_MATLAB (the hdl_2026_r1 env contract)
   alongside the legacy MATLAB var so the top-level design reuses HDL
   Coder's in-memory project instead of calling create_project.

3. plugin_rd.m: add quiet.mk and Makefile to CustomFiles. The nested
   xcvr_wizard sub-build shells out to make, whose Makefile chain includes
   the HDL-root quiet.mk; HDL Coder only copies the folders listed in
   CustomFiles into the work area, so the root file was missing and the
   sub-make failed with "../../../quiet.mk: No such file or directory".

4. patch_xcvr_matlab_env.py (new, invoked by build_bsp.sh): patch the
   branch's adi_project_xilinx.tcl so adi_xcvr_project (a) runs its nested
   make with ADI_MATLAB/MATLAB unset -- otherwise the standalone
   xcvr_wizard Vivado inherits in-memory mode, skips create_project, and
   dies with "No projects are currently open" -- and (b) globs for the
   generated <xcvr>_cfng.txt when the reconstructed path is absent, since
   the Makefile's output-directory token order (RATE_REFCLK_PLLTYPE) does
   not match the Tcl reconstruction when ADI_PROJECT_DIR is unset.

5. matlab_processors.tcl: resolve the CPU/control AXI interconnect cell
   dynamically (adi_cpu_interconnect_cell) instead of hardcoding
   axi_cpu_interconnect. hdl_2026_r1 renamed it to a carrier-specific
   SmartConnect (axi_hpm0_lpd_interconnect on ZynqMP, axi_gp0_interconnect
   on Zynq-7000, axi_axi_interconnect on MicroBlaze), so the post-build
   preprocessing matched zero cells and failed "'set_property' expects at
   least one object".

6. get_memory_axi_interface_info.m: update the AXI4-Lite insertion point
   for every platform to the hdl_2026_r1 interconnect name (only the
   AD9081 entry had been migrated). HDL Coder's generated
   vivado_insert_ip.tcl otherwise connected the DUT to a non-existent
   axi_cpu_interconnect/M**_AXI and failed with empty connect_bd_intf_net
   arguments.
@tfcollins

Copy link
Copy Markdown
Collaborator Author

Multi-platform BSP build support on Vivado 2025.1 / hdl_2026_r1

The migration was verified on AD9081/ZCU102, but the other targeting platforms failed BSP project generation on Vivado 2025.1. Running BSPTests with SynthesizeDesign=false (project generation + IP packaging, no hardware) on each platform surfaced six distinct issues in the toolbox's HDL Coder integration and BSP staging. AD9081 was immune because its reference design uses neither the transceiver wizard nor the classic CPU interconnect.

Commit 44753c5 fixes all six. Each was found by fixing the previous one and re-running the full ~55-min build, so they are strictly sequential discoveries:

# Symptom Fix
1 invalid command name "adi_xcvr_project" build_bsp.sh stopped clobbering the HDL branch's adi_project_xilinx.tcl (which defines the new proc) with the stale toolbox fork; added a guard
2 project reuses wrong mode system_project_rxtx.tcl sets ADI_MATLAB (the hdl_2026_r1 env contract) alongside legacy MATLAB
3 ../../../quiet.mk: No such file plugin_rd.m CustomFiles now includes quiet.mk + Makefile so HDL Coder copies them into the work area for the nested xcvr sub-make
4 No projects are currently open / GTHE4_cfng.txt: no such file patch_xcvr_matlab_env.py scrubs ADI_MATLAB/MATLAB from the nested xcvr sub-make and globs for the real cfng file (Makefile token order ≠ Tcl reconstruction when ADI_PROJECT_DIR is unset)
5 'set_property' expects at least one object matlab_processors.tcl resolves the CPU interconnect cell dynamically (adi_cpu_interconnect_cell) — hdl_2026_r1 renamed it to a carrier-specific SmartConnect (axi_hpm0_lpd_interconnect / axi_gp0_interconnect / axi_axi_interconnect)
6 connect_bd_intf_net ... cannot be empty (DUT AXI4-Lite insertion) get_memory_axi_interface_info.m updated the interconnect insertion point for every platform (only the AD9081 entry had been migrated)

Verified

daq2/zcu102 rx: PASS end-to-end on Vivado 2025.1 — "Task Create Project successful", full IP Core Generation workflow complete, build finished without exception. (No BOOT.BIN is expected: that requires SynthesizeDesign=true/hardware, intentionally out of scope here.)

BUILD_SUMMARY tag=daq2_zcu102_rx_fix7 passed=1 failed=0

The remaining platforms — ad9434/zc706, ad9265/zc706, ad9783/zcu102, ad9208/vcu118, and daq2 tx/rxtx — are building now with the same fixes to confirm they generalize; I'll post the completed per-platform matrix when the sequence finishes. No hardware/bitstream synthesis was run; this validates project generation and IP packaging only.

@tfcollins

Copy link
Copy Markdown
Collaborator Author

Multi-platform BSP build matrix on Vivado 2025.1 / hdl_2026_r1 — complete

Ran project generation (BSPTests) for every targeting platform on Vivado 2025.1 with the six fixes in 44753c5. Result: all platforms build correctly on 2025.1.

Platform / carrier Mode Result Notes
daq2 / zcu102 rx ✅ PASS Full IP Core Generation workflow
daq2 / zcu102 tx ✅ PASS
daq2 / zcu102 rxtx ✅ PASS
ad9434_fmc / zc706 rx ✅ PASS axi_gp0_interconnect
ad9265_fmc / zc706 rx ✅ PASS axi_gp0_interconnect
ad9783_ebz / zcu102 tx ✅ PASS axi_hpm0_lpd_interconnect
ad9208_dual_ebz / vcu118 rx ⚠️ builds; blocked at bitstream by IP license see below
AD9081 / zcu102 (reference) ✅ (already verified, + physical HW)

ad9208 / vcu118 — not a migration issue

This is the one MicroBlaze design, and its system_project.tcl runs the full implementation + write_bitstream flow (unlike the HDL-Coder IP-core-generation path the others use). On 2025.1 it synthesized and implemented cleanly — opt/place/phys-opt/route all completed with 0 errors and produced routed checkpoints. The single failure is at bitstream write:

ERROR: [Common 17-69] ... bitstream generation is not permitted:
  .../axi_ethernet_0/inst/mac/inst/bd_4bad_mac_0_core (<encrypted cellview>)
The following IP(s) require licenses greater than a Design Linking license
to generate bitstream: tri_mode_eth_mac

That is a Vivado IP-license limitation of the build host (tri_mode_eth_mac needs a full license; only Design_Linking is available), entirely orthogonal to the R2025b/hdl_2026_r1 migration. The interconnect resolver worked here too (fell through to the MicroBlaze axi_axi_interconnect). Project generation, IP packaging, synthesis, and implementation are all confirmed working on 2025.1; only the final bitstream step is license-gated on this machine.

Summary

  • 6/6 platform configs generate + build on Vivado 2025.1.
  • 5/6 complete their configured flow outright; ad9208/vcu118 completes through implementation and only its bitstream step is blocked by a host IP-license constraint, not by any toolbox or migration defect.
  • No hardware/physical testing in scope for this pass (per request); this validates build correctness on 2025.1.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant