Skip to content

HW Verify Issue 69 Ad9681 DDR Readout

Benjamin Reese edited this page Aug 14, 2026 · 2 revisions

HW Verify — Issue #69: Adopt surf Ad9681 DDR ADC readout modules

Item: Issue #69 (Adopt surf Ad9681 DDR ADC readout modules). Board status: Needs HW Test · Track: DDR readout · Priority: P0. Branch test-ad9681-ddr (+4/−1 vs. main).

← back to Hardware Verification

What we are verifying

This adopts surf's new Ad9681 DDR ADC readout modules. The Warm-TDM diff is tiny (5 files: DataPath.vhd, ColumnFpgaBoardModel.vhd, _ColumnFpgaBoard.py, _DataPath.py, and the surf submodule pointer). The task is to build a Column target with the DDR modules and confirm the ADC data path still works on real hardware — i.e. the ADC locks, delays tune, and channels stream sane values.

External blocker — check first. The surf submodule points at v2.72.0-108-ga66f8c61f, which lives only on the surf branch adc-ddr-readout-cleanup. This cannot be built for release until surf merges and tags those modules. Confirm the surf modules have been released/tagged before starting a release build; for an interim bench check you can build against the branch pointer already in the submodule.

Prerequisites

  1. Confirm the surf DDR modules are available (released tag, or the branch the submodule points at is checked out):

    git -C <warm-tdm>/firmware/submodules/surf describe --tags
    git -C <warm-tdm> submodule status firmware/submodules/surf
  2. Vivado 2024.1 sourced (see Common bench setup).

Procedure

Part 1 — build the firmware

  1. Check out test-ad9681-ddr, init submodules, and build the affected Column target:

    cd <warm-tdm>
    git checkout test-ad9681-ddr
    git submodule update --init --recursive
    source /sdf/group/faders/tools/xilinx/2024.1/Vivado/2024.1/settings64.sh
    cd firmware/targets/ColumnFpgaBoard      # (or the specific DDR Column target)
    make prom

    Confirm the build passes timing (no hold-time errors — the reason we pin 2024.1) and produces an image.

  2. Load the image onto the column board and start the server against it.

Part 2 — confirm the ADC path

  1. Connect a client and initialize the ADC:

    cb = sess.group.ColumnBoard[0]
    cb.InitDacAdc()          # configures Ad9681, relocks the DDR readout
  2. Confirm the DDR readout is locked and stays locked:

    rd = cb.DataPath.Ad9681Readout
    print("Locked   :", rd.Locked.get())          # both lanes should be True
    print("LostLock :", rd.LostLockCount.get())    # should be stable / not climbing

    If not locked, tune the IDELAYs (rd.AllDelay0() / rd.AllDelay1() / per-channel ChannelDelay) and relock (rd.Relock()), then re-check LostLockCount holds steady.

  3. Confirm live ADC data is sane:

    print(rd.AdcChannel.get())     # 8 deserialized codes — should vary, not stuck
    print(rd.AdcVoltage.get())     # same in volts
    cb.SaOutAdc.get()              # averaged ADC readback

Part 3 — end-to-end readout

  1. Take a short streaming acquisition and confirm frames flow and decode:

    sess.group.ColTuneEnable.set([True] * 8)
    sess.group.RowIndexOrderList.set([0, 1, 2, 3])
    ops.setup_mux(num_pts=512, sample_end_offset=100, sample_num=250, enable_pid=False)
    f = ops.take_data(acq_time_sec=5.0)
    ops.plot_stream_data("c*r*", stream_data_id=f)

    Confirm the EventBuilder counters advance during readout (cb.DataPath.EventBuilder.DaqReadoutCount) and the plotted channels carry real data.

  2. Compare against the pre-DDR readout on the same board/setup (values, noise) to confirm no regression from the readout-module swap.

Pass criteria

  • test-ad9681-ddr builds a Column target on Vivado 2024.1, timing clean.
  • ADC locks after InitDacAdc, LostLockCount stable.
  • AdcChannel/AdcVoltage show live, varying, physical values.
  • End-to-end streaming acquisition decodes with data on the expected channels.
  • No regression vs. the previous (non-DDR) readout on the same setup.

Record

  • surf tag/branch used; Warm-TDM commit on test-ad9681-ddr; Vivado version:
  • Build result (timing pass?), image name:
  • Lock + LostLockCount behavior:
  • ADC channel values; streaming decode result:
  • Regression comparison vs. non-DDR:

References

  • Issue #69 (diff scope + the surf-release blocker)
  • firmware/python/warm_tdm/_DataPath.py, _ColumnFpgaBoard.pyAd9681Readout, InitDacAdc
  • surf .../devices/analog_devices/_Ad9681.pyRelock, Locked, LostLockCount, OutputMode (DDR modes), ChannelDelay/AllDelay0/AllDelay1
  • Branch merge roadmap — DDR track sequencing

Clone this wiki locally