Q1 Sequence Processor#

Note

On this page, QRM, QCM, QRM_RF, QCM_RF refer to instances of Module of the respective module type. QCoDeS Parameters in this page link to the Cluster QRM module, but are typically also available for other module types.

Sequencer parameters concerning acquisition are only available on QRM type modules.

Description#

The Q1 sequencer is the heart of the Quantum Control/Readout Modules (QRM/QCM) at Qblox. The sequencers are split into the sequence processor, arbitrary waveform generation (AWG), and acquisition paths as shown in the figures below. Each sequence processor controls two AWG paths and, in the case of QRM modules, two acquisition paths. The processor itself provides a ubiquitous interface across all modules for the end user. Each sequencer processor is, in turn, split into a classical and real-time pipeline. The classical pipeline is responsible for any classical instructions related to program flow or arithmetic and the real-time pipeline is responsible for real-time instructions that are used to create the experiment timeline.

The simplified architecture of the Q1 sequencers is presented below:

QCM sequencer with AWG path.

QCM sequencer with AWG paths.#

QRM sequencer.

QRM sequencer with AWG and acquisition paths.#

Applications#

The Q1 sequence processor provides a ubiquitous platform across qblox’s instruments for developing low-level control and measurement sequences. The Python interface allows for fast development of experimental setups while the underlying Q1ASM programs grant access to precise and flexible control over the instruments.

Programming control sequences#

For QCM/QCM-RF modules the Q1 sequence processor is used to develop control sequences to program the modules for qubit control. For more information on the applications of Quantum Control Modules that utilize the Q1 Sequence Processor, please refer to QCM applications and QCM-RF applications.

Programming readout sequences#

For QRM/QRM-RF modules the Q1 sequence processor is used to develop readout (AWG and acquisition) sequences to program the modules for qubit measurement. For more information on the applications of Quantum Readout Modules that utilize the Q1 Sequence Processor, please refer to QRM applications and QRM-RF applications.

Features#

Sequencer Layout#

Block diagram of Q1 Sequencer

1. Instruction Memory

2. Data Memory

3. Classical Core

4. Latches

5. Buffer

6. Real-time core

1. Instruction Memory#

Memory storing the instructions of the Q1ASM program to be executed. Commands are either classical or real-time in nature, defining whether they are executed by the classical core or passed to the buffer to be executed by the real-time core. For QCM modules the maximum number of instructions per program is 16384 and for QRM modules the maximum number of instructions per program is 12288.

2. Data Memory#

Data memory is a set of registers that are used to store data during the execution of a Q1ASM program. These registers are referenced as R# from 0 to 63.

3. Classical Core#

The classical core is the computing block that executes all classical instructions in the Q1ASM program. For a list of all classical commands available in Q1ASM refer to Instructions.

4. Latches#

Updates to playback parameters including NCO frequency, phase, amplitude, and offset are latched and await any of the play, acquire or update parameter commands, before the update to the parameter is physically set. For a break down on all Q1ASM commands that are latched, refer to Instructions.

5. Buffer#

The buffer stores the real-time commands ready for execution by the real-time core. This buffer holds up to 32 real-time commands at a time.

6. Real-time core#

The real-time core is the processing unit that executes all real-time commands. The real-time core is connected to both the external trigger and SYNQ protocols, which allow real-time cores to be synchronized across modules and clusters using the wait_sync Q1ASM command. For a breakdown of all real-time commands please refer to Instructions.

AWG Path#

Block diagram of awg path of Q1 Sequencer

The AWG path has the following features across two pathways:

1. Waveform Memory

2. Digital Gain

3. Digital Offset

4. NCO

5. Mixer Correction

6. Mixing Stage

1. Waveform Memory#

The AWG path has access to all waveforms supplied in the sequence. These waveforms are referenced in the Q1ASM program for playback with the play command. The waveform memory for each sequencer is 16384 samples (total duration of all waveforms on this sequencers), and the maximum number of waveforms that can be stored on a sequencer is 1024.

2. Digital Gain#

Each sequencer has a dedicated gain step for both paths 0 and 1, which can be statically configured using the Sequencer.gain_awg_path0() parameters. However, the gain can also be dynamically controlled using the set_awg_gain instruction of the sequence processor which enables pulse parametrization (see section Instructions). The static and dynamic gain controls are complementary.

Note

If modulated IQ signals are used for an output pair, the gain Sequencer.gain_awg_path0() has to be the same for both paths.

3. Digital Offset#

Following the gain stage an offset is applied to the waveform before modulation with the NCO. The offset of each path in a sequencer is set using the Sequencer.offset_awg_path0() parameters.

4. NCO#

