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:
|
||||
"""
|
||||
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):
|
||||
self.channel = channel
|
||||
self.base_addr = (self.channel.phaser.channel_base + 1 +
|
||||
|
@ -1314,7 +1418,7 @@ class Miqro:
|
|||
(asf & 0xffff) | (pow << 16))
|
||||
|
||||
@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
|
||||
ftw = int32(round(frequency*((1 << 30)/(62.5*MHz))))
|
||||
asf = int32(round(amplitude*0xffff))
|
||||
|
|
Loading…
Reference in New Issue