Code Documentation

Hose side code, USB

pdq.host.crc module

class pdq.host.crc.CRC(poly, data_width=8)[source]

Generic and simple table driven CRC calculator.

This implementation is:

  • MSB first data
  • “un-reversed” full polynomial (i.e. starts with 0x1)
  • no initial complement
  • no final complement

Handle any variation on those details outside this class.

>>> r = CRC(0x1814141AB)(b"123456789")  # crc-32q
>>> assert r == 0x3010BF7F, hex(r)

pdq.host.protocol module

class pdq.host.protocol.Channel(max_data, num_frames)[source]

PDQ Channel.

num_frames

int – Number of frames supported.

max_data

int – Number of 16 bit data words per channel.

segments

list[Segment] – Segments added to this channel.

clear()[source]

Remove all segments.

new_segment()[source]

Create and attach a new Segment to this channel.

Returns:Segment
place()[source]

Place segments contiguously.

Assign segment start addresses and determine length of data.

Returns:Amount of memory in use on this channel.
Return type:int
serialize(entry=None)[source]

Serialize the memory for this channel.

Places the segments contiguously in memory after the frame table. Allocates and assigns segment and frame table addresses. Serializes segment data and prepends frame address table.

Parameters:entry (list[Segment]) – See table().
Returns:Channel memory data.
Return type:bytes
table(entry=None)[source]

Generate the frame address table.

Unused frame indices are assigned the zero address in the frame address table. This will cause the memory parser to remain in the frame address table until another frame is selected.

The frame entry segments can be any segments in the channel.

Parameters:entry (list[Segment]) – List of initial segments for each frame. If not specified, the first num_frames segments are used as frame entry points.
Returns:Frame address table.
Return type:bytes
class pdq.host.protocol.PDQBase(num_boards=3, num_dacs=3, num_frames=32)[source]

PDQ stack.

checksum

int – Running checksum of data written.

num_channels

int – Number of channels in this stack.

num_boards

int – Number of boards in this stack.

num_dacs

int – Number of DAC outputs per board.

num_frames

int – Number of frames supported.

channels

list[Channel] – List of Channel in this stack.

get_config(board=15)[source]

Read configuration register.

get_crc(board=15)[source]

Read checksum register.

See also

set_crc()

get_frame(board=15)[source]

Read frame selection register.

See also

set_frame()

ping()[source]

Ping method returning True. Required for ARTIQ remote controller.

program(program, channels=None)[source]

Serialize a wavesynth program and write it to the channels in the stack.

The Channel targeted are cleared and each frame in the wavesynth program is appended to a fresh set of Segment of the channels. All segments are allocated, the frame address tale is generated, the channels are serialized and their memories are written.

Short single-cycle lines are prepended and appended to each frame to allow proper write interlocking and to assure that the memory reader can be reliably parked in the frame address table. The first line of each frame is mandatorily triggered.

Parameters:
  • program (list) – Wavesynth program to serialize.
  • channels (list[int]) – Channel indices to use. If unspecified, all channels are used.
program_segments(segments, data)[source]

Append the wavesynth lines to the given segments.

Parameters:
  • segments (list[Segment]) – List of Segment to append the lines to.
  • data (list) – List of wavesynth lines.
set_config(reset=0, clk2x=0, enable=1, trigger=0, aux_miso=0, aux_dac=7, board=15)[source]

Set the configuration register.

Parameters:
  • reset (bool) – Reset the board. Memory is not reset. Self-clearing.
  • clk2x (bool) – Enable the clock multiplier (100 MHz instead of 50 MHz)
  • enable (bool) – Enable the reading and execution of waveform data from memory.
  • trigger (bool) – Soft trigger. Logical or with the F1 TTL Input hardware trigger.
  • aux_miso (bool) – Drive SPI MISO on the AUX/F5 OUT TTL port of each board. If False/0, drive the masked logical OR of the DAC channels’ aux data.
  • aux_dac (int) – DAC channel mask for AUX/F5. Each bit represents one channel. AUX/F5 is: aux_miso ? spi_miso : (aux_dac & Cat(_.aux for _ in channels) != 0)
  • board (int) – Board to write to (0-0xe), 0xf for all boards.
