Board Space register tree ========================= Rationale --------- The board-space register tree is a memory-mapped configuration, diagnostics, and data-retrieval mechanism built on the SPI register-tree access model, which maps 16-bit FPGA registers to an addressable space. This tree is a dedicated register hierarchy with fixed access commands intended for automatic use by the microcontroller FPGA driver. It allows the microcontroller to query FPGA data associated with board hardware and common firmware modules defined by the base HotRIO standard. The mechanism provides a consistent interface for diagnostics and status retrieval, as well as control-command execution, enabling deterministic FPGA management without user intervention. Additional register trees may be instantiated in user logic to expose configuration and diagnostic features required by custom applications. Because these features are typically application-specific, they are not suitable for hardcoding in the FPGA driver. The board-space register tree therefore defines a stable, predefined set of parameters that enables the microcontroller to access critical information and respond according to a known register structure. General description ------------------- The board-space structure is hardware-dependent and may vary across boards in topology, register count, and register semantics. Its design is determined by board-level hardware requirements and available diagnostic capabilities. Despite this variability, board-space implementations follow a common architectural pattern. Board-facing functionality is organized into six register categories (blocks): - **Interrupt block**: **Mandatory** and always placed first. This block contains a single 16-bit interrupt-flag register used by the microcontroller driver, together with a physical interrupt line, to detect and process board-level events. - **Control block**: **Mandatory** and always placed second. This block contains registers used to control and monitor FPGA user-logic status, independent of the specific user design. The microcontroller uses this information to manage the system startup sequence. - **Signature block**: **Mandatory** and always placed third. This block contains constant signature registers that identify target hardware and firmware version, allowing the microcontroller to validate compatibility. - **Hardware interface block**: **Optional**. This block contains registers used to control and monitor board hardware interfaces. The microcontroller may use it for automatic checks and hardware configuration. Its content is highly board-specific; only standardized hardware-interface sub-blocks are included here. Hardware-related sub-blocks specific to a single board design are placed in the **Custom block**. Typical examples include SFP interfaces and Eurocard expansion-slot interfaces. - **Communications block**: **Optional**. This block contains one register sub-block per communication interface implemented in the design. It depends on the hardware/firmware combination and may vary significantly by firmware configuration. However, because these interface blocks are part of the horizontal HotRIO project, they are treated as sufficiently standardized to belong to board-space. - **Custom block**: **Optional** and use-case specific. This block forms the boundary between board-space and user-space by containing diagnostic and control registers for hardware features specific to one board or a subset of boards. Interrupt block ^^^^^^^^^^^^^^^ The board-space interrupt block is mandatory and present in every implementation. It contains a single 16-bit register, the **Interrupt register**, mapped at board-space address ``0x00``. This register exposes interrupt/event flag bits, where each bit corresponds to a specific system event that must be signaled to the microcontroller through a dedicated physical interrupt I/O line. The primary purpose of this register is to provide low-latency FPGA-to-microcontroller notification for critical and real-time events. All bits in this register operate as notification flags. When an associated event occurs, its corresponding bit is set to ``1``. The flag bits are logically ORed and routed to the interrupt I/O line between the FPGA and the management microcontroller, such that the line is asserted when any enabled flag is asserted. Read behavior for this register differs from standard board-space registers. When a read transaction is issued to this address, interrupt flags are latched, temporarily preventing new notifications from propagating to the register and asserting the interrupt line. Additional details are provided in the :doc:`FPGA interrupt line documentation page `. As shown in the register definition, the Interrupt register provides the following event flags: - **Control-register status flag**: Asserts when the control register changes, notifying the microcontroller that FPGA status has changed. - **Communication-interface status flag**: Applies to all interfaces in the **Communications block** and asserts when any communication-interface status changes. - **Sideband-interface status flag**: Provides equivalent behavior for sideband communication interfaces and asserts when any sideband-interface status changes. - **User-logic event flag**: Asserted by user logic when microcontroller intervention is required. The trigger is application-specific, but this flag remains in board-space because it supports hardware-level wake-up and notification behavior. The Interrupt register has a non-standard, latched-read behavior designed to provide deterministic interrupt servicing. 1. When any enabled event occurs, its corresponding flag bit is set and remains set. 2. The OR of all asserted flag bits drives the FPGA-to-microcontroller interrupt line. 3. At the start of a microcontroller read transaction to the Interrupt register, the register value is frozen (new flag assertions are not reflected in the value being read). 4. When the read completes, the Interrupt register is cleared to ``0`` and the interrupt line is deasserted. 5. Events that occur while the read/freeze window is active are still captured internally in FPGA latch logic, but are not exposed on the Interrupt register or interrupt line until the post-read recovery period has elapsed. This mechanism lets the microcontroller process one coherent interrupt snapshot at a time and prevents ambiguity between consecutive interrupt events. .. regtreedoc:: :file: ./source/design/Architecture/boardSpace.json :register: ["Interrupt register"] Control block ^^^^^^^^^^^^^ The control block is mandatory in all board-space implementations. It consists of two 16-bit registers located at addresses ``0x01`` and ``0x02``, and provides a standardized interface for firmware status monitoring and control. The block is intentionally divided into: - a **read-only (RO) status register** for diagnostics and runtime status reporting from FPGA user logic; - a **read/write (RW) command register** for control requests issued by the microcontroller. This separation improves interface clarity, avoids ambiguity between status and command paths, and supports deterministic driver behavior. Functionally, the control block is the primary interface to the firmware state machine that governs user-logic execution state. The microcontroller writes control commands to request state transitions, while reading back status to verify transition completion and current operating mode. Additional information is available in the :doc:`User logic state machine <>` documentation page. The control block also exposes a Single Error Detection status indication for the currently executing firmware image. This mechanism is intended for safety-relevant systems and enables runtime detection of firmware corruption events. As described in the Interrupt block section, any change in the **Control Register Output** value (that is, any bit transition) asserts the corresponding control-status interrupt flag in the Interrupt register and triggers the FPGA interrupt line. .. regtreedoc:: :file: ./source/design/Architecture/boardSpace.json :register: ["Control Register Output"] .. regtreedoc:: :file: ./source/design/Architecture/boardSpace.json :register: ["Control Register Input"] Signature block ^^^^^^^^^^^^^^^ The signature block is mandatory and consists of two 16-bit constant registers located at addresses ``0x03`` and ``0x04``. Together, these registers provide deterministic hardware and firmware identification. The **Hardware signature** register contains a 16-bit unsigned identifier that shall match the hardware ID expected by the board-specific FPGA driver running on the microcontroller. Since each board software package includes a driver tailored to the corresponding board-space layout, this check is used during startup to validate hardware/firmware compatibility. If the identifier does not match, the firmware image shall be treated as incompatible with the target platform. The **Firmware signature** register contains a 16-bit unsigned identifier defined at project creation time. This value acts as a firmware revision or firmware-key tag and can be used by the microcontroller to enforce execution policy (for example, allowing only approved firmware variants on a given board unit). This mechanism supports both hardware-level compatibility control and application-level deployment constraints. .. regtreedoc:: :file: ./source/design/Architecture/boardSpace.json :register: ["Hardware signature"] .. regtreedoc:: :file: ./source/design/Architecture/boardSpace.json :register: ["Firmware signature"] Hardware interface block ^^^^^^^^^^^^^^^^^^^^^^^^ The hardware interface block contains standardized sub-blocks that expose onboard hardware-interface configuration, diagnostics, control parameters, and runtime data. Its composition is board-dependent: each board includes a specific set of sub-blocks arranged according to the available hardware interfaces. For example, a Corcovado board exposes four Eurocard expansion-slot sub-blocks and four SFP sub-blocks, reflecting its physical interface count. By contrast, an Ipanema board exposes only two SFP sub-blocks and no expansion-slot sub-blocks. Although this block varies across board families, its layout is deterministic for a given board. Therefore, the microcontroller does not require an in-band discovery mechanism for sub-block count in this section, because the board-specific FPGA driver already encodes the expected structure. The individual sub-block definitions are standardized and part of the board-space specification. Documentation for the currently supported sub-block types is listed below. Currently available hardware-interface sub-blocks: .. toctree:: :maxdepth: 1 HardwareSubBlocks/EurocardExpansionSlotSubBlock HardwareSubBlocks/SFPSubBlock The specifics of the hardware interface block (the sub-blocks that make up this block) are defined per-board as the type of hardware is board-dependant. Therefore, for specific information regarding this sub-block please refer to the documentation of your target board. Communications block ^^^^^^^^^^^^^^^^^^^^ The base address of the Communications block is not fixed. It is determined by the total length of the preceding **Hardware interface block**, which is board-dependent. Therefore, all addresses in this section are expressed relative to the start of the Communications block (Offset). The Communications block contains register sub-blocks used to configure, control, monitor, and exchange data with communication interfaces implemented in the firmware image. Typical interfaces include HotRIO master and slave, HotRIO double-ring master and slave, and UDP data endpoints, as well as additional standardized interfaces defined by the HotRIO horizontal project. The number and types of communication-interface sub-blocks are firmware-dependent and are not strictly constrained by board hardware. In addition to communication interfaces, this block includes sideband-interface sub-blocks. These provide microcontroller access to sideband channels associated with communication interfaces when sideband functionality is enabled. As with communication interfaces, the number of sideband sub-blocks is variable and determined by firmware configuration. To support deterministic parsing of this variable-length structure, the first register in the Communications block contains two counters: - an 8-bit unsigned count of communication-interface sub-blocks; - an 8-bit unsigned count of sideband-interface sub-blocks. Communication-interface sub-blocks begin at offset ``+ 0x0001`` and are packed sequentially. Each sub-block starts with a type/header register that identifies the sub-block format. Given the sub-block type, the microcontroller can determine its length and compute the start address of the next sub-block. Sideband-interface sub-blocks follow immediately after the communication-interface sub-block region and use the same parsing method. .. regtreedoc:: :file: ./source/design/Architecture/boardSpace.json :register: ["Communications block counters"] :addressoverride: Offset + 0x0000 A comprehensive list of the available sub-blocks for the communication interfaces can be found here: .. toctree:: :maxdepth: 1 CommunicationsSubBlocks/HotRIOSlaveSubBlock CommunicationsSubBlocks/HotRIOMasterSubBlock CommunicationsSubBlocks/UDPFormatterSubBlock A comprehensive list of the available sub-blocks for the sideband interfaces can be found here: .. toctree:: :maxdepth: 1 SidebandSubBlocks/HotRIOSidebandSlaveSubBlock SidebandSubBlocks/HotRIOSidebandMasterSubBlock Custom block ^^^^^^^^^^^^ The Custom block is board-specific and defines the boundary between standardized board-space content and application- or board-specific extensions. Its purpose is to expose diagnostic, status, and control registers that are required for a given board design but are not covered by the standardized blocks described above. Depending on board requirements, this block may be: - empty; - populated with a fixed and predefined set of sub-blocks; or - populated with a variable set of sub-blocks encoded dynamically at runtime. When a variable-length layout is used, the recommended approach is the same as in the Communications block: include a sub-block counter register, then pack sub-blocks sequentially with a type/header register at the start of each sub-block. The microcontroller can then parse the region deterministically by reading the sub-block type, deriving the sub-block length, and computing the start address of the next sub-block. Because this block is intentionally flexible, its exact structure, register semantics, and addressing rules shall be defined in the documentation for each target board.