Runtime net-zero pulse compensation#

Added in version 2026.10.0: See the release notes for details.

In certain experimental quantum computing setups, a single control often has to carry two distinct electrical signals. For example in superconducting qubits it could require sending a steady magnetic flux, while microwave pulses are sent to perform quantum gates. In semiconductor spin qubits, one may send a static voltage to tune the plunger gate electrostatically which confines the quantum dot while sending a modulated signal which drives the qubit for operations. Combining both signals onto one control line also reduces the number of coaxial lines, and with it the thermal load on the fridge. A component which allows for such diplexing is a bias tee.

A bias tee is a three-port diplexer which allows one to send a high-frequency signal through a capacitor (known as the RF port) and separately send a DC signal through an inductor (known as the DC port) on the second line. After passing through the bias tee, these signals get combined at the output of the bias tee.

<sodipodi:namedview id=”namedview1” pagecolor=”#ffffff” bordercolor=”#000000” borderopacity=”0.25” inkscape:showpageshadow=”2” inkscape:pageopacity=”0.0” inkscape:pagecheckerboard=”0” inkscape:deskcolor=”#d1d1d1” inkscape:document-units=”mm” inkscape:zoom=”11.588215” inkscape:cx=”6.7309763” inkscape:cy=”13.763983” inkscape:window-width=”1920” inkscape:window-height=”1094” inkscape:window-x=”886” inkscape:window-y=”2149” inkscape:window-maximized=”1” inkscape:current-layer=”layer1” /> C L RF DC RF + DC Bias tee

<sodipodi:namedview id=”namedview1” pagecolor=”#ffffff” bordercolor=”#459db9ff” borderopacity=”0.25” inkscape:showpageshadow=”2” inkscape:pageopacity=”0.0” inkscape:pagecheckerboard=”0” inkscape:deskcolor=”#d1d1d1” inkscape:document-units=”mm” inkscape:zoom=”8.1941054” inkscape:cx=”9.5190379” inkscape:cy=”4.6984995” inkscape:window-width=”3840” inkscape:window-height=”2054” inkscape:window-x=”-11” inkscape:window-y=”-11” inkscape:window-maximized=”1” inkscape:current-layer=”layer1” showgrid=”false” /> C L Bias tee RF DC RF + DC

Figure 1: Schematic over the bias tee with the different ports (input signals RF, DC and combined output signal RF+DC) residing on the diplexer.

However, the components present in the bias tee (seen in figure 1) distort the signals passing through it. Firstly, it introduces signal distortions due to the capacitor acting as an RC high-pass filter on the incoming pulse at the RF port. Since the capacitor blocks low-frequency components below the cut-off frequency of the bias tee, it may introduce a decay over time based on the pulse which is sent. This decay is proportional to \(e^{-t/RC}\), where \(RC\) is the time constant \(\tau\) of the bias tee, dependent on the cut-off frequency of the bias tee i.e. \(f_c = \frac{1}{2\pi\tau}\).

To counteract the distortions caused by the bias tee, the user may predistort the signal by using the integrated inverse-high pass filter in the output path of the Qubit Control Module (QCM), as seen in the real-time predistortions user guide.

Apart from signal distortions, the bias tee also contributes to charge accumulation over time when unipolar pulses (pulses of only positive or negative amplitude) are applied repeatedly. Whenever unipolar pulses are sent via the bias tee’s RF line, it leaves a residual charge on the capacitor that initially does not fully dissipate between the pulses. When these pulses are repeated this residual charge drifts the bias line of the control pulse positively or negatively depending on the unipolar pulse, e.g. as seen in figure 2 below where positive unipolar pulses result in a negative long-term decay. This drift results in inaccurate qubit control which is undesired for qubit operations and requires counteraction.

<sodipodi:namedview id=”namedview1” pagecolor=”#ffffff” bordercolor=”#000000” borderopacity=”0.25” inkscape:showpageshadow=”2” inkscape:pageopacity=”0.0” inkscape:pagecheckerboard=”0” inkscape:deskcolor=”#d1d1d1” inkscape:document-units=”mm” inkscape:zoom=”22.627417” inkscape:cx=”20.594485” inkscape:cy=”1.3037281” inkscape:window-width=”1920” inkscape:window-height=”1094” inkscape:window-x=”886” inkscape:window-y=”2149” inkscape:window-maximized=”1” inkscape:current-layer=”layer1” /> Bias tee RF signal DC signal RF signal DC signal

