Source code for basil.HL.fast_spi_rx

#
# ------------------------------------------------------------
# Copyright (c) All rights reserved
# SiLab, Institute of Physics, University of Bonn
# ------------------------------------------------------------
#
"""Fast SPI receive interface for reading variable-width serial data.

Provides a register-level hardware layer to arm/disarm capture, query
frame-size configuration, check for lost words, and parse 32-bit FIFO
words into (identifier, frame_counter, spi_data) tuples.
"""

from basil.HL.RegisterHardwareLayer import RegisterHardwareLayer


[docs] class fast_spi_rx(RegisterHardwareLayer): """Fast SPI interface with variable data width support. The module outputs 32-bit words containing: - IDENTIFIER (4 bits) - Frame counter (28 - DATA_SIZE bits) - SPI data (DATA_SIZE bits) The DATA_SIZE parameter must match the DATA_SIZE parameter used in the FPGA firmware (fast_spi_rx_core.v). Captured data is read via the dedicated FIFO output ports (not the register bus). At the system level, these feed into a SiTCP FIFO stream accessed through daq["fifo0"].get_data(). """ _registers = { "RESET": {"descr": {"addr": 0, "size": 8, "properties": ["writeonly"]}}, "VERSION": {"descr": {"addr": 0, "size": 8, "properties": ["ro"]}}, "EN": {"descr": {"addr": 2, "size": 1, "offset": 0}}, "LOST_COUNT": {"descr": {"addr": 3, "size": 8, "properties": ["ro"]}}, "DATA_SIZE": {"descr": {"addr": 4, "size": 8, "properties": ["ro"]}}, } _require_version = "==1" def __init__(self, intf, conf): """Initialize the fast_spi_rx hardware layer. Args: intf: The low-level interface to the hardware. conf: Configuration dictionary passed to the base class. """ super(fast_spi_rx, self).__init__(intf, conf)
[docs] def get_size(self): """Return the DATA_SIZE (SPI data width in bits) used for parsing captured words. Reads the value from the hardware DATA_SIZE register (addr 4). """ return self.DATA_SIZE
[docs] def reset(self): """Soft reset the module. Clears internal counters and shift registers on the next SEQ_CLK edge.""" self.RESET = 0
[docs] def set_en(self, value): """Arm/disarm capture. When enabled, serial data on SDI is captured on each rising edge of SEQ_CLK while SEN is high. """ self.EN = value
[docs] def get_en(self): """Return whether capture is armed (True) or disarmed (False).""" return self.EN
[docs] def get_lost_count(self): """Return the count of lost data words due to CDC FIFO overflow. Non-zero indicates the capture rate exceeded the readout rate. """ return self.LOST_COUNT
[docs] def parse_word(self, word): """Parse a 32-bit FIFO word into (identifier, frame_counter, spi_data). The split between frame counter and captured data is determined by get_size(). Useful for parsing words read via daq["fifo0"].get_data(). Args: word: A 32-bit integer from the fast_spi_rx output FIFO. Returns: tuple: (identifier, frame_counter, spi_data) """ data_size = self.get_size() identifier = (word >> 28) & 0xF spi_data = word & ((1 << data_size) - 1) frame_counter_bits = 28 - data_size if frame_counter_bits > 0: frame_counter = (word >> data_size) & ((1 << frame_counter_bits) - 1) else: frame_counter = 0 return identifier, frame_counter, spi_data