Each Q1 sequencer has a dedicated numerically controlled oscillator (NCO). This NCO can be used to track the qubit or resonator phase (at a fixed frequency) in real-time. This NCO can be swept from -500MHz to 500MHz.

The frequency of the NCO and phase can be statically controlled using the Sequencer.nco_freq() and Sequencer.nco_phase_offs() parameters. However, the frequency and phase of the NCO can also be dynamically controlled using the set_freq, reset_ph, set_ph, and set_ph_delta instructions of the sequence processor, which enables pulse parametrization and execution of virtual Z-gates (see section Instructions). The static and dynamic phase control is complementary. Modulation is enabled using the Sequencer.mod_en_awg() parameter. Demodulation is enabled using the Sequencer.demod_en_acq() parameter.

For further in depth details and a tutorial on how to utilize the Q1 sequencer NCO capabilities, please refer to the NCO tutorial.

5. Mixer Correction#

The phase of the NCO can be offset between paths to allow for IQ mixer correction.

6. Mixing Stage#

The Sequencer has an onboard mixing stage for modulating a set waveform envelope at a set frequency between -500MHz and 500MHz.

Acquisition Path#

Block diagram of awg path of Q1 Sequencer

1. Demodulation

2. Time of Flight Compensation

3. Weight Memory

4. Integrator

5. Rotation

6. Thresholding

7. Binning and Averaging

8. Scope

1. Demodulation#

Each sequencer with an acquisition path has a digital demodulation unit onboard that can demodulate signals from -500MHz to 500MHz.

2. Time of Flight Compensation#

To enable reliable demodulation a time of flight compensation can be programmed into the NCO used for demodulation, allowing for accurate phase matching between IF and acquired signal.

3. Weight Memory#

The weight memory stores the integration weights set by the user in the provided sequence. This is an optional capability, and acquisition is performed an unitary integration by default. The maximum number of weights that can be stored is 32.

4. Integrator#

The integrator block performs a square integration, or applies the provided integration weights to the incoming data. When using the square integration, the length of the integration is restricted to 16 777 212 ns. For the weighted integration, this is limited to the length of the weight memory of 16 380 ns.

5. Rotation#

The acquisition path performs a rotation of the data before thresholding. This acts to allow for thresholding to be set at an arbitrary gradient through the IQ plane. Setting the rotation is the equivalent of setting the angle of the separator used for thresholding in the IQ plane. Details on how to set and use this rotation are provided below in 6. Thresholding.

6. Thresholding#

The thresholding unit evaluates all data above the set threshold, returning a 1 if it is above and a 0 otherwise. This result is shared across the cluster for applications in feedback.

One way of identifying the qubit state from a measurement (e.g. via an integrated acquisition) is by defining a threshold for measured I-Q points. The threshold can be imagined as a line through the I-Q-plane, where every point on one side is defined as a 0, and all the others as a 1. The threshold line is controlled by two sequencer settings: thresholded_acq_rotation and thresholded_acq_threshold, as illustrated in the figure below

thresholded acquisition explanation

illustration of the acquisition threshold#

By default (left figure) we have thresholded_acq_rotation = 0 and thresholded_acq_threshold = 0, where every measured data point with I<0 is assigned the state 0, and the remaining data points are assigned the state 1. The first setting, thresholded_acq_rotation rotates the threshold line by an angle in degrees (0-360), clockwise. The second setting, thresholded_acq_threshold, sets the threshold that is compared to the rotated integrated acquisition result.

These settings can be set for each sequencer individually, e.g.

qrm.sequencer0.thresholded_acq_rotation(30)
qrm.sequencer0.thresholded_acq_threshold(0.15)

then, after arming and starting the sequence, the thresholded acquisitions can be retrieved from

qrm.get_acquisitions(0)['0']['acquisition']['bins']['threshold']

7. Binning and Averaging#

The acquired integrated values can be stored in different memory entries or bins. Every sequencer has 132072 bins available. On top of that, saving multiple acquisition to the same bins allows one to average the value. The number of averages is saved to the acquisition data as well. The bins and averaging used are set in the 1. Sequences supplied to the sequencer before operation. An example is presented in the binning tutorial.

8. Scope#

The Scope acquisition can be configured to be triggered by the input level or by the sequencer through commands QRM.scope_acq_trigger_mode_path0(), followed by QRM.scope_acq_trigger_level_path0() or QRM.scope_acq_sequencer_select(), respectively. When the sequencer is selected to trigger the scope acquisition, every acquisition will trigger the capture of 16k input samples on both inputs and will store the raw input samples in a temporary buffer. Every time an acquisition is started, this temporary memory is overwritten, so it is vital to move the samples from the temporary buffer to a more lasting location before the start of the next acquisition. Learn how to use this mode by following the relevant scope tutorial.

