See also

A Jupyter notebook version of this tutorial can be downloaded here.

Inverse high-pass (IHP) filter#

This tutorial demonstrates the use of the IHP filter pre distortions available on a Qblox QCM. The tutorial showcases:

  • Generate a pulse sequence on the QCM.

  • Enable the filter which pre distorts the pulse sequence.

  • Introduce a bias tee in the setup.

To revisit the information about the feature, please go through the user guide on Real Time Predistortions.

[1]:
# ## Setup
# First, we are going to import the required packages

from __future__ import annotations
[2]:
from __future__ import annotations

from qcodes.instrument import find_or_create_instrument

from qblox_instruments import Cluster, ClusterType

Scan For Clusters#

We scan for the available devices connected via ethernet using the Plug & Play functionality of the Qblox Instruments package (see Plug & Play for more info).

!qblox-pnp list

[3]:
cluster_ip = "10.10.200.42"
cluster_name = "cluster0"

Connect to Cluster#

We now make a connection with the Cluster.

[4]:
cluster: Cluster = find_or_create_instrument(
    Cluster,
    recreate=True,
    name=cluster_name,
    identifier=cluster_ip,
    dummy_cfg=(
        {
            2: ClusterType.CLUSTER_QCM,
            4: ClusterType.CLUSTER_QRM,
            6: ClusterType.CLUSTER_QCM_RF,
            8: ClusterType.CLUSTER_QRM_RF,
            10: ClusterType.CLUSTER_QTM,
            12: ClusterType.CLUSTER_QRC,
            16: ClusterType.CLUSTER_QSM,
        }
        if cluster_ip is None
        else None
    ),
)

cluster.reset()
print(cluster.get_system_status())
Status: OKAY, Flags: NONE, Slot flags: NONE

Get connected modules#

[5]:
# QCM baseband modules
modules = cluster.get_connected_modules(lambda mod: mod.is_qcm_type and not mod.is_rf_type)
# This uses the module of the correct type with the lowest slot index
module = list(modules.values())[0]

Upload sequence#

The sequence on the QCM will play a balanced pulse through dynamic voltage offsets. At the end of the pulse, the reset_netzero command will maintain the bias level of the pulse, depending on when it is scheduled.

Important: Since the reset_netzero instruction resets the accumulated bias of the IHP filter to 0, it is strongly advised to schedule the instruction at the end of the program to ensure reproducibility between runs. In the case where the expected pulse sequence is net zero in area (as in this tutorial), it is also recommended to schedule the reset_netzero instruction after the pulse block if multiple iterations of the block is executed to ensure that the voltage is at 0 V before the next iteration starts. If a reset_netzero is omitted from the pulse sequence while the IHP filter is active, it may cause output overflow given that the pulse sequence is unipolar.

[6]:
seq_prog = """
    wait_sync 4
    set_awg_offs 15000, 15000     # Set a positive offset. In this case less than half of the total dynamic range is chosen.
    upd_param 1000                # Execute the offset and wait for 1 us.
    set_awg_offs -15000, -15000   # Set a negative offset. Same magnitude as the previous offset.
    upd_param 1000                # Execute the offset and wait for 1 us.
    set_awg_offs 0, 0             # Set the offset back to 0.
    reset_netzero                 # Add the reset netzero command after the pulse.
    upd_param 1000                # Execute the reset netzero command and offset, wait for 1 us.
stop
"""
[7]:
# Add sequence to single dictionary
sequence = {
    "waveforms": {},
    "weights": {},
    "acquisitions": {},
    "program": seq_prog,
}

The sequence which has been defined above will be uploaded to the first sequencer, sequencer0 and connected to out0_1. This means that our signal will be executed on QCM O1 and QCM O2 on the QCM.

[8]:
module.sequencer0.sequence(sequence)  # Upload sequence to sequencer 0
module.disconnect_outputs()  # Disconnect outputs to reconfigure the channel mapping between sequencer and output.
module.sequencer0.connect_sequencer("out0_1")  # Connect sequencer 0 to both output 0 and output 1.

Now, we may arm and start the sequencer to observe the outputs QCM O1 and QCM O2 on an oscilloscope. Ensure that the oscilloscope is triggering on one of the channels in single mode to observe the signal.

[9]:
# Arm and start the sequencer
module.arm_sequencer(0)
module.start_sequencer()

# Print status of the sequencer
print(module.get_sequencer_status(0))
Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []

The following figure is the output of the executed sequence.

drawing

Figure 1: Signal output from two QCM outputs. QCM O1 (yellow signal) and QCM O2 (green signal).

Note: As seen in Figure 1, there is undershoot present in the signal generated. To correct for these distortions, you may utilize the existing filters in the real-time predistortions block. For more information on how to configure for these distortions, visit Real-time predistortions documentation.

Apply the IHP filter#

