Лабораторная 11.8 - AD9361 gpreg BPSK overlay and first discovery burst¶
Lab 11.8 - AD9361 gpreg BPSK overlay and first discovery burst¶
Goal¶
Move from the placeholder AXI-Lite bring-up path to the first course-specific AD9361 hardware overlay that preserves a PS-visible control plane while the exact board-matched boot shell is re-established:
PS / software -> axi_gpreg @ 0x79040000 -> staged sample-domain bridge -> AD9361 TX/RX path
This lab is the first clean handoff from the executable Block 5 modem toward the imported vendor AD9361 shell that matches the real course board (xc7z020clg400-2).
Engineering decision¶
As of 2026-06-21, the checked-in overlay mode is intentionally reduced to gpreg_only.
That rollback is deliberate:
- it keeps the control path simple and inspectable;
- it preserves the Linux-visible RX and TX DMA shell so the stock device tree still probes cleanly;
- it separates
axi_gpregaddress-map validation from the harder AD9361 clean-boot problem; - it avoids treating a rebuilt but not yet boot-safe PL image as a valid RF measurement baseline.
The earlier burst-enabled TX experiments remain useful as historical evidence, but they are not the current safe checked-in baseline. The next gated step is to treat the extracted stock BOOT-partition payload as the only externally loaded boot-safe anchor for now, then explain why the source-correlated editable shells still lose AD9361 before more RF discovery work.
New hardware files¶
| File | Purpose |
|---|---|
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/system_project.tcl |
creates the clean course Vivado project for xc7z020clg400-2 |
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/system_bd.tcl |
sources the imported AD9361 baseline and adds the course overlay |
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/vendor_system_bd_clg400.tcl |
frozen vendor block-design shell extracted from the working board image |
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/build_bitstream.tcl |
deterministic batch build that emits the course bitstream and XSA |
hardware/7020_ad936x_sdr/rebuild_vendor_xpr_snapshot_mio_patch.tcl |
disposable Vivado flow that rebuilds the saved vendor zc702.xpr snapshot after patching only sys_ps7 MIO14/15 |
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/bpsk_zynq_ber_gpreg_bridge.v |
staged clock-domain bridge for the next sample-path reintegration step |
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/course_dac_fifo_source_mux.v |
staged TX-path mux kept for the later DAC reintegration step, not enabled in the current gpreg_only mode |
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/README.md |
build notes, register contract, and first-burst constraints |
New software helper¶
| File | Purpose |
|---|---|
blocks/block_11_integrated_sdr_project/python/lab_11_8_axi_gpreg_bpsk_bringup.py |
programs the gpreg control words, launches one burst, polls busy/done/timeout, and reads BER counters |
blocks/block_11_integrated_sdr_project/python/lab_11_12_runtime_fpga_manager_reload.py |
uploads a checked .bit.bin payload over SSH, hot-loads it through Linux fpga_manager, then re-probes axi_gpreg and the host-visible IIO context |
blocks/block_11_integrated_sdr_project/python/lab_11_13_stock_vs_runtime_rx_compare.py |
proves on one live board run that stock-shell RX capture still works before reload, then repeats the same checks after runtime hot-load and records the breakage |
blocks/block_11_integrated_sdr_project/python/lab_11_15_runtime_bridge_rx_host_tx_probe.py |
hot-loads the intermediate bridge_rx_only overlay, runs one idle gpreg witness, then repeats the same witness while stock host TX transmits the shared BPSK burst, now also decoding the optional raw RX-tap CAPTURE_DEBUG word |
blocks/block_11_integrated_sdr_project/python/runtime_rx_common.py |
shared helper that reads and restores the stock RX common control request after the runtime overlay reload |
blocks/block_11_integrated_sdr_project/python/lab_11_16_runtime_rx_common_reinit_probe.py |
proves what the manual RX common re-init changes and what it still does not fix on the host capture path |
blocks/block_11_integrated_sdr_project/python/lab_11_17_runtime_rx_common_reinit_start_offset_sweep.py |
sweeps start_offset after the runtime RX common re-init while stock host TX drives the shared BPSK burst |
Register contract¶
Base address: 0x79040000
| Offset | Meaning |
|---|---|
0x000 |
axi_gpreg version register |
0x004 |
axi_gpreg ID register, expected 0x4250534B |
0x404 |
GPREG0 output: control word, bit 0 = start edge, bit 1 = clear sticky done, bits 3:2 = RX decision mode (I, -I, Q, -Q) |
0x408 |
GPREG0 input: status word, bit 0 = synchronized start level, bit 1 = busy, bit 2 = sticky done, bit 3 = sticky RX timeout/abort |
0x444 |
GPREG1 output: FRAME_BIT_COUNT |
0x448 |
GPREG1 input: RECEIVED_BITS |
0x484 |
GPREG2 output: PREAMBLE_COUNT |
0x488 |
GPREG2 input: TOTAL_ERRORS |
0x4C4 |
GPREG3 output: START_OFFSET |
0x4C8 |
GPREG3 input: PAYLOAD_ERRORS |
0x508 |
GPREG4 input: bridge signature, expected 0x4250534B |
0x548 |
GPREG5 input: packed TX_VALID_COUNT plus RX decision-sign debug |
0x588 |
GPREG6 input: bridge-side RX_VALID_COUNT |
0x5C8 |
GPREG7 input: packed raw RX-tap CAPTURE_DEBUG word |
GPREG5 now packs one extra runtime witness alongside the low 12 bits of
TX_VALID_COUNT:
- bits
11:0:tx_valid_count_lsb12; - bits
19:12: low 8 bits of the recovered-bit1count; - bits
27:20: low 8 bits of the recovered-bit valid count; - bit
28: any non-zero hard-decision input sample seen; - bit
29: any negative hard-decision input sample seen; - bit
30: any recovered bit1seen; - bit
31: any recovered-bit valid pulse seen.
CAPTURE_DEBUG packs one compact runtime witness word:
- bit
31: any rawcapture_in_validpulse seen; - bit
30: any non-zero rawRX1 I/Qsample seen; - bit
29: any rawcapture_in_validpulse seen while the BER core was active; - bit
28: any rawRX1 Isample seen negative at the bridge tap; - bit
27: any rawRX1 Qsample seen negative at the bridge tap; - bits
26:14: low 13 bits of the rawcapture_in_validpulse count; - bits
13:0: peak absolute rawRX1sample magnitude in unsigned Q14 units.
Build prerequisites¶
Generate the Block 5 memory files first:
python blocks/block_05_fpga_hdl_flow/python/generate_bpsk_rrc_tx_fir_vectors.py
python blocks/block_05_fpga_hdl_flow/python/generate_bpsk_framed_loopback_vectors.py
Then create the Vivado project and export the handoff:
vivado -mode batch -source hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/system_project.tcl
vivado -mode batch -source hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/build_bitstream.tcl
Expected outputs after a successful build:
- bitstream at
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/build/course_bpsk_fmcomms2_zc702.runs/impl_1/system_top.bit; - XSA at
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/course_bpsk_fmcomms2_zc702.sdk/system_top.xsa; - timing logs at
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/timing_synth.logandtiming_impl.log; - confirm that the new XSA contains
axi_gpreg_bpskat0x79040000; - reuse the helper below on Linux or over SSH.
Local mock run¶
python blocks/block_11_integrated_sdr_project/python/lab_11_8_axi_gpreg_bpsk_bringup.py \
--backend mock \
--json-out docs/assets/lab118_axi_gpreg_bringup_mock.json
Expected local behavior:
- both the
axi_gpregID and the bridge signature read back as0x4250534B; busy_observedanddone_observedare bothtrue;timed_out_observedisfalse;received_bits == frame_bit_count;total_errors == 0;payload_errors == 0.
Linux or SSH run¶
Direct Linux /dev/mem access on the board:
sudo python blocks/block_11_integrated_sdr_project/python/lab_11_8_axi_gpreg_bpsk_bringup.py \
--backend mmap \
--base-addr 0x79040000 \
--frame-bit-count 281 \
--preamble-count 25 \
--start-offset 62 \
--json-out reports/lab118_axi_gpreg_bringup.json
Host-side remote devmem access over Ethernet:
python blocks/block_11_integrated_sdr_project/python/lab_11_8_axi_gpreg_bpsk_bringup.py \
--backend ssh-devmem \
--ssh-host 192.168.40.1 \
--ssh-user root \
--ssh-password analog \
--base-addr 0x79040000
Current live evidence¶
There are two evidence layers and they should not be conflated.
Historical burst-enabled overlay evidence:
The earlier hardware overlay was rebuilt, loaded through Linux fpga_manager, and probed from the host over Ethernet.
Historical evidence paths:
- XSA:
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/course_bpsk_fmcomms2_zc702.sdk/system_top.xsa; - bitstream:
hardware/7020_ad936x_sdr/hdl/course_bpsk_fmcomms2_zc702/build/course_bpsk_fmcomms2_zc702.runs/impl_1/system_top.bit; - live helper report:
docs/assets/lab118_axi_gpreg_bringup_live.json.
Observed historical facts on the board:
devmem 0x79040000 32 -> 0x00040063;devmem 0x79040004 32 -> 0x4250534B;devmem 0x79040508 32 -> 0x4250534B;- helper result:
final_status = 0x0000080C; done_observed = true;timed_out_observed = true;received_bits = 0;- RF setup during the discovery run: TX attenuation
-60 dB, RX gain manual20 dB, AGC disabled.
Runtime revalidation on 2026-06-23:
The corrected word-swapped bridge_txrx_mux payload was reloaded again through
Linux fpga_manager from the stock-shell baseline, this time using the new
runtime helper:
- helper:
blocks/block_11_integrated_sdr_project/python/lab_11_12_runtime_fpga_manager_reload.py; - runtime reload report:
docs/assets/lab118_runtime_fpga_manager_reload_live.json; - post-reload gpreg report:
docs/assets/lab118_axi_gpreg_bringup_runtime_20260623.json; - post-reload burst-capture report:
docs/assets/lab110_iio_burst_capture_runtime_20260623.json; - post-reload compact RF sweep:
docs/assets/lab119_rf_discovery_sweep_runtime_20260623.json.
Observed runtime facts on the board:
- baseline stock shell still returned a
Bus errorwhen reading0x79040004, soaxi_gpregwas absent before the hot load; fpga_manageracceptedbridge_txrx_mux.wordswap.bit.binand remained inoperatingstate;- after the reload,
devmem 0x79040004 32 -> 0x4250534Banddevmem 0x79040508 32 -> 0x4250534Bagain; - the gpreg burst helper still returned
final_status = 0x0000080C,tx_valid_count = 2376,rx_valid_count = 0, andreceived_bits = 0; - unlike the earlier broken live state, the host-side IIO context still enumerated
ad9361-phy,cf-ad9361-dds-core-lpc, andcf-ad9361-lpcafter the runtime reload; - however, a short timed
iio_readdevcapture still returned refill timeoutUnknown error (110)and produced zero samples; - the compact safe-power RF sweep over
START_OFFSET = 48, 62, 74,RX gain = 10/20 dB, andTX attenuation = -80/-70 dBkept the same result on every attempt:received_bits = 0,tx_valid_count = 2376,rx_valid_count = 0.
Stock-versus-runtime comparison on 2026-06-23:
The dedicated comparison helper then ran one more stricter A/B check on the same board:
- helper:
blocks/block_11_integrated_sdr_project/python/lab_11_13_stock_vs_runtime_rx_compare.py; - live comparison report:
docs/assets/lab113_stock_vs_runtime_rx_compare_live.json.
Observed comparison facts on the board:
- before any hot load, the stock shell still supported both a direct host-side
libiio Buffer.refill()capture and a shortiio_readdevcapture; - in the live comparison, stock
libiioreturned16384complex samples and stockiio_readdevreturned65536bytes with empty stderr; - after the corrected runtime hot load,
axi_gpregremained readable and again reportedfinal_status = 0x0000080C,tx_valid_count = 2376,rx_valid_count = 0, andreceived_bits = 0; - after that same reload, direct host
libiiofailed withOSError: [Errno 110] host unreachable, whileiio_readdevagain failed with refill timeoutUnknown error (110); - the same A/B report also showed
cf-ad9361-dds-core-lpcchanging fromsync_start_enable = armon the stock shell tosync_start_enable = disarmafter the runtime reload.
Intermediate bridge_rx_only runtime witness on 2026-06-23:
The next live runtime step moved from bridge_txrx_mux to the narrower
intermediate bridge_rx_only overlay so the vendor TX path stayed untouched
while the bridge reattached only to the RX sample tap.
- helper:
blocks/block_11_integrated_sdr_project/python/lab_11_15_runtime_bridge_rx_host_tx_probe.py; - earlier live witness report:
docs/assets/lab115_runtime_bridge_rx_host_tx_probe_live_20260623_bridge_rx_only_b.json; - refined live witness report:
docs/assets/lab115_runtime_bridge_rx_host_tx_probe_live_20260623_bridge_rx_only_debug_a.json.
Observed bridge_rx_only facts on the board:
- the rebuilt
bridge_rx_onlyrawsystem_top.bitwas converted to the correct word-swapped runtime payload and accepted by Linuxfpga_manager; - after the hot load, the board still exposed
ad9361-phy,cf-ad9361-dds-core-lpc, andcf-ad9361-lpc, withaxi_gpregagain readable at0x79040000; - the first idle gpreg witness still returned
tx_valid_count = 2376,rx_valid_count = 0, andreceived_bits = 0; - the helper then reconfigured stock AD9361 TX/RX for the shared deterministic BPSK burst at
915 MHz,3.84 MS/s,480 ksym/s,TX -50 dB,RX +35 dB; - even with that live host-driven stock TX burst active, the second witness still returned
tx_valid_count = 2376,rx_valid_count = 0, andreceived_bits = 0; - the refined
CAPTURE_DEBUGwitness then made the RX starvation more specific: both the idle probe and the host-TX probe read backcapture_debug_word = 0, withcapture_valid_seen_any = false,capture_nonzero_seen_any = false,capture_valid_count_lsb15 = 0, andcapture_peak_abs_max_q14 = 0; - the refined report conclusion is therefore stronger than the original
...bridge_rx_only_b.jsonwitness: after the runtime hot load, the bridge does not merely miss BER frames, it sees no raw RX-tap activity at all; - the helper rebooted the board afterwards and confirmed a safe return to the stock shell baseline.
Runtime RX common re-init breakthrough on 2026-06-23:
The next live step checked whether the runtime hot load left the AD9361 RX common block in a different control state than the stock shell and whether forcing the stock request bits back in would revive the live receive path.
- helper:
blocks/block_11_integrated_sdr_project/python/lab_11_16_runtime_rx_common_reinit_probe.py; - helper:
blocks/block_11_integrated_sdr_project/python/lab_11_17_runtime_rx_common_reinit_start_offset_sweep.py; - helper:
blocks/block_11_integrated_sdr_project/python/lab_11_18_runtime_rx_common_reinit_fresh_session_sweep.py; - live re-init probe:
docs/assets/lab116_runtime_rx_common_reinit_probe_live_20260623.json; - live host-TX witness after re-init:
docs/assets/lab116_runtime_rx_common_reinit_host_tx_probe_live_20260623.json; - live start-offset sweep after re-init:
docs/assets/lab117_runtime_rx_common_reinit_start_offset_sweep_live_20260623.json. - live fresh-session single-point decision-debug proof:
docs/assets/lab119_runtime_rx_decision_debug_single_point_live_20260623.json; - partial wide fresh-session start-offset sweep:
docs/assets/lab118_runtime_rx_common_reinit_fresh_session_start_offset_wide_live_20260623.json.
Observed post-reinit facts on the board:
- right after the runtime hot load, the RX common request register fell back to
rx_common_ctrl_req = 0x00000000, and the correspondingrx_common_clk_count/rx_common_statusreadbacks were both zero; - restoring the stock request word
0x79020040 <- 0x00000003revived non-zero RX clock/status activity immediately, withrx_common_clk_count = 0x00013AE5andrx_common_status = 0x00000005; - the same re-init also cleared the raw input-side reset witness:
adc_input_reset_asserted_currentdropped tofalse, and both the input-side and RX-tap debug words became non-zero again; - despite that fabric-side recovery, the dedicated A/B helper still reproduced the same host-side failures after the hot load: direct
libiio Buffer.refill()still raisedOSError: [Errno 110] host unreachable, andiio_readdevstill failed withUnable to refill buffer: Unknown error (110); - the reinit-assisted host-TX witness then proved that the runtime overlay was no longer starved at the sample tap:
rx_valid_countbecame non-zero, the rawCAPTURE_DEBUGword showed valid/non-zero activity, and the bridge could again observe the RX stream during stock host TX; - the first checked-in
start_offsetsweep after that re-init found a real full-frame receive window on the first post-TX attempt:start_offset = 32completed281received bits with144total errors and136payload errors, while later attempts in the same TX session fell back to timeout-like behavior. - a wider fresh-session sweep then removed simple
start_offsetblame from the shortlist: offsets from0through576kept the same281 / 144 / 136result, with identicalrx_valid_count = 2982andcapture_peak_abs_max_q14 = 4095; - the new packed decision-sign witness finally made the failure mode explicit on a full-frame receive: the recovered-bit path asserted valid pulses, the hard-decision input was non-zero, but it never went negative and never produced a recovered
1, so the live BER counters were effectively comparing the expected frame against an all-zero recovered bit stream.
Offset-binary root cause and post-fix live retune on 2026-06-23:
- the stricter raw-sign witness
docs/assets/lab120_runtime_capture_sign_single_point_live_20260623.jsonthen showed that the raw bridge tap itself never went negative even thoughcapture_peak_abs_max_q14 = 4095, which ruled out a dead RX path and pointed to a sample-format mismatch instead; - inspecting the imported ADI HDL (
ad_datafmt.vandup_adc_channel.v) explained why: with the default RX data-format controls left at zero, theaxi_ad9361receive path exposes raw 12-bit offset-binary samples rather than signed two's-complement samples at the bridge tap; - the bridge now corrects those low 12 bits locally before feeding
bpsk_zynq_ber_top, whileCAPTURE_DEBUGintentionally still reports the raw unformatted tap so the source-level explanation remains auditable; - the immediate live post-fix proof
docs/assets/lab121_runtime_offset_binary_fix_single_point_live_20260623.jsonshowed that the old all-zero-stream failure is really gone:decision_negative_seen_any = trueandrecovered_one_seen_any = truenow appear on hardware; - the remaining BER is still high, but now tunable rather than collapsed:
docs/assets/lab122_runtime_offset_binary_fix_phase_sweep_live_20260623.jsonimproved the best point to281 / 129 / 120atstart_offset = 34,docs/assets/lab123_runtime_offset_binary_fix_tx_phase_sweep_live_20260623.jsonshowed only a modest extra gain from TX phase, anddocs/assets/lab124_runtime_offset_binary_fix_gain_sweep_live_20260623.jsonreached the current best live runtime point281 / 127 / 114atstart_offset = 34,tx_phase = 315 deg,rx_gain = 5 dB.
Self-timed bridge_txrx_mux follow-up on 2026-06-23:
- the new runtime helper
blocks/block_11_integrated_sdr_project/python/lab_11_19_runtime_bridge_txrx_self_timed_bringup.pyremoves the asynchronous host-side cyclic TX dependency and instead hot-loadsbridge_txrx_mux, restoresrx_common, configures AD9361, and launches the burst from the PL side through the samestartcontrol word; - the first self-timed single-point proof
docs/assets/lab125_runtime_bridge_txrx_self_timed_single_point_live_20260623.jsonshowed that this path now completes a full281-bit frame with no timeout, which closes the earlier "missing-frame because TX is asynchronous" concern well enough to continue debugging BER on the deterministic path itself; - the residual BER is still not low, so the next lightweight experiment added control-plane-selectable RX decision modes through GPREG0 bits
3:2; - the exploratory mode sweep
docs/assets/lab126_runtime_bridge_txrx_self_timed_mode_sweep_live_20260623.jsonsuggests thatneg-iis better than the defaultion the self-timed path, while the follow-up clean rerundocs/assets/lab126_runtime_bridge_txrx_self_timed_neg_i_single_point_live_20260623.jsonshows that the path still reaches a full frame but remains session-sensitive.
Current checked-in safety baseline:
- the stock-safe recovery path is still
hardware/7020_ad936x_sdr/stock_system_top_from_BOOT.bin; under the olduEnv.txtloadb-on-.bit.binfallback it was not proof of arbitrary external PL replacement, but under the new manual UARTfpga loadpath it is now the only externally loaded boot-safe candidate demonstrated so far; - the extracted stock BOOT partition is also the only externally loaded PL payload that now passes manual UART
fpga loadwith AD9361 still alive; seedocs/assets/lab112_clean_boot_pl_validation.json; - the standalone vendor reference
hardware/7020_ad936x_sdr/ps/ad936x_no_os_reference/platform/hw/system_top.bitremains the source-correlated raw control candidate, but it still fails AD9361 both as rawfpga loadband as manual.bit.binfpga load; hardware/7020_ad936x_sdr/boot/validate_clean_boot_overlay.pycaptures the decisive UART evidence for rawfpga loadb, whilehardware/7020_ad936x_sdr/boot/validate_manual_uart_fpga_load.pynow covers the manual.bit.binfpga loadpath;- the rebuilt
vendor_onlyshell now also passes Vivado project creation, implementation, bitstream generation, and XSA export, but still fails clean boot with the same AD9361 calibration timeout; - the new
bridge_rx_onlymode now passes Vivado project creation, implementation, bitstream generation, and XSA export; - the saved vendor
zc702.xprsnapshot, rebuilt throughhardware/7020_ad936x_sdr/rebuild_vendor_xpr_snapshot_mio_patch.tcl, still exports an XSA with zero module/memrange/parameter drift against the vendor reference, but its direct rawsystem.bitload still fails AD9361 clean boot with the same calibration timeout; - the newer
bridge_txrx_muxraw-clean-boot candidate now proves that the course-owned overlay really reaches PL and exposesaxi_gpregon the board after reboot; seedocs/assets/lab118_axi_gpreg_bringup_cleanboot_raw.json; - the earlier helper-generated
bridge_txrx_mux.bit.bincandidate was rejected by U-Bootfpga loadwithzynq_validate_bitstream: Bitstream is not validated yet (diff 1700), so the later healthy AD9361 state in that path came from the untouched stock PL shell; - after fixing the
.bit -> .bit.binconversion to the correct word-swapped payload, the regeneratedbridge_txrx_mux.bit.bincandidate is now accepted by manual UARTfpga load, but Linux still falls into the same AD9361 calibration timeout and exposes onlyiio:device0; - regenerated boot-time candidates from both
AD936X_PL.zipandAD936X_only_PL.zipwere rejected and summarized indocs/assets/lab112_clean_boot_pl_validation.json.
Interpretation:
- the PS-to-PL gpreg control plane was validated on real hardware at least once in the earlier burst-enabled overlay;
- the same gpreg control plane is now also readable after a direct raw clean boot of the
bridge_txrx_muxcandidate, with both ID and signature equal to0x4250534B,tx_valid_count > 0, andrx_valid_count == 0; - the corrected runtime
fpga_managerreload now reproduces the same gpreg readback from the stock Linux shell without losing basic IIO device enumeration, so the blocker is no longer "the board cannot see the overlay at all"; - the stock-versus-runtime comparison now proves that the stock Linux shell still supports both host RX capture paths before any reload, while the runtime hot load breaks both of them even though
axi_gpregstays visible; - the refined
bridge_rx_onlyruntime witness now adds a stronger negative result: even when the stock vendor TX path transmits the shared BPSK burst successfully, the bridge still seesrx_valid_count = 0and the raw RX-tapCAPTURE_DEBUGword remains all zeros; - the runtime RX common re-init result is stronger than the earlier negative witness: the fabric-side RX path can now be revived after the hot load, but the host libiio/DMAC capture path still remains broken;
- the first post-reinit
start_offsetsweep shows that the runtime BPSK receive path is now alive enough to complete a full281-bit receive attempt, so the blocker is no longer dead RX plumbing; - the offset-binary explanation closes that specific bug: the receive chain is no longer stuck with unsigned raw AD9361 samples, and negative decisions / recovered
1bits now appear on hardware; - the new self-timed
bridge_txrx_muxresult removes the earlier "host-side cyclic TX is the whole problem" explanation: full frames are now reproducible without timeout on the PL-owned TX/RX path, but BER still depends on decision polarity and drifts across sessions; - the next blocker is therefore a narrower receive-side problem: stabilize the deterministic self-timed path, then decide whether the right next step is a slightly richer phase/axis correction stage or a true preamble/frame detector in the FPGA receive path;
- the normalized pure-Tcl
vendor_onlyflow now eliminates the earlierMIO14/15drift, but it is still blocked by four read-only or disabled derived parameters:sys_ps7.PCW_S_AXI_HP0_FREQMHZ,axi_ad9361_adc_dma.DMA_AXI_PROTOCOL_SRC,axi_ad9361_dac_dma.DMA_AXI_PROTOCOL_DEST, andaxi_ad9361.SPEED_GRADE; seedocs/assets/vendor_reference_vs_vendor_only_handoff_diff.json; - the saved vendor
zc702.xprsnapshot is still the preferred editable source witness once rebuilt through the MIO14/15 patch flow, but it is not yet a boot-safe RF baseline; seedocs/assets/vendor_reference_vs_vendor_xpr_mio14_15_patch_handoff_diff.json; - the current checked-in HDL now also includes an intermediate
bridge_rx_onlyreintegration mode that is validated in Vivado but not yet in clean boot; - the extracted stock partition from
BOOT.binis now the only externally loaded boot-safe reintegration anchor, but it is not yet editable or source-correlated enough for the final course overlay; - the immediate next task is to remove the remaining asynchronous-frame ambiguity from the runtime BER path, then continue retuning timing / phase with the sample-format bug already closed, while separately continuing the boot-safe-shell investigation for the editable clean-boot path.
Next gated re-enable order¶
- Confirm that the candidate custom boot-time PL image is accepted by the relevant validator path: raw
.bitthroughvalidate_clean_boot_overlay.pyor.bit.binthroughvalidate_manual_uart_fpga_load.py. - Confirm the board IP,
axi_gpregID register, and bridge signature before writing frame parameters. - Re-enable the sample-domain bridge while keeping the Linux-visible DMA shell intact.
- Keep AD9361 TX attenuation at the minimum output power setting available on the board.
- Keep RX gain low and manual. Do not enable AGC for the first renewed burst.
- Launch one short burst only.
- Observe
busyand thendoneordone after timeout. - Read
RECEIVED_BITS,TOTAL_ERRORS, andPAYLOAD_ERRORS. - Only then resume repeated sweeps or BER campaigns.
Report checklist¶
- [ ] Attach the regenerated XSA path and confirm
axi_gpreg_bpsk. - [ ] Attach the regenerated bitstream path.
- [ ] Show the
0x79040000base address in the exported handoff. - [ ] Record one successful ID readback and one successful signature readback.
- [ ] Show programmed
FRAME_BIT_COUNT,PREAMBLE_COUNT, andSTART_OFFSET. - [ ] State whether
busy,done, andtimeoutwere observed. - [ ] Record
RECEIVED_BITS,TOTAL_ERRORS, andPAYLOAD_ERRORS. - [ ] List the AD9361 TX attenuation and RX gain used for the first renewed burst.
Engineering conclusion template¶
The gpreg-based AD9361 overlay is ready / not ready as a clean-boot baseline.
The exported handoff contains / does not contain the expected control window.
The next gated reintegration step is ______ and its success criterion is ______.