TTL Trigger Acquisition Path#

Block diagram of awg path of Q1 Sequencer

1. Input Select

2. Threshold

3. Edge Detect

4. Enable

5. Bin Counter

6. Averaging/Binning

1. Input Select#

In the TTL trigger path, one of the inputs is selected using the qblox_instruments Sequencer.ttl_acq_input_select() parameter.

2. Threshold#

The thresholding unit evaluates all data above the set threshold, returning a 1 if it is above and a 0 otherwise. This result can be shared across the cluster for feedback applications.

The threshold for this acquisition can be set for each sequencer individually, e.g.

qrm.sequencer0.ttl_acq_threshold(0.5)

3. Edge Detect#

When a TTL trigger is detected at the threshold comparator, the resulting one-bit signal is pushed through an edge detection to transform the TTL trigger of undetermined duration into a single clock cycle trigger pulse.

4. Enable#

The TTL trigger path is always active, but its output results are gated based on the enable parameter in the acquire_ttl Q1ASM instruction.

5. Bin Counter#

The bin index is given as an argument of the instruction and is automatically incremented by each detected trigger through the bin counter. Sequencer.ttl_acq_auto_bin_incr_en() selects if the bin index is automatically incremented when acquiring multiple triggers.

6. Averaging/Binning#

The resulting trigger pulse and the associated ADC values that caused the trigger detection can be stored through the binning and averaging module. When doing this, the retrigger rate is restricted to roughly 1MHz.

The TTL acquisition will be saved in ‘averages’ and can be retrieved by:

qrm.get_acquisitions(0)['0']['acquisition']['bins']['averages']

Continuous Waveform Mode#

The sequencer also supports a continuous waveform mode of operation, where the waveform playback control of the sequence processor is completely bypassed and a single waveform is just played back on a loop. This mode can be enabled using the Sequencer.cont_mode_en_awg_path0() parameters and the waveform can be selected using the Sequencer.cont_mode_waveform_idx_awg_path0() parameters. The waveforms used in this mode must have a minimum length of 4 ns.

When in continuous mode, simply program, arm, start, and stop the sequencer using the regular control functions and parameters (i.e. Sequencer.sequence(), arm_sequencer(), start_sequencer() and stop_sequencer()). However, be aware that the sequencer processor can still control parts of the AWG path, like phase, gain, and offset, while the sequencer operates in this mode. Therefore, we advise programming the sequence processor with a single stop instruction.

Multiplexing#

All Q1 sequence processors are allowed to be connected to any combination of outputs at the same time. This enables easy and flexible targeting of multiple qubits on a single channel.

The output multiplexer can be statically configured through the Sequencer.connect_out0() and Sequencer.connect_acq_I() parameters.

The routing possibilities are uniform for all outputs on the different modules. Inputs and outputs follow the same connection rules. Any input or output can be connected to either path 0 (I) or path 1 (Q) of any combination of sequencers.

In the QCM-RF and QRM-RF modules, the complex signal is upconverted to the GHz regime, resulting in half the number of outputs. To simplify the interface, an input/output is always connected to both sequencer paths for RF modules. For more details, see QCM-RF Block Diagram and QRM-RF Block Diagram.

Clearing the channel map#

The default state is that the I quadrature is connected to all even inputs and outputs of all sequencers, and Q to odd inputs and outputs. This is so that the modules can always play a sequence in their default state. For most applications, only a small number of these connections is enabled. Therefore, there are convenience functions to clear the channel map:

# To set all connect_out* parameters for all sequencers to 'off':
instrument.disconnect_outputs()

# To set all connect_acq* parameters for all sequencers to 'off':
instrument.disconnect_inputs()

Bulk setting connections#

In most cases, the goal is simply to connect a sequencer to an output, either in real (only I) or complex (I and Q) mode. The convenience function connect_sequencer() facilitates this. The function takes one or more string arguments of the format <direction><channel> or <direction><I-channel>_<Q-channel>. <direction> must be in to make a connection between an input and the acquisition path, out to make a connection from the waveform generator to an output, or io to do both. The channels must be integer channel indices. If only one channel is specified, the sequencer operates in real mode; if two channels are specified, it operates in complex mode.

If any of the arguments is invalid, or if there are conflicts with existing connections, the function will raise an Exception without affecting the channel map. For this reason, we recommend clearing the channel map before attempting to bulk set connections.

A few common examples:

Connect single sequencer on a QRM baseband (complex)

instrument.disconnect_inputs()
instrument.disconnect_outputs()
instrument.sequencer0.connect_sequencer("out0_1")