set_crc(crc=0, board=15)[source]

Set/reset the checksum register.

Parameters:
  • crc (int) – Checksum value to write.
  • board (int) – Board to write to (0-0xe), 0xf for all boards.
set_frame(frame, board=15)[source]

Set the current frame.

Parameters:
  • frame (int) – Frame to select.
  • board (int) – Board to write to (0-0xe), 0xf for all boards.
set_reg(adr, data, board)[source]

Set a register.

Parameters:
  • adr (int) – Register address to write to (0-3).
  • data (int) – Data to write (1 byte)
  • board (int) – Board to write to (0-0xe), 0xf for all boards.
write_mem(mem, adr, data, board=15)[source]

Write to channel memory.

Parameters:
  • mem (int) – Channel memory to write to.
  • data (bytes) – Data to write to memory.
  • adr (int) – Start address to write data to.
pdq.host.protocol.PDQ_CMD(board, is_mem, adr, we)[source]

Pack PDQ command fields into command byte.

Parameters:
  • board – Board address, 0 to 15, with 15 = 0xf denoting broadcast to all boards connected.
  • is_mem – If 1, adr denote the address of the memory to access (0 to 2). Otherwise adr denotes the register to access.
  • adr – Address of the register or memory to access. (PDQ_ADR_CONFIG, PDQ_ADR_FRAME, PDQ_ADR_CRC).
  • we – If 1 then write, otherwise read.
class pdq.host.protocol.Segment[source]

Serialize the lines for a single Segment.

max_time

int – Maximum duration of a line.

max_val

int – Maximum absolute value (scale) of the DAC output.

max_out

float – Output voltage at max_val. In Volt.

out_scale

float – Steps per Volt.

cordic_gain

float – CORDIC amplitude gain.

addr

int – Address assigned to this segment.

data

bytes – Serialized segment data.

bias(amplitude=[], **kwargs)[source]

Append a bias line to this segment.

Parameters:
  • amplitude (list[float]) – Amplitude coefficients in in Volts and increasing powers of 1/(2**shift*clock_period). Discrete time compensation will be applied.
  • **kwargs – Passed to line().
dds(amplitude=[], phase=[], **kwargs)[source]

Append a DDS line to this segment.

Parameters:
  • amplitude (list[float]) – Amplitude coefficients in in Volts and increasing powers of 1/(2**shift*clock_period). Discrete time compensation and CORDIC gain compensation will be applied by this method.
  • phase (list[float]) – Phase/frequency/chirp coefficients. phase[0] in turns, phase[1] in turns/clock_period, phase[2] in turns/(clock_period**2*2**shift).
  • **kwargs – Passed to line().
line(typ, duration, data, trigger=False, silence=False, aux=False, shift=0, jump=False, clear=False, wait=False)[source]

Append a line to this segment.

Parameters:
  • typ (int) – Output module to target with this line.
  • duration (int) – Duration of the line in units of clock_period*2**shift.
  • data (bytes) – Opaque data for the output module.
  • trigger (bool) – Wait for trigger assertion before executing this line.
  • silence (bool) – Disable DAC clocks for the duration of this line.
  • aux (bool) – Assert the AUX (F5 TTL) output during this line. The corresponding global AUX routing setting determines which channels control AUX.
  • shift (int) – Duration and spline evolution exponent.
  • jump (bool) – Return to the frame address table after this line.
  • clear (bool) – Clear the DDS phase accumulator when starting to exectute this line.
  • wait (bool) – Wait for trigger assertion before executing the next line.
static pack(values)[source]

Pack spline data.

Parameters:
  • widths (list[int]) – Widths of values in multiples of 16 bits.
  • values (list[int]) – Values to pack.
Returns:

Packed data.

Return type:

bytes

pdq.host.protocol.discrete_compensate(c)[source]

