See also

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

In-situ Mixer Calibration#

The Cluster RF Modules (QCM-RF and QRM-RF) have integrated IQ mixers that handle both upconversion and downconversion of RF signals. These mixers use a local oscillator (LO) with a frequency of \(\omega_{LO}\). During upconversion, they combine signals from the I and Q paths, which have a frequency of \(\omega_{NCO}\), resulting in an output signal at \(\omega_{LO} + \omega_{NCO}\). However, due to the inherent mathematical imperfections of IQ mixers, the output also includes an unwanted signal at \(\omega_{LO}\) (known as leakage) and another at \(\omega_{LO} - \omega_{NCO}\) (called the undesired sideband).

In this tutorial, we are going to look at ways to suppress the LO leakage and undesired sideband. This process is called mixer calibration.

To run this tutorial optimally, you will need:

  • A QCM-RF or QRM-RF module

  • Spectrum analyzer

  • Two SMA-cables

Setup#

First, we are going to import the required packages.

[1]:
from __future__ import annotations

import json
from typing import TYPE_CHECKING, Callable

from qcodes.instrument import find_or_create_instrument

from qblox_instruments import Cluster, ClusterType

if TYPE_CHECKING:
    from qblox_instruments.qcodes_drivers.module import Module

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

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

Connect to Cluster#

We now make a connection with the Cluster.

[3]:
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,
        }
        if cluster_ip is None
        else None
    ),
)

Get connected modules#

[4]:
def get_connected_modules(cluster: Cluster, filter_fn: Callable | None = None) -> dict[int, Module]:
    def checked_filter_fn(mod: ClusterType) -> bool:
        if filter_fn is not None:
            return filter_fn(mod)
        return True

    return {
        mod.slot_idx: mod for mod in cluster.modules if mod.present() and checked_filter_fn(mod)
    }
[5]:
# QCM-RF modules
modules = get_connected_modules(cluster, lambda mod: not mod.is_qrm_type and mod.is_rf_type)
[6]:
# This uses the module of the correct type with the lowest slot index
module = list(modules.values())[0]

Reset the Cluster#

We reset the Cluster to enter a well-defined state. Note that resetting will clear all stored parameters, so resetting between experiments is usually not desirable.

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

We upload a simple sequence program that keeps playing the DC waveform at 30 percent IF power (waveform amplitude = 0.3). This will be modulated and upconverted within the QRM-RF before outputting.

[8]:
# Sequence program.
seq_prog = """
      wait_sync 4

loop: play    0,0,1200
      jmp     @loop
"""
waveforms = {"dc": {"data": [0.3 for i in range(0, 1200)], "index": 0}}

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

module.sequencer0.sequence("sequence.json")

Let’s configure the sequencer to generate an IF frequency of \(100\) MHz. To get an output frequency of \(5.0\) GHz, we then have to configure the LO to run at \(4.9\) GHz.

[9]:
# Configure the Local oscillator

lo_freq = 4.9e9
nco_freq = 100e6
module.disconnect_outputs()
[10]:
# Configure channel map
module.sequencer0.connect_sequencer("out0")
module.out0_lo_freq(lo_freq)
[11]:
module.sequencer0.marker_ovr_en(True)
module.sequencer0.marker_ovr_value(3)  # Enables output on QRM-RF

# Configure the sequencer
module.sequencer0.mod_en_awg(True)
module.sequencer0.nco_freq(nco_freq)
module.sequencer0.sync_en(True)

module.arm_sequencer(0)
module.start_sequencer(0)

print(module.get_sequencer_status(0))
Status: OKAY, State: RUNNING, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []

Connect the output of the QRM-RF (O1) to the spectrum analyzer. This is what the output looks like on the spectrum analyzer (center frequency at 4.85 GHz with 600 MHz bandwidth). We see three peaks which correspond to (from the right) 5 GHz (desired signal), 4.9 GHz (LO Leakage) and 4.8 GHz (unwanted sideband).

IQ_Mixer_Calib_before.png

We will use the hardware mixer calibration capabilities of the Cluster RF modules to suppress the LO and sideband. This calibration routine is carried out by the internal circuitry of the modules hence requiring no cabling on the output channels.

PLEASE NOTE:

  1. The output switches are turned OFF when the modules are performing calibration and are turned back ON after calibration.

  2. Calibration also interrupts other sequencers within the module. Consequently, please restart the necessary sequencers (arm_sequencer and start_sequencer) that should be operational after completing the calibration process. Sequencers in other modules will continue to run as usual.

  3. We expect a typical suppression of 35 dBc for LO and sideband tones when calibrating a (signal) tone with 30 percent of the maximum IF power. It is possible to achieve more than 55 dBc of spurious free dynamic range (SFDR) when calibrating the mixers manually. Please follow the subsequent section for manually calibrating the mixer.

