HDAWG

Initialize the tk.HDAWG instrument drivers as in the previous example and setup and connect the device. Its device serial is dev8030 and we connect via ethernet (1gbe) to the host at 10.42.0.226.

[1]:
import zhinst.toolkit as tk

hdawg = tk.HDAWG("hdawg1", "dev8030", interface="1gbe", host="10.42.0.226")
hdawg.setup()              # set up data server connection
hdawg.connect_device()     # connect device to data server
Successfully connected to data server at 10.42.0.2268004 api version: 6
Successfully connected to device DEV8030 on interface 1GBE

AWG cores

The HDAWG features eight AWG channels grouped in four AWG Cores with two channels each. These four AWG Cores can be accessed through the awgs property of the instruemnt driver. awgs is a list of four HDAWG-specific AWGCore objects. The AWGCore handles the basic functionality to control the AWG Core and program its sequencer to play a specific series of waveforms and commands.

[2]:
hdawg.awgs[0]
[2]:
hdawg1: <zhinst.toolkit.control.drivers.hdawg.AWG object at 0x00000203DB7BE128>
    parent  : <zhinst.toolkit.control.drivers.hdawg.HDAWG object at 0x00000203DA1E09B0>
    index   : 0
    sequence:
           type: None
            ('target', <DeviceTypes.HDAWG: 'hdawg'>)
            ('clock_rate', 2400000000.0)
            ('period', 0.0001)
            ('trigger_mode', 'None')
            ('repetitions', 1)
            ('alignment', 'End with Trigger')
            ('n_HW_loop', 1)
            ('dead_time', 5e-06)
            ('trigger_delay', 0)
            ('latency', 1.6e-07)
            ('trigger_cmd_1', '//\n')
            ('trigger_cmd_2', '//\n')
            ('wait_cycles', 0)
            ('dead_cycles', 0)
            ('reset_phase', False)
      IQ Modulation DISABLED

An AWG Core features a list of zhinst-toolkit Parameters as well as methods that allow for a high-level control of the AWG Core. The Parameters control the channel outputs as well as their modulation settings.

For instance, the channel outputs can be turned on and off like this:

[3]:
hdawg.awgs[0].output1("on")
hdawg.awgs[0].output2("on")

# are the outputs really on now?
hdawg.awgs[0].outputs()
[3]:
('on', 'on')
[4]:
hdawg.awgs[0].outputs(("off", "off"))

AWG output modulation

The output modulation for both channel outputs can be turned on with:

[5]:
hdawg.awgs[0].enable_iq_modulation()

This method applies the corresponding settings for IQ Modulation using one of the internal oscillators and two sine generators. The sines are used to modulate the AWG output channels at a 90 degree phase difference. The parameters modulation_freq, modulation_phase_shift and gain1, gain2 correspond to the settings of the oscillator and the sine generators.

[6]:
hdawg.awgs[0].modulation_freq
[6]:
Node: oscs/0/freq
Description: Sets the modulation frequency of the AWG output channels.
Type: Double
Properties: Read, Write
Unit: Hz

A simple sweep of the modulation frequency could look like this:

[7]:
import numpy as np
import time

for f in np.linspace(10e6, 20e6, 101):
    hdawg.awgs[0].modulation_freq(f)
    # do something here
    time.sleep(0.1)

The AWG Core also holds a SequenceProgram that defines the pulse sequence played by the AWG Sequencer. One of the next examples will describe how this sequence program is defined and how you can configure it to play the sequence of waveforms that you want to use.

Programming the AWG core

[8]:
hdawg.awgs[0].outputs(("on", "on"))    # turn the outputs on

All the parameters of the sequence program are set using set_sequence_params(...) which lets the user pass keyword arguments. The most important ones are

  • sequence_type: the type of sequence to be programmed. The ‘Simple’ sequence type allows the user to upload their own sample-based waveforms which are played in a well defined sequence.

  • period: the period in seconds in which the single shots of the experiment should be repeated

  • repetitions: the number of repetitions of the sequence

[9]:
hdawg.awgs[0].set_sequence_params(
    sequence_type="Simple",            # let the user uplaod the sample-defined waveforms
    period=20e-6,                      # play the waveform every 20 us
    repetitions=1e3,                   # repeat 1000 times
)

Because we are using the ‘Simple’ sequence type, we can define the waveforms as numpy arrays. The waveform is defined by samples, which means that the timing calculation has to be taken care of by the user! For example the sampling rate of the HDAWG is 2.4 Gs, thus a waveform of 1000 samples correpsonds to a duration of 1000 / 2.4e9 = 416.6 ns.

We first reset the queue to ensure it is empty, then we add our waveform to the queue. The waveform is always defined for both channels of the AWG Core simultaneously.

[10]:
wave1 = np.ones(1000)
wave2 = -np.ones(1000)

hdawg.awgs[0].reset_queue()                   # reset the queue
hdawg.awgs[0].queue_waveform(wave1, wave2)    # add the waveform to the queue

# what is in the queue?
hdawg.awgs[0].waveforms
Current length of queue: 1
[10]:
[<zhinst.toolkit.helpers.waveform.Waveform at 0x203e1844a20>]

Next, we need to tell the AWG Core to compile the sequence program and to upload all the waveforms in the queue. The method compile_and_upload_waveforms() takes care of both these jobs for the ‘Simple’ sequence (to ensure the correct sequence program is compiled before all the waveforms are uploaded).

[11]:
hdawg.awgs[0].compile_and_upload_waveforms()  # compile the sequence program and uplaod all waveforms in the queue
Compilation successful
hdawg1-0: Sequencer status: ELF file uploaded
Upload of 1 waveforms took 0.026985 s

Now we can run our seuqence program.

[12]:
hdawg.awgs[0].run()        # start the AWG Core
hdawg.awgs[0].wait_done()  # wait until the AWG Core has finished playing the program

This program will output two rectangular pulses of length 1000 samples (416.6 ns) with amplitude 1 on channel 1 and amplitude -1 on channel 2. The waveforms are played every 20 us and are repeated 1000 times.