Control Sequencers#
A control sequencer is a type of Q1 sequencer whose signal path is an arbitrary waveform generator (awg) and generates two streams of output signals called path_0 and path_1.
The following describes the parts or blocks of the signal path of a control sequencer along with examples to illustrate how the blocks work together. Some of the blocks perform mathematical operations to a signal. In these cases, a formula of the form \(y(t)=f(x(t))\) is presented, where \(t\) is time in discrete time steps of 1 ns corresponding to each time sample, \(y(t)\) is the output of the block, given that \(x(t)\) is the input to the block. The function \(f(x(t))\) can be manipulated using Q1ASM instructions or QCoDeS commands depending on the block.
Arbitrary waveform generator (AWG)#
1. Waveform playback#
A control sequencer has a certain waveform memory from which signals can be played. The user can upload waveforms while uploading a sequence using the Sequencer.sequence() method. The method takes a dictionary as an argument, and one of the keys must be waveforms, which itself is a dictionary with a python list of floating point values in the range of 1.0 to -1.0 with a resolution of one nanosecond per sample. See below an example:
Example: waveform upload
from scipy.signal.windows import gaussian
sequencer0.sequence(
{
"waveforms": {
# 4 ns ramp waveform
"wfm1": {
data = [0.0, 0.1, 0.2, 0.3],
index = 0
},
# 100 ns gaussian waveform (100 pts -> 100 ns)
"gaussian": {
data = list(gaussian(100, 20)),
index = 1
}
},
...
}
)
Important
The data supplied to the waveform dictionary must be a python list. It cannot be a numpy array.
The waveform memory for each sequencer is 16384 samples (total of all waveforms stored in one sequencer), and the maximum number of waveforms that can be stored on a sequencer is 1024. The stored waveforms can be retrieved using Sequencer.get_waveforms().
The play RT instruction is used to start waveform playback from the waveform memory. The instruction takes two arguments before the real-time duration argument. The first two are the waveform indices for path 0 and path 1. Once the play instruction is executed by the RT core, the waveform is then completely played irrespective of further instructions, except when the RT core issues the playback of another waveform, in which case the waveform will be stopped and the new waveform will start.
Example: Play waveform
The example below assumes that the sequence dictionary in the Example: waveform upload above is uploaded to the sequencer.
play 0,1,200 # Play wfm1 on path_0 and gaussian on path_1. Then wait 200 ns.
play 1,1,100 # Play gaussian on both path_0 and path_1. Then wait 100 ns.
play 1,1,50 # Play gaussian on both path_0 and path_1. Then wait 50 ns.
# Interrupt playback of gaussian from the previous play.
play 0,0,4 # Play wfm1 on both path_0 and path_1. Then wait 4 ns.
stop
Note
If the waveform is shorter than duration, the output is zeros after waveform playback.
2. Gain#
A control sequencer has a dedicated gain step for both paths 0 and 1, which can either be configured using the ControlSequencer.gain_awg_path0() QCoDeS parameter or within a sequence using the set_awg_gain Q1ASM latched instruction of the Q1 sequencer which enables pulse parametrization. The QCoDeS and Q1ASM gain controls are multiplied together before the gain is applied to the signal.
The set_awg_gain Q1ASM latched instruction takes two integers from -32768 to 32767 as arguments for the gain of the two paths.
Mathematically, this block is:
where,
\(G\) is the gain from the
ControlSequencer.gain_awg_path0()QCoDeS parameter and\(g\) is the gain from the
set_awg_gainQ1ASM latched register.
Note
If modulated IQ signals are used for an output pair, it is good practice to set the same gain for both paths, i.e., ControlSequencer.gain_awg_path0() = ControlSequencer.gain_awg_path1()
Example: Increasing gains
The following example plays 10 gaussian pulses with increasing amplitude.
The example assumes that the sequence dictionary in the Example: waveform upload above is uploaded to the sequencer.
move 10, R0 # Loop counter
move 1000, R1 # Initial gain of 1000
start:
set_awg_gain R1, R1 # Set gain to value in R1.
play 1,1,100 # Play gaussian on both path_0 and path_1. Then wait 100 ns.
add R1, 1000, R1 # R1 = R1 + 1000
loop R0, @start
stop
3. Offset#
A control sequencer has a dedicated offset step for both paths 0 and 1, which can either be configured using the ControlSequencer.offset_awg_path0() QCoDeS parameter or within a sequence using the set_awg_offs Q1ASM latched instruction of the Q1 sequencer which enables pulse parametrization. The QCoDeS and Q1ASM offset controls are added together before the gain is applied to the signal.
The set_awg_offs Q1ASM latched instruction takes two integers from -32768 to 32767 as arguments for the offset of the two paths.
Mathematically, this block is:
where,
\(O\) is the offset from the
ControlSequencer.offset_awg_path0()QCoDeS parameter and\(o\) is the offset from the
set_awg_offsQ1ASM latched register.
Note
If modulated IQ signals are used for an output pair, it is good practice to set the same offset for both paths, i.e., ControlSequencer.offset_awg_path0() = ControlSequencer.offset_awg_path1()
Example: Increasing offsets
The following example plays 10 gaussian pulses with increasing offsets.
The example assumes that the sequence dictionary in the Example: waveform upload above is uploaded to the sequencer.
move 10, R0 # Loop counter
move 1000, R1 # Initial offset of 1000
start:
set_awg_offs R1, R1 # Set offset to value in R1.
play 1,1,100 # Play gaussian on both path_0 and path_1. Then wait 100 ns.
add R1, 1000, R1 # R1 = R1 + 1000
loop R0, @start
stop
4. Numerically controlled oscillator (NCO)#
A control sequencer has a numerically controlled oscillator (NCO) whose frequency and phase parameters either be configured using the ControlSequencer.nco_freq() and ControlSequencer.nco_phase_offs() QCoDeS parameters or within a sequence using the set_freq, reset_ph, set_ph, and set_ph_delta Q1ASM latched instructions.
The NCO outputs a two signals (\(n_I\) and \(n_Q\)), which can be interpreted as a complex signal (\(\mathbf{n}(t)\)).
Real signals
Complex signals
where,
\(\omega = 2\pi f\) where \(f\) is the frequency of the NCO.
\(f\) can be set using the
ControlSequencer.nco_freq()QCoDeS parameter or theset_freqQ1ASM instruction.\(t'\) is the time internal to the NCO.
It is set to zero with the
reset_phinstruction. Note that thereset_phinstruction also sets \(\phi=0\) and \(\Phi=0\). Theset_ph_deltaQ1ASM instruction induces a phase kick \(t'\rightarrow t' + \delta\phi/\omega\) at the instant that the signal path is updated (when the next RT instruction is executed).\(\Phi\) is the phase offset.
It is set from the
ControlSequencer.nco_phase_offs()QCoDeS parameter.\(\phi\) is the phase offset.
It is set from the
set_phQ1ASM latched register.
The ControlSequencer.nco_phase_offs() QCoDeS parameter and set_ph Q1ASM instruction are added together before it is applied to the NCO.
Warning
The ControlSequencer.nco_freq() QCoDeS parameter and set_freq Q1ASM instruction override each other. We highly recommend setting NCO frequencies only either using QCoDeS or Q1ASM and not both.
For further in depth details and a tutorial on how to use the Q1 sequencer NCO capabilities, please refer to the NCO tutorial.
5. Modulation (mixer)#
The two output signals from the NCO (\(\mathbf{n}(t) = n_I(t) + \mathbf{i}n_Q(t)\)) and the signal from paths 0 and 1 (\(\mathbf{x}(t) = x_0(t) + \mathbf{i}x_1(t)\)) are multiplied as complex signals in this block to output a modulated signal (\(\mathbf{y}(t) = y_0(t) + \mathbf{i}y_1(t)\)).
Real signals
Complex signals
Note
The \(1/\sqrt{2}\) factor ensures that the output is limited to \(\pm 1\).
Modulation is enabled using the ControlSequencer.mod_en_awg() parameter.
Example: Pulses of increasing frequency
The following example plays 10 square pulses with increasing frequency from 0 to 9 MHz.
move 10, R0 # Loop counter
move 0, R1 # Initial frequency of 0 Hz
start:
set_freq R1 # Set the frequency to R1/4 Hz. The argument is in multiples of 0.25 Hz.
set_awg_offs 32767, 32767 # Set the path_0 and path_1 offset to maximum.
upd_param 1000 # Apply the offset to the output and wait 1 us.
set_awg_offs 0, 0 # Set the path_0 and path_1 offset to 0.
upd_param 4 # Apply the offset to the output and wait 4 ns.
add R1, 4000000, R1 # R1 = R1 + 4000000. Corresponding to 1 MHz.
loop R0, @start
stop
5.1 Mixer Correction#
If the two signals (path 0 and 1) generated by the control sequencer are meant to be used as the I and Q signals to a physical mixer (such as in the RF modules), one may want to correct for mixer imperfections. The mixer correction block allows the user to set an amplitude ratio (\(\alpha\)) and a phase offset (\(\phi_m\)) between the I and Q signals, so that the output of the physical mixer is ideal. The output of the mixer correction block is calculated by the mixer correction block as follows:
where,
\(\alpha\) is the amplitude ratio between the I and Q signals set by
ControlSequencer.mixer_corr_gain_ratio()QCoDeS parameter.\(\phi_m\) is the phase offset between the I and Q signals set by
ControlSequencer.mixer_corr_phase_offset_degree()QCoDeS parameter.
Please refer to the Automatic mixer calibration tutorial and Manual mixer calibration tutorial for more details.