See also

An IPython notebook version of this tutorial can be downloaded here:

basic_sequencing.ipynb

Basic sequencing

In this tutorial we will demonstrate basic sequencer based operations (see section Sequencer). This includes creating a sequence, consisting of waveforms and a simple Q1ASM program, and executing this sequence synchronously on multiple sequencers.

The sequence is going to consecutively play two waveforms, a gaussian and block with a duration of 20ns each, with an increasing wait period in between them. We will increase the wait period 20ns a 100 times after which the sequence is stopped. The sequence will also trigger marker output 1 at every interval, so that the sequence can be easily monitored on an oscilloscope.

Setup

First, we are going to import the required packages and connect to the instrument.

[1]:
#Set up the environment.
import scipy.signal
import json
import matplotlib.pyplot
import numpy
import os

from qblox_instruments import Pulsar

#Close any existing connections to any Pulsar.
Pulsar.close_all()

#Connect to the Pulsar at default IP address.
pulsar = Pulsar("pulsar", "192.168.0.2")

#Reset the instrument for good measure.
pulsar.reset()
print("Status:")
print(pulsar.get_system_state())
Status:
SystemState(status=<SystemStatus.OKAY: 2>, flags=[])

Generate waveforms

Next, we need to create the gaussian and block waveforms for the sequence.

[2]:
#Waveform parameters
waveform_length = 20 #nanoseconds

#Waveform dictionary (data will hold the samples and index will be used to select the waveforms in the instrument).
waveforms = {
                "gaussian": {"data": scipy.signal.gaussian(waveform_length, std=0.12 * waveform_length).tolist(), "index": 0},
                "block":    {"data": [1.0 for i in range(0, waveform_length)],                                    "index": 1}
            }

Let’s plot the waveforms to see what we have created.

[3]:
time    = numpy.arange(0, max(map(lambda d: len(d["data"]), waveforms.values())), 1)
fig, ax = matplotlib.pyplot.subplots(1,1, figsize=(10, 10/1.61))

for wf, d in waveforms.items():
    ax.plot(time[:len(d["data"])], d["data"], ".-", linewidth=0.5, label=wf)

ax.legend(loc=4)
ax.yaxis.grid()
ax.xaxis.grid()
ax.set_ylabel("Waveform primitive amplitude")
ax.set_xlabel("Time (ns)")

matplotlib.pyplot.draw()
matplotlib.pyplot.show()
../_images/tutorials_basic_sequencing_6_0.png

Create Q1ASM program

Now that we have the waveforms for the sequence, we need a Q1ASM program that sequences the waveforms as previously described.

[4]:
#Sequence program.
seq_prog = """
       move      100,R0   #Loop iterator.
       move      20,R1    #Initial wait period in ns.
       wait_sync 4        #Wait for sequencers to synchronize and then wait another 4ns.

loop:  set_mrk   1        #Set marker output 1.
       play      0,1,4    #Play a gaussian and a block on output path 0 and 1 respectively and wait 4ns.
       set_mrk   0        #Reset marker output 1.
       upd_param 16       #Update parameters and wait the remaining 16ns of the waveforms.

       wait      R1       #Wait period.

       play      1,0,20   #Play a block and a gaussian on output path 0 and 1 respectively.
       wait      1000     #Wait a 1us in between iterations.
       add       R1,20,R1 #Increase wait period by 20ns.
       loop      R0,@loop #Subtract one from loop iterator.

       stop               #Stop the sequence after the last iteration.
"""

Upload sequence

Now that we have the waveforms and Q1ASM program, we can combine them in a sequence stored in a JSON file.

[5]:
#Add sequence to single dictionary and write to JSON file.
seqeunce = {"waveforms": waveforms, "weights": {}, "acquisitions": {}, "program": seq_prog}
with open("sequence.json", 'w', encoding='utf-8') as file:
    json.dump(seqeunce, file, indent=4)
    file.close()

Let’s write the JSON file to the instruments. We will use sequencer 0 and 1, which will drive outputs \(\text{O}^{[1-2]}\) and \(\text{O}^{[3-4]}\) respectively.

[6]:
#Upload sequence.
pulsar.sequencer0.sequence("sequence.json")
pulsar.sequencer1.sequence("sequence.json")

Play sequence

The sequence has been uploaded to the instrument. Now we need to configure the sequencers in the instrument to use the wait_sync instruction at the start of the Q1ASM program to synchronize.

