Voltage offsets and long waveforms#

In this section we introduce how to use voltage offsets and build up long waveforms using Qblox Cluster modules.

Voltage offsets#

Qblox modules can set and hold a voltage on their outputs using the VoltageOffset operation. The operation supports real and complex outputs, and it has effectively zero duration, meaning it takes effect at the exact moment you schedule it, and you can schedule other operations simultaneously. It can be used as follows:

 1from quantify_scheduler.backends.qblox.operations import VoltageOffset
 2
 3
 4voltage_offset_real = VoltageOffset(
 5    offset_path_I=0.5,
 6    offset_path_Q=0.0,
 7    port="q3:mw",
 8    clock="q3.01",
 9)
10
11voltage_offset_complex = VoltageOffset(
12    offset_path_I=0.5,
13    offset_path_Q=0.5,
14    port="q3:mw",
15    clock="q3.01",
16)
17
18sched = Schedule("offset_sched")
19sched.add_resource(ClockResource(name="q3.01", freq=9e9))
20
21ref_op = sched.add(voltage_offset_real)
22
23# It's possible to schedule a voltage offset simultaneously with a pulse
24sched.add(voltage_offset_complex, ref_op=ref_op, rel_time=1e-7)
25sched.add(SquarePulse(amp=1, duration=1e-7, port="q3:mw", clock="q3.01"))
26
27compiler = SerialCompiler(name="compiler")
28compiled_sched = compiler.compile(
29    schedule=sched, config=quantum_device.generate_compilation_config()
30)

Note that the offset will remain on the output until the schedule execution ends, or until a new voltage offset is set.

Important

While voltage offsets have effectively zero duration, the hardware does require 4 ns of “buffer” time after they are scheduled. That is, voltage offsets cannot be scheduled right at the end of the schedule, or at the end of a Control flow block (e.g., a loop).

If you do want a voltage offset at those moments, it is necessary to leave some time (at least 4 ns) by inserting an IdlePulse.

For example, the following is not possible:

 1from quantify_scheduler.operations.pulse_library import IdlePulse
 2
 3sched = Schedule("offset_sched")
 4sched.add_resource(ClockResource(name="q3.01", freq=9e9))
 5
 6sched.add(
 7    VoltageOffset(offset_path_I=0.5, offset_path_Q=0.0, port="q3:mw", clock="q3.01")
 8)
 9sched.add(SquarePulse(amp=1, duration=1e-7, port="q3:mw", clock="q3.01"))
10sched.add(
11    VoltageOffset(offset_path_I=0.0, offset_path_Q=0.0, port="q3:mw", clock="q3.01")
12)
13
14compiler = SerialCompiler(name="compiler")
15try:
16    compiled_sched = compiler.compile(
17        schedule=sched, config=quantum_device.generate_compilation_config()
18    )
19except RuntimeError as err:
20    print(err)
VoltageOffset operation Pulse "VoltageOffset" (t0=1e-07, duration=0.0) with start time 1e-07 cannot be scheduled at the very end of a Schedule. The Schedule can be extended by adding an IdlePulse operation with a duration of at least 4 ns, or the VoltageOffset can be replaced by another operation.

Instead, some time should be left at the end like so:

 1sched = Schedule("offset_sched")
 2sched.add_resource(ClockResource(name="q3.01", freq=9e9))
 3
 4sched.add(
 5    VoltageOffset(offset_path_I=0.5, offset_path_Q=0.0, port="q3:mw", clock="q3.01")
 6)
 7sched.add(SquarePulse(amp=1, duration=1e-7, port="q3:mw", clock="q3.01"))
 8sched.add(
 9    VoltageOffset(offset_path_I=0.0, offset_path_Q=0.0, port="q3:mw", clock="q3.01")
10)
11sched.add(IdlePulse(4e-9))
12
13compiler = SerialCompiler(name="compiler")
14compiled_sched = compiler.compile(
15    schedule=sched, config=quantum_device.generate_compilation_config()
16)

Long waveforms via StitchedPulse#

The sequencers in Qblox modules have a waveform sample limit of MAX_SAMPLE_SIZE_WAVEFORMS. Trying to play many (long) waveforms might cause you to exceed this limit. For certain waveforms, however, it is possible to use the available memory more efficiently. This section explains how to do this with the StitchedPulse.

Factory functions#

For convenience, quantify-scheduler provides helper functions for the square (long_square_pulse()), ramp (long_ramp_pulse()) and staircase (staircase_pulse()) waveforms for when they become too long to fit into the waveform memory of the hardware.

from quantify_scheduler.backends.qblox.operations import (
    long_ramp_pulse,
    long_square_pulse,
    staircase_pulse,
)


sched = Schedule("Basic long pulses")
sched.add(
    long_square_pulse(
        amp=0.5,
        duration=10e-6,
        port="q0:fl",
        clock=BasebandClockResource.IDENTITY,
    ),
)
sched.add(
    long_ramp_pulse(
        amp=1.0,
        duration=10e-6,
        port="q0:fl",
        offset=-0.5,
        clock=BasebandClockResource.IDENTITY,
    ),
    rel_time=5e-7,
)
sched.add(
    staircase_pulse(
        start_amp=-0.5,
        final_amp=0.5,
        num_steps=20,
        duration=10e-6,
        port="q0:fl",
        clock=BasebandClockResource.IDENTITY,
    ),
    rel_time=5e-7,
)

quantum_device = QuantumDevice("quantum_device")
device_compiler = SerialCompiler("Device compiler", quantum_device)

comp_sched = device_compiler.compile(sched)
comp_sched.plot_pulse_diagram(plot_backend="plotly")