<sodipodi:namedview id=”namedview1” pagecolor=”#ffffff” bordercolor=”#459db9ff” borderopacity=”0.25” inkscape:showpageshadow=”2” inkscape:pageopacity=”0.0” inkscape:pagecheckerboard=”0” inkscape:deskcolor=”#d1d1d1” inkscape:document-units=”mm” inkscape:zoom=”22.627417” inkscape:cx=”13.302446” inkscape:cy=”6.2092814” inkscape:window-width=”1920” inkscape:window-height=”1094” inkscape:window-x=”886” inkscape:window-y=”2149” inkscape:window-maximized=”1” inkscape:current-layer=”layer1” /> Bias tee RF signal DC signal RF signal DC signal

Figure 2: Schematic of the control signal before and after passing the bias tee. After passing the bias tee, the signal experiences signal decay and distortions due to the bias tee.

In order to counteract the long-term decay seen in figure 2, a compensating pulse of inverted polarity that spans the equal area is typically scheduled at a non-critical time after a pulse train which needs compensation to cancel out the long-term decay. By executing such a pulse, the total area of the pulse now results in a net-zero area. This net-zero area allows the capacitor to discharge and therefore counteracts the charge accumulation. This keeps the DC baseline at the desired level over long durations for accurate qubit control.

Just as the inverse high-pass filter on the QCM output path counteracts the distortion, this user guide showcases how the charge accumulation can be counteracted through net-zero pulse generation on the QCM.

Net-zero pulse compensation with the QCM#

To facilitate compensating for charge accumulation, the QCM can compute the required inverse pulse at runtime. As it is based on the output generated by the module, net-zero pulse compensation can be used even in combination with advanced feedback.

<sodipodi:namedview id=”namedview1” pagecolor=”#ffffff” bordercolor=”#000000” borderopacity=”0.25” inkscape:showpageshadow=”2” inkscape:pageopacity=”0.0” inkscape:pagecheckerboard=”0” inkscape:deskcolor=”#d1d1d1” inkscape:document-units=”mm” inkscape:zoom=”8.1941056” inkscape:cx=”58.700732” inkscape:cy=”61.568648” inkscape:window-width=”1920” inkscape:window-height=”1094” inkscape:window-x=”886” inkscape:window-y=”2149” inkscape:window-maximized=”1” inkscape:current-layer=”svg1” showgrid=”false” /> Net-zero pulseslew rate Real-time Arbitrary pulse Net-zero pulse amplitude Net-zero pulse compensation Maximum compensationlength Net-zero pulse

<sodipodi:namedview id=”namedview1” pagecolor=”#ffffff” bordercolor=”#000000” borderopacity=”0.25” inkscape:showpageshadow=”2” inkscape:pageopacity=”0.0” inkscape:pagecheckerboard=”0” inkscape:deskcolor=”#d1d1d1” inkscape:document-units=”mm” inkscape:zoom=”5.7941076” inkscape:cx=”49.015313” inkscape:cy=”93.457015” inkscape:window-width=”1920” inkscape:window-height=”1094” inkscape:window-x=”886” inkscape:window-y=”2149” inkscape:window-maximized=”1” inkscape:current-layer=”svg1” /> Real-time Arbitrary pulse Net-zero pulse compensation Maximum compensationlength Net-zero pulse Net-zero pulseslew rate Net-zero pulse amplitude

Figure 3: Functionality of the net-zeroing pulse on an arbitrary pulse sequence.

The net-zero compensation pulse, as shown in figure 3, is generated through a dedicated Q1ASM real-time instruction namely play_netzero maxt, duration. The play_netzero instruction executes a net-zero compensating pulse at runtime based on all pulses played previously on that output.

The play_netzero instruction has two arguments, maxt which is the maximum compensation length of the net-zero pulse and can be set between [0 ns, 4 294 967 295 ns]. The values of maxt can be set as an immediate or set as a register where the value resides. The duration refers to a wait time after starting the compensation pulse, as with any other real-time instruction.