Multiplexed sequencers on a QRM baseband (complex)

instrument.disconnect_inputs()
instrument.disconnect_outputs()
for seq in instrument.sequencers:
    seq.connect_sequencer("io0_1")

Multiplexed sequencers on a QRM-RF (complex)

instrument.disconnect_inputs()
instrument.disconnect_outputs()
for seq in instrument.sequencers:
    seq.connect_sequencer("io0")

Sequencers 1:1 on a QCM baseband (real)

instrument.disconnect_outputs()
for idx in range(4):
    instrument[f"sequencer{idx}"].connect_sequencer(f"out{idx}")

Sequencers 1:1 on a QCM-RF (complex)

instrument.disconnect_outputs()
for idx in range(2):
    instrument[f"sequencer{idx}"].connect_sequencer(f"out{idx}")

Operation#

Q1 Sequencer processors have an arbitrary wave generation (AWG) path, and in the case of QRM modules, also have an acquisition path. Each sequencer shares the following features:

1. Sequences

2. Waveforms

3. Acquisitions

4. Weights

5. Program

1. Sequences#

Q1 Sequence Processors are programmed using sequence constructs which consist of 4 key parts: waveforms, weights, acquisitions, and a program. This section will break down the high-level structure of a sequence before going into detail on each of these 4 parts that can make up a sequence.

The sequencers are programmed with a sequence using the Sequencer.sequence() function parameter. The sequence argument can be a JSON filename or a JSON compatible dictionary. We recommend using the first when taking snapshots of the instrument configuration using QCoDeS snapshots to reduce snapshot sizes and promote sequence reuse between experiment runs/iterations where possible. The content of the JSON file/dictionary is expected to adhere to the following format:

  • waveforms: Indicates that the following waveforms are intended for the AWG path.

    • waveform name: Replace by string containing the waveform name.

      • data: List of floating point values to express the waveform.

      • index: Integer index used by the Q1ASM program to refer to the waveform.

    • For more details please go to section 2. Waveforms below

  • weights: Indicates that the following weight functions are intended for the

    integration units of the acquisition path (only used by the QRM or QRM-RF).

    • weight name: Replace by string containing the weight name.

      • data: List of floating point values to express the weight.

      • index: Integer index used by the Q1ASM program to refer to the weight.

    • For more details please go to section 4. Weights below

  • acquisitions: Indicates that the following acquisitions are available for

    the acquisition path to refer to (only used by the QRM or QRM-RF).

    • acquisition name: Replace by string containing the acquisition name.

      • num_bins: Number of bins in acquisition.

      • index: Integer index used by the Q1ASM program to refer to the acquisition.

    • For more details please go to section 3. Acquisitions below

  • program: Single string containing the entire sequence processor Q1ASM program.

    • For more details please go to section 5. Program below

    • For details of the instructions used in Q1ASM programs please go to Instructions

2. Waveforms#

The waveforms are expressed as a list of floating point values in the range of 1.0 to -1.0 with a resolution of one nanosecond per sample. The AWG path uses these waveforms to parametrically generate pulses on its outputs.

Waveform playback is started by the play Q1ASM instruction. Each waveform is paired with an index, which is used by this instruction to refer to the associated waveform. The waveform is then completely played irrespective of further sequence processor instructions, except when the sequence processor issues the playback of another waveform, in which case the waveform will be stopped and the new waveform will start. In case the time between waveforms is longer than the waveform length, the intermediate time will be filled by samples with a value of zero. The maximum number of waveforms that can be stored is 1024.

The programmed waveforms can be retrieved using get_waveforms().

3. Acquisitions#

Scope Acquisitions:

Acquisitions are started by the acquire, acquire_weighed, or acquire_ttl Q1ASM instructions, and will trigger the capture of 16k input samples on both inputs. This mode of operation is called scope mode and will store the raw input samples in a temporary buffer. Every time an acquisition is started, this temporary memory is overwritten, so it is vital to move the samples from the temporary buffer to a more lasting location before the start of the next acquisition. This is done by calling store_scope_acquisition(), which moves the samples into the specified acquisition in the acquisition list of the sequencer, located in the RAM of the instrument. Multiple acquisitions can be stored in this list before being retrieved from the instrument by simply calling get_acquisitions(). Acquisitions are returned as a dictionary of acquisitions. Scope mode data is located under the scope key as lists of floating point values in a range of 1.0 to -1.0 with a resolution of one nanosecond per sample, as well as an indication if the ADC was out-of-range during the measurement. The maximum duration of the scope is 16 380 ns.

Note

