I3C Controller overview¶
Architecture¶
The design is partitioned into two primary subsystems: the Host Controller Interface (HCI) and the Host Controller (HC). These subsystems communicate via command/response queues and shared lookup tables (DAT/DCT).
High-Level Block Diagram¶
Figure 1 High-Level Block Diagram¶
Subsystems¶
HCI (Host Controller Interface):
Interface: AXI/AHB (Slave interface).
Function: Handles communication with the Host CPU. It populates Control and Status Registers (CSRs) and transfers relevant information between the CSRs and the internal hardware queues (Command, Response, TX, RX, IBI).
HC (Host Controller):
Function: Reads operational data from the queues and translates them into physical I3C transactions (driving SDA/SCL output signals).
Components: Consists of the
flow_activemodule (protocol logic) and the low-level PHY FSMs (i3c_controller_fsm/i2c_controller_fsm).
Data Flow¶
Command Generation: Software writes commands to HCI CSRs.
Queue Population: HCI logic pushes these commands into the Command Queue.
Execution: HC fetches commands, consults the Device Address Table (DAT) or Device Characteristics Table (DCT), and executes the transaction on the bus.
Response: Results are written back to the Response Queue for software to read.
Features List¶
Host Controller Interface (HCI)¶
Registers (RDL): Full implementation of the Register Description List for configuration and status monitoring.
Queues: Support for Command, Response, TX, RX, and IBI queues.
Tables:
DAT (Device Address Table): Storage for Dynamic Addresses and device types.
DCT (Device Characteristics Table): Storage for device-specific parameters (PID, BCR, DCR).
Controller Core Logic¶
SDA Arbitration Management: Handling of bus arbitration during Start/Restart phases.
Frame Generation:
Read Frame: Support for SDR Read transactions with and without
7'h7EI3C address.Write Frame: Support for SDR Write transactions with and without
7'h7EI3C address.
IBI Handling: Detection and processing of In-Band Interrupts from Targets.
HDR Pattern Generation:
HDR Exit Pattern: Logic to generate the specific sequence to exit High Data Rate modes (ensuring bus reset/compatibility).
Error Handling: Target Error Detection and Escalation mechanisms.
Common Command Codes (CCC)¶
The I3C Controller includes support for the following subset of CCCs required for basic bus management and initialization.
Broadcast Support¶
ENEC: Enable Events Command (Broadcast).
DISEC: Disable Events Command (Broadcast).
RSTDAA: Reset Dynamic Address Assignment (Broadcast).
ENTDAA: Enter Dynamic Address Assignment (Broadcast).
SETAASA: Set All Addresses to Static Address (Broadcast).
Direct Support¶
ENEC: Enable Events Command (Direct).
DISEC: Disable Events Command (Direct).
SETDASA: Set Dynamic Address from Static Address (Direct).
SETNEWDA: Set New Dynamic Address (Direct).
GETPID: Get Provisional ID (Direct).
GETBCR: Get Bus Characteristics Register (Direct).
GETDCR: Get Device Characteristics Register (Direct).
GETSTATUS: Get Device Status (Direct).
Dynamic Address Assignment (DAA)¶
The controller implements Dynamic Address Assignment (DAA) in accordance with the bus initialization sequence defined in the I3C Basic Specification (Section 5.1.4.2) and the usage guidelines for the ENTDAA CCC in the I3C HCI Specification (Section 8.4.1.1).
When configuring the DAA procedure, software developers must adhere to the following guidelines:
Pre-populate the DAT: All Device Address Table (DAT) entries for targets awaiting a dynamic address must be fully populated before initiating the DAA procedure with the
ENTDAACCC.Handling Unassigned Targets: If the specified
DEV_COUNTnumber of dynamic addresses has been successfully assigned, but unaddressed devices still remain on the bus, the controller will return a value of0x1in theDATA_LENGTHfield of the Response Descriptor. This signals to the host that at least one target device still requires an address.DCT Initialization: The Device Characteristics Table (DCT) Index always starts at
0.
In-Band Interrupts (IBI)¶
The I3C Controller supports the detection and servicing of In-Band Interrupts (IBIs) initiated by target devices. The controller can recognize and process these interrupts whether they are raised during a Bus Available condition or during arbitrable address headers.
IBI Rejection and DAT Lookup¶
Before accepting an IBI, the controller validates the request against the target’s Device Address Table (DAT) entry. When a target drives its dynamic address onto the bus during an IBI request, the controller utilizes a reverse lookup table to quickly resolve this dynamic address back to the target’s specific DAT index.
Once the corresponding DAT entry is retrieved, the controller checks its configuration fields to decide whether to acknowledge (ACK) or reject (NACK) the interrupt.
The IBI is automatically rejected if the bitwise condition IBI_REJECT | ~IBI_PAYLOAD is met.
Specifically:
IBI_REJECT: If this field is set (1), the controller explicitly rejects all IBI requests from this target.~IBI_PAYLOAD: If theIBI_PAYLOADfield is clear (0), the controller will also reject the IBI, ensuring that targets not explicitly authorized to send payload data are denied.
IBI Data Packing¶
When an accepted IBI is processed, the controller writes the resulting data into the PIOCONTROL.IBI_PORT CSR.
To ensure efficient reading by the host software, the IBI data is packed into the 32-bit port in the following sequence:
IBI Status Descriptor: The first 32-bit word (DWORD) written to the port is always the IBI Status Descriptor. This descriptor contains vital metadata about the interrupt, including the
data_length(in bytes) of the incoming payload as well as the dynamic address of the target issuing the IBI.Payload Data: The Status Descriptor is immediately followed by the actual IBI data payload. The data is chunked and written as
(data_length + 3) / 4DWORDs.Mandatory Data Byte (MDB) Placement: If the target sends a Mandatory Data Byte (MDB), it is always packed into the Least Significant Byte (LSB) of the very first data DWORD immediately following the Status Descriptor.
Internal Buffer & Overflow Handling¶
In accordance with the I3C HCI Specification (Section 6.9.1, IBI Handling in PIO Mode), the controller utilizes an internal hardware buffer to temporarily hold the target’s optional IBI data bytes during the read transaction.
Overflow Condition: If a target attempts to send a number of optional bytes that is greater than or equal to the internal buffer size, the controller will flag an error and immediately abort the IBI transaction.
Data Retention: In the event of a buffer overflow and subsequent abort, the controller recovers by writing the first buffer size bytes (the maximum data it successfully captured before the abort) into the
IBI_PORT.
Error Conditions¶
The MVP supports the following ERROR_STATUS conditions from Table 1 Error Status Codes in Response Descriptor I3C TCRI Spec.
Error Code |
ERR_STATUS Value |
I3C TCRI Spec Section |
Notes |
|---|---|---|---|
CRC |
0x1 |
6.4.1.1 |
|
PARITY |
0x2 |
6.4.1.2 |
|
FRAME |
0x3 |
6.4.1.3 |
|
ADDR_HEADER |
0x4 |
6.4.1.4 |
|
NACK |
0x5 |
6.4.1.5 |
|
OVL |
0x6 |
6.4.1.6 |
|
I3C_SHORT_READ_ERR |
0x7 |
6.4.1.7 |
|
HC_ABORTED |
0x8 |
6.4.1.8 |
|
I2C_WR_DATA_NACK or BUS_ABORTED |
0x9 |
6.4.1.9 |
|
NOT_SUPPORTED |
0xA |
6.4.1.10 |
|
ABORTED_WITH_CRC |
0xB |
6.4.1.11 |
This is used as an internal default state for errors. This means that internal hardware bugs can mistakenly produce the AbortedWithCRC error status. |
Transfer Type Specific |
0xC – 0xF |
6.4.1.12 |
Microarchitecture¶
The Host Controller (HC) logic is split into a “decode” stage (Flow Active FSM) and “execute” stage (i3c/i2c controller FSM).
flow_active (Decode FSM)¶
This module acts as a decoder. It consumes raw data from queues and converts it into control signals (fmt_* signals) for the downstream controller FSMs.
Control and data are handled strictly in 9-bit blocks (1 byte + T-bit/ACK). Once the sending or receiving of a 9-bit block begins, the process cannot be aborted halfway through.
Operating Principle¶
Interfaces:
Upstream: Read/Write access to HCI Queues (Cmd, Resp, Tx, Rx, IBI).
Downstream:
fmtinterface (fmt_byte_o+ flags) toi2c_controller_fsm/i3c_controller_fsm.
Operating Principle:
Operates in PIO Mode (Programmed I/O) using SDR (Standard Data Rate).
fmt_byte_ois the data, that will be sent on the I3C bus.
FSM States & Transitions:
Idle: Waits for
i3c_fsm_en_isignal indicating a new command is present in the Command Queue or IBI to wake up FSM.WaitForCmd: Fetches the 64-bit Command Descriptor from the Command Queue.
FetchDAT: Retrieves the Device Address Table (DAT) entry corresponding to the command’s Device Index. Transitions to the execution stage based on
cmd_attr(Command Attribute).Execution:
I2C Write Immediate / I3C Write Immediate: uses immediate command descriptor format and reads data directly from the command descriptor.
I2C Write Regular / I3C Write Regular: uses regular command descriptor format and reads data from TX Queue
I2C Read / I3C Read: uses regular command descriptor format and writes data into RX Queue
WriteResp: Generates a Response Descriptor, loads it into the Response Queue, and returns to Idle.
Figure 2 Flow Active FSM¶
Signal List¶
Signal |
Direction |
Width |
Description |
|
input |
1 |
Clock |
|
input |
1 |
Active low reset |
|
input |
1 |
Command FIFO queue full flag |
|
input |
|
Command FIFO ready threshold |
|
input |
1 |
Command FIFO ready threshold trigger |
|
input |
1 |
Command FIFO empty flag |
|
input |
1 |
Command FIFO read valid |
|
output |
1 |
Command FIFO read ready |
|
input |
|
Command FIFO read data |
|
input |
1 |
RX FIFO queue full flag |
|
input |
|
RX FIFO start threshold |
|
input |
1 |
RX FIFO start threshold trigger |
|
input |
|
RX FIFO ready threshold |
|
input |
1 |
RX FIFO ready threshold trigger |
|
input |
1 |
RX FIFO empty flag |
|
output |
1 |
RX FIFO write valid |
|
input |
1 |
RX FIFO write ready |
|
output |
|
RX FIFO write data |
|
input |
1 |
TX FIFO queue full flag |
|
input |
|
TX FIFO start threshold |
|
input |
1 |
TX FIFO start threshold trigger |
|
input |
|
TX FIFO ready threshold |
|
input |
1 |
TX FIFO ready threshold trigger |
|
input |
1 |
TX FIFO empty flag |
|
input |
1 |
TX FIFO read valid |
|
output |
1 |
TX FIFO read ready |
|
input |
|
TX FIFO read data |
|
input |
1 |
Response FIFO queue full flag |
|
input |
|
Response FIFO ready threshold |
|
input |
1 |
Response FIFO ready threshold trigger |
|
input |
1 |
Response FIFO empty flag |
|
output |
1 |
Response FIFO write valid |
|
input |
1 |
Response FIFO write ready |
|
output |
|
Response FIFO write data |
|
input |
1 |
IBI FIFO queue full flag |
|
input |
|
IBI FIFO ready threshold |
|
input |
1 |
IBI FIFO ready threshold trigger |
|
input |
1 |
IBI FIFO empty flag |
|
output |
1 |
IBI FIFO write valid |
|
input |
1 |
IBI FIFO write ready |
|
output |
|
IBI FIFO write data |
|
input |
|
DAT memory interface |
|
output |
1 |
DAT read valid HW |
|
output |
|
DAT index HW |
|
input |
64 |
DAT read data HW |
|
output |
1 |
DCT write valid HW |
|
output |
1 |
DCT read valid HW |
|
output |
|
DCT index HW |
|
output |
128 |
DCT write data HW |
|
input |
128 |
DCT read data HW |
|
output |
1 |
Enable host functionality |
|
output |
1 |
Is an I2C transfer flag |
|
input |
1 |
I2C command complete flag |
|
input |
1 |
PHY select OD/PP input |
|
output |
1 |
PHY select OD/PP output |
|
output |
1 |
Format FIFO read valid |
|
output |
|
Format FIFO depth |
|
input |
1 |
Format FIFO read ready |
|
input |
1 |
Format FIFO read done |
|
output |
8 |
Format TX byte output |
|
output |
1 |
Format TX bit output (T bit) |
|
output |
1 |
Format flag: start before |
|
output |
1 |
Format flag: restart after |
|
output |
1 |
Format flag: stop after |
|
output |
1 |
Format flag: read continue |
|
input |
1 |
Format receive NACK |
|
input |
1 |
SDA line arbitration is detected |
|
input |
8 |
Format RX byte input |
|
input |
1 |
Format RX bit input |
|
output |
1 |
Format flag: read bytes |
|
input |
1 |
Format flag: read valid |
|
output |
1 |
Format flag: NAK OK |
|
output |
1 |
Format flag: HDR exit |
|
output |
1 |
Unhandled unexpected NAK |
|
output |
1 |
Unhandled NAK timeout |
|
input |
1 |
I2C Controller RX FIFO write valid |
|
input |
|
I2C Controller RX FIFO write data |
|
input |
1 |
I3C FSM enable |
|
output |
1 |
I3C FSM idle status |
|
input |
1 |
PIO RS input |
|
input |
1 |
Halt on command sequence timeout |
|
input |
1 |
HC_CONTROL.RESUME CSR field |
|
input |
1 |
HC_CONTROL.ABORT | PIO_CONTROL.ABORT CSR fields |
|
output |
|
I3C Error structure |
|
output |
|
I3C Interrupt structure |
i3c_controller_fsm (Execute / Timing FSM for I3C)¶
This module acts as the main controller of the I3C bus, handling the serialization of data and generation of the Start (S), Stop (P) and repeated Start (Sr) conditions. It also handles switching between Open Drain mode and Push Pull mode, also respecting the different timing requirements (See 6.2 Timing Specification I3C Basic Spec).
Operating Principle¶
Function:
Consumes
fmtsignals (byte data + control flags like Start/Stop/Nak) from theflow_activemodule.Drives physical SDA and SCL lines.
Timing FSM: Generates the SCL clock based on I3C SDR timing requirements (in Open Drain and Push Pull mode).
Serialization: Serializes the
fmt_byteonto the SDA line for write transactions.Parallelization: Parallelizes received data into a
fmt_bytefor theflow_activemodule for read transactions.Protocol Framing: Reacts to
fmt_flag_startandfmt_flag_stopto generate Start/Stop conditions, as well asfmt_flag_restartto generate a repeated Start condition.
Signal List¶
Signal |
Direction |
Width |
Description |
|
input |
1 |
Clock |
|
input |
1 |
Active low reset |
|
input |
1 |
Interface to SCL input |
|
input |
1 |
Interface to SDA input |
|
output |
1 |
Interface to SCL output |
|
output |
1 |
Interface to SDA output |
|
input |
|
Bus state |
|
output |
1 |
PHY select Open-Drain/Push-Pull output |
|
input |
1 |
Is I2C transfer flag |
|
input |
|
High period of the SCL in clock units |
|
input |
|
Low period of the SCL in clock units |
|
input |
|
High period of the SCL in clock units (Open-Drain Mode) |
|
input |
|
High period of the SCL in clock units (Open-Drain Mode during init procedure) |
|
input |
|
Low period of the SCL in clock units (Open-Drain Mode) |
|
input |
|
Rise time of both SDA and SCL in clock units |
|
input |
|
Fall time of both SDA and SCL in clock units |
|
input |
|
Hold time for START in clock units (Open-Drain Mode) |
|
input |
|
Hold time for repeated START in clock units |
|
input |
|
Setup time for repeated START in clock units |
|
input |
|
Setup time for STOP in clock units |
|
input |
|
Setup time for SDA during START in clock units (Open-Drain Mode) |
|
input |
|
Data setup time in clock units |
|
input |
|
Data hold time in clock units |
|
input |
|
Bus free time between STOP and START in clock units |
|
input |
|
Bus IDLE condition time in clock units |
|
input |
|
Bus AVAILABLE condition time in clock units |
|
input |
1 |
Format FIFO read valid |
|
output |
1 |
Format FIFO read ready |
|
output |
1 |
Format FIFO read done |
|
input |
8 |
Format TX byte input |
|
input |
1 |
Format TX bit input (T bit) |
|
input |
1 |
Format flag: start before |
|
input |
1 |
Format flag: stop after |
|
input |
1 |
Format flag: restart after |
|
output |
1 |
Format receive NACK |
|
output |
1 |
SDA line arbitration is detected |
|
output |
8 |
Format RX byte output |
|
output |
1 |
Format RX bit output (T bit) |
|
input |
1 |
Format flag: read bytes |
|
input |
1 |
Format flag: read continue |
|
output |
1 |
Format flag: read valid |
|
input |
1 |
Format flag: HDR exit |
i2c_controller_fsm (Execute / Timing FSM for I2C)¶
This module acts as the main controller of the I2C bus, handling the serialization of data and generation of the Start (S), Stop (P) and repeated Start (Sr) conditions. It handles the I2C timing requirements (See 6.2 Timing Specification I3C Basic Spec). Note that all transactions in I2C are in Open Drain mode. This module is taken from the Open Titan I2C Core.
Operating Principle¶
Function:
Consumes
fmtsignals (byte data + control flags like Start/Stop/Nak) from theflow_activemodule.Drives physical SDA and SCL lines.
Timing FSM: Generates the SCL clock based on I3C SDR timing requirements (in Open Drain and Push Pull mode).
Serialization: Serializes the
fmt_byteonto the SDA line for write transactions.Parallelization: Parallelizes received data into a
fmt_bytefor theflow_activemodule for read transactions.Protocol Framing: Reacts to
fmt_flag_startandfmt_flag_stopto generate Start/Stop conditions. (Differently to thei3c_controller_fsmthis module does not have afmt_repeated_startflag. It generates a repeated start by setting thefmt_flag_start.)
Signal List¶
Signal |
Direction |
Width |
Description |
|
input |
1 |
Clock |
|
input |
1 |
Active low reset |
|
input |
1 |
Interface to SCL input |
|
output |
1 |
Interface to SCL output |
|
input |
1 |
Interface to SDA input |
|
output |
1 |
Interface to SDA output |
|
input |
1 |
Enable host functionality |
|
input |
1 |
Indicates there is valid data in format FIFO |
|
input |
|
Format FIFO depth |
|
output |
1 |
Populates format FIFO |
|
input |
8 |
Byte in format FIFO to be sent to target |
|
input |
1 |
Issue START before sending byte |
|
input |
1 |
Issue STOP after sending byte |
|
input |
1 |
Indicates byte is a number of reads |
|
input |
1 |
Host to send ACK to final byte read |
|
input |
1 |
No ACK is expected |
|
input |
1 |
Unhandled unexpected NAK |
|
input |
1 |
NACK handler timeout event not cleared |
|
output |
1 |
High if there is valid data in RX FIFO |
|
output |
|
Byte in RX FIFO read from target |
|
output |
1 |
Indicates the host is idle |
|
input |
|
High period of the SCL in clock units |
|
input |
|
Low period of the SCL in clock units |
|
input |
|
Rise time of both SDA and SCL in clock units |
|
input |
|
Fall time of both SDA and SCL in clock units |
|
input |
|
Hold time for (repeated) START in clock units |
|
input |
|
Setup time for repeated START in clock units |
|
input |
|
Setup time for STOP in clock units |
|
input |
|
Data setup time in clock units |
|
input |
|
Data hold time in clock units |
|
input |
|
Bus free time between STOP and START in clock units |
|
input |
31 |
Max time target connected to this host may stretch the clock (UNUSED) |
|
input |
1 |
Assert if target stretches clock past max (UNUSED) |
|
input |
31 |
Timeout threshold for unhandled Host-Mode ‘nak’ IRQ (UNUSED) |
|
input |
1 |
Enable for host NACK handler timeout |
|
output |
1 |
Target didn’t ACK when expected (UNUSED) |
|
output |
1 |
SW didn’t handle the NACK in time (UNUSED) |
|
output |
1 |
Other device forcing SCL low (UNUSED) |
|
output |
1 |
Other device forcing SDA low (UNUSED) |
|
output |
1 |
Target stretches clock past max time (UNUSED) |
|
output |
1 |
SDA is not constant during SCL pulse (UNUSED) |
|
output |
1 |
Command is complete |
SRAM Macros¶
The internal memory structures for the Device Address Table (DAT) and Device Characteristic Table (DCT) are implemented using the OpenTitan generic single-port RAM macro (prim_generic_ram_1p).
This parameterized module provides standard wrapper for synchronous single-port SRAM instantiation. The source code for this macro can be referenced in the i3c-core repository: prim_generic_ram_1p.sv.
Memory Block |
Width (Bits) |
Depth (Words) |
Size |
DAT (Device Address Table) |
64 |
32 |
2 kbit |
DCT (Device Characteristic Table) |
128 |
32 |
4 kbit |