The shape of the net-zero pulse is also determined by two additional parameters, which are set with the Qblox-instruments (QBI) API. As seen in figure 3, these are the net-zero pulse amplitude, and the net-zero pulse slew rate:

  • Net-zero pulse amplitude: The net-zero pulse amplitude specifies the magnitude of the compensating pulse and is set via module.out{x}_net_zero_pulse_amplitude(<amp>), where x specifies the output of the QCM. The net-zero pulse amplitude ranges between [3.0518e-5, 1]. These values correspond to the 16-bit DAC range of the QCM, where the amplitude can be described as \(A = \frac{V}{V_{max}}\). \(V_{max}\) corresponds to the maximum voltage of the QCM i.e. \(V_{max}= 2.5 V\)

  • Net-zero pulse slew rate: The net-zero pulse slew rate specifies the rate at which the pulse ramps to the set net-zero pulse amplitude and is set via module.out{x}_net_zero_pulse_slew_rate(<rate [1/s]>), where x specifies the output of the QCM. The slew rate is there to ensure that no sudden voltage transitions occur when the net-zero pulse is sent to the device under test. The slew rate (expressed in \(1/s\)) is controlled by a 30-bit register governed by the equation \(\frac{A \times 10^9}{4n}\), where \(n\) is a positive integer and \(10^9\) is a scaling factor from nanoseconds to seconds. This produces a functional range [0.93132, 2.5e8], bounded by a maximum value at \(A=1\) and \(n=1\) (\(\frac{10^9}{4}\)) down to a minimum defined by the least significant bit of \(\frac{1 \times 10^9}{2^{30}}\). If a chosen slew rate does not align with the multiples of 4, the net-zero pulse automatically selects the next slower rate.

To be able to use the net-zero pulse, the corresponding FPGA block needs to be enabled. This is done via module.out{x}_net_zero_pulse_en(bool), where x denotes the output of the QCM.

Important

If the module.out{x}_net_zero_pulse_en(False), then the play_netzero instruction will be replaced by wait.

Since the compensation happens in hardware, you may need to query the state of the net-zero block i.e. the block which calculates the net-zero pulse. Therefore, the status of it can be fetched via module.get_out{x}_net_zero_pulse_status(). This retrieves three status flags related to the net-zero block:

  • error_overflow: Returns True if the accumulated area sent via the given output exceeded the maximum trackable area (8.588s at 2.5 V) of the net-zero block. This means that a net-zero pulse will not be generated. Otherwise, returns False.

  • operation_status: Returns True if the net-zero block is still compensating the area. Returns False if the net-zero block is done compensating.

  • warning_re_triggered: Returns True if a net-zero pulse compensation was triggered while the previous compensation was running. Otherwise returns False.

If the net-zero pulse happens to be disabled on the given output i.e. module.out{x}_net_zero_pulse_en(False), the net-zero block will suppress the error_overflow flag which means that this flag will not be updated.

Important

Whenever an error_overflow is triggered i.e. True, the net-zero block is prevented from outputting the net-zero pulse as it exceeds the tolerance level of the net-zero block. To reset the error_overflow flag such that a net-zero pulse can be generated, one has to execute a cluster.reset() followed by reconfiguring the parameters to satisfy the tolerance of the net-zero block such that an overflow is prevented. For more details on how to configure your parameters, see Choice of net-zero pulse parameters below.

Usage of net-zero pulse compensation#

To utilize the feature of net-zero pulse compensation on the QCM, below are guidelines on how to generate the net-zero compensation pulse at runtime.

  1. Configure the parameters of the net-zero pulse

    Start by configuring the QBI parameters of the net-zero pulse amplitude and slew rate on the desired output. Then followed by enabling the net-zero pulse. The reason for configuring these parameters first is mainly that net-zero pulse amplitude and net-zero pulse slew rate are governed by the constraints of the specific use case. This can also be seen in the corresponding net-zero pulse compensation tutorial

    Enabling the net-zero pulse is not sufficient on its own: you must also arm and start a Q1ASM program that contains the play_netzero instruction. If the play_netzero instruction is omitted from the uploaded Q1ASM program, module.out{x}_net_zero_pulse_en(True) will have no effect. Same holds for the net-zero pulse amplitude and net-zero pulse slew rate.

  2. Q1ASM with net-zero pulse

    Create a Q1ASM program which consists of the desired pulse sequence followed by the net-zero pulse which is to compensate for the initial pulse sequence. As an example, a predefined waveform with index 0 in a predefined waveform dictionary will be compensated via the play_netzero instruction to showcase how the instruction is used.

    q1_prog = """
     play 0, 0, 3000         # Play the initial pulse sequence through the predefined waveform, indexed 0 and wait for 3 us.
     play_netzero 4000, 4000 # Execute the net-zero pulse and wait for 4 us. The maximum compensation length for the net-zero pulse is chosen as 4 us.
     stop
    """
    

    Note that the choice of 4 µs in the example above for the maxt and 4 µs for the duration are arbitrarily chosen here. The general rule is to ensure that no further pulse is executed on the channel until maxt has elapsed in real-time. For maxt \(\leq\) 65535 ns you can simply set duration \(\geq\) maxt. For longer maxt, an explanation of how it is achieved will be presented in a section further below (see Long net-zero pulses).

    Note

    The net-zero pulse will utilize the maximum compensation length needed to compensate to make the total area net-zero. Based on the net-zero pulse amplitude and slew rate, if a lesser compensation length was used compared to the specified maximum compensation length, the remainder of the net-zero pulse will be played at 0 V for the remainder of the real-time duration.