[7]:
#Configure the sequencers to synchronize.
pulsar.sequencer0.sync_en(True)
pulsar.sequencer1.sync_en(True)

#Map sequencers to specific outputs (but first disable all sequencer connections).
for sequencer in pulsar.sequencers:
    for out in range(0, 4):
        if hasattr(sequencer, "channel_map_path{}_out{}_en".format(out%2, out)):
            sequencer.set("channel_map_path{}_out{}_en".format(out%2, out), False)

#If it is a QRM, we only map sequencer 0 to the outputs.
pulsar.sequencer0.channel_map_path0_out0_en(True)
pulsar.sequencer0.channel_map_path1_out1_en(True)
if pulsar.is_qcm_type:
    pulsar.sequencer1.channel_map_path0_out2_en(True)
    pulsar.sequencer1.channel_map_path1_out3_en(True)

Now let’s start the sequence. If you want to observe the sequence, this is the time to connect an oscilloscope to marker output 1 and one or more of the four outputs. Configure the oscilloscope to trigger on the marker output 1.

[8]:
#Arm and start both sequencers.
pulsar.arm_sequencer(0)
pulsar.arm_sequencer(1)
pulsar.start_sequencer()

#Print status of both sequencers.
print("Status:")
print(pulsar.get_sequencer_state(0))
print(pulsar.get_sequencer_state(1))
Status:
SequencerState(status=<SequencerStatus.STOPPED: 5>, flags=[])
SequencerState(status=<SequencerStatus.STOPPED: 5>, flags=[])

Stop

Finally, let’s stop the sequencers if they haven’t already and close the instrument connection.

[9]:
#Stop both sequencers.
pulsar.stop_sequencer()

#Print status of both sequencers (should now say it is stopped).
print("Status:")
print(pulsar.get_sequencer_state(0))
print(pulsar.get_sequencer_state(1))
print()

#Print an overview of the instrument parameters.
print("Snapshot:")
pulsar.print_readable_snapshot(update=True)

#Close the instrument connection.
pulsar.close()
Status:
SequencerState(status=<SequencerStatus.STOPPED: 5>, flags=[<SequencerStatusFlags.FORCED_STOP: 2>])
SequencerState(status=<SequencerStatus.STOPPED: 5>, flags=[<SequencerStatusFlags.FORCED_STOP: 2>])

Snapshot:
pulsar:
        parameter                    value
