Hello,
Following up on another topic I posted recently on configuring the LMK clocks using the xrfclk driver, now I’m stuck on actually streaming data to the DAC.
By that I mean I can’t observe anything at the output of DAC230, via the XM655, using an oscilloscope.
My setup (TCL attached), with clock domains highlighted:
RF config:
The PL clock is 100Mhz.
(Sidenote: I tried without DMA before, as I posted on the topic I linked).
And what I’m running via Jupyter, with some output omitted for brevity (also attached):
import xrfclk
import xrfdc
import pynq.lib.dma
from pynq import allocate
import numpy as np
import matplotlib.pylab as plt
xrfclk.set_ref_clks(245.76)
from pynq import Overlay
ol = Overlay("/home/xilinx/overlays/zcu216_nmcp_dma2/zcu216_nmcp88.bit")
ol?
…
axi_dma_0 : pynq.lib.dma.DMA
usp_rf_data_converter_0 : xrfdc.RFdc
zynq_ultra_ps_e_0 : pynq.overlay.DefaultIP
…
rf = ol.usp_rf_data_converter_0
rf.IPStatus
{‘DACTileStatus’: [{‘IsEnabled’: 0,
‘TileState’: 0,
‘BlockStatusMask’: 0,
‘PowerUpState’: 0,
‘PLLState’: 0},
{‘IsEnabled’: 0,
‘TileState’: 0,
‘BlockStatusMask’: 0,
‘PowerUpState’: 0,
‘PLLState’: 0},
> {‘IsEnabled’: 1,
> ‘TileState’: 15,
> ‘BlockStatusMask’: 1,
> ‘PowerUpState’: 1,
> ‘PLLState’: 1},
{‘IsEnabled’: 0,
‘TileState’: 0,
‘BlockStatusMask’: 0,
‘PowerUpState’: 0,
‘PLLState’: 0}],
tile2 = rf.dac_tiles[2]
tile2.PLLConfig
tile2.SetupFIFO(True)
dac_block = tile2.blocks[0]
dac_block.BlockStatus
dac_block.MixerSettings
{‘Freq’: 0.0,
‘PhaseOffset’: 0.0,
‘EventSource’: 2,
‘CoarseMixFreq’: 4,
‘MixerMode’: 1,
‘FineMixerScale’: 0,
‘MixerType’: 1}
# Adapted from: https://repositorio.uam.es/handle/10486/697509
def sine_gen(a, f, fs, n):
w = 2 * np.pi * f
dt = 1 / fs
t = np.arange(0, n, 1) * dt
return a * np.exp(1j * w * t)
def to_fp(data):
# split into real and img
data_real = np.multiply(np.real(data), np.power(2, 15)).astype(np.int32)
data_imag = np.multiply(np.imag(data), np.power(2, 15)).astype(np.int32)
data_real = np.where((data_real >= 32768), 32767, data_real)
data_imag = np.where((data_imag >= 32768), 32767, data_imag)
# pack into uint32
data_iq = np.zeros(len(data_real), dtype=np.uint32)
data_imag_shifted = np.uint32(np.bitwise_and((data_imag << 16), 0xFFFF0000))
data_real_shifted = np.uint32(np.bitwise_and((data_real << 0), 0x0000FFFF))
data_iq = np.bitwise_or(data_imag_shifted, data_real_shifted)
return [data_iq, data_real, data_imag]
def DMAWave(freq):
a = 1 # Amplitude
f = freq * 1e6 # Desired frequency (Mhz)
fs = 786.432e6 # Sampling rate
n = 8 * 786.432 # nr samples (?)
signal_gen = sine_gen(a, f, fs, n)
array_fp = to_fp(signal_gen)
return array_fp;
def toDMABuf(array_fp):
n = len(array_fp)
in_buffer = allocate(shape=(n,), dtype=np.int32)
for i in range(n):
in_buffer[i] = array_fp[i]
return in_buffer
f = 20 # Desired frequency (Mhz) (?)
wav = DMAWave(f)
# check the wave(s)
plt.plot(wav[1][:100])
plt.plot(wav[2][:100])
plt.show()
# put into "allocate" type buffer for DMA
buf = toDMABuf(wav[0])
# send forever
dmatx = ol.axi_dma_0.sendchannel
while(1):
dmatx.transfer(buf)
dmatx.wait()
This last cell runs until I stop it (or eventually the board stops responding entirely, either via ssh, via ttyUSB, or Jupyter… and I have to power cycle it).
I suspect I’m missing some initialization on the Data converter at the Notebook/Python level? I’m not sure if calling tile2.SetupFIFO(True)
is enough to “initialize” the tile (?). I’m not even quite sure what this call does, as I’m going by existing RFSoC-Book examples (e.g., rfscoc_qpsk, rfsoc_sam, etc).
I’ve also tried in Real → Real mode (generating a uint32 sine wave and sending that via DMA), without success.
Any help would be appreciated, regards,
Nuno
zcu216_nmcp_dma2.ipynb (38.3 KB)
zcu216_nmcp_dma2.tcl (109.3 KB)