Since the net-zero pulse is generated in the digital domain, to tune the outgoing pulse to net-zero in the analog domain, the user may need to consider tuning the 0 V point. This is done by tuning the digital offset via module.out{x}_offset(), which is applied after the RTP block, according to the use case. This is only necessary if precise net-zero needs to be considered.

Important

The net-zero pulse and the IHP filter are intended to work in tandem. Therefore, ensure to specify the same output channel in which the predistortions and the net-zero pulse parameters will be applied such that:

  • Net-zero pulse addresses the long-term decay to prevent charge accumulation which shifts the bias line of the control pulse.

  • IHP filter addresses the signal distortions introduced by the bias tee by predistorting the signal on the desired output path.

Note

The reset_netzero instruction does also reset the net-zero accumulator, similarly to the IHP filter accumulator. Note that the end of the net-zero pulse already ensures that the pulse sequence goes back to the desired offset level at the end. However, if an explicit reset is required it may be scheduled after the play_netzero instruction.

Choice of net-zero pulse parameters#

The choice of the maximum compensation length, slew rate and amplitude together determine the compensating area. Therefore, these parameters can be configured in multiple ways, and in no particular order. A good rule of thumb when configuring the parameters of the net-zero pulse is it should correspond to the orders of magnitude of the pulse sequence which needs compensation i.e. the magnitude of its pulse amplitude and duration, and with an added margin to generate the net-zero pulse. Below are a few things to consider for the choice of parameters:

  • The maximum compensation length should roughly correspond to the product of the pulse amplitude and time of the pulse that is to be compensated, divided by the net-zero pulse amplitude and with an added margin to ensure that the maximum compensation length is achieved for the net-zero pulse.

    • If the maximum compensation length does not generate a net-zero pulse, either due to an insufficient area, then increase the maximum compensation length, maxt such that a net-zero pulse is generated. This indicates that the added margin of maxt was not sufficient enough.

  • Choose the net-zero pulse amplitude which is suitable for the use case since this corresponds to the outputted voltage of the net-zero pulse.

    • If a lower net-zero pulse amplitude was chosen based on the use case, the user can instead increase the maximum compensation length of the play_netzero to accumulate the needed net-zero pulse.

  • The choice of slew rate can be set to any desired rate up to the maximum allowed slew rate which is based on the chosen net-zero pulse amplitude. A faster the slew rate means faster voltage transitions at the device under test. Therefore the choice of slew rate heavily depends on the use case to prevent unwanted voltage transitions.

    • If a slow enough slew rate is chosen, it will not reach the net-zero pulse amplitude in the specified time i.e. time of slew did not reach the net-zero pulse amplitude in half the time of the compensation length that was used by the net-zero block. This means that no compensation pulse will be played. In this case the area continues to accumulate until it becomes large enough such that the condition can be met.

Long net-zero pulses#

Since any real-time instruction is limited up to 65535 ns, one real-time instruction is not able to execute net-zero compensation pulses which require longer maximum compensation length (from 65536 ns up to 4,294,967,295 ns). To achieve these net-zero pulses for long maximum compensation length, so-called long net-zero pulses, the user must prevent the sequencer from issuing the next real-time instruction until maxt has elapsed. To do so, a wait loop which makes up the rest of the duration remaining of the maximum compensation length must be scheduled to ensure that the desired net-zero pulse gets executed before another instruction takes place. An example of how such a long net-zero pulse can be achieved, is seen below. In this case a maximum compensation length, maxt of 1 ms has been chosen:

q1_prog = f"""
  move 999, R0
  ...                           # Specify the long pulse sequence to be compensated here.
  play_netzero {int(1e6)}, 1000 # Execute a net-zero pulse and wait for 1 us. The maximum compensation length is chosen as 1 ms.
  wait_loop:                    # Create a wait loop that waits for 999 us. 
    wait 1000              
    sub R0, 1, R0               # Decrease R0 with 1.
    jnz @wait_loop              # Iterate over the wait loop until R0 is 0.
  ...                           # Continuation of the pulse sequence.
  stop
"""

For more examples regarding the net-zero pulse functionality in the QCM, visit the net-zero pulse compensation tutorial.