Compensate spline coefficients for discrete accumulators.

Given continuous-time b-spline coefficients, this function compensates for the effect of discrete time steps in the target devices.

The compensation is performed in-place.

pdq.host.usb module

class pdq.host.usb.PDQ(url=None, dev=None, **kwargs)[source]

Initialize PDQ USB/Parallel device stack.

Note

This device should only be used if the PDQ is intended to be configured using the USB connection and not via SPI.

Parameters:
  • url (str) – Pyserial device URL. Can be hwgrep:// style (search for serial number, bus topology, USB VID:PID combination), COM15 for a Windows COM port number, /dev/ttyUSB0 for a Linux serial port.
  • dev (file-like) – File handle to use as device. If passed, url is ignored.
  • **kwargs – See PDQBase .
close()[source]

Close the USB device handle.

flush()[source]

Flush pending data.

set_reg(adr, data, board)[source]

Set a register.

Parameters:
  • adr (int) – Register address to write to (0-3).
  • data (int) – Data to write (1 byte)
  • board (int) – Board to write to (0-0xe), 0xf for all boards.
write(data)[source]

Write data to the PDQ board over USB/parallel.

SOF/EOF control sequences are appended/prepended to the (escaped) data. The running checksum is updated.

Parameters:data (bytes) – Data to write.
write_mem(mem, adr, data, board=15)[source]

Write to channel memory.

Parameters:
  • mem (int) – Channel memory to write to.
  • data (bytes) – Data to write to memory.
  • adr (int) – Start address to write data to.

pdq.host.cli module

PDQ frontend.
Evaluates times and voltages, interpolates and uploads them.

usage: pdq [-h] [-s SERIAL] [-c CHANNEL] [-f FRAME] [-t TIMES] [-v VOLTAGES]
           [-o ORDER] [-a] [-k AUX_DAC] [-u DUMP] [-r] [-m] [-n] [-e] [-d]

Named Arguments

-s, --serial