Suppression of LO Leakage#

The module.out0_in0_lo_cal() or module.out{x}_lo_cal() functions can be called to calibrate the LO leakage as shown below.

[12]:
module.out0_lo_cal()  # calibrate the LO leakage for output 0
[ ]:

Suppression of Undesired Sideband#

Similar to the LO suppression scheme, undesired sideband can also be suppressed using the sequencer.sideband_cal() function.

[13]:
module.sequencer0.sideband_cal()
module.arm_sequencer(0)
module.start_sequencer()

NOTE : If you would like to achieve better SFDR for your experiments, please calibrate the mixer manually.

Stop#

Finally, let’s stop the sequencers if they haven’t already and close the instrument connection. One can also display a detailed snapshot containing the instrument parameters before closing the connection by uncommenting the corresponding lines.

[14]:
# Stop both sequencers.
module.stop_sequencer()

# Print status of both sequencers (should now say it is stopped).
print(module.get_sequencer_status(0))
print(module.get_sequencer_status(1))
print()

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

# Reset the cluster
cluster.reset()
print(cluster.get_system_status())
Status: OKAY, State: STOPPED, Info Flags: FORCED_STOP, Warning Flags: NONE, Error Flags: NONE, Log: []
Status: OKAY, State: STOPPED, Info Flags: NONE, Warning Flags: NONE, Error Flags: NONE, Log: []

Snapshot:
cluster0_module6:
        parameter                    value
--------------------------------------------------------------------------------
marker0_exp0_config           : bypassed
marker0_exp1_config           : bypassed
marker0_exp2_config           : bypassed
marker0_exp3_config           : bypassed
marker0_fir_config            : bypassed
marker0_inv_en                : False
marker1_exp0_config           : bypassed
marker1_exp1_config           : bypassed
marker1_exp2_config           : bypassed
marker1_exp3_config           : bypassed
marker1_fir_config            : bypassed
marker1_inv_en                : False
marker2_exp0_config           : bypassed
marker2_exp1_config           : bypassed
marker2_exp2_config           : bypassed
marker2_exp3_config           : bypassed
marker2_fir_config            : bypassed
marker3_exp0_config           : bypassed
marker3_exp1_config           : bypassed
marker3_exp2_config           : bypassed
marker3_exp3_config           : bypassed
marker3_fir_config            : bypassed
out0_att                      : 0 (dB)
out0_exp0_config              : bypassed
out0_exp1_config              : bypassed
out0_exp2_config              : bypassed
out0_exp3_config              : bypassed
out0_fir_config               : bypassed
out0_latency                  : 0 (s)
out0_lo_en                    : True
out0_lo_freq                  : 4900000000 (Hz)
out0_lo_freq_cal_type_default : off (Hz)
out0_offset_path0             : -4.0319 (mV)
out0_offset_path1             : -3.4269 (mV)
out1_att                      : 0 (dB)
out1_exp0_config              : bypassed
out1_exp1_config              : bypassed
out1_exp2_config              : bypassed
out1_exp3_config              : bypassed
out1_fir_config               : bypassed
out1_latency                  : 0 (s)
out1_lo_en                    : True
out1_lo_freq                  : 6000000000 (Hz)
out1_lo_freq_cal_type_default : off (Hz)
out1_offset_path0             : 7.625 (mV)
out1_offset_path1             : 7.625 (mV)
present                       : True
cluster0_module6_sequencer0:
        parameter                       value
--------------------------------------------------------------------------------
connect_out0                     :      IQ
connect_out1                     :      off
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
gain_awg_path0                   :      1
gain_awg_path1                   :      1
marker_ovr_en                    :      True
marker_ovr_value                 :      3
mixer_corr_gain_ratio            :      0.98678
mixer_corr_phase_offset_degree   :      -19.017
mod_en_awg                       :      True
nco_freq                         :      1e+08 (Hz)
nco_freq_cal_type_default        :      off (Hz)
nco_phase_offs                   :      0 (Degrees)
nco_prop_delay_comp              :      0 (ns)
nco_prop_delay_comp_en           :      False (ns)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
sync_en                          :      True
trigger10_count_threshold        :      1
trigger10_threshold_invert       :      False
trigger11_count_threshold        :      1
trigger11_threshold_invert       :      False
trigger12_count_threshold        :      1
trigger12_threshold_invert       :      False
trigger13_count_threshold        :      1
trigger13_threshold_invert       :      False
trigger14_count_threshold        :      1
trigger14_threshold_invert       :      False
trigger15_count_threshold        :      1
trigger15_threshold_invert       :      False
trigger1_count_threshold         :      1
trigger1_threshold_invert        :      False
trigger2_count_threshold         :      1
trigger2_threshold_invert        :      False
trigger3_count_threshold         :      1
trigger3_threshold_invert        :      False
trigger4_count_threshold         :      1
trigger4_threshold_invert        :      False
trigger5_count_threshold         :      1
trigger5_threshold_invert        :      False
trigger6_count_threshold         :      1
trigger6_threshold_invert        :      False
trigger7_count_threshold         :      1
trigger7_threshold_invert        :      False
trigger8_count_threshold         :      1
trigger8_threshold_invert        :      False
trigger9_count_threshold         :      1
trigger9_threshold_invert        :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
cluster0_module6_sequencer1:
        parameter                       value