Each output of the QCM module is configurable with the inverse high-pass filter. This filter can be in one of three states in the QCM:

  1. enabled: The filter is enabled. Note that the playback is delayed with 32 ns from the IHP filter and 60 ns of activating any filter in the filter path.

  2. bypassed: The filter is disabled.

  3. delay_comp: The filter is disabled but is delayed as if it were enabled, that is 92 ns.

In a QRM, QCM-RF, QRM-RF or QRC there are no filters, and so the enabled mode doesn’t exist.

Configure the IHP filter#

With the sequence being connected to both QCM O1 and QCM O2, we will enable the IHP filter only on QCM O1 and compare the effect of the filter against the non pre-distorted signal on QCM O2. Since the signal is going through the filter on QCM O1 we will add a delay compensation for the signal on QCM O2 to ensure that the signals are arriving at the same time. Apart from activating the IHP filter, a time constant is also needed which shall match the cutoff frequency of the high-pass filter it passes through. In this segment of the tutorial, the time constant will be set to 1 us.

[10]:
module.out0_ihp_tau_constant(1e-6)  # Set the time constant (1 us) of the filter
module.out0_ihp_config("enabled")  # Enable the filter on QCM O1.
module.out1_ihp_config("delay_comp")  # Enable delay compensation on QCM O2.
[11]:
# Arm and start the sequencer.
module.arm_sequencer(0)
module.start_sequencer()

# Print status of the sequencer
print(module.get_sequencer_status(0))
Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []

Executing the sequence with the filter enabled on QCM O1 and adding a delay compensation on QCM O2, gives the following result on the oscilloscope.

drawing

Figure 2: IHP filter with 1 us time constant enabled on QCM O1 (yellow signal). Delay compensation activated on QCM O2 (green signal).

To observe the delay of the filter, one can change the IHP filter configuration of QCM O2 to module.out1_ihp_config("bypassed"). With bypassed specified on QCM O2, it will result in the signal rising 92 ns before the signal coming from QCM O1.

Setup including a bias tee#

Now, we will introduce a bias tee in the setup. The bias tee is a diplexer which combines an RF signal (via a capacitor) with a DC signal (via an inductor) such that a combined RF and DC signal is generated at the output of the bias tee. This implies that the bias tee allows for high-frequency components along with DC voltage to pass through, without interfering with each other. However, this also means that the bias tee introduces distortions to the signal as it acts as a filter. These distortions are caused by the cutoff frequency of the bias tee. With the IHP filter, this part of the tutorial will showcase how such distortions caused by a bias tee can be corrected for.

To our setup, we will now connect the QCM O1 to the input of the RF line of our bias tee. Then, the combined RF and DC line is connected to the oscilloscope. The DC line will be kept open. The connection from QCM O2 to the oscilloscope remains unchanged.

Before configuring the IHP filter, we will first observe the distortions which are introduced by the bias tee on the oscilloscope. Since the filter was previously enabled on QCM O1 and delay compensated on QCM O2, we will configure both channels to bypass the filter to see the distortions caused by the bias tee on QCM O1.

[12]:
module.out0_ihp_config("bypassed")  # Bypassing the IHP filter for out0
module.out1_ihp_config("bypassed")  # Bypassing the IHP filter for out1
[13]:
module.arm_sequencer(0)
module.start_sequencer()

# Print status of the sequencer
print(module.get_sequencer_status(0))
Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []

drawing

Figure 3: Distortions (circled in red) from a bias tee connected to QCM O1 (yellow signal). No distortions observed on QCM O2 (green signal).

As seen in Figure 3, without the IHP filter activated on QCM O1, that output remains distorted due to the line going through a bias tee. The signal from QCM O2 remains unchanged, since there is no bias tee connected to that line.

Now, we can configure the IHP filter to correct for these distortions. Since the bias tee introduces distortions based on its cut-off frequency, the time constant tau will be chosen to match that frequency. In this case, a ZFBT-6GW+ Mini-Circuits bias tee was used and therefore, the time constant tau was chosen as 11.5 us.

[14]:
# Configure the IHP filter
module.out0_ihp_tau_constant(11.5e-6)
module.out0_ihp_config("enabled")
module.out1_ihp_config("delay_comp")
[15]:
# Arm and start the sequencer
module.arm_sequencer(0)
module.start_sequencer()

# Print status of the sequencer
print(module.get_sequencer_status(0))
Status: OKAY, State: STOPPED, Exit Code: 0, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []

By enabling the IHP filter and setting the time constant to match the cut-off frequency of the chosen bias tee on QCM O1, we obtain the following on the oscilloscope.

drawing

Figure 4: IHP filter activated on QCM O1 (yellow signal) and delay compensated on QCM O2 (green signal).

As seen in Figure 4, the signal from QCM O1 has now been corrected if we compare the highlighted area (circled in red) to the signal in Figure 3 in which the filter was deactivated. By comparing the two scenarios, we can see the effect of the IHP filter whenever there is a high-pass filter present in the setup and how the IHP filter may correct for the introduced distortions.