Closed tristanlorriaux closed 1 year ago
Output of loopBack:
Your understanding is correct.
If I understand correctly what you want to do, it's solvable without phase reset. You want phase-coherent upconversion/downconversion in the generator and readout, so you should frequency-match them and not change their phase. You want to play a tone with a frequency offset: you can do this by applying the frequency offset to the envelope.
class FreqShiftProgram(AveragerProgram):
def initialize(self):
cfg = self.cfg
style = cfg['style']
for iCh, ch in enumerate(cfg["gen_chs"]): # configure the pulse lengths and upconversion frequencies
length_gen = self.us2cycles(cfg['length'], gen_ch=ch)
self.declare_gen(ch=ch, nqz=cfg['nqz'][iCh], ro_ch=cfg["ro_chs"][0])
delta_freq = cfg['delta_freq']
self.default_pulse_registers(ch=ch,
gain=cfg['pulse_gain'],
phase=0)
iqdata = 32000*np.exp(2j*pi*self.cycles2us(np.arange(length_gen*16), gen_ch=ch)/16*delta_freq)
idata = np.real(iqdata).astype(np.int16)
qdata = np.imag(iqdata).astype(np.int16)
self.add_pulse(ch=ch, name="measure", idata=idata, qdata=qdata)
self.set_pulse_registers(ch=ch, style="arb", waveform="measure",
freq=self.freq2reg(cfg['pulse_freq'], ro_ch=cfg["ro_chs"][0]))
for iCh, ch in enumerate(cfg["ro_chs"]): # configure the readout lengths and downconversion frequencies
length_ro = self.us2cycles(cfg['length']+cfg['readout_padding'], ro_ch=ch)
self.declare_readout(ch=ch, freq=cfg["pulse_freq"],
length=length_ro,
sel=cfg['ro_sel'],
gen_ch=cfg["gen_chs"][0])
self.synci(200) # give processor some time to configure pulses
def body(self):
self.measure(pulse_ch=self.cfg["gen_chs"],
adcs=self.ro_chs,
pins=[0],
adc_trig_offset=self.us2cycles(self.cfg["adc_trig_offset"]),
wait=True,
syncdelay=self.us2cycles(self.cfg["relax_delay"]))
config = {
'gen_chs': [4],
'ro_chs': [1],
'nqz': [1],
'ro_sel': 'product',
'style': 'arb',
'pulse_gain': 30000, # a.u.
'pulse_freq': 400, # MHz
'delta_freq': 1,
'adc_trig_offset': 0.4, # us
'length': 1.0, # us
'readout_padding': 0.1, # us
'relax_delay': 2, # us
'reps': 1,
# 'soft_avgs': 1
'soft_avgs': 100
}
prog = FreqShiftProgram(soccfg, config)
iq_list = prog.acquire_decimated(soc, progress=True)
# Plot results.
plt.plot(iq_list[0][0])
plt.plot(iq_list[0][1])
gives the following in loopback, which is coherent over any number of averages:
Great, this does solve our problem! Thanks a lot for the quick response and a neat solution!
Hi there !
We are trying to acquire a signal at a different frequency than the drive, and to demodulate it with coherent phase. To do this we need seperate generators for the DAC and the ADC, and to reset the phase of both at the beginning of each sequence, which we apparently cannot do. From issue 120 we understand this may be due to the ADC being now controlled by the PYNQ, not the tProc, so the latter connot adjust its phase mid-flight. Is this interpretation correct, and if so, is there any cheaper solution other than sacrificing two tProc channels for ADCs? Because we sure can use more DAC channels.
We are using the ZCU216, with the basic firmware:
And below is a minimum example, where we try to measure the DAC0 loopback to ADC1, offset by 10 MHz, and get 10 traces with random phase.