Before calling store_scope_acquisition(), be sure to call get_sequencer_state() and get_acquisition_state() in that order. This ensures that both the sequencer has finished and that there is an acquisition ready.

The acquisition path also has an averaging function set through the QRM.scope_acq_avg_mode_en_path0() parameters. This enables the automatic accumulation of acquisitions, where sample N of acquisition M is automatically accumulated to sample N of acquisition M+1. This happens while the acquisition is still in the temporary buffer, so after the desired number of averaging acquisitions is completed, call store_scope_acquisition() to store the accumulated result in the acquisition list. Once retrieved from the instrument, the accumulated samples will automatically be divided by the number of averages to get the actual averaged acquisition result.

Tip

For debug purposes, the acquisition path can also be triggered using a trigger level, where if the input exceeds this level, an acquisition is started. See the QRM.scope_acq_trigger_mode_path0() and QRM.scope_acq_trigger_level_path0() parameters for more information.

Square Weight Acquisitions:

The acquire Q1ASM command performs a square weight acquisition over a certain period and stores the result in a bin of the provided acquisition in the sequence. The integration is executed using square weights with a preset length set through the associated QCoDeS parameter Sequencer.integration_length_acq() (must be a multiple of 4, with a maximum of 16 777 212). The maximum number of acquisitions that can be stored is 32.

acquire 0,0,16384      # Start acquisition using acquisition at index 0 and place in the bin at index 0, then wait for 16484ns
stop                           #Stop sequencer

Weighed Acquisitions:

The acquire_weighed Q1ASM command performs an acquisition that utilizes the weights provided in the sequence for integration of the acquired signal.

acquire_weighted 0,0,0,1,1000  #Acquire for 1000ns using acquisition at index 0 and place in bin at index 0, using weights at index 0 for path 0 and index 1 for path 1
stop                  #Stop sequencer

TTL Trigger Acquisitions:

The acquire_ttl instruction is used to detect TTL triggers on one of the instrument’s inputs when it exceeds a configurable threshold. The input is selected using Sequencer.ttl_acq_input_select(), while the threshold is set using Sequencer.ttl_acq_threshold(). The instruction enables the TTL trigger acquisition path by setting the enable argument to 1 and needs to actively disable the path again by using the same instruction with its enable argument set to 0. While the TTL trigger acquisition path is enabled, real-time integration and discretization is disabled.

acquire_ttl 0,0,1,1000 #Acquire triggers and wait for 1000ns
acquire_ttl 0,0,0,4    #Stop acquiring triggers and wait for 4ns
stop                   #Stop sequencer

When a rising edge is detected on the input that exceeds the threshold while the path is enabled, a TTL trigger is detected and its ADC value at which it was detected is stored in the bin specified by the instruction’s bin index argument. No new TTL triggers will be detected until a new rising edge exceeds the configured threshold.

When multiple triggers are detected while the path is enabled, the storage strategy is determined by the Sequencer.ttl_acq_auto_bin_incr_en() parameter. When Sequencer.ttl_acq_auto_bin_incr_en() is enabled, the bin index is automatically incremented every time a TTL trigger is detected. This gives the ability to store every ADC value individually and allows you to count the number of TTL triggers by counting the number of valid bins stored at the end of the sequence. Alternatively, when Sequencer.ttl_acq_auto_bin_incr_en() is disabled the same bin is reused for every detected TTL trigger. This allows averaging the ADC values in hardware and allows you to count the number of TTL triggers by looking at the average count of that bin at the end of the sequence.

The resulting acquisition data can be retrieved using get_acquisitions(). The ADC values at which TTL triggers were detected are stored in the integration key as lists of floating point values in a range of 1.0 to -1.0. They replace the integration results of regular acquisitions.

4. Weights#

The weights are expressed as a list of floating point values in the range of 1.0 to -1.0 with a resolution of one nanosecond per sample. The integration units in the acquisition path apply (i.e. multiply) these weights during the integration process when the acquisition path is triggered for weighted integration.

Weighed integration is triggered by the acquire_weighed instruction. Each weight is paired with an index, which is used by this instruction to refer to the associated weight. The weight is then played, like the waveforms discussed in the previous section, and determines the length of the integration. The weighted integration process continues irrespective of further sequence processor instructions, except when the sequence processor issues another acquisition using the acquire or acquire_weighed instructions, in which case the integration will be stopped, the result will be stored and a new integration will start. For non-weighted integrations the max length of integration is 16 777 212 ns, for weighted integrations it is the same as the maximum scope length, 16 380 ns.

The programmed weights can be retrieved using get_weights().

5. Program#

