---
title: "How can I program multi-channel sequences with the OPX+?"
date: "2022-01-10T10:13:41+00:00"
url: "https://www.quantum-machines.co/faq/how-can-i-program-multi-channel-sequences-with-the-opx/"
---

# How can I program multi-channel sequences with the OPX+?

The OPX+’s Pulse Processor is a multi-core processor. Each pulser core executes its own sequence independently of the others, unless a protocol calls for inter-core dependencies. Synchronizing and coordinating different threads is handled by the compiler behind the scenes, making it easy to set up complex experiments with simple instructions.

Suppose we want to play a Gaussian pulse with amplitude A1 to qubit\_1, simultaneously with another Gaussian with amplitude A2 to qubit\_2. This would be done with the following QUA program:

```
`play(‘gaussian’*amp(A1), ‘qubit_1’)play(‘gaussian’*amp(A2), ‘qubit_2’)`
```

The two `play()` commands address different threads, and therefore play simultaneously. This results in an output as shown below:

![Gaussian-pulse-output](https://www.quantum-machines.co/wp-content/uploads/2022/01/4-1.png)
We can delay one of the pulses by using the `wait()` command. In the following code, the `qubit_1` thread alone is delayed by 20 clock cycles, while the `qubit_2` thread is unaffected:

```
`wait(20,’qubit_1’)play(‘gaussian’*amp(A1), ‘qubit_1’)play(‘gaussian’*amp(A2), ‘qubit_2’)`
```

![delayed-Gaussian-pulse-output](https://www.quantum-machines.co/wp-content/uploads/2022/01/5-1.png)

Many experiment protocols call for one sequence to begin only after another sequence is finished. Rather than manually calculate the duration of the first sequence, this can be implemented in QUA with the `align()` command:

```
<span style="font-weight: 400;">play(‘gaussian’*amp(A1), ‘qubit_1’)
</span><span style="font-weight: 400;">wait(20,’qubit_1’)
</span><span style="font-weight: 400;">play(‘gaussian’*amp(A1), ‘qubit_1’)
</span><span style="font-weight: 400;">align(‘qubit_1’, ‘qubit_2’)
</span><span style="font-weight: 400;">play(‘gaussian’*amp(A2), ‘qubit_2’)</span>
```

This results in the following output:

![align-Gaussian-pulse](https://www.quantum-machines.co/wp-content/uploads/2022/01/6.png)

The `align(‘qubit_1’, ‘qubit_2’)` command causes the two threads to wait for each other. Any command appearing below this line that addresses either of the two threads will only be implemented after both have completed all commands appearing above this line. **This dependency is evaluated in real time, and synchronizes the threads even if the duration of the first sequence is not known at compile time!**

This last point is vital for many sequences, such as repeat-until-success protocols. Consider the following code:

```
<span style="font-weight: 400;">with while_(result>0.2 && N < 1000):
</span><span style="font-weight: 400;">          ### Subroutine involving ‘qubit_1’ ###
</span><span style="font-weight: 400;">          align(‘qubit_1’, ’qubit_2’)
</span><span style="font-weight: 400;">          play(‘gaussian’*amp(A2), ‘qubit_2’)</span>
```

This will run a nondeterministic `while()` loop, within which the OPX+ might play pulses to `qubit_1`, measure it, update the `result` variable based on the measurement, and increment the counter variable `N`. It might run a single iteration before exiting the loop, and it might run 1,000. This is not known at compile time. But the simple `align()` still synchronizes the pulses, with all of the real-time control complexity handled by the compiler.