device url [“hwgrep://”]

Default: “hwgrep://”

-c, --channel

channel: 3*board_num+dac_num [0]

Default: 0

-f, --frame

frame [0]

Default: 0

-t, --times

sample times (s) [“np.arange(5)*1e-6”]

Default: “np.arange(5)*1e-6”

-v, --voltages

sample voltages (V) [“(1-np.cos(t/t[-1]*2*np.pi))/2”]

Default: “(1-np.cos(t/t[-1]*2*np.pi))/2”

-o, --order

interpolation (0: const, 1: lin, 2: quad, 3: cubic) [3]

Default: 3

-a, --aux-miso

route MISO to AUX/F5 TTL output [False]

Default: False

-k, --aux-dac

DAC channel OR mask to AUX/F5 TTL output [0x7]

Default: 7

-u, --dump dump to file [None]
-r, --reset

do reset before

Default: False

-m, --multiplier
 

100MHz clock [False]

Default: False

-n, --disarm

disarm group [False]

Default: False

-e, --free

software trigger [False]

Default: False

-d, --debug

debug communications

Default: False

pdq.host.cli.main(dev=None, args=None)[source]

Test a PDQ stack.

Parse command line arguments, configures PDQ stack, interpolate the time/voltage data using a spline, generate a wavesynth program from the data and upload it to the specified channel. Then perform the desired arming/triggering/starting functions on the stack.

ARTIQ-facing components

pdq.artiq.spi module

class pdq.artiq.spi.PDQ(dmgr, spi_device, chip_select=1, **kwargs)[source]

PDQ smart arbitrary waveform generator stack.

Provides access to a stack of PDQ boards connected via SPI using PDQ gateware version 3 or later.

The SPI bus is wired with CS_N from the core device connected to F2 IN on the master PDQ, CLK connected to F3 IN, MOSI connected to F4 IN and MISO (optionally) connected to F5 OUT. F1 TTL Input Trigger remains as waveform trigger input. Due to hardware constraints, there can only be one board connected to the core device’s MISO line and therefore there can only be SPI readback from one board at any time.

Parameters:
  • spi_device – Name of the SPI bus this device is on.
  • chip_select – Value to drive on the chip select lines of the SPI bus during transactions.
get_reg(adr, board)[source]

Get a PDQ register.

Parameters:
  • adr – Address of the register (_PDQ_ADR_CONFIG, _PDQ_ADR_FRAME, _PDQ_ADR_CRC).
  • board – Board to access, 0xf to write to all boards.
Returns:

Register data (8 bit).

read_mem(mem, adr, data, board=15, buffer=8)[source]

Read from DAC channel waveform data memory.

Parameters:
  • mem – DAC channel memory to access (0 to 2).
  • adr – Start address.
  • data – Memory data. List of 16 bit integers.
  • board – Board to access (0-15) with 0xf = 15 being broadcast to all boards.
set_reg(adr, data, board)[source]

Set a PDQ register.

Parameters:
  • adr – Address of the register (_PDQ_ADR_CONFIG, _PDQ_ADR_FRAME, _PDQ_ADR_CRC).
  • data – Register data (8 bit).
  • board – Board to access, 0xf to write to all boards.
setup_bus(write_div=24, read_div=64)[source]

Configure the SPI bus and the SPI transaction parameters for this device. This method has to be called before any other method if the bus has been used to access a different device in the meantime.

This method advances the timeline by the duration of two RTIO-to-Wishbone bus transactions.

Parameters:
  • write_div – Write clock divider.
  • read_div – Read clock divider.
write_mem(mem, adr, data, board=15)[source]

Write to DAC channel waveform data memory.

Parameters:
  • mem – DAC channel memory to access (0 to 2).
  • adr – Start address.
  • data – Memory data. List of 16 bit integers.
  • board – Board to access (0-15) with 0xf = 15 being broadcast to all boards.

pdq.artiq.aqctl_pdq module

PDQ controller.

Use this controller for PDQ stacks that are connected via USB.

usage: aqctl_pdq [-h] [-d DEVICE] [--simulation] [--dump DUMP] [-r]
                 [-b BOARDS]

Named Arguments

-d, --device serial port
--simulation

do not open any device but dump data

Default: False

--dump

file to dump simulation data into

Default: “pdq_dump.bin”

-r, --reset

reset device [False]

Default: False

-b, --boards

number of boards [3]

Default: 3

pdq.artiq.mediator module

exception pdq.artiq.mediator.ArmError[source]

Raised when attempting to arm an already armed PDQ, to modify the program of an armed PDQ, or to play a segment on a disarmed PDQ.

exception pdq.artiq.mediator.FrameActiveError[source]

Raised when a frame is active and playback of a segment from another frame is attempted.

exception pdq.artiq.mediator.InvalidatedError[source]

Raised when attemting to use a frame or segment that has been invalidated (due to disarming the PDQ).

exception pdq.artiq.mediator.SegmentSequenceError[source]

Raised when attempting to play back a named segment which is not the next in the sequence.

Gateware

pdq.gateware.pdq module

class pdq.gateware.pdq.CRG(platform)[source]

PDQ Clock and Reset generator.

Parameters:platform (Platform) – PDQ Platform.
rst

Signal – Reset input.

dcm_sel

Signal – Select doubled clock. Input.

dcm_locked

Signal – DCM locked. Output.

cd_sys

ClockDomain – System clock domain driven.

cd_sys_n

ClockDomain – Inverted system clock domain driven.

class pdq.gateware.pdq.Pdq(*args, **kwargs)[source]

PDQ Top module.

Wires up USB FIFO reader gateware.ft245r.Ft345r_rx, clock and reset generator CRG, and the DAC output signals. Delegates the wiring of the remaining modules to PdqBase.

pads.g2_out is assigned the DCM locked signal.

Parameters:platform (Platform) – PDQ platform.
class pdq.gateware.pdq.PdqBase(ctrl_pads, mem_depths=(8192, 8192, 4096))[source]

PDQ Base configuration.

Used both in functional simulation and final gateware.

Holds the three gateware.dac.Dac and the communication handler gateware.comm.Comm.

Parameters:
  • ctrl_pads (Record) – Control pads for gateware.comm.Comm.
  • mem_depth (list[int]) – Memory depths for the DAC channels.
dacs

list – List of gateware.dac.Dac.

comm

Modulegateware.comm.Comm.

pdq.gateware.comm module

class pdq.gateware.comm.Arbiter(width=8)[source]

Simple arbiter for two framed data streams. Uses end-of-packet (eop) to detect that sink0 is inactive and yields to sink1.

class pdq.gateware.comm.Comm(ctrl_pads, dacs)[source]

USB Protocol handler.

Parameters:
  • ctrl_pads (Record) – Control signal pads.
  • dacs (list) – List of gateware.dac.Dac.
sink

Endpoint[bus_layout] – 8 bit data sink containing both the control sequencences and the data stream.

Control command handler.

Controls the input and output TTL signals, handles the excaped control commands.

Parameters:
  • pads (Record) – Pads containing the TTL input and output control signals
  • dacs (list) – List of gateware.dac.Dac.
rg

ResetGen

proto

Protocol

spi

SPISlave

class pdq.gateware.comm.FTDI2SPI[source]

Converts parallel data stream from FTDI chip into framed SPI-like data.

It uses the Unescaper to to detect escaped start-of-frame SOF and EOF characters.

sink

Endpoint – Raw data from FTDI parallel bus.

source

Endpoint – Framed data stream (eop asserted when there is no active frame).

class pdq.gateware.comm.Protocol(mems)[source]

Handles the register and memory protocols and reads/writes data in the channel memories.

Parameters:mems (list) – List of memories from gateware.dac.Dac.
sink

Endpoint – 8 bit data sink.

source

Endpoint – 8 bit data source for SPI MISO read-back.

board

Signal(4) – Board address.

config

Record – Configuration register.

frame

Signal(max=32) – Selected frame.

class pdq.gateware.comm.ResetGen(n=128)[source]

Reset generator.

Asserts reset for a given number of cycles when triggered.

Parameters:n (int) – number of cycles.
trigger

Signal – Trigger input.

reset

Signal – Reset output. Active high.

pdq.gateware.dac module

class pdq.gateware.dac.Dac(fifo=0, **kwargs)[source]

Output module.

Holds the Memory, the Parser, the Sequencer, and its two output line executors.

Parameters:
parser

The memory Parser.

out

The Sequencer and output executor. Connect its data to the DAC.

class pdq.gateware.dac.Dds(line, stb, inc)[source]

DDS spline interpolator.

The line data is interpreted as:

  • 16 bit amplitude offset
  • 32 bit amplitude first order derivative
  • 48 bit amplitude second order derivative
  • 48 bit amplitude third order derivative
  • 16 bit phase offset
  • 32 bit frequency word
  • 48 bit chirp
Parameters:
  • line (Record[line_layout]) – Next line to be executed. Input.
  • stb (Signal) – Load data from next line. Input.
  • inc (Signal) – Evolve clock enable. Input.
data

Signal[16] – Output data from this spline.

class pdq.gateware.dac.Parser(mem_depth=4096)[source]

Memory parser.

Reads memory controlled by TTL signals, builds lines, and submits them to its output.

Parameters:mem_depth (int) – Memory depth in 16 bit entries.
mem

Memory – Memory to read from.

source

Endpoint[line_layout] – Endpoint of lines read from memory. Output.

arm

Signal – Allow triggers. If disarmed, the next line will not be read. Instead, the Parser will return to the frame address table. Input.

start

Signal – Allow leaving the frame address table. Input.

frame

Signal[3] – Values of the frame selection lines. Input.

class pdq.gateware.dac.Sequencer[source]

Line sequencer.

Controls execution of a line. Owns the executors that evolve the line data and sums them together to generate the output. Also manages the line duration counter, the 2**shift counter and the acknowledgment of new line data when the previous is finished.

sink

Endpoint[line_layout] – Line data sink.

trigger

Signal – Trigger input.

arm

Signal – Arm input.

aux

Signal – TTL AUX (F5) output.

silence

Signal – Silence DAC clocks output.

data

Signal[16] – Output value to be send to the DAC.

class pdq.gateware.dac.Volt(line, stb, inc)[source]

DC bias spline interpolator.

The line data is interpreted as a concatenation of:

  • 16 bit amplitude offset
  • 32 bit amplitude first order derivative
  • 48 bit amplitude second order derivative
  • 48 bit amplitude third order derivative
Parameters:
  • line (Record[line_layout]) – Next line to be executed. Input.
  • stb (Signal) – Load data from next line. Input.
  • inc (Signal) – Evolve clock enable. Input.
data

Signal[16] – Output data from this spline.

pdq.gateware.platform module

class pdq.gateware.platform.Platform[source]

PDQ Platform.

  • Xilinx Spartan 3A 500E in a PQ208 package.
  • 50 MHz single ended input clock.
  • Single FT245R USB parallel FIFO.
  • Three 16 bit LVDS DACs.
  • Several TTL control lines.

pdq.gateware.escape module

class pdq.gateware.escape.Unescaper(layout, escape=165)[source]

Split a data stream into an escaped low bandwidth command stream and an unescaped high bandwidth data stream.

Items in the input stream that are escaped by being prefixed with the escape character, will be directed to the source_b output Endpoint.

Items that are not escaped, and the escaped escape character itself are directed at the source_a output Endpoint.

Parameters:
  • layout (layout) – Stream layout to split.
  • escape (int) – Escape character.
sink

Endpoint[layout] – Input stream.

source0

Endpoint[layout] – High bandwidth unescaped data Endpoint.

source1

Endpoint[layout] – Low bandwidth command Endpoint.

pdq.gateware.ft245r module

class pdq.gateware.ft245r.Ft245r_rx(pads, clk=10.0)[source]

FTDI FT345R synchronous reader.

Parameters:
  • pads (Record[ft345r_layout]) – Pads to the FT245R.
  • clk (float) – Clock period in ns.
source

Endpoint[bus_layout] – 8 bit data source. Output.

busy

Signal – Data available but not acknowledged by sink. Output.

class pdq.gateware.ft245r.SimFt245r_rx(data)[source]

pdq.gateware.spi module

class pdq.gateware.spi.Debouncer(cycles=1)[source]

Debounce a signal.

The initial change on input is passed through immediately. But further changes are suppressed for cycles.

Parameters:cycles (int) – Block furhter level changes for that many cycles after an initial change.
i

Signal – Input, needs a MultiReg in front of it if this is an asynchronous signal.

o

Signal – Debounced output.

class pdq.gateware.spi.SPISlave(*args, **kwargs)[source]

SPI slave.

  • CLK_PHA, CLK_POL = 0,0
  • MSB first
Parameters:width (int) – Shift register width in bits.
spi

Record – SPI bus record consisting of cs_n, clk, mosi, miso, oe_s, and oe_m. Use oe_s (driven by the slave) to wire up a tristate half-duplex data line. Use oe_m on the master side.

data

Endpoint – SPI parallel communication stream.

  • mosi: width bits read on the mosi line in the previous clock
    cycles
  • miso: width bits to be written on miso line in the next
    cycles
  • stb: data available in mosi and data read from miso.
  • ack: in half-duplex mode, drive miso on the combined
    miso/mosi data line
cs_n

Signal – use to s.reset.eq(s.cs_n) and for framing logic.

class pdq.gateware.spi.ShiftRegister(width)[source]

Shift register for an SPI slave.

Parameters:width (int) – Register width in bits.
i

Signal – Serial input.

o

Signal – Serial output.

data

Signal(width) – Content of the shift register.

next

Signal(width) – Combinatorial content of the register in the next cycle.

stb

Signal – Strobe signal indicating that width bits have been shifted (in and out) and the register value can be swapped.