The sequence programs are written in the custom Q1ASM assembly language described in Q1ASM. All sequence processor instructions are executed by the classical pipeline and the real-time instructions are also executed by the real-time pipeline. These latter instructions are intended to control the AWG and acquisition paths in a real-time fashion. Once processed by the classical pipeline they are queued in the real-time pipeline awaiting further execution. A total of 32 instructions can be queued and once the queue is full, the classical part will stall on any further real-time instructions.

Once execution of the real-time instructions by the real-time pipeline is started, care must be taken to not cause an underrun of the queue. An underrun will potentially cause undetermined real-time behavior and desynchronize any synchronized sequencers. Therefore, when this is detected, the sequencer is completely stopped. A likely cause of underruns is a loop with a very short (i.e. < 24ns) real-time run-time, since the jump of a loop takes some cycles to be executed by the classical pipeline. See the column Execution time of Instructions for execution times in the classical pipeline for each instruction.

Finally, be aware that moving data into a register using an instruction takes a cycle to complete. This means that when an instruction reads from a register that the previous instruction has written to, a nop instruction must be placed in between these consecutive instructions for the value to be correctly read.

The state of the sequencers, including any errors, can be queried through get_sequencer_state().

Q1ASM#

The sequence programs are written in the custom Q1ASM assembly language described on this page. All sequence processor instructions are executed by the classical pipeline and the real-time instructions are also executed by the real-time pipeline. These latter instructions are intended to control the AWG and acquisition paths in a real-time fashion. Once processed by the classical pipeline they are queued in the real-time pipeline awaiting further execution. A total of 32 instructions can be queued and once the queue is full, the classical part will stall on any further real-time instructions.

Once execution of the real-time instructions by the real-time pipeline is started, care must be taken to not cause an underrun of the queue. An underrun will potentially cause undetermined real-time behavior and desynchronize any synchronized sequencers. Therefore, when this is detected, the sequencer is completely stopped. A likely cause of underruns is a loop with a very short (i.e. < 24ns) real-time run-time, since the jump of a loop takes some cycles to be executed by the classical pipeline.

Finally, be aware that moving data into a register using an instruction takes a cycle to complete. This means that when an instruction reads from a register that the previous instruction has written to, a nop instruction must be placed in between these consecutive instructions for the value to be correctly read.

The state of the sequencers, including any errors, can be queried through get_sequencer_state().

Assembly syntax#

Assembly source for the Q1 processor consists of lines containing directives or code, all of which are case sensitive. Any input starting with # until end-of-line is treated as comment.

Directives#

The assembler supports user-defined aliases using the .DEF <name> <value> directive, which defines name as an alias for value. name is an identifier consisting of upper- and lower-case letters and numbers, starting with a letter. value can be any string (e.g. 42 or R63).

Code#

A source line has the following format:

[label:] instruction argument,argument,... [comment]

Fields must be separated by white space (combinations of space and tab), operands may be separated by white space.

Arguments

Q1ASM instructions make use of the following argument types:

Type

Acronym

Format

Description

Immediate

I

#

32-bit decimal or hexadecimal value (e.g. 1000, -42, 0xFFFFFFFF)

Register

R

R#

Register address in range 0 to 63 (e.g. R0), containing a 32-bit unsigned integer.

Labels

Any instruction can be preceded by a label, i.e. an identifier followed by a ‘:’ character. Labels are also allowed to be on a separate line. A label represents the instruction address of the following instruction.

Label references

A label defined as label: can be referred to in (immediate) instruction arguments as @label. Forward references are allowed, the definition need not precede the reference. Labels can be used with instructions that can alter program flow (i.e. jmp, jge, jlt and loop), but also with any other instruction.

Alias references

Names defined by .DEF name ... can be referred to in (immediate or register) instruction arguments as $name. Forward references are not allowed, the .DEF must precede the reference.

Instructions#

A sequencer consists of the Q1 processor, and the real-time pipeline as co-processor. The Q1 processor generates real-time instructions and queues them for execution by the real-time pipeline. Q1-only and real-time instructions are listed in two separate tables below.

Wall-time of an experiment is determined only by the duration argument of real time instructions. The Q1 execution time is only relevant if the Q1 processor cannot keep up with the wall-time demanded by the duration arguments: If this is the case and the queue runs out, the Sequencer will halt and raise an error flag.

The arguments of an instruction are specified as arg0_name: type, arg1_name: type, .... An instruction may have multiple allowed combinations of arguments, those are specified on separate lines. The execution time on the Q1 processor may depend on the argument type and is specified in ns for each combination of arguments.

Q1 Instructions#

These instructions are used to compose and manipulate the arguments of real-time instructions. They are always executed before the next real-time instruction, and therefore take zero wall-time.

Instruction

Signature

Q1 Execution time (ns)