--------------------------------------------------------------------------------
connect_out0                     :      off
connect_out1                     :      off
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
gain_awg_path0                   :      1
gain_awg_path1                   :      1
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_freq_cal_type_default        :      off (Hz)
nco_phase_offs                   :      0 (Degrees)
nco_prop_delay_comp              :      0 (ns)
nco_prop_delay_comp_en           :      False (ns)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
sync_en                          :      False
trigger10_count_threshold        :      1
trigger10_threshold_invert       :      False
trigger11_count_threshold        :      1
trigger11_threshold_invert       :      False
trigger12_count_threshold        :      1
trigger12_threshold_invert       :      False
trigger13_count_threshold        :      1
trigger13_threshold_invert       :      False
trigger14_count_threshold        :      1
trigger14_threshold_invert       :      False
trigger15_count_threshold        :      1
trigger15_threshold_invert       :      False
trigger1_count_threshold         :      1
trigger1_threshold_invert        :      False
trigger2_count_threshold         :      1
trigger2_threshold_invert        :      False
trigger3_count_threshold         :      1
trigger3_threshold_invert        :      False
trigger4_count_threshold         :      1
trigger4_threshold_invert        :      False
trigger5_count_threshold         :      1
trigger5_threshold_invert        :      False
trigger6_count_threshold         :      1
trigger6_threshold_invert        :      False
trigger7_count_threshold         :      1
trigger7_threshold_invert        :      False
trigger8_count_threshold         :      1
trigger8_threshold_invert        :      False
trigger9_count_threshold         :      1
trigger9_threshold_invert        :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
cluster0_module6_sequencer2:
        parameter                       value
--------------------------------------------------------------------------------
connect_out0                     :      off
connect_out1                     :      off
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
gain_awg_path0                   :      1
gain_awg_path1                   :      1
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_freq_cal_type_default        :      off (Hz)
nco_phase_offs                   :      0 (Degrees)
nco_prop_delay_comp              :      0 (ns)
nco_prop_delay_comp_en           :      False (ns)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
sync_en                          :      False
trigger10_count_threshold        :      1
trigger10_threshold_invert       :      False
trigger11_count_threshold        :      1
trigger11_threshold_invert       :      False
trigger12_count_threshold        :      1
trigger12_threshold_invert       :      False
trigger13_count_threshold        :      1
trigger13_threshold_invert       :      False
trigger14_count_threshold        :      1
trigger14_threshold_invert       :      False
trigger15_count_threshold        :      1
trigger15_threshold_invert       :      False
trigger1_count_threshold         :      1
trigger1_threshold_invert        :      False
trigger2_count_threshold         :      1
trigger2_threshold_invert        :      False
trigger3_count_threshold         :      1
trigger3_threshold_invert        :      False
trigger4_count_threshold         :      1
trigger4_threshold_invert        :      False
trigger5_count_threshold         :      1
trigger5_threshold_invert        :      False
trigger6_count_threshold         :      1
trigger6_threshold_invert        :      False
trigger7_count_threshold         :      1
trigger7_threshold_invert        :      False
trigger8_count_threshold         :      1
trigger8_threshold_invert        :      False
trigger9_count_threshold         :      1
trigger9_threshold_invert        :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
cluster0_module6_sequencer3:
        parameter                       value
