From a84dc7414839740f00996fd458368b875582d82e Mon Sep 17 00:00:00 2001 From: lharnaldi Date: Fri, 1 May 2026 11:12:33 -0500 Subject: [PATCH 1/3] Add SGv6 documentation --- docs/firmware.rst | 18 +- docs/signal_generator_v6.rst | 359 +++++++++++++++++++++++++++++++++++ 2 files changed, 376 insertions(+), 1 deletion(-) create mode 100644 docs/signal_generator_v6.rst diff --git a/docs/firmware.rst b/docs/firmware.rst index 401724bd1..31604d566 100644 --- a/docs/firmware.rst +++ b/docs/firmware.rst @@ -8,7 +8,7 @@ This system includes the following components: * 2 input channels connected to ADCs. * 1 instance of tProcessor 64-bit instructions, 32-bit registers. -Sampling frequency of ADC blocks is given by the variable ``soc.fs_adc``. Sampling frequency of DACs is stored in variable ``soc.fs_adc``. Fast-speed buffers were removed to save memory space. Raw data can be captured after x8 down-sampling. +Sampling frequency of ADC blocks is given by the variable ``soc.fs_adc``. Sampling frequency of DACs is stored in variable ``soc.fs_dac``. Fast-speed buffers were removed to save memory space. Raw data can be captured after x8 down-sampling. Output channels driving DACs use the updated Signal Generator V4, which has the possibility to upload I/Q envelopes, and uses 32-bit resolution for both frequency and phase. The format of the control word was updated accordingly to accomodate the bits. See example asm files for a detailed description of the fields. The maximum length of the I/Q envelopes is given by the variable ``soc.gens[i].MAX_LENGTH``. @@ -73,3 +73,19 @@ Firmware parameters * tProc stack size: 256 samples of 32 bits, 1k Byte total * Phase conversion from deg to reg: Phase resolution is 32-bit, that is :math:`\Delta \phi = 2 \pi /2^{32}` or :math:`360/2^{32}` * Gain is 16-bit signed [-32768,32767] + +Intellectual Property Cores +--------------------------- + +The firmware is built around the following IP cores: + +* Xilinx RF Data Converter IP, which provides the interface to the ADCs and DACs. +* Xilinx AXI DMA IP, which provides the interface to the tProcessor for data transfer +* Custom-designed IPs for the readout block, average and buffer block, and signal generator block, which are described in more detail in the `QICK assembly language documentation` + +.. toctree:: + :maxdepth: 2 + :caption: Signal Generator v6 + :hidden: + + signal_generator_v6 \ No newline at end of file diff --git a/docs/signal_generator_v6.rst b/docs/signal_generator_v6.rst new file mode 100644 index 000000000..5c43fd4e7 --- /dev/null +++ b/docs/signal_generator_v6.rst @@ -0,0 +1,359 @@ +======================================================== +Signal Generator v6 – QICK +======================================================== + +.. contents:: + :local: + :depth: 2 + +.. image:: _static/qick_sg_v6.png + :alt: QICK Signal Generator v6 block diagram + :align: center + :width: 700px + +The **Signal Generator v6** (SG-v6) is the newest version of QICK’s +on-chip waveform engine. It supersedes SG-v5 with a richer feature set, +lower latency, and full compatibility with all QICK-compatible boards +(ZCU216, ZCU111, etc.). The module lives in the ``qick`` firmware +repository under ``firmware/ip/axis_signal_gen_v6/`` and is exposed to Python +through the :class:`qick.drivers.generator` class. + +-------------------------------------------------------------------- +1. General Description +-------------------------------------------------------------------- + +The **Signal Generator v6 (SG-v6)** is the QICK waveform generation module +implemented in the ``signal_gen_top`` firmware entity. Its architecture combines: + +* A **dual-port memory (BRAM)** to store envelope samples. +* A **FIFO** to queue 160-bit waveform descriptors. +* A central ``signal_gen`` block that reads the FIFO, accesses memory, and generates + the output through N parallel DDS channels. + +The module supports two synthesis-configurable operating modes: + +* **DDS Mode** (``GEN_DDS = "TRUE"``): generates complex tones with upconversion. +* **Baseband Mode** (``GEN_DDS = "FALSE"``): outputs only the envelope, without DDS. + +And two envelope types: + +* **COMPLEX** (``ENVELOPE_TYPE = "COMPLEX"``): separate memories for real and imaginary parts. +* **REAL** (``ENVELOPE_TYPE = "REAL"``): real part only; the imaginary part is forced to zero. + +-------------------------------------------------------------------- +2. Synthesis Parameters +-------------------------------------------------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 20 15 55 + + * - Parameter + - Default Value + - Description + * - ``N`` + - 16 + - Memory address bus size (number of bits). The effective table depth + is **2^N** samples per bank. + * - ``N_DDS`` + - 16 + - Number of parallel DDS blocks and, therefore, samples emitted per clock + cycle on the ``m_axis_tdata_o`` output bus (total width = ``N_DDS × 16`` bits). + * - ``GEN_DDS`` + - ``"TRUE"`` + - ``"TRUE"`` instantiates DDS blocks for upconversion. ``"FALSE"`` generates only + the baseband envelope. + * - ``ENVELOPE_TYPE`` + - ``"COMPLEX"`` + - ``"COMPLEX"`` instantiates separate BRAMs for real and imaginary parts. ``"REAL"`` + uses only the real BRAM and assigns zero to the imaginary part. + +-------------------------------------------------------------------- +3. Interface Ports +-------------------------------------------------------------------- + +3.1 Clock and Reset +^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :header-rows: 1 + :widths: 30 10 50 + + * - Signal + - Direction + - Description + * - ``aresetn`` + - input + - Active-low reset for the main clock domain (``aclk``). + * - ``aclk`` + - input + - Main clock. Drives the FIFO, the ``signal_gen`` block, and the output bus. + +3.2 S0_AXIS – Envelope Sample Loading +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Slave AXI-Stream interface to transfer envelope samples to the internal BRAM. +It operates in the ``s0_axis_aclk`` domain, which can be different from ``aclk``. + +.. list-table:: + :header-rows: 1 + :widths: 30 10 10 50 + + * - Signal + - Direction + - Width + - Description + * - ``s0_axis_aresetn`` + - input + - 1 + - Active-low reset for the S0 domain. + * - ``s0_axis_aclk`` + - input + - 1 + - S0 domain clock. Can differ from ``aclk`` (dual-clock BRAM). + * - ``s0_axis_tdata_i`` + - input + - 32 + - Sample data. Bits [15:0] = real part; bits [31:16] = imaginary part + (only written if ``ENVELOPE_TYPE = "COMPLEX"``). + * - ``s0_axis_tvalid_i`` + - input + - 1 + - Indicates valid data on the bus (standard AXI-Stream protocol). + * - ``s0_axis_tready_o`` + - output + - 1 + - Module indicates availability to receive data. + +3.3 S1_AXIS – Waveform Queue +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Slave AXI-Stream interface to queue **160-bit** waveform descriptors. +Each descriptor defines the parameters for a playback burst. + +.. list-table:: + :header-rows: 1 + :widths: 30 10 10 50 + + * - Signal + - Direction + - Width + - Description + * - ``s1_axis_tdata_i`` + - input + - 160 + - 160-bit waveform descriptor. The ``signal_gen`` block interprets its + content internally. + * - ``s1_axis_tvalid_i`` + - input + - 1 + - Indicates a valid descriptor. Connected directly to ``fifo_wr_en``. + * - ``s1_axis_tready_o`` + - output + - 1 + - Asserted when the internal FIFO is not full (``~fifo_full``). + +3.4 M_AXIS – Data Output +^^^^^^^^^^^^^^^^^^^^^^^^^ + +Master AXI-Stream interface that delivers generated samples to the DAC or the +next block in the datapath. + +.. list-table:: + :header-rows: 1 + :widths: 30 10 10 50 + + * - Signal + - Direction + - Width + - Description + * - ``m_axis_tready_i`` + - input + - 1 + - Consumer indicates it can accept data. + * - ``m_axis_tvalid_o`` + - output + - 1 + - Module indicates that ``m_axis_tdata_o`` contains valid data. + * - ``m_axis_tdata_o`` + - output + - ``N_DDS × 16`` + - Output sample bus. With default values (``N_DDS = 16``), the width is + **256 bits**, corresponding to 16 samples of 16 bits per cycle. + +3.5 Control Registers +^^^^^^^^^^^^^^^^^^^^^ + +.. list-table:: + :header-rows: 1 + :widths: 30 10 10 50 + + * - Signal + - Direction + - Width + - Description + * - ``START_ADDR_REG`` + - input + - 32 + - Starting address in BRAM where the ``data_writer`` will begin writing + samples received via S0_AXIS. + * - ``WE_REG`` + - input + - 1 + - BRAM write enable. When asserted, the ``data_writer`` propagates the + write to the selected BRAM. + +-------------------------------------------------------------------- +4. Internal Architecture +-------------------------------------------------------------------- + +The ``signal_gen_top`` module instantiates and connects four main blocks: + +4.1 FIFO (``fifo_xpm``) +^^^^^^^^^^^^^^^^^^^^^^^ + +* Data width: **160 bits**. +* Depth: **16 entries**. +* Writing occurs directly from S1_AXIS (``fifo_wr_en = s1_axis_tvalid_i``). +* The ``fifo_full`` flag controls the ``s1_axis_tready_o`` signal (backpressure). +* The ``signal_gen`` block manages reading (``fifo_rd_en``). + +4.2 Data Writer (``data_writer``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Receives samples via S0_AXIS and writes them to the correct BRAM according to the +``START_ADDR_REG`` and ``WE_REG`` registers. It generates bank enable signals +(``mem_ena``, an ``N_DDS``-bit vector), address (``mem_addra``), and data (``mem_dia``). + +4.3 BRAM Memories (``bram_dp_xpm``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +**N_DDS** BRAM instances are generated (one per DDS channel), each **16 bits wide** +and **2^N** positions deep. + +* **Port A (Write):** ``s0_axis_aclk`` domain. Receives data from the ``data_writer``. +* **Port B (Read):** ``aclk`` domain. The ``signal_gen`` provides the address + ``mem_addrb`` and receives data in parallel. + +If ``ENVELOPE_TYPE = "COMPLEX"``, a second BRAM per channel is instantiated for +the imaginary part (data in bits [31:16] of the S0 bus). If ``ENVELOPE_TYPE = "REAL"``, +the ``mem_dob_imag`` signal is forced to zero. + +.. note:: + + Both BRAMs (real and imaginary) of a channel share the same read address + ``mem_addrb`` and enable pin ``mem_ena[i]``, ensuring coherence between + real and imaginary parts. + +4.4 Signal Generator (``signal_gen``) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The core of the module. It reads descriptors from the FIFO, generates memory +addresses, and produces output samples by combining the envelope read from BRAM +with the DDS blocks. The ``GEN_DDS`` parameter controls whether internal DDS +blocks are instantiated. + +-------------------------------------------------------------------- +5. Data Flow Diagram +-------------------------------------------------------------------- + +:: + + S0_AXIS ──► data_writer ──► BRAM_real[0..N_DDS-1] ──┐ + BRAM_imag[0..N_DDS-1] ──┤ + ▼ + S1_AXIS ──► fifo_xpm ──────────────────────────► signal_gen ──► M_AXIS + (+ DDS if GEN_DDS=TRUE) + + Registers: START_ADDR_REG, WE_REG ──► data_writer + +-------------------------------------------------------------------- +6. Python Usage (QICK) +-------------------------------------------------------------------- + +The module is exposed through the :class:`qick.SignalGenerator` class. Below +is a minimal usage example: + +.. code-block:: python + :caption: Basic Example – Generating and playing a tone + + from qick import QickSoc + + q = QickSoc() + q.initialize() + + sg = q.get_signal_generator(0) + + # Load a Gaussian envelope (real and imaginary parts) + sg.load_waveform(envelope_i, envelope_q, start_addr=0) + + # Configure waveform descriptor and queue + sg.set_pulse(freq=100e6, phase=0, gain=0.5, length=100) + sg.trigger() + + q.close() + +.. note:: + + The 160-bit descriptor sent via S1_AXIS is generated internally by the + QICK Python class. For bit-format details, see the source code for + ``qick.SignalGenerator.pack_waveform()``. + +-------------------------------------------------------------------- +7. Implementation Considerations +-------------------------------------------------------------------- + +**Clock Domains:** + The module contains two clock domains (``s0_axis_aclk`` and ``aclk``). Domain + crossing is resolved via dual-clock BRAMs. Ensure appropriate timing constraints + are applied in the XDC file. + +**BRAM Read Latency:** + The ``bram_dp_xpm`` instances have ``OUT_REG_ENA = 1``, adding one cycle + of latency to the read port to improve timing. + +**Output Bus Width:** + The ``m_axis_tdata_o`` bus is ``N_DDS × 16`` bits wide. With the default + ``N_DDS = 16``, this equals **256 bits** (32 bytes) per transaction. + +**Memory Depth:** + With parameter ``N = 16``, each BRAM has **65,536 positions** of 16 bits, + equivalent to **128 KB** per bank (real or imaginary). + +**FIFO Capacity:** + The waveform FIFO has a capacity for **16 descriptors** of 160 bits. + If the producer is faster than the consumer, the ``s1_axis_tready_o`` + signal must be managed. + +-------------------------------------------------------------------- +8. Default Parameters – Quick Summary +-------------------------------------------------------------------- + +.. list-table:: + :header-rows: 1 + :widths: 30 70 + + * - Configuration + - Value + * - Samples per cycle (M_AXIS) + - 16 (``N_DDS = 16``) + * - Output bus width + - 256 bits + * - Table depth per bank + - 65,536 samples (``N = 16``) + * - FIFO capacity + - 16 descriptors of 160 bits + * - Envelope type + - Complex (I + Q) + * - DDS Mode + - Enabled (upconversion) + +-------------------------------------------------------------------- +9. Relevant Source Files +-------------------------------------------------------------------- + +* ``signal_gen_top.v`` – Top module described in this document. +* ``signal_gen.v`` – DDS core and playback logic. +* ``data_writer.v`` – BRAM sample writing from AXI-Stream. +* ``fifo_xpm.v`` – Parameterizable FIFO based on Xilinx XPM primitives. +* ``bram_dp_xpm.v`` – Parameterizable dual-port BRAM (Xilinx XPM). From 9feec408a8c9fe86d9899f182ad4c4ad018f75bc Mon Sep 17 00:00:00 2001 From: lharnaldi Date: Fri, 1 May 2026 11:15:18 -0500 Subject: [PATCH 2/3] Fix inline literal formatting and closes #92 --- docs/firmware.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/firmware.rst b/docs/firmware.rst index 31604d566..c080f5ef2 100644 --- a/docs/firmware.rst +++ b/docs/firmware.rst @@ -88,4 +88,4 @@ The firmware is built around the following IP cores: :caption: Signal Generator v6 :hidden: - signal_generator_v6 \ No newline at end of file + signal_generator_v6 From 6f1685f596984ecb4b5a731404032015067dc5a5 Mon Sep 17 00:00:00 2001 From: "QICK actions [bot]" <129547417+qickbot@users.noreply.github.com> Date: Tue, 23 Jun 2026 20:31:10 +0000 Subject: [PATCH 3/3] update version --- qick_lib/qick/VERSION | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qick_lib/qick/VERSION b/qick_lib/qick/VERSION index 5ce335bc5..614abced7 100644 --- a/qick_lib/qick/VERSION +++ b/qick_lib/qick/VERSION @@ -1 +1 @@ -0.2.418 +0.2.419