Description of instruction

Control instructions

illegal

4

Instruction that should not be executed. If it is executed, the sequencer will stop with the illegal instruction flag set.

stop

4

Instruction that stops the sequencer.

nop

4

No operation instruction, that does nothing. It is used to pass a single cycle in the classic part of the sequencer without any operations.

Jump instructions

jmp

address: I

address: R

16

16

Jump to the instruction indicated by address.

jge

a: R, b: I, address: I

a: R, b: I, address: R

24 on jump, 12 on continue

24 on jump, 12 on continue

If a is greater or equal to b, jump to the instruction indicated by address.

jlt

a: R, b: I, address: I

a: R, b: I, address: R

24 on jump, 12 on continue

24 on jump, 12 on continue

If a is less than b, jump to the instruction indicated by address.

loop

a: R, address: I

a: R, address: R

24 on jump, 12 on continue

24 on jump, 12 on continue

Decrement a by one and, if the result is non-zero, jump to the instruction indicated by address.

Arithmetic instructions

move

source: I, destination: R

source: R, destination: R

4

4

source is moved / copied to destination. destination = source

not

source: I, destination: R

source: R, destination: R

12

12

Bit-wise invert source and move the result to destination. destination = ~source

add

a: R, b: I, destination: R

a: R, b: R, destination: R

12

16

Add b to a and move the result to destination. destination = a + b

sub

a: R, b: I, destination: R

a: R, b: R, destination: R

12

16

Subtract b from a and move the result to destination. destination = a - b

and

a: R, b: I, destination: R

a: R, b: R, destination: R

12

16

Bit-wise AND a and b and move the result to destination. destination = a & b

or

a: R, b: I, destination: R

a: R, b: R, destination: R

12

16

Bit-wise OR a and b and move the result to destination. destination = a | b

xor

a: R, b: I, destination: R

a: R, b: R, destination: R

12

16

Bit-wise XOR a and b and move the result to destination. destination = a ^ b

asl

a: R, b: I, destination: R

a: R, b: R, destination: R

12

16

Bit-wise left-shift a by b number of bits and move the result to destination. destination = a << b

asr

a: R, b: I, destination: R

a: R, b: R, destination: R

12

16

Bit-wise right-shift a by b number of bits and move the result to destination. destination = a >> b

Parameter operation instructions

The parameters are latched and only updated when the upd_param, play, acquire, acquire_weighed or acquire_ttl instructions are executed.

set_mrk

mask: I

mask: R

4

4

Set marker output channels to val (bits 0-3), where the bit index corresponds to the channel index for baseband modules.

For QCM-RF modules, bit indices 0 & 1 correspond to enabling output 1 and 2 switches respectively; indices 2 & 3 correspond to marker output 2 and 1 (sic!) respectively.

For QRM-RF modules, bit index 0 is inactive, bit index 1 corresponds to enabling output 1 switch; indices 2 & 3 correspond to marker output 1 and 2 (sic!) respectively.

The values are OR´ed by that of other sequencers.

set_freq

value: I

value: R

4

4

Set the frequency of the NCO used by the AWG and acquisition using value. The frequency is divided into 4e9 steps between -500 and 500 MHz and expressed as an integer between -2e9 and 2e9 (e.g.1 MHz=4e6).

reset_ph

4

Reset the absolute phase of the NCO used by the AWG and acquisition to 0°. This also resets any relative phase offsets that were already statically or dynamically set.

set_ph

value: I

value: R

4

4

Set the absolute phase of the NCO used by the AWG and acquisition using value. The phase is divided into 1e9 steps between 0° and 360°, expressed as an integer between 0 and 1e9 (e.g 45°=125e6).

set_ph_delta

value: I

value: R

4

4

Set an offset on top of the relative phase of the NCO used by the AWG and acquisition. The offset is applied on top of the phase set using set_ph. See set_ph for more details regarding the argument.

set_awg_gain

value_0: I, value_1: I

value_0: R, value_1: R

4

8

Set AWG gain for path 0 using value_0 and path 1 using value_1. Both are integers in [-32 768, 32 767].

set_awg_offs

value_0: I, value_1: I

value_0: R, value_1: R

4

8

Set AWG offset for path 0 using value_0 and path 1 using value_1. Both values are integers in [-32 768, 32 767].

Real-time instructions#

These instructions have a duration argument, which corresponds to the wall-time of an experiment. The duration is counted from the beginning of an instruction. This is what enables e.g. parallel playback and acquisition.

The real-time instructions to the pipeline form a time-line of real-time operations. To ensure deterministic behavior, this time-line cannot be interrupted/broken. As a result, once the real-time pipeline is started by the first real-time instruction in a sequence, it cannot be stalled. Therefore, the real-time pipeline will never wait for the Q1 processor. In case of a conflict, the sequencer will halt and raise an error flag.

