Octave¶
Introduction¶
The octave is a complementary solution for enhancing the OPX capabilities by up- and down-converting its analog outputs, creating a seamless RF front-end OPX. With the octave, one can have up to five RF outputs and two combined RF inputs operating in a frequency band of 2GHz to 18GHz. The following page serves as a user manual for the octave. For port specifications and block diagram, see the octave hardware section
See octave front panel for more information.
Getting Started¶
In order to work with the octave one needs to configure the device and set the connectivity between the OPX and the octave.
Note
Install the latest QUA
package by typing pip install -U qm-qua
.
Initiate Octave Config¶
Create a new instance of QmOctaveConfig
and add the specific device to the instance.
from qm.octave import QmOctaveConfig
octave_config = QmOctaveConfig()
octave_config.add_device_info(octave_name, octave_ip, octave_port)
octave_name
is the name of the specific octave device as defined by the user. For example octave_name = 'my_octave'.octave_ip
needs to be specified.octave_port
needs to be specified.
Info
When using more than one octave in the cluster, one needs to use add_device_info()
for each octave.
Create File for Calibration Parameters¶
By using the set_calibration_db()
command
calibraion_db.json
is created at the given path.
This file will be used for saving the calibration parameters.
See Calibration for more information.
Tip
- One can save
calibraion_db.json
file at the current working directory by settingpath=os.getcwd()
- Different users of the same octave can have different calibration databases.
- Multiple users can share the same calibration database file by either using the same path for it or simply sharing it with each other after calibration.
Open Quantum Machine Manager¶
When opening a qmm
, one needs to pass the octave configuration instance.
Set the OPX-Octave Connectivity¶
It is needed to set the connectivity between the OPX's analog outputs and the octave's I,Q ports. (See octave front panel for more information)
The default connectivity is:
Note
The default connectivity is related to the connections between the OPX's analog outputs and the Octave's IQ pairs.
This is done by using the set_opx_octave_mapping()
command
octave_name
is the name of the specific octave device as defined by the user. For example octave_name = 'my_octave'.controller_name
is the name of the OPX device that is connected to this specific octave. For example controller_name = 'con1'
If the user wants to set a different port mapping, there is a need to specify the port mapping and use the add_opx_octave_port_mapping()
command
For example, if one wants to connect
- Analog Output 1 -> I2
- Analog Output 2 -> Q2
- Analog Output 3 -> I4
- Analog Output 4 -> Q4
it can be done by:
portmap = {
('con1', 1) : ('octave1', 'I2'),
('con1', 2) : ('octave1', 'Q2'),
('con1', 3) : ('octave1', 'I4'),
('con1', 4) : ('octave1', 'Q4'),
}
octave_config.set_opx_octave_mapping(portmap)
Clock Settings¶
The user can work with octave's internal clock or input an external clock at the octave's back panel.
Setting the clock is done by the set_clock()
command.
Internal Clock¶
If one wants to work with internal clock, use the command
from qm.octave.octave_manager import ClockMode
qm.octave.set_clock(octave_name, clock_mode=ClockMode.Internal)
Note
octave_name
is the name of the specific octave device as defined by the user. For example octave_name = 'my_octave'.
External Clock¶
When working with External clock, the user needs to specify the clock frequency, which can be either 10MHz, 100MHz or 1GHz.
For example, in order to define a 10MHz external clock use the command
from qm.octave.octave_manager import ClockMode
qm.octave.set_clock(octave_name, clock_mode=ClockMode.External_10MHz)
Note
octave_name
is the name of the specific octave device as defined by the user. For example octave_name = 'my_octave'.
Important
The output clock of the octave is always 1GHz.
Up Conversion Chain¶
There are five up converter modules in the octave. Each one of them is associated with an I,Q pair. For example, I1
Q1
pair is associated with up converter number 1 and the RF signal will be outputted from RF1
port. (See octave front panel)
Moreover, there are four internal synthesizers inside the octave. Three of them are used for up converting the signal (as can be seen in the octave block diagram), while the fourth one is used for calibration purposes.
Furthermore, it is possible to use an external LO instead of the internal one. This can be used, for example, if one wants to have five different LO frequencies simultaneously.
In order to set the up-conversion chain, one needs to configure the following:
LO Signal¶
Setting the LO Source is done by the set_lo_source()
command.
Internal LO¶
Note
When using an internal LO, one needs to set_lo_frequency()
as well.
External LO¶
When working with External LO, the user needs to specify the specific LO port on the octave's back panel.
For example, if one wants to input an external LO to the first up converting module, use the command:
Warning
LO source number must correspond to the up converter module number.
Note
Due to the internal connectivity between the modules, the following requirements should be considered when using external LO:
-
If both up-converters 2 and 3 are being utilized, with one using an internal LO and the other using an external LO, the configuration must be set up as follows: up-converter 2 will utilize the external LO, and up-converter 3 will use the internal LO.
-
If both up-converters 4 and 5 are being utilized, with one using an internal LO and the other using an external LO, the configuration must be set up as follows: up-converter 4 will utilize the external LO, and up-converter 5 will use the internal LO.
Output Gain¶
There is a variable attenuator and amplifier inside each up converter module. That means that one can change the gain of the outputted signal.
This is done using the set_rf_output_gain()
command
Note
gain_dB should be in the range \([-20:0.5:20]dB\).
Info
When changing the LO frequency, either the external LO or the internal one, there is a need to run this command again in order get the desired gain.
i.e. for internal LO,
qm.octave.set_lo_source(element, OctaveLOSource.Internal)
qm.octave.set_lo_frequency(element, LO)
qm.octave.set_rf_output_gain(element, gain_dB)
and for external LO
Output Mode¶
At the output of each up converter module, a fast switch sets the output mode. The user can change the mode of the fast switch using the command set_rf_output_mode()
to one of the following:
on
- Output is always onoff
- Output is always offtrig_normal
- The output will play when rising edge is detected in the octave's digital port.trig_inverse
- The output will play when falling edge is detected in the octave's digital port.
For example, if one wants to output a signal only when a rising edge is detected in the octave's digital port, use the following command
Warning
Don't forget to connect the OPX's digital output to the relevant Trig port (as can be seen in the octave front panel). Moreover, it's important to calibrate the digital output's delay
and buffer
parameters.
Calibrating the Digital Pulse¶
There is an intrinsic delay between the time that the digital pulse arrives at the octave and the time that the RF pulse outputs from the octave. This time depends on the path of the digital signal inside the octave, computation time, and the time it takes for the digital switch to open. Hence, it's important to calibrate the delay
and buffer
parameters. The suggested parameters are: delay
= 87 ns, buffer
= 15 ns.
Note
These parameters may vary between different ports due to small intrinsic cable differences inside the octave and different external cables between the octave and the OPX.
Down Conversion Chain¶
There are two down converters inside the octave.
In order to down convert the signal, one needs to specify two things:
-
RFin
port using the commandset_qua_element_octave_rf_in_port()
For example, if using
RF1in
port: -
LO signal using the command
set_downconversion()
Internal LO¶
External LO¶
Note
After the down converter module, the signal passes through an IF module. The IF module mode can be changed using the command set_downconversion()
with three possible modes:
-
direct
- the signal bypasses the IF module (default) -
envelope
- the signal passes through an envelope detector -
mixer
- the signal passes through a low frequency mixer
Info
After the down converter modules, I1
and I2
are combined, pass through a bias Tee and outputted from IFOUT1
. While Q1
and Q2
are combined, pass through a bias Tee and outputted from IFOUT2
. The lower IF frequency cutoff after downconversion is around 10 MHz.
Warning
In order to use down converter 2 one needs to input an LO signal to the Dmd2LO port on the octave's back panel. It is possible to loop back the signal from the relevant Synth on the octave's back panel.
Automatic Calibration¶
It is possible to run an automatic calibration in order to calibrate the IQ mixers inside each up converter module. To do so:
- Connect the OPX's analog outputs to the octave's I,Q pairs.
- Connect the OPX's analog inputs to the
IFOUT1
,IFOUT2
octave's ports.
Then calibrate using the calibrate_element()
command:
Note
(LO, IF)
is theLO
andIF
frequency as written in themixer
section associated with thiselement
.- The user can provide a list of pairs of
(LO, IF)
as long as all theLOs
are the same for one calibration command.
Info
- When running this command, the OPX sends pulses through the analog outputs to the octave. Those pulses gets up converted and are sent internally to the down converters modules. Then, the down converted signal is sent to the OPX through the
IFOUT1
,IFOUT2
ports. The calculation is done on the OPX's FPGA and the calibrated parameters and saved in thecalibration_db.json
file. - By default, this command closes all running quantum machines. Hence, one needs to open a quantum machine after calibration.
- When the user opens a quantum machine, the calibrated parameters are taken automatically from the
calibraion_db.json
file.
Example¶
In the following example you can see how to use the octave in order to up-convert and down-convert the resonator element.
The relevant parts in the configuration are
"resonator": {
"mixInputs": {
"I": ("con1", 1),
"Q": ("con1", 2),
"lo_frequency": resonator_LO,
"mixer": "octave_my_octave_1",
},
"outputs": {
"out1": ("con1", 1),
"out2": ("con1", 2),
},
...
}
...
"mixers": {
"octave_my_octave_1": [
{
"intermediate_frequency": resonator_IF,
"lo_frequency": resonator_LO,
"correction": (1, 0, 0, 1),
}
],
},
Info
The name of the mixer that is used within an element that is associated to the octave in the configuration should be "octave_octave_name_RFportnumber"
.
octave_name
is the name of the specific octave device as defined by the user.RFportnumber
can be 1 to 5.- An example for the mixer name
"octave_my_octave_1"
.
Then the API commands are
from qm.octave.octave_manager import ClockMode
octave_config = QmOctaveConfig()
octave_config.set_calibration_db(os.getcwd())
octave_config.add_device_info("my_octave", octave_ip, octave_port)
octave_config.set_opx_octave_mapping([("con1", "my_octave")])
qmm = QuantumMachinesManager(host=opx_ip, port=opx_port, octave=octave_config)
qm = qmm.open_qm(config)
# clock settings #
qm.octave.set_clock("my_octave", clock_mode=ClockMode.Internal)
# up-conversion chain #
qm.octave.set_lo_source("resonator", OctaveLOSource.Internal)
qm.octave.set_lo_frequency("resonator", resonator_LO)
qm.octave.set_rf_output_gain("resonator", 0)
qm.octave.set_rf_output_mode("resonator", RFOutputMode.on)
# down-conversion chain #
qm.octave.set_qua_element_octave_rf_in_port("resonator", "my_octave", 1)
qm.octave.set_downconversion("resonator", lo_source=RFInputLOSource.Internal)
# automatic calibration #
qm.octave.calibrate_element("resonator", [(resonator_LO, resonator_IF)])
qm = qmm.open_qm(config)
Note
The octave settings in the case are:
- Using an internal clock
- Using the default port mapping
- The up-converter is using an internal LO synthesizer, with gain 0 and output mode "on"
- The down converter chain is using an internal LO synthesizer and RF1in port
Batch Octave Commands for Quick Setting¶
Since qm-qua
version 1.1 it is possible to send many octave configuration commands in one message for a faster octave configuration. This is done using what we call Batch Mode
.
In order to use it one must add [start_batch_mode()
][qm.octave.qm_octave.QmOctave.start_batch_mode] before writing all the configuration commands and after the commands add a new line with
[end_batch_mode()
][qm.octave.qm_octave.QmOctave.end_batch_mode]. for example:
qm.octave.start_batch_mode()
qm.octave.set_lo_source("resonator", OctaveLOSource.Internal)
qm.octave.set_lo_frequency("resonator", resonator_LO)
qm.octave.set_rf_output_gain("resonator", 0)
qm.octave.set_rf_output_mode("resonator", RFOutputMode.on)
qm.octave.set_qua_element_octave_rf_in_port("resonator", "my_octave", 1)
qm.octave.set_downconversion("resonator", lo_source=RFInputLOSource.Internal)
qm.octave.end_batch_mode()
with qm.octave.batch_mode():
qm.octave.set_lo_source("resonator", OctaveLOSource.Internal)
qm.octave.set_lo_frequency("resonator", resonator_LO)
qm.octave.set_rf_output_gain("resonator", 0)
qm.octave.set_rf_output_mode("resonator", RFOutputMode.on)
qm.octave.set_qua_element_octave_rf_in_port("resonator", "my_octave", 1)
qm.octave.set_downconversion("resonator", lo_source=RFInputLOSource.Internal)
Examples and Usage Tutorials¶
Take a look at the octave tutorial in our GitHub repository, where you can find a template for integrating the octave within your experiments!