--------------------------------------------------------------------------------
connect_out0                     :      off
connect_out1                     :      off
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
gain_awg_path0                   :      1
gain_awg_path1                   :      1
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_freq_cal_type_default        :      off (Hz)
nco_phase_offs                   :      0 (Degrees)
nco_prop_delay_comp              :      0 (ns)
nco_prop_delay_comp_en           :      False (ns)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
sync_en                          :      False
trigger10_count_threshold        :      1
trigger10_threshold_invert       :      False
trigger11_count_threshold        :      1
trigger11_threshold_invert       :      False
trigger12_count_threshold        :      1
trigger12_threshold_invert       :      False
trigger13_count_threshold        :      1
trigger13_threshold_invert       :      False
trigger14_count_threshold        :      1
trigger14_threshold_invert       :      False
trigger15_count_threshold        :      1
trigger15_threshold_invert       :      False
trigger1_count_threshold         :      1
trigger1_threshold_invert        :      False
trigger2_count_threshold         :      1
trigger2_threshold_invert        :      False
trigger3_count_threshold         :      1
trigger3_threshold_invert        :      False
trigger4_count_threshold         :      1
trigger4_threshold_invert        :      False
trigger5_count_threshold         :      1
trigger5_threshold_invert        :      False
trigger6_count_threshold         :      1
trigger6_threshold_invert        :      False
trigger7_count_threshold         :      1
trigger7_threshold_invert        :      False
trigger8_count_threshold         :      1
trigger8_threshold_invert        :      False
trigger9_count_threshold         :      1
trigger9_threshold_invert        :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
cluster0_module6_sequencer4:
        parameter                       value
--------------------------------------------------------------------------------
connect_out0                     :      off
connect_out1                     :      off
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
gain_awg_path0                   :      1
gain_awg_path1                   :      1
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_freq_cal_type_default        :      off (Hz)
nco_phase_offs                   :      0 (Degrees)
nco_prop_delay_comp              :      0 (ns)
nco_prop_delay_comp_en           :      False (ns)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
sync_en                          :      False
trigger10_count_threshold        :      1
trigger10_threshold_invert       :      False
trigger11_count_threshold        :      1
trigger11_threshold_invert       :      False
trigger12_count_threshold        :      1
trigger12_threshold_invert       :      False
trigger13_count_threshold        :      1
trigger13_threshold_invert       :      False
trigger14_count_threshold        :      1
trigger14_threshold_invert       :      False
trigger15_count_threshold        :      1
trigger15_threshold_invert       :      False
trigger1_count_threshold         :      1
trigger1_threshold_invert        :      False
trigger2_count_threshold         :      1
trigger2_threshold_invert        :      False
trigger3_count_threshold         :      1
trigger3_threshold_invert        :      False
trigger4_count_threshold         :      1
trigger4_threshold_invert        :      False
trigger5_count_threshold         :      1
trigger5_threshold_invert        :      False
trigger6_count_threshold         :      1
trigger6_threshold_invert        :      False
trigger7_count_threshold         :      1
trigger7_threshold_invert        :      False
trigger8_count_threshold         :      1
trigger8_threshold_invert        :      False
trigger9_count_threshold         :      1
trigger9_threshold_invert        :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
cluster0_module6_sequencer5:
        parameter                       value
--------------------------------------------------------------------------------
connect_out0                     :      off
connect_out1                     :      off
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
gain_awg_path0                   :      1
gain_awg_path1                   :      1
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_freq_cal_type_default        :      off (Hz)
nco_phase_offs                   :      0 (Degrees)
nco_prop_delay_comp              :      0 (ns)
nco_prop_delay_comp_en           :      False (ns)
offset_awg_path0                 :      0
offset_awg_path1                 :      0
sync_en                          :      False
trigger10_count_threshold        :      1
trigger10_threshold_invert       :      False
trigger11_count_threshold        :      1
trigger11_threshold_invert       :      False
trigger12_count_threshold        :      1
trigger12_threshold_invert       :      False
trigger13_count_threshold        :      1
trigger13_threshold_invert       :      False
trigger14_count_threshold        :      1
trigger14_threshold_invert       :      False
trigger15_count_threshold        :      1
trigger15_threshold_invert       :      False
trigger1_count_threshold         :      1
trigger1_threshold_invert        :      False
trigger2_count_threshold         :      1
trigger2_threshold_invert        :      False
trigger3_count_threshold         :      1
trigger3_threshold_invert        :      False
trigger4_count_threshold         :      1
trigger4_threshold_invert        :      False
trigger5_count_threshold         :      1
trigger5_threshold_invert        :      False
trigger6_count_threshold         :      1
trigger6_threshold_invert        :      False
trigger7_count_threshold         :      1
trigger7_threshold_invert        :      False
trigger8_count_threshold         :      1
trigger8_threshold_invert        :      False
trigger9_count_threshold         :      1
trigger9_threshold_invert        :      False
upsample_rate_awg_path0          :      0
upsample_rate_awg_path1          :      0
Status: OKAY, Flags: NONE, Slot flags: NONE