The duration can be set at a resolution of 1 ns, with a minimum of 4 ns.

Instruction

Signature

Q1 Execution time (ns)

Description of instruction

Conditional instructions

set_cond

enable: I, mask: I, operator: I, else_duration: I

enable: R, mask: R, operator: R, else_duration: I

4

12

Enable/disable conditionality on all following real-time instructions based on enable. The condition is based on the trigger network address counters being thresholded based on the associated counter threshold parameters set through QCoDeS.

The results are masked using mask (bits 0-14), where the bit index plus one corresponds to the trigger address.

This creates a selection to include in the final logical operation set using operator. Logical operators are OR, NOR, AND, NAND, XOR, XNOR, where a value for operator of 0 is OR and 5 is XNOR respectively.

The logical operation result (true/false) determines the condition. If the condition is true upon evaluation, the next real-time instruction is executed. Else the real-time path ignores the instruction and waits for else_duration nanoseconds before continuing to the next.

All following real-time instructions are subject to the same condition, until either the conditionality is disabled or updated. Disabling the conditionality does not affect the address counters and does not trigger else_duration.

See also Feedback.

Real-time IO operation instructions

upd_param

duration: I

4

Update the latched parameters, and then wait for duration nanoseconds.

play

wave_0: I, wave_1: I, duration: I

wave_0: R, wave_1: R, duration: I

4

8

Update the latched parameters, interrupt currently playing waves and start playing AWG waveforms stored at indexes wave_0 on path 0 and wave_1 on path 1.

acquire

acquisition: I, bin: I, duration: I

acquisition: I, bin: R, duration: I

4

4

Update the latched parameters, interrupt currently active acquisitions and start the acquisition referred to using index acquisition and store the bin data in bin index bin.

Integration is executed using a square weight with a preset length through the associated QCoDeS parameter.

acquire_weighed

acquisition: I, bin: I, weight_0: I, weight_1: I, duration: I

acquisition: I, bin: R, weight_0: R, weight_1: R, duration: I

4

12

Update the latched parameters, interrupt currently active acquisitions and start the acquisition referred to using index acquisition and store the bin data in bin index bin.

Integration is executed using weights stored at indices weight_0 for path 0 and weight_1 for path 1.

acquire_ttl

acquisition: I, bin: I, enable:I, duration: I

acquisition: I, bin: R, enable:I, duration: I

4

4

Update the latched parameters, start the TTL trigger acquisition referred to using index acquisition and store the bin data in bin index bin. Enable the acquisition by writing 1 to enable.

The TTL trigger acquisition has to be actively disabled afterwards by writing 0 to enable.

Real-time trigger count control instructions

set_latch_en

enable: I, duration: I

enable: R, duration: I

4

4

Enable/disable all trigger network address counters. Once enabled, the trigger network address counters will count all triggers on the trigger network. When disabled, the counters hold their last values.

latch_rst

duration: I

duration: R

4

4

Reset all trigger network address counters back to 0.

Real-time wait operation instructions

wait

duration: I

duration: R

4

4

Wait for duration` nanoseconds.

wait_trigger

trigger: I, duration: I

trigger: R, duration: R

4

4

Wait for a trigger on the trigger network at the address set using trigger.

wait_sync

duration: I

duration: R

4

4

Wait for SYNQ to complete on all connected sequencers over all connected instruments.

Note

All operations and parameters are executed/updated on a 1 ns timegrid, except for instructions that operate on the sequencer’s NCOs (set_freq, reset_ph, set_ph, set_ph_delta`). For now, those parameters are updated on a 4 ns timegrid. The minimum time between frequency updates (set_freq) for the NCO is 8ns.

When doing back-to-back scope acquisitions, their duration must be a multiple of 4 ns. This behavior of the scope acquisitions will be patched in a following release.

Example#

This is a simple example of a Q1ASM program. It enables each marker channel output for 1μs and then stops.

      move      1,R0        # Start at marker output channel 0 (move 1 into R0)
      nop                   # Wait a cycle for R0 to be available.

loop: set_mrk   R0          # Set marker output channels to R0
      upd_param 1000        # Update marker output channels and wait 1μs.
      asl       R0,1,R0     # Move to next marker output channel (left-shift R0).
      nop                   # Wait a cycle for R0 to be available.
      jlt       R0,16,@loop # Loop until all 4 marker output channels have been set once.

      set_mrk   0           # Reset marker output channels.
      upd_param 4           # Update marker output channels.
      stop                  # Stop sequencer.