--------------------------------------------------------------------------------
IDN                           : {'manufacturer': 'qblox', 'model': 'pulsar_qr...
in0_gain                      : -6 (dB)
in1_gain                      : -6 (dB)
out0_offset                   : 0 (V)
out1_offset                   : 0 (V)
reference_source              : internal
scope_acq_avg_mode_en_path0   : False
scope_acq_avg_mode_en_path1   : False
scope_acq_sequencer_select    : 0
scope_acq_trigger_level_path0 : 0
scope_acq_trigger_level_path1 : 0
scope_acq_trigger_mode_path0  : sequencer
scope_acq_trigger_mode_path1  : sequencer
pulsar_sequencer0:
        parameter                       value
--------------------------------------------------------------------------------
channel_map_path0_out0_en        :      True
channel_map_path1_out1_en        :      True
cont_mode_en_awg_path0           :      False
cont_mode_en_awg_path1           :      False
cont_mode_waveform_idx_awg_path0 :      0
cont_mode_waveform_idx_awg_path1 :      0
demod_en_acq                     :      False
discretization_threshold_acq     :      0
gain_awg_path0                   :      1
gain_awg_path1                   :      1
integration_length_acq           :      1024
marker_ovr_en                    :      False
marker_ovr_value                 :      0
mixer_corr_gain_ratio            :      1
mixer_corr_phase_offset_degree   :      -0
mod_en_awg                       :      False
nco_freq                         :      0 (Hz)
nco_phase_offs                   :      0 (Degrees)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
phase_rotation_acq               :      0 (Degrees)
sequence                         :      sequence.json
sync_en                          :      True
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
pulsar_sequencer1:
        parameter                       value
--------------------------------------------------------------------------------
channel_map_path0_out0_en        :      False
channel_map_path1_out1_en        :      False
cont_mode_en_awg_path0           :      False
cont_mode_en_awg_path1           :      False
cont_mode_waveform_idx_awg_path0 :      0
cont_mode_waveform_idx_awg_path1 :      0
demod_en_acq                     :      False
discretization_threshold_acq     :      0
gain_awg_path0                   :      1
gain_awg_path1                   :      1
integration_length_acq           :      1024
marker_ovr_en                    :      False
marker_ovr_value                 :      0
mixer_corr_gain_ratio            :      1
mixer_corr_phase_offset_degree   :      -0
mod_en_awg                       :      False
nco_freq                         :      0 (Hz)
nco_phase_offs                   :      0 (Degrees)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
phase_rotation_acq               :      0 (Degrees)
sequence                         :      sequence.json
sync_en                          :      True
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
pulsar_sequencer2:
        parameter                       value
--------------------------------------------------------------------------------
channel_map_path0_out0_en        :      False
channel_map_path1_out1_en        :      False
cont_mode_en_awg_path0           :      False
cont_mode_en_awg_path1           :      False
cont_mode_waveform_idx_awg_path0 :      0
cont_mode_waveform_idx_awg_path1 :      0
demod_en_acq                     :      False
discretization_threshold_acq     :      0
gain_awg_path0                   :      1
gain_awg_path1                   :      1
integration_length_acq           :      1024
marker_ovr_en                    :      False
marker_ovr_value                 :      0
mixer_corr_gain_ratio            :      1
mixer_corr_phase_offset_degree   :      -0
mod_en_awg                       :      False
nco_freq                         :      0 (Hz)
nco_phase_offs                   :      0 (Degrees)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
phase_rotation_acq               :      0 (Degrees)
sequence                         :      None
sync_en                          :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
pulsar_sequencer3:
        parameter                       value
--------------------------------------------------------------------------------
channel_map_path0_out0_en        :      False
channel_map_path1_out1_en        :      False
cont_mode_en_awg_path0           :      False
cont_mode_en_awg_path1           :      False
cont_mode_waveform_idx_awg_path0 :      0
cont_mode_waveform_idx_awg_path1 :      0
demod_en_acq                     :      False
discretization_threshold_acq     :      0
gain_awg_path0                   :      1
gain_awg_path1                   :      1
integration_length_acq           :      1024
marker_ovr_en                    :      False
marker_ovr_value                 :      0
mixer_corr_gain_ratio            :      1
mixer_corr_phase_offset_degree   :      -0
mod_en_awg                       :      False
nco_freq                         :      0 (Hz)
nco_phase_offs                   :      0 (Degrees)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
phase_rotation_acq               :      0 (Degrees)
sequence                         :      None
sync_en                          :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
pulsar_sequencer4:
        parameter                       value
--------------------------------------------------------------------------------
channel_map_path0_out0_en        :      False
channel_map_path1_out1_en        :      False
cont_mode_en_awg_path0           :      False
cont_mode_en_awg_path1           :      False
cont_mode_waveform_idx_awg_path0 :      0
cont_mode_waveform_idx_awg_path1 :      0
demod_en_acq                     :      False
discretization_threshold_acq     :      0
gain_awg_path0                   :      1
gain_awg_path1                   :      1
integration_length_acq           :      1024
marker_ovr_en                    :      False
marker_ovr_value                 :      0
mixer_corr_gain_ratio            :      1
mixer_corr_phase_offset_degree   :      -0
mod_en_awg                       :      False
nco_freq                         :      0 (Hz)
nco_phase_offs                   :      0 (Degrees)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
phase_rotation_acq               :      0 (Degrees)
sequence                         :      None
sync_en                          :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
pulsar_sequencer5:
        parameter                       value
--------------------------------------------------------------------------------
channel_map_path0_out0_en        :      False
channel_map_path1_out1_en        :      False
cont_mode_en_awg_path0           :      False
cont_mode_en_awg_path1           :      False
cont_mode_waveform_idx_awg_path0 :      0
cont_mode_waveform_idx_awg_path1 :      0
demod_en_acq                     :      False
discretization_threshold_acq     :      0
gain_awg_path0                   :      1
gain_awg_path1                   :      1
integration_length_acq           :      1024
marker_ovr_en                    :      False
marker_ovr_value                 :      0
mixer_corr_gain_ratio            :      1
mixer_corr_phase_offset_degree   :      -0
mod_en_awg                       :      False
nco_freq                         :      0 (Hz)
nco_phase_offs                   :      0 (Degrees)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
phase_rotation_acq               :      0 (Degrees)
sequence                         :      None
sync_en                          :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0