forked from M-Labs/artiq
add some docs
This commit is contained in:
parent
fa3678f8a3
commit
876f26ee30
|
@ -1279,6 +1279,110 @@ class PhaserOscillator:
|
||||||
|
|
||||||
|
|
||||||
class Miqro:
|
class Miqro:
|
||||||
|
"""
|
||||||
|
Miqro pulse generator.
|
||||||
|
|
||||||
|
Notes
|
||||||
|
-----
|
||||||
|
* The `_mu` suffix in method names refers to parameters and data in "machine units",
|
||||||
|
i.e. integers. Conversion methods and wrappers to convert from SI units (Hz frequency,
|
||||||
|
full scale amplitude, turns phase, seconds time) are provided.
|
||||||
|
* The annotation that some operation is "expensive" does not mean it is impossible, just
|
||||||
|
that it may take a significant amount of time and resources to execute such that
|
||||||
|
it may be impractical when used often or during fast pulse sequences.
|
||||||
|
They are intended for use in calibration and initialization.
|
||||||
|
|
||||||
|
Functionality
|
||||||
|
-------------
|
||||||
|
A Miqro instance represents one RF output.
|
||||||
|
The output is generated by with the following data flow:
|
||||||
|
|
||||||
|
### Oscillators
|
||||||
|
* There are n_osc = 16 oscillators with oscillator IDs 0..n_osc-1.
|
||||||
|
* Each oscillator outputs one tone at any given time
|
||||||
|
I/Q (quadrature, a.k.a. complex) 2x16 bit signed data
|
||||||
|
at tau = 4 ns sample intervals, 250 MS/s, Nyquist 125 MHz, bandwidth 200 MHz
|
||||||
|
(from f = -100..+100 MHz, taking into account the interpolation anti-aliasing
|
||||||
|
filters in subsequent interpolators),
|
||||||
|
32 bit frequency (f) resolution (~ 1/16 Hz),
|
||||||
|
16 bit unsigned amplitude (a) resolution
|
||||||
|
16 bit phase (p) resolution
|
||||||
|
* The output phase p' of each oscillator at time t (boot/reset/initialization of the
|
||||||
|
device at t=0) is then p' = f*t + p (mod 1 turn) where f and p are the
|
||||||
|
(currently active) profile frequency and phase.
|
||||||
|
The terms "phase coherent" and "phase tracking" are defined to refer to this
|
||||||
|
choice of oscillator output phase p'.
|
||||||
|
Note that the phase p is not accumulated (on top of previous
|
||||||
|
phases, previous profiles, or oscillator history). It is "absolute" in the
|
||||||
|
sense that frequency f and phase p fully determine oscillator
|
||||||
|
output phase p' at time t. This is unlike typical DDS behavior.
|
||||||
|
* Frequency, phase and amplitude of each oscillator are configurable by selecting one of
|
||||||
|
n_profile = 32 profiles 0..n_profile-1. This selection is fast and can be done for
|
||||||
|
each pulse.
|
||||||
|
* Note: one profile per oscillator (usually profile index 0) should be reserved
|
||||||
|
for the NOP (no operation, identity) profile, usually with zero
|
||||||
|
amplitude.
|
||||||
|
* Data for each profile for each oscillator can be configured
|
||||||
|
individually. Storing profile data should be considered "expensive".
|
||||||
|
|
||||||
|
### Summation
|
||||||
|
* The oscillator outputs are added together (wrapping addition).
|
||||||
|
* The user must ensure that the sum of oscillators outputs does
|
||||||
|
not exceed the (16 bit signed) data range. In general that means that the sum of the
|
||||||
|
amplitudes must not exceed the range.
|
||||||
|
|
||||||
|
### Shaper
|
||||||
|
* The summed output stream is then multiplied with a the complex-valued output of a
|
||||||
|
triggerable shaper.
|
||||||
|
* Triggering the shaper corresponds to passing a pulse from all
|
||||||
|
oscillators to the RF output.
|
||||||
|
* Any previously staged profiles and phase offsets become active simultaneously
|
||||||
|
(on the same output sample) when triggering the shaper.
|
||||||
|
* The shaper reads (replays) window samples from a memory of size n_window = 1 << 10 starting
|
||||||
|
and stopping at memory locations specified.
|
||||||
|
* Each window memory segment starts with a header determining segment
|
||||||
|
length and interpolation parameters.
|
||||||
|
* The window samples are interpolated by a factor (rate change) r where log2(r) = 0..n_cic=12
|
||||||
|
selectable when triggering.
|
||||||
|
* The interpolation order is constant, linear, quadratic, or cubic. This
|
||||||
|
corresponds to interpolation modes from rectangular window (1st order CIC)
|
||||||
|
or zero order hold) and to Parzen window (4th order CIC, cubic spline),
|
||||||
|
selectable when triggering.
|
||||||
|
* This results in support for pulse lengths of between tau and a bit more than
|
||||||
|
(1 << 12 + 10) tau ~ 17 ms.
|
||||||
|
* Windows can be configured to be head-less and/or tail-less, meaning, they
|
||||||
|
do not feed zero-amplitude samples into the shaper before and after
|
||||||
|
each window. This is used to implement pulses with arbitrary length or
|
||||||
|
CW output.
|
||||||
|
* The window memory can be segmented by choosing different start indices
|
||||||
|
to support different windows selectable when triggering.
|
||||||
|
|
||||||
|
### DAC
|
||||||
|
* This section of the data flow is analogous to the `base` Phaser mode.
|
||||||
|
* The DAC receives the 250 MS/s I/Q data stream and interpolates it to 1 GS/s I/Q
|
||||||
|
(with a bandwidth 200 MHz).
|
||||||
|
* It then applies a (expensive to change) frequency offset of
|
||||||
|
f1 = -400 MHz..400 MHz.
|
||||||
|
* Then the DAC converts the data stream to 2 analog outputs I and Q.
|
||||||
|
* The signals go through two anti-aliasing filters with 340 MHz 3dB bandwidth.
|
||||||
|
|
||||||
|
### IQ Mixer and PLL (Upconverter variant)
|
||||||
|
* The analog I and Q signals after the filter are upconverted in a single-sideband IQ
|
||||||
|
mixer with a f2 = 0.3 GHz..4.8 GHz LO (the "carrier").
|
||||||
|
* The output goes through a digitally switchable attenuator (0..31.5 dB attenuation) and
|
||||||
|
is available at an SMA output with a typical max signal level of 0 to -10 dBm (TBC).
|
||||||
|
|
||||||
|
### Overall properties
|
||||||
|
* The resulting phase of that signal is
|
||||||
|
(f + f1 + f2)*t + p + s(t - t0) + p1 + p2 (mod 1 turn)
|
||||||
|
where p1 and p2 are constant but arbitrary and undetermined phase offsets of the
|
||||||
|
two (common) upconversion stages, s(t - t0) is the phase of the interpolated
|
||||||
|
shaper output, and t0 is the trigger time (fiducial of the shaper).
|
||||||
|
Unsurprisingly the frequency is the derivative of the phase.
|
||||||
|
* The minimum time to change profiles and phase offsets is ~128 ns (estimate, TBC).
|
||||||
|
This is the minimum practical pulse interval.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, channel):
|
def __init__(self, channel):
|
||||||
self.channel = channel
|
self.channel = channel
|
||||||
self.base_addr = (self.channel.phaser.channel_base + 1 +
|
self.base_addr = (self.channel.phaser.channel_base + 1 +
|
||||||
|
@ -1314,7 +1418,7 @@ class Miqro:
|
||||||
(asf & 0xffff) | (pow << 16))
|
(asf & 0xffff) | (pow << 16))
|
||||||
|
|
||||||
@kernel
|
@kernel
|
||||||
def set_profile(oscillator, profile, frequency, amplitude, phase=0.):
|
def set_profile(self, oscillator, profile, frequency, amplitude, phase=0.):
|
||||||
# frequency is interpreted in the Nyquist sense, i.e. aliased
|
# frequency is interpreted in the Nyquist sense, i.e. aliased
|
||||||
ftw = int32(round(frequency*((1 << 30)/(62.5*MHz))))
|
ftw = int32(round(frequency*((1 << 30)/(62.5*MHz))))
|
||||||
asf = int32(round(amplitude*0xffff))
|
asf = int32(round(amplitude*0xffff))
|
||||||
|
|
Loading…
Reference in New Issue