Hello,
I just upgraded my ZCU111 from PYNQ2.7 to PYNQ3.0.1 and I can’t figure out why my RFDC DAC output looks bad. I have a design built using Vivado 2022.1 that uses an HLS URAM block to store a waveform which is played out of the DAC. We have a driver which writes values from Python to the URAM. I am using the same .bit
and .hwh
and HLS driver. It works great in PYNQ2.7-- I can generate a single sine wave an get a nice tone out of the DAC. In PYNQ3.0.1 this is what I’m getting on a Spectrum Analyzer:
At first I thought maybe it was a clocking issue. I used xrfclk
to program the PLLs to the correct value (I have 409.6 set as the PLL reference in Vivado).
xrfclk.set_ref_clks(lmk_freq=122.88, lmx_freq=409.6)
I can see the PLL LEDs come on when I run this. Here is the output of my clock dict:
{0: {'enable': 1, 'divisor0': 15, 'divisor1': 1},
1: {'enable': 0, 'divisor0': 4, 'divisor1': 1},
2: {'enable': 0, 'divisor0': 4, 'divisor1': 1},
3: {'enable': 0, 'divisor0': 4, 'divisor1': 1}}
I’m sure they are programmed because I can run the rest of my design without the board hanging.
Here is some sample python including the driver code internals:
import pynq
import numpy as np
import xrfclk
xrfclk.set_ref_clks(lmk_freq=122.88, lmx_freq=409.6)
## Generate a sine wave
fs = 4.096e9 # DAC Samle Rate
n = 2**19 # URAM Table is 2**19 complex samples
freq = 300e6 # Hz
freq_res = fs / n # DAC frequency resolution
quant_freq = np.round(freq / freq_res) * freq_res # quantize frequency
t = 2 * np.pi * np.arange(n)/fs
sine_wave = 1*np.exp(1j * t * quant_freq)
## Prepare values for the HLS IP Run Config
data = (sine_wave*8192).round().clip(-8192, 8191)*16 # quantize data
replay_len = data.size // 16
tlast_every = int(256)
tlast= True
## Fill Buffer with Samples in Proper Order
buffer = pynq.allocate(2 ** 20, dtype=np.uint16)
iload = data.real.astype(np.int16)
qload = data.imag.astype(np.int16)
for i in range(16):
buffer[i:data.size * 2:32] = iload[i::16]
buffer[i+16:data.size * 2:32] = qload[i::16]
## Update DAC Table Register Map with Values
ol.dac_table.register_map.a_1 = buffer.device_address
ol.dac_table.register_map.length_r = replay_len - 1 # length counter
ol.dac_table.register_map.tlast = bool(tlast)
ol.dac_table.register_map.replay_length = tlast_every-1
ol.dac_table.register_map.run = 1
ol.dac_table.register_map.CTRL.AP_START = 1 # start
I downloaded the PYNQ2.6 registers.py so I can read the “write-only” registers in the dac_table
register map and the values look correct:
RegisterMap {
CTRL = Register(AP_START=1, AP_DONE=0, AP_IDLE=0, AP_READY=0, RESERVED_1=0, AUTO_RESTART=0, RESERVED_2=0, RESERVED_3=0, RESERVED_4=0),
GIER = Register(Enable=0, RESERVED=0),
IP_IER = Register(CHAN0_INT_EN=0, CHAN1_INT_EN=0, RESERVED=0),
IP_ISR = Register(CHAN0_INT_ST=0, CHAN1_INT_ST=0, RESERVED=0),
a_1 = Register(a=2017460224),
a_2 = Register(a=0),
length_r = Register(length_r=32767, RESERVED=0),
tlast = Register(tlast=1, RESERVED=0),
replay_length = Register(replay_length=255, RESERVED=0),
run = Register(run=1, RESERVED=0)
}
I’ve been looking at the change log and commit history for PYNQ2.7 → PYNQ3.0.1 and nothing is jumping out at me that might relate to this.
If anyone has further suggestions or debugging ideas please let me know!
Thanks,
Jenny
Test .hwh
and .bit
attached.
test.zip (6.1 MB)