qick.qick
The lower-level driver for the QICK library. Contains classes for interfacing with the SoC.
Classes
|
AxisSwitch class to control Xilinx AXI-Stream switch IP |
|
This class loads, initializes, and provides access to the QICK firmware. |
|
Extends the xrfdc driver. |
- class qick.qick.AxisSwitch(*args: Any, **kwargs: Any)[source]
Bases:
SocIPAxisSwitch class to control Xilinx AXI-Stream switch IP
- class qick.qick.RFDC(*args: Any, **kwargs: Any)[source]
Bases:
SocIP,RFdcExtends the xrfdc driver. Calling xrfdc functions is slow (typically ~8 ms per call). We therefore cache parameters that need to be set in program initialization, such as Nyquist zone and frequency.
- map_clocks(soc)[source]
Map the clock networks driving the various IP blocks, and determine the resulting constraints on the RFDC sampling rates. This method gets run early in QickSoc initialization because it’s needed to check validity of a requested set of sampling freqs.
This code assumes that the RFDC configuration dictionary has been filled (this happens in RFDC driver initialization). It does not assume that configure_connections() has been run on all drivers.
- restart_all_tiles()[source]
Restart all DAC and ADC tiles using XRFdc_StartUp.
This will re-lock tile PLLs, reset DDS phases to random values, and reset all logic driven by RF clocks. It won’t reset RFDC registers (e.g. if you set custom sampling rates, those will stay in place).
- valid_sample_rates(tiletype, tile)[source]
Return an array of valid sample rates. This code is based on XRFdc_SetPLLConf().
- round_sample_rate(tiletype, tile, fs_target)[source]
Return the closest achievable sample rate to the requested value.
- configure_sample_rates(dac_sample_rates=None, adc_sample_rates=None)[source]
Set the tile sample rates. This should only be called as part of initialization.
- Parameters:
dac_sample_rates (dict[int, float]) – Sample rates to override the values compiled into the firmware. This should be a dictionary mapping DAC tiles to sample rates (in megasamples per second).
adc_sample_rates (dict[int, float]) – Sample rates to override the values compiled into the firmware. This should be a dictionary mapping ADC tiles to sample rates (in megasamples per second).
- set_mixer_freq(blockname, f, blocktype='dac', phase_reset=True, force=False)[source]
Set the NCO frequency that will be mixed with the generator output (for DAC) or raw ADC data (for ADC).
Note that the RFdc driver does its own math to round the frequency to the NCO’s frequency step. If you want predictable behavior, the frequency you use here should already be rounded. Rounding is normally done for you as part of AbsQickProgram.declare_gen().
- blocknameint
channel ID (2-digit string)
- ffloat
NCO frequency (MHz)
- blocktypestr
‘dac’ or ‘adc’
- force: bool
force update, even if the setting is the same
- phase_resetbool
if we change the frequency, also reset the NCO’s phase accumulator
- set_nyquist(blockname, nqz, blocktype='dac', force=False)[source]
Sets channel to operate in Nyquist zone nqz. This setting doesn’t change the DAC output frequencies: you will always have some power at both the demanded frequency and its image(s). Setting the NQZ to 2 increases output power in the 2nd/3rd Nyquist zones. See “RF-DAC Nyquist Zone Operation” in PG269.
- get_nyquist(blockname, blocktype='dac')[source]
Get the current Nyquist zone setting for a channel.
- get_adc_attenuator(blockname)[source]
Read the ADC’s built-in step attenuator.
Only available for RFSoC Gen 3 (ZCU216, RFSoC4x2).
- set_adc_attenuator(blockname, attenuation)[source]
Set the ADC’s built-in step attenuator. The requested value will be rounded to the nearest valid value (0-27 dB inclusive, 1 dB steps).
Only available for RFSoC Gen 3 (ZCU216, RFSoC4x2).
- set_adc_cal(blockname, cal, calblocks)[source]
Set calibration coefficients for an ADC.
See the Xilinx documentation for explanations and cautions:
https://docs.amd.com/r/en-US/pg269-rf-data-converter/Getting/Setting-Calibration-Coefficients
- restart_adc_tile(tile)[source]
Restart an ADC tile.
This is useful as a way to rerun the OCB2 offset calibration, though of course it resets all of the calibrations. WHatever voltage the ADCs on this tile are seeing when you run this, that will be 0 ADU.
- Parameters:
tile (int) – ADC tile number (0-3)
- freeze_adc_cal(blockname)[source]
Freeze an ADC’s calibration (stop the background calibration).
See the Xilinx documentation:
https://docs.amd.com/r/en-US/pg269-rf-data-converter/Background-Calibration-Process
- Parameters:
blockname (str) – Channel ID (2-digit string)
- unfreeze_adc_cal(blockname, calblocks=None)[source]
Unfreeze an ADC’s calibration (resume the background calibration).
See the Xilinx documentation:
https://docs.amd.com/r/en-US/pg269-rf-data-converter/Background-Calibration-Process
- Parameters:
blockname (str) – Channel ID (2-digit string)
- class qick.qick.QickSoc(*args: Any, **kwargs: Any)[source]
Bases:
Overlay,QickConfigThis class loads, initializes, and provides access to the QICK firmware.
- Parameters:
bitfile (str) – Path to the firmware bitfile. This should end with .bit, and the corresponding .hwh file must be in the same directory.
download (bool) – Load the bitfile into the FPGA logic. If you are certain that the bitfile you specified is already running, you can use False here.
no_tproc (bool) – Use if this is a special firmware that doesn’t have a tProcessor.
no_rf (bool) – Use if this is a special firmware that doesn’t have an RF data converter.
force_init_clks (bool) – Re-initialize the board clocks regardless of whether they appear to be locked. Specifying (as True or False) the clk_output or external_clk options will also force clock initialization.
clk_output (bool or None) – If true, output a copy of the RF reference. This option is supported for the ZCU111 (get 122.88 MHz from J108) and ZCU216 (get 245.76 MHz from OUTPUT_REF J10).
external_clk (bool or None) – If true, lock the board clocks to an external reference. This option is supported for the ZCU111 (put 12.8 MHz on External_REF_CLK J109), ZCU216 (put 10 MHz on INPUT_REF_CLK J11), and RFSoC 4x2 (put 10 MHz on CLK_IN).
dac_sample_rates (dict[int, float] or None) – Sample rates to override the values compiled into the firmware. This should be a dictionary mapping DAC tiles to sample rates (in megasamples per second).
adc_sample_rates (dict[int, float] or None) – Sample rates to override the values compiled into the firmware. This should be a dictionary mapping ADC tiles to sample rates (in megasamples per second).
- map_signal_paths(no_tproc)[source]
Make lists of signal generator, readout, and buffer blocks in the firmware. Also map the switches connecting the generators and buffers to DMA. Fill the config dictionary with parameters of the DAC and ADC channels.
- config_clocks(force_init_clks, clk_output, external_clk)[source]
Configure PLLs if requested, or if any ADC/DAC is not locked. The ADC/DAC PLL lock status is read through the RFDC IP, so this assumes that the bitstream has already been downloaded. The reference clock frequency must already have been read from the firmware config.
- clocks_locked()[source]
Checks whether the DAC and ADC PLLs are locked. This can only be run after the bitstream has been downloaded. A failure usually means the FPGA is not getting a good reference clock from the on-board clock chips.
- Returns:
clock status
- Return type:
- pl_reset(reinit=True)[source]
Reset all firmware IP blocks. This pulses the pl_resetn0 line from the PS (also known as the “fabric reset” or the “PS-PL reset”). Every firmware block’s reset logic is triggered by this pulse. The main visible effect of this reset is to reset the start times of all the phase-coherent DDS oscillators.
Some firmware blocks have startup code in their __initialize__() to configure the block after the firmware is loaded. That configuration gets wiped out by a PL reset, so this method also re-configures those blocks.
More info on the PL reset: The reset sequence is defined in psu_ps_pl_reset_config_data() in psu_init.c. You can find this in the BSP or the firmware project files. The reset sequence and the memory addresses invovled appear to be the same for all RFSoCs.
https://support.xilinx.com/s/article/68962 https://support.xilinx.com/s/question/0D52E00006lLhBnSAK/zynq-ultrascale-howto-reset-the-pl https://docs.amd.com/r/en-US/ug1137-zynq-ultrascale-mpsoc-swdev/GPIO-Reset-to-PL https://docs.amd.com/r/en-US/pg201-zynq-ultrascale-plus-processing-system/Fabric-Reset-Enable
- Parameters:
reinit (bool) – Reinitialize firmware blocks. False is OK if you haven’t run map_signal_paths() yet (which triggers block initialization).
- get_sample_rates()[source]
Produce dictionaries of the current sample rates of the DAC and ADC tiles. A dictionary of this form can be used to configure the sample rates at SoC initialization.
- valid_sample_rates(tiletype, tile)[source]
Return an array of valid sample rates. This does not account for dependencies due to clock groups, or the restriction that you’re not allowed to raise the sample rate.
- Parameters:
- Returns:
Array of sample rates, in Msps
- Return type:
- round_sample_rate(tiletype, tile, fs_target)[source]
Return the closest achievable sample rate to the requested value. This does not account for dependencies due to clock groups, or the restriction that you’re not allowed to raise the sample rate.
- get_decimated(ch, address=0, length=None)[source]
Acquires data from the readout decimated buffer
- Parameters:
- Returns:
List of I and Q decimated arrays
- Return type:
- get_accumulated(ch, address=0, length=None)[source]
Acquires data from the readout accumulated buffer
- configure_readout(ch, ro_regs)[source]
Configure readout channel output style and frequency. This method is only for use with PYNQ-configured readouts.
- config_avg(ch, address=0, length=1, edge_counting=False, high_threshold=1000, low_threshold=0)[source]
Configure accumulated buffer; must then enable using enable_buf()
- config_buf(ch, address=0, length=1)[source]
Configure decimated buffer; must then enable using enable_buf()
- enable_buf(ch, enable_avg=True, enable_buf=True)[source]
Enable capture of accumulated and/or decimated data for a buffer
- load_weights(ch, data, addr=0)[source]
Load weights array to a weighted buffer.
- Parameters:
ch (int) – Readout channel to configure
data (numpy.ndarray of int16) – array of 16-bit (I, Q) values for weights
address (int) – starting address
- load_envelope(ch, data, addr)[source]
Load envelope data into a signal generator.
- Parameters:
ch (int) – Generator channel to configure
data (numpy.ndarray of int16) – Array of (I, Q) values for pulse envelope
addr (int) – Starting address
- set_mixer_freq(ch, f, ro_ch=None, phase_reset=True)[source]
Set mixer frequency for a signal generator. If the generator does not have a mixer, you will get an error.
- Parameters:
ch (int) – DAC channel (index in ‘gens’ list)
f (float) – Mixer frequency (in MHz)
ro_ch (int) – readout channel (index in ‘readouts’ list) for frequency matching use None if you don’t want mixer freq to be rounded to a valid readout frequency
phase_reset (bool) – if this changes the frequency, also reset the phase (so if we go to freq=0, we end up on the real axis)
- set_adc_attenuator(blockname, attenuation)[source]
Set the RFSoC ADC’s built-in step attenuator. The requested value will be rounded to the nearest valid value (0-27 dB inclusive, 1 dB steps).
Only available for RFSoC Gen 3 (ZCU216, RFSoC4x2). See https://docs.amd.com/r/en-US/pg269-rf-data-converter/Digital-Step-Attenuator-Gen-3/DFE.
- Parameters:
- Returns:
The rounded attenuation value that was actually set (dB)
- Return type:
- get_adc_attenuator(blockname)[source]
Read the RFSoC ADC’s built-in step attenuator.
Only available for RFSoC Gen 3 (ZCU216, RFSoC4x2). See https://docs.amd.com/r/en-US/pg269-rf-data-converter/Digital-Step-Attenuator-Gen-3/DFE.
- freeze_adc_cals(blocknames)[source]
Freeze the calibrations (stop the background calibration) of a list of RFSoC ADCs.
See the Xilinx documentation:
https://docs.amd.com/r/en-US/pg269-rf-data-converter/Background-Calibration-Process
- unfreeze_adc_cals(blocknames)[source]
Unfreeze the calibrations (resume the background calibration) of a list of RFSoC ADCs.
See the Xilinx documentation:
https://docs.amd.com/r/en-US/pg269-rf-data-converter/Background-Calibration-Process
- config_mux_gen(ch, tones)[source]
Set up a list of tones all at once, using raw (integer) units. If the supplied list of tones is shorter than the number supported, the extra tones will have their gains set to 0.
- config_mux_readout(pfbpath, cfgs, sel=None)[source]
Set up a list of readout frequencies all at once, using raw (integer) units.
- set_iq(ch, f, i, q, ro_ch=None, phase_reset=True)[source]
Set frequency, I, and Q for a constant-IQ output.
- Parameters:
ch (int) – DAC channel (index in ‘gens’ list)
f (float) – frequency (in MHz)
i (float) – I value (in range -1 to 1)
q (float) – Q value (in range -1 to 1)
ro_ch (int) – readout channel (index in ‘readouts’ list) for frequency matching use None if you don’t want freq to be rounded to a valid readout frequency
phase_reset (bool) – if this changes the frequency, also reset the phase (so if we go to freq=0, we end up on the real axis)
- load_bin_program(binprog, load_mem=True)[source]
Write the program to the tProc program memory.
- Parameters:
binprog (numpy.ndarray or dict) – compiled program (format depends on tProc version)
load_mem (bool) – write waveform and data memory now (can do this later with reload_mem())
- reload_mem()[source]
Reload the waveform and data memory, overwriting any changes made by running the program.
- load_mem(data, mem_sel='dmem', addr=0)[source]
Write a block of the selected tProc memory. For tProc v1 only the data memory (“dmem”) is valid. For tProc v2 the program, data, and waveform memory are all accessible.
- Parameters:
data (numpy.ndarray of int) – Data to be loaded 32-bit array of shape (n, 8) for pmem and wmem, (n) for dmem
mem_sel (str) – “pmem”, “dmem”, “wmem”
addr (int) – Starting write address
- read_mem(length, mem_sel='dmem', addr=0)[source]
Read a block of the selected tProc memory. For tProc v1 only the data memory (“dmem”) is valid. For tProc v2 the program, data, and waveform memory are all accessible.
- Parameters:
- Returns:
32-bit array of shape (n, 8) for pmem and wmem, (n) for dmem
- Return type:
- start_src(src)[source]
Sets the start source of tProc
- Parameters:
src (str) – start source “internal” or “external”
- start_tproc()[source]
Start the tProc.
If the tProc is configured for external start, this does nothing (the tProc will start on the first start signal it sees after external start is enabled).
- stop_tproc(lazy=False)[source]
Stop the tProc. This is somewhat slow (tens of ms) for tProc v1.
- Parameters:
lazy (bool) – Only stop the tProc if it’s easy (i.e. do nothing for v1)
- clear_tproc_counter(addr)[source]
Initialize the tProc shot counter. For tProc v1, the data memory at the specified address is zeroed. For tProc v2, the tProc is reset, which zeroes all registers (the address is ignored).
Typical tProc v2 programs will also initialize the counter registers at the beginning of the program, but zeroing the counter now is important to distinguish “program waiting for external start” from “program complete.”
- Parameters:
addr (int) – Counter address
- get_tproc_counter(addr)[source]
Read the tProc shot counter. For tProc V1, this accesses the data memory at the given address. For tProc V2, this accesses one of the two special AXI-readable registers.
- reset_gens()[source]
Reset the tProc and run a minimal tProc program that drives all signal generators with 0’s. Useful for stopping any periodic or stdysel=”last” outputs that may have been driven by a previous program.
- start_readout(total_shots, counter_addr=1, ch_list=None, reads_per_shot=1, stride=None)[source]
Start a streaming readout of the accumulated buffers.
- poll_data(totaltime=0.1, timeout=None)[source]
Get as much data as possible from the streamer data queue. Stop when any of the following conditions are met: * all the data has been transferred (based on the total_count) * we got data, and it has been totaltime seconds since poll_data was called * timeout is defined, and the timeout expired without getting new data in the queue If there are errors in the error queue, raise the first one.
- prepare_round()[source]
This runs before a program starts running. This is called by acquire/acquire_decimated/run_rounds; user code should not call it.
By default this does nothing, but a subclass of QickSoc may override this.
- cleanup_round()[source]
This runs after a program has finished running. This is called by acquire/acquire_decimated/run_rounds; user code should not call it.
By default this does nothing, but a subclass of QickSoc may override this.
- clear_ddr4(length=None)[source]
Clear the DDR4 buffer, filling it with 0’s. This is not necessary (the buffer will overwrite old data), but may be useful for debugging. Clearing the full buffer (4 GB) typically takes 4-5 seconds.
- Parameters:
length (int) – Number of samples to clear (starting at the beginning of the buffer). If None, clear the entire buffer.
- get_ddr4(nt, start=None)[source]
Get data from the DDR4 buffer. The first samples (typically 401 or 801) of the buffer are always stale data from the previous acquisition.
- Parameters:
nt (int) – Number of data transfers (each transfer is 128 or 256 decimated samples) to retrieve. If start=None, the amount of data will be reduced (see below).
start (int) – Number of samples to skip at the beginning of the buffer. If a value is specified, the end address of the transfer window will also be incremented. If None, the junk at the start of the buffer will be skipped but the end address will not be incremented. This reduces the amount of data, giving you exactly the block of valid data from a DDR4 trigger with the same value of nt.
- arm_ddr4(ch, nt, force_overwrite=False)[source]
Prepare the DDR4 buffer to take data. This must be called before starting a program that triggers the buffer. Once the buffer is armed, the first trigger it receives will cause the buffer to record the specified amount of data. Later triggers will have no effect.
- Parameters:
ch (int) – The readout channel to record (index in ‘readouts’ list).
nt (int) – Number of data transfers to record; the number of IQ samples/transfer (128 or 256) is printed in the QickSoc config. Note that the amount of useful data is less (see
get_ddr4)force_overwrite (bool) – Allow a DDR4 acqusition that exceeds the DDR4 memory capacity. The memory will be used as a circular buffer: later transfers will wrap around to the beginning of the memory and overwrite older data.
- arm_mr(ch)[source]
Prepare the Multi-Rate buffer to take data. This must be called before starting a program that triggers the buffer. Once the buffer is armed, the first trigger it receives will cause the buffer to record until the buffer is filled. Later triggers will have no effect.
- Parameters:
ch (int) – The readout channel to record (index in ‘readouts’ list).
- get_mr(start=None)[source]
Get data from the multi-rate buffer. The first 8 samples are always stale data from the previous acquisition. The transfer window always extends to the end of the buffer.
- Parameters:
start (int) – Number of samples to skip at the beginning of the buffer. If None, the junk at the start of the buffer is skipped.
- tt_readmem(blk, mem)[source]
Read one of the specified time-tagger block’s memories. Reading a time-tagger memory clears it.
- tt_config(blk, threshold, wr_smp=32, filt=False, slope=False, invert=False, interp=0, deadtime=5)[source]
Configure the specified time-tagger block.
- Parameters:
blk (int) – The time tagger block to flush (index in `time_taggers’ list).
threshold (int) – Tag threshold (-2^15 through 2^15-1).
wr_smp (int) – Number of 8-sample chunks to capture per tag in the SMP memory (1 through 32). If this time tagger has no SMP memory, this is ignored.
filt (bool) – Trigger on signal after a 2-sample smoothing filter.
slope (bool) – Trigger on slope (difference between consecutive samples), not level.
invert (bool) – Trigger on inverted signal.
interp (int) – Number of bits for interpolation (0 through 7).
deadtime (int) – Minimum time (in fabric ticks, 8 samples) between one tag and the next (5 through 255). This should be larger than the expected pulse width, otherwise you will get double-triggering on the same pulse.