diff --git a/_images/i3c_csr_rd.png b/_images/i3c_csr_rd.png
new file mode 100644
index 0000000..f75923e
Binary files /dev/null and b/_images/i3c_csr_rd.png differ
diff --git a/_images/i3c_csr_wr.png b/_images/i3c_csr_wr.png
new file mode 100644
index 0000000..c0c5f50
Binary files /dev/null and b/_images/i3c_csr_wr.png differ
diff --git a/_images/recovery_handler.png b/_images/recovery_handler.png
new file mode 100644
index 0000000..ad4f21d
Binary files /dev/null and b/_images/recovery_handler.png differ
diff --git a/_images/recovery_handler_bd.png b/_images/recovery_handler_bd.png
new file mode 100644
index 0000000..d0d1040
Binary files /dev/null and b/_images/recovery_handler_bd.png differ
diff --git a/_sources/ci_queues.md.txt b/_sources/ci_queues.md.txt
index 1395ffa..c01bbcd 100644
--- a/_sources/ci_queues.md.txt
+++ b/_sources/ci_queues.md.txt
@@ -13,32 +13,32 @@ Controller Interface queues consist of:
Controller Interface queues are depth-configurable with the [I3C Configuration](config.md#configuring-the-i3c-core).
Queues generate several status indicators that will be used to trigger appropriate interrupts:
- * `*_fifo_empty_` - no elements are enqueued in corresponding FIFO.
+ * `*_fifo_empty_` - no elements are enqueued in the corresponding FIFO.
* `*_fifo_full_` - `*_FIFO_DEPTH` are enqueued in the corresponding FIFO.
* `*_fifo_apch_thld_` - the user-defined threshold has been reached.
## Queue threshold
-Command and response queue thresholds are controlled via [QUEUE_THLD_CTRL](https://github.com/chipsalliance/i3c-core-rdl/blob/4028ed29254aefdbe9c805e8bfaa275e200994ba/src/rdl/pio_registers.rdl#L44) register.
+Command and response queue thresholds are controlled via the [QUEUE_THLD_CTRL](https://github.com/chipsalliance/i3c-core-rdl/blob/4028ed29254aefdbe9c805e8bfaa275e200994ba/src/rdl/pio_registers.rdl#L44) register.
RX and TX data queue thresholds are controlled via [DATA_BUFFER_THLD_CTRL](https://github.com/chipsalliance/i3c-core-rdl/blob/4028ed29254aefdbe9c805e8bfaa275e200994ba/src/rdl/pio_registers.rdl#L75).
### Command queue threshold
-* The threshold for command queue is set by a write to the `QUEUE_THLD_CTRL` to the 8-bit `CMD_EMPTY_BUF_THLD` field.
-* The threshold `N` of range `<1, 255>` (inclusive) will cause an `CMD_QUEUE_READY_STAT` interrupt when there's `N` or more remaining empty entries left in the command queue.
-* If the `N` value is greater than the size of the command queue (`CMD_FIFO_DEPTH`) the full depth will be considered (the threshold will be set to `CMD_FIFO_DEPTH`).
+* The threshold for command queue is set by a write to the 8-bit `CMD_EMPTY_BUF_THLD` field of the `QUEUE_THLD_CTRL` register.
+* The `N` threshold of `<1, 255>` range (inclusive) will cause an `CMD_QUEUE_READY_STAT` interrupt when there's `N` or more remaining empty entries in the command queue.
+* If the `N` value is greater than the size of the command queue (`CMD_FIFO_DEPTH`), the full depth will be considered (the threshold will be set to `CMD_FIFO_DEPTH`).
-### Response queue threshold
-* The threshold for response queue is set by a write to `QUEUE_THLD_CTRL` to the 8-bit `RESP_BUF_THLD` field.
-* The threshold `N` of range `<1, 255>` (inclusive) will cause an `RESP_READY_STAT` interrupt when there's `N` or more responses enqueued in the response queue.
-* If the `N` value is greater or equal than the size of the response queue (`RESP_FIFO_DEPTH`) the full depth will be considered (the threshold will be set to `RESP_FIFO_DEPTH - 1`)
+### Response queue threshold
+* The threshold for response queue is set by a write to the 8-bit `RESP_BUF_THLD` field of the `QUEUE_THLD_CTRL` register.
+* The `N` threshold of `<1, 255>` range (inclusive) will cause an `RESP_READY_STAT` interrupt when there's `N` or more responses enqueued in the response queue.
+* If the `N` value is greater or equal than the size of the response queue (`RESP_FIFO_DEPTH`), the full depth will be considered (the threshold will be set to `RESP_FIFO_DEPTH - 1`)
### TX queue threshold
-* The threshold for the TX queue is set by a write to `DATA_BUFFER_THLD_CTRL` to the 3-bit `TX_BUF_THLD` field.
-* The threshold `N` of range `<0, 7>` (inclusive) will trigger an `TX_THLD_STAT` interrupt when `2^(N+1)` (`2` to the power of `N+1`) `DWORD` empty entries are available in the TX queue.
-* The software must provide an `N` value that corresponds to the threshold less or equal than `TX_FIFO_DEPTH`, otherwise the `clog2(TX_FIFO_DEPTH) - 1` will be applied.
+* The threshold for the TX queue is set by a write to the 3-bit `TX_BUF_THLD` field of the `DATA_BUFFER_THLD_CTRL` register.
+* The `N` threshold of `<0, 7>` range (inclusive) will trigger an `TX_THLD_STAT` interrupt when `2^(N+1)` (`2` to the power of `N+1`) empty `DWORD` entries are available in the TX queue.
+* The software must provide an `N` value that corresponds to the threshold less or equal than `TX_FIFO_DEPTH`, otherwise `clog2(TX_FIFO_DEPTH) - 1` will be applied.
### RX queue threshold
-* The threshold for the RX queue is set by a write to `DATA_BUFFER_THLD_CTRL` to the 3-bit `RX_BUF_THLD` field.
-* The threshold `N` of range `<0, 7>` (inclusive) will trigger an `RX_THLD_STAT` interrupt when `2^(N+1)` (`2` to the power of `N+1`) `DWORD` entries are enqueued in the RX queue.
-* The software must provide an `N` value that corresponds to the threshold less than `RX_FIFO_DEPTH`, otherwise the `clog2(RX_FIFO_DEPTH) - 2` will be applied.
+* The threshold for the RX queue is set by a write to the 3-bit `RX_BUF_THLD` field of the `DATA_BUFFER_THLD_CTRL` register.
+* The `N` threshold of `<0, 7>` range (inclusive) will trigger an `RX_THLD_STAT` interrupt when `2^(N+1)` (`2` to the power of `N+1`) `DWORD` entries are enqueued in the RX queue.
+* The software must provide an `N` value that corresponds to the threshold less than `RX_FIFO_DEPTH`, otherwise `clog2(RX_FIFO_DEPTH) - 2` will be applied.
-All queues utilize [caliptra_prim_fifo_sync.sv](https://github.com/chipsalliance/caliptra-rtl/blob/9c815c335a92901b27458271a885b2128e51e687/src/caliptra_prim/rtl/caliptra_prim_fifo_sync.sv#L9) fifo implementation.
\ No newline at end of file
+All queues utilize the [caliptra_prim_fifo_sync.sv](https://github.com/chipsalliance/caliptra-rtl/blob/9c815c335a92901b27458271a885b2128e51e687/src/caliptra_prim/rtl/caliptra_prim_fifo_sync.sv#L9) FIFO implementation.
\ No newline at end of file
diff --git a/_sources/dv.md.txt b/_sources/dv.md.txt
index 51d1b1a..59cb88b 100644
--- a/_sources/dv.md.txt
+++ b/_sources/dv.md.txt
@@ -1,8 +1,8 @@
# Design verification
-This chapter presents available models and tools, which are used for I3C verification.
-The core is verified with [the Cocotb/Verilator + unit tests](../../verification/block) and [the UVM test suite](../../verification/uvm_i3c/).
+This chapter presents the available models and tools which are used for I3C verification.
+The core is verified with [the Cocotb/Verilator + unit tests](../../verification/cocotb/block) and [the UVM test suite](../../verification/uvm_i3c).
## Verification plan
-The verification plan is [here](../../verification/uvm_i3c/testplan.hjson).
+The verification plans can be found [here](../../verification/uvm_i3c).
diff --git a/_sources/ext_cap.md.txt b/_sources/ext_cap.md.txt
index edaf432..a65c56d 100644
--- a/_sources/ext_cap.md.txt
+++ b/_sources/ext_cap.md.txt
@@ -60,7 +60,7 @@ This specification provides definitions and descriptions of the following Capabi
The Controller Config Capability follows section 7.7.3 of the [I3C HCI Specification](introduction.md#spec-i3c-hci).
-### Secure Firmware Recovery Interface (ID=0xC0)
+### Secure Firmware Recovery Interface (ID=0xC0)
This section is based on the Open Compute Project Secure Firmware Recovery, Version 1.0 and I3C Target Recovery Specification
diff --git a/_sources/index.md.txt b/_sources/index.md.txt
index b9f6401..717c053 100644
--- a/_sources/index.md.txt
+++ b/_sources/index.md.txt
@@ -29,6 +29,7 @@ normal_operation
:maxdepth: 2
ext_cap
+recovery_flow
```
```{toctree}
diff --git a/_sources/introduction.md.txt b/_sources/introduction.md.txt
index e3deac2..fff3734 100644
--- a/_sources/introduction.md.txt
+++ b/_sources/introduction.md.txt
@@ -1,6 +1,6 @@
# Introduction
-This document describes the open-source I3C Basic controller.
+This document describes the open source I3C Basic controller.
The scope of the project includes:
* Secondary Controller Mode
* Active Controller Mode
@@ -10,15 +10,15 @@ The scope of the project includes:
Secondary Controller Mode with generic TX/RX transfers can serve the same role as an I3C Target Device with support for Legacy I2C communication.
```
-The I3C Core provides a Controller Interface, which is developed in compliance with:
+The I3C Core provides a Controller Interface which is developed in compliance with:
* MIPI Alliance Specification for I3C Basic, Version 1.1.1
* MIPI Alliance Specification for I3C HCI, Version 1.2
* MIPI Alliance Specification for I3C TCRI, Version 1.0
-Specification documents can be obtained directly from [MIPI website](https://www.mipi.org/specifications/i3c-hci), however, a login with MIPI Alliance account is required.
+The specification documents can be obtained directly from the [MIPI website](https://www.mipi.org/specifications/i3c-hci), however, a login with a MIPI Alliance account is required.
Some terminology of the MIPI Alliance Specifications carry over to this documentation and requires additional context:
-* `Active Controller Mode` is the mode, in which the I3C Core initiates transfers on the I3C bus and is primarily responsible for bus initialization and management
+* `Active Controller Mode` is the mode in which the I3C Core initiates transfers on the I3C bus and is primarily responsible for bus initialization and management
* `Secondary Controller Mode` is the mode, in which the I3C Core joins the I3C Bus as a Target Device and is conditionally responsible for specific bus management tasks
* `Secondary Controller Mode` and `Standby Controller Mode` are used interchangeably
* `Controller Interface` and `Host Controller Interface` are used interchangeably
diff --git a/_sources/recovery_flow.md.txt b/_sources/recovery_flow.md.txt
new file mode 100644
index 0000000..2313891
--- /dev/null
+++ b/_sources/recovery_flow.md.txt
@@ -0,0 +1,102 @@
+# Recovery flow
+
+The recovery flow is implemented according to OCP Secure Firmware Recovery standard v1.1-rc3.
+In recovery mode, the I3C Core acts as an I3C Target Device.
+In the Recovery Mode the Recovery Initiator Device (e.g. BMC) is primarily responsible for streaming the Firmware Recovery Image to the I3C Core.
+In order to facilitate this process, the I3C Core implements CSRs as specified in the [Secure Firmware Recovery Interface](ext_cap.md#secure_firmware_recovery_interface).
+The firmware is responsible for implementing the recovery flow and transfering firmware data to the program memory.
+
+The recovery flow adheres to the following steps:
+
+1. Upon reset the hardware sets FIFO size and region type in the `INDIRECT_FIFO_STATUS` CSR
+2. The device's firmware configures the I3C core and sets appropriate bits in `PROT_CAP` CSR to indicate its recovery capabilities
+ These must include the mandatory ones:
+ - bit 0 (`DEVICE_ID`)
+ - bit 4 (`DEVICE_STATUS`)
+ - bit 6 (`Local C-image support`) or bit 7 (`Push C-image support`)
+ - bit 5 (`INDIRECT_CTRL`) only if bit 7 is set
+2. Upon request for recovery mode entry, the firmware writes 0x3 (Recovery mode) to `DEVICE_STATUS`
+ :::{note}
+ What actually triggers the recovery mode?
+ :::
+3. The Recovery Handler writes 0x1 (Awaiting recovery image) to `RECOVERY_STATUS` and sets recovery image index to 0
+4. The Recovery Initiator writes to `INDIRECT_FIFO_CTRL` to inform the Recovery handler about the image size
+ - Component Memory Space (`CMS`) field is set to 0
+5. The Recovery Initiator writes a data chunk to the receive fifo via `INDIRECT_FIFO_DATA` CSR.
+ The I3C core responds with a NACK in case when the FIFO is full.
+6. The Recovery Handler updates FIFO pointers (Read Index and Write Index) presented in `INDIRECT_FIFO_STATUS` CSR
+7. The device's firmware reacts to a signal (interrupt, CSR poll?) that a data chunk has been written to the FIFO
+8. The device's firmware reads the data chunk from the FIFO and stores it in appropriate location in memory
+9. Steps 5 to 8 are repeated until the Recovery handler detects that the whole firmware image has been transmitted
+10. The device's firmware polls `RECOVERY_CONTROL` register until it receives the "Activate image" command from the Recovery Initiator
+11. The device's firmware updates the `RECOVERY_STATUS` CSR to indicate that the uploaded firmware is being booted
+
+## Recovery handler
+
+Since the OCP Secure Firmware Recovery standard describes a set of CSRs that are the interface between the device being updated and the Recovery Initiator, I3C transactions that implement accessing them must be handled in logic instead of firmware which is the purpose of the Recovery Handler block.
+
+When the recovery mode is active the handler takes over the TTI interface of the controller effectively detaching it from TTI CSRs.
+![](img/recovery_handler.png)
+
+The architecture of the Recovery Handler module is shown in the block diagram below:
+![](img/recovery_handler_bd.png)
+
+The module's backend is connected directly to the controller's TTI interface.
+There are several muxes on RX and TX data paths which allow bypassing the module in normal operation mode and remove/inject data in recovery mode.
+There are two `PEC` (Packet Error Code) blocks responsible for calculating CRC for RX and TX data paths.
+The CRC algorithm operates on individual bytes and implements C(x) = x^8+x^2+x^1+1 polynomial (see MCTP I3C binding, section 5.3.1).
+The frontend is connected to I3C core CSRs accessible by software.
+
+### Normal operation
+
+When recovery mode is inactive switches `R4SW`, `T4SW` are closed and all muxes are set to form a direct path between controller's TTI interface, TTI queues and TTI CSRs.
+
+### Recovery operation
+
+In recovery mode switches `R4SW` and `T4SW` are open and muxes `R4MUX` and `T4MUX` connect TTI queues frontend to recovery CSRs (`INDIRECT_FIFO`). Apart from the muxes, there's additional logic that controls when data can be accessed through `INDIRECT_FIFO` interface.
+
+## CSR access via I3C
+
+Recovery mode CSRs are accessible through I3C bus. The following protocol is used to implement read/write operations:
+
+### CSR Write
+![](img/i3c_csr_wr.png)
+
+The Recovery Initiator sends command byte followed by 16-bit payload length LSB and MSB bytes using I3C private transfers.
+Payload data bytes follow ended by a Packet Error Code (PEC) checksum.
+
+### CSR Read
+![](img/i3c_csr_rd.png)
+
+For CSR read the Recovery Initiator sends only the command byte and PEC checksum.
+Next, it issues a repeated start and begins a private read transaction.
+The device responds by sending data length LSB and MSB bytes followed by the data and PEC.
+
+## Recovery handler operation
+
+The main job of the Recovery Handler is providing hardware means for an active controller to access CSRs relevant to recovery operation.
+
+### CSR write
+
+When the Recovery Initiator tries to write to a CSR through I3C it first sends the command byte followed by two length bytes which are received by the handler logic.
+If the length is non-zero the handler resets the `PEC` block and sets `R2MUX` to pass the remaining data to TTI RX data queue.
+The `R2MUX` disconnects the queue just before the last byte which is the PEC checksum.
+Finally, The last byte is compared with the checksum computed by the `PEC` block.
+
+If the checksum matches the command handling part of the handler logic reads data from the TTI RX data queue and updates relevant CSR fields.
+
+If the checksum does not match then the handler discards all the data in the queue.
+
+In case of an `INDIRECT_FIFO_DATA` write command the handler does not process the data at all. Instead it opens `R3MUX` to make it available to the software.
+When the software reads data from `INDIRECT_FIFO_DATA` CSR the handler updates the queue pointer in `INDIRECT_FIFO_STATUS` CSR.
+
+### CSR read
+
+A CSR read begins similarly as write by receiving the command byte.
+Following that, the command handling part reads data from the CSR being read and passes it to the transmit part which formats the response I3C packet.
+
+The transmit logic injects CSR length, resets TX `PEC` module, sends the CSR content to the I3C core and finally injects the calculated PEC checksum.
+
+:::{note}
+TODO: Handle `INDIRECT_FIFO_DATA` read. This is not a priority as firmware write is more important than readback.
+:::
diff --git a/_sources/timings.md.txt b/_sources/timings.md.txt
index 3f75da6..0e42350 100644
--- a/_sources/timings.md.txt
+++ b/_sources/timings.md.txt
@@ -2,13 +2,13 @@
In this chapter we present:
* the SoC Management Interface
- * implemented oversampling of the I3C signals
- * implemented driver
+ * the implemented oversampling of the I3C signals
+ * the implemented drivers
The I3C Core exposes control over the electrical and timing configurations via [the SoC Management Interface](../../src/rdl/soc_management_interface.rdl).
```{note}
-Current numbers are not final and subject to change. Reserved for future.
+Current numbers are not final and are subject to change. Reserved for future.
```
## Clock speed and oversampling
@@ -31,20 +31,20 @@ In Active Controller Mode:
## Open-drain vs Push-pull configuration
-The I3C controller uses both Open-Drain and Push-Pull drivers and different timings are used for them.
+The I3C controller uses both Open-Drain and Push-Pull drivers, and different timings are used for them.
The Open-Drain and Push-Pull drivers are both used within one I3C Frame.
## Rise and fall times
Driver strength can be adjusted by setting correct values in the I3C Pad Attribute Configuration Register.
-The minimum allowed rise/fall times are: `150e6*bus_period`, which is 12 ns for the 12.5 MHz bus.
-When calculating timings it is worth to include all falling edges in the LOW state.
+The minimum allowed rise/fall times are `150e6*bus_period`, which is 12 ns for the 12.5 MHz bus.
+When calculating timings, it is worth including all falling edges in the LOW state.
Similarly, all the rising edges are part of the HIGH state.
This is because we will flip the bit in the internal implementation at the start of t{sub}`CR,CF` and then the actual rise/fall time will occur naturally.
## Timing control registers
-The SoC Management Interface defines the following registers, which can be used for timing control:
+The SoC Management Interface defines the following registers which can be used for timing control:
* `T_R_REG`
* `T_F_REG`
* `T_SU_DAT_REG`
@@ -58,9 +58,9 @@ The SoC Management Interface defines the following registers, which can be used
* `T_AVAL_REG`
* `T_IDLE_REG`
-Value of each of these registers expresses time delay, expressed in the I3C clock period.
-Default values are provided for the 500MHz clock.
-A python script [timing.py](../../tools/timing/timing.py) is provided to recalculate values for higher clock frequencies.
+The value of each of these registers expresses time delay, expressed in the I3C clock period.
+The default values are provided for the 500MHz clock.
+The [timing.py](../../tools/timing/timing.py) Python script is provided to recalculate values for higher clock frequencies.
### Rise/fall Time Register
### Setup Time Register
diff --git a/_sources/top.md.txt b/_sources/top.md.txt
index 1c02082..1871e11 100644
--- a/_sources/top.md.txt
+++ b/_sources/top.md.txt
@@ -23,8 +23,8 @@ Top level view (detailed)
## Controller Interface (CI)
-CI defines the CSR layout and how the host should interact with them to trigger desired I3C functions.
-The I3C core uses the PIO mode meaning that all interaction between it and the host happens through CSRs (as opposed to DMA mode where there's a separate path for the core to access memory).
+The CI defines the CSR layout and how the host should interact with them to trigger desired I3C functions.
+The I3C core uses the PIO mode, meaning that all interaction between the core and the host happens through CSRs (as opposed to the DMA mode where there's a separate path for the core to access memory).
:::{figure-md} hci
![](img/hci.png)
@@ -50,11 +50,11 @@ See section "7.5 PIO Mode Registers (PIO_BASE +)" of the HCI specification.
### Queues
CI queues facilitate communication between software-issued requests and the I3C controller logic.
-Each request is issued through appropriate ports of PIO Control register file.
+Each request is issued through appropriate ports of the PIO Control register file.
The data is then collected from those ports and enqueued on appropriate queues.
-CI then issues enqueued commands to the I3C controller logic and fetches transaction responses (if present).
+The CI then issues enqueued commands to the I3C controller logic and fetches transaction responses (if present).
-The queues are divided accordingly to their purpose:
+The queues are divided according to their purpose:
* Command queue
* 64-bit wide
* Enqueues to-be-issued command descriptors
@@ -73,13 +73,13 @@ Both command and response descriptors are addressed with the index to the DAT ta
Command descriptors are fixed to 64-bit (2-DWORD).
Response descriptors are fixed to 32-bit (1-DWORD).
-For the details see [Controller Interface Queues](ci_queues.md#controller-interface-queues) section.
+For details, see the [Controller Interface Queues](ci_queues.md#controller-interface-queues) section.
### DAT & DCT
To increase flexibility of the design, both DAT and DCT tables are instantiated as memories external from the I3C Core.
Access paths to these memories are routed through the Controller Interface module directly to the underlying DAT/DCT access logic.
-Such approach ensures very convenient way of replacing memory models for specific target architecture.
+Such an approach ensures a very convenient way of replacing memory models for specific target architecture.
:::{figure-md} dat_dct
![](img/dat_dct.png)
@@ -90,54 +90,54 @@ Block diagram of DAT and DCT connections
#### Device Address Table (DAT)
The Controller should perform initial I3C Bus enumeration after initialization.
-During this process, software driver should assign static address for each device that is prior known on the bus.
-Additionally, for every Dynamic Addressing capable Device, dynamic address shall be set for each valid DAT entry, as part of the Dynamic Address Assignment process.
-Once the DAT is set up, devices can be assigned dynamic addresses in following ways:
-* **SETDASA** (direct) and **SETAASA** (broadcast) to assign dynamic address based on static address,
+During this process, the software driver should assign a static address for each device that is prior known on the bus.
+Additionally, for every Dynamic Addressing capable Device, a dynamic address will be set for each valid DAT entry, as part of the Dynamic Address Assignment process.
+Once the DAT is set up, devices can be assigned dynamic addresses in the following ways:
+* **SETDASA** (direct) and **SETAASA** (broadcast) to assign a dynamic address based on a static address,
* **ENTDAA** to enter dynamic address assignment procedure.
-After bus initialization, the DAT is not affected by physically removing the device from the bus and can be updated by sending **SETNEWDA** (set new dynamic address) CCC or **SETGRPA** (set group address) CCC.
+After bus initialization, the DAT is not affected by physically removing the device from the bus and can be updated by sending the **SETNEWDA** (set new dynamic address) CCC or the **SETGRPA** (set group address) CCC.
-Dynamically addressed I3C targets with their DAT entries can be reset by sending **RSTDAA** command on the bus.
+Dynamically addressed I3C targets with their DAT entries can be reset by sending the **RSTDAA** command on the bus.
Assigned groups of addresses can be cleared by sending **RSTGRPA**.
In case the I3C Controller enters standby mode by passing the active controller role to another device, there is no requirement (on hardware) to keep the DAT table up-to-date.
-However, when the I3C Controller transitions back to the Active Controller role, it should receive **DEFTGTS** CCC that provides states of all targets present on the bus.
+However, when the I3C Controller transitions back to the Active Controller role, it should receive the **DEFTGTS** CCC that provides states of all targets present on the bus.
The software driver should then update the DAT table.
-Since the DAT memory is writable from software, it must support single 32-bit word masked access so that the software can write data without overwriting whole table entry.
+Since the DAT memory is writable from software, it must support single 32-bit word masked access so that the software can write data without overwriting the whole table entry.
#### Device Characteristic Table (DCT)
-During dynamic address assignment, each target device on the bus must report its BCR, DCR and PID which are then saved in the Device Characteristic Table.
-The only I3C command that modifies content of the DCT is **ENTDAA**.
+During dynamic address assignment, each target device on the bus must report its BCR, DCR and PID, which are then saved in the Device Characteristic Table.
+The only I3C command that modifies the content of the DCT is **ENTDAA**.
From the software point of view, DCT memory is read only and should never be written to.
### CSR
-CSRs are implemented from [SystemRDL description](https://github.com/chipsalliance/i3c-core/tree/main/src/rdl) and implementation uses [generated SV files](https://github.com/chipsalliance/i3c-core/tree/main/src/csr).
+CSRs are implemented from the [SystemRDL description](https://github.com/chipsalliance/i3c-core/tree/main/src/rdl) using the [generated SV files](https://github.com/chipsalliance/i3c-core/tree/main/src/csr).
### AXI communication
This layer provides an AXI frontend to integrate the I3C controller with the designated system.
-The implementation is derived from the Caliptra's implementation of the AXI subordinate, which is being developed on [branch](https://github.com/chipsalliance/caliptra-rtl/tree/cwhitehead-msft-gen2-axi-modules).
+The implementation is derived from Caliptra's implementation of the AXI subordinate, which is being developed on [this branch](https://github.com/chipsalliance/caliptra-rtl/tree/cwhitehead-msft-gen2-axi-modules).
### AHB communication
This layer provides an AHB-compliant frontend to integrate the I3C controller with the designated system.
It intermediates between AHB-issued CSR access commands and controller's internal access protocol with the use of [ahb_to_reg_adapter](https://github.com/chipsalliance/caliptra-rtl/blob/9c815c335a92901b27458271a885b2128e51e687/src/libs/rtl/ahb_to_reg_adapter.sv#L24).
-The AHB-Lite implementation bases on AMBA 3 AHB-Lite Protocol Specification IHI0033A.
+The AHB-Lite implementation is based on the AMBA 3 AHB-Lite Protocol Specification IHI0033A.
-As of now, only non-sequential transfer mode is supported.
+As of now, only the non-sequential transfer mode is supported.
The AHB-Lite interface is compliant with the Caliptra system and by default is parameterized with `ADDR_WIDTH=32`, `DATA_WIDTH=64`.
-AHB-Lite interface allows for the following parameters to be configured:
+The AHB-Lite interface allows for the following parameters to be configured:
* `AHB_DATA_WIDTH`
* `AHB_ADDR_WIDTH`
-Because the size of the CSRs is fixed to 32-bits, only the lowest 32-bits of `haddress` and `hwdata` channels will be accounted for.
+Because the size of the CSRs is fixed to 32-bits, only the lowest 32-bits of the `haddress` and `hwdata` channels will be accounted for.
## I3C Controller
@@ -149,7 +149,7 @@ Main part of the system.
Block diagram of the I3C Controller
:::
-When the I3C Core acts as an Active Controller, it follows the flow presented on {numref}`i3c_flow_fsm`.
+When the I3C Core acts as an Active Controller, it follows the flow presented in {numref}`i3c_flow_fsm`.
:::{figure-md} i3c_flow_fsm
![](img/i3c_flow_fsm.png)
@@ -160,16 +160,16 @@ FSM: Active Controller
### Bus arbitration (5.1.2.2.1)
In an I3C (or multi-master I2C) system, it is possible that multiple devices connected to the bus will try to take over the bus control at the same time.
-Arbitration process must occur to resolve access.
-All devices that are concurrently transmitting an address follow the same rule:
-1. If the current bit to transmit is a 0, then the Device shall drive SDA Low after the falling edge of SCL and hold Low until the next falling edge of SCL.
+An arbitration process must occur to resolve access.
+All devices that are concurrently transmitting an address follow the same rules:
+1. If the current bit to transmit is a 0, then the Device will drive SDA Low after the falling edge of SCL and hold Low until the next falling edge of SCL.
:::{Note}
Other Devices may also be driving SDA Low, but that is acceptable.
:::
-2. If the current bit to transmit is a 1, then the Device shall not drive SDA, but rather shall High-Z SDA on the falling edge of SCL.
- * Additionally, the Device shall monitor the SDA on the rising edge of SCL to determine whether another Device has driven SDA Low.
- * If another Device has driven the SDA Low, then the Device has "*lost*" the Arbitration and shall not further participate in this Address Header.
- That is, the Device shall not transmit any more bits, but may wait for a future START (but not a Repeated START).
+2. If the current bit to transmit is a 1, then the Device will not drive SDA, but rather High-Z SDA on the falling edge of SCL.
+ * Additionally, the Device will monitor the SDA on the rising edge of SCL to determine whether another Device has driven SDA Low.
+ * If another Device has driven the SDA Low, then the Device has "*lost*" the Arbitration and will not further participate in this Address Header.
+ That is, the Device will not transmit any more bits, but may wait for a future START (but not a Repeated START).
:::{note}
Section 5.1.2.2.2 of the I3C specification describes possible arbitration enhancements.
@@ -178,7 +178,7 @@ Section 5.1.2.2.2 of the I3C specification describes possible arbitration enhanc
## Common PHY Layer
The PHY is responsible for controlling external bus signals (SDA, SCL) and synchronizing them with an internal clock. It should also support bus arbitration.
-The [I2C Core](https://opentitan.org/book/hw/ip/i2c/index.html) from the Opentitan project can be used as a reference design for basic features of the PHY.
+The [I2C Core](https://opentitan.org/book/hw/ip/i2c/index.html) from the OpenTitan project can be used as a reference design for basic features of the PHY.
:::{figure-md} i3c_phy
![](img/i3c_phy.png)
@@ -193,11 +193,11 @@ Bus lines should be HIGH unless any device ties them to the GROUND.
:::{note}
In addition to the active Open Drain class Pull-Up, a High-Keeper is also required on the Bus.
-The High-Keeper on the Bus shall be strong enough to prevent system leakage from pulling SDA, and sometimes SCL, Low.
-The High-Keeper on the Bus shall also be weak enough that a Target with the minimum I{sub}`OL` PHY is able to pull SDA, SCL, or both Low within the Minimum t{sub}`DIG_L` period.
+The High-Keeper on the Bus should be strong enough to prevent system leakage from pulling SDA, and sometimes SCL, Low.
+The High-Keeper on the Bus should also be weak enough for a Target with the minimum I{sub}`OL` PHY to be able to pull SDA, SCL, or both Low within the Minimum t{sub}`DIG_L` period.
-The High-Keeper should be implemented during physical design.
-PHY driver strength modelling will not be performed in this project.
+The High-Keeper should be implemented during the physical design.
+PHY driver strength modeling will not be performed in this project.
Base Controller will be delivered without the High-Keeper, however, it may become a configuration option later on.
:::
@@ -207,39 +207,39 @@ Each bus line must be capable of switching between 4 logic states:
3. Open Drain Pull-Up
4. Assert LOW
-The Opentitan I2C Core implements a [Virtual Open Drain](https://opentitan.org/book/hw/ip/i2c/doc/theory_of_operation.html#virtual-open-drain) functionality which seems like a good solution for implementing the desired behavior on FPGA devices while at the same time keeping it easy to use in silicon chips. Each bus line consists of 3 lines:
+The OpenTitan I2C Core implements a [Virtual Open Drain](https://opentitan.org/book/hw/ip/i2c/doc/theory_of_operation.html#virtual-open-drain) functionality which seems like a good solution for implementing the desired behavior on FPGA devices, while at the same time keeping it easy to use in silicon chips. Each bus line consists of 3 lines:
1. Signal input (`scl_i`, `sda_i`) - external input from the bus lines.
2. Signal output (`scl_o`, `sda_o`) - internal signal, it is tied to the GROUND.
3. Signal output enable (`scl_en_o`, `sda_en_o`) - internal signal enable, controlled by the core FSM.
This interface makes it easy to construct tri-state buffers.
-The controller will never assert external bus lines HIGH since it is assumed that these lines are pulled up to V{sub}`dd` externally.
+The controller will never assert the external bus lines HIGH, since it is assumed that these lines are pulled up to V{sub}`dd` externally.
Switching from output to input is enough to achieve signals asserted HIGH.
Verilator does not natively support `x` and `z` states and their handling is explained in the [official documentation](https://verilator.org/guide/latest/languages.html?highlight=tristate#tri-inout).
-Cocotb requires a wrapper to interact properly with an `inout` which is described in [Cocotb discussion #3506](https://github.com/cocotb/cocotb/discussions/3506).
+Cocotb requires a wrapper to interact properly with an `inout`, which is described in [Cocotb discussion #3506](https://github.com/cocotb/cocotb/discussions/3506).
Considering these limitations, PHY is being tested functionally using Cocotb and tri-state logic.
-Additionally, there is a RTL testbench run in Verilator and Icarus simulators that checks whether High-Z is set properly on I3C bus lines when the controller request high bus state.
+Additionally, there is an RTL testbench run in Verilator and Icarus simulators that checks whether High-Z is set properly on I3C bus lines when the controller requests a high bus state.
### Clock synchronization (5.1.7)
-While Legacy I2C protocol requires clock synchronization between each master and bus, I3C does not need such mechanism due to the handoff procedure.
-If currently active Controller wants to pass Controller privileges to another device, it should run the handoff procedure and then it shall issue a `GETACCR` command followed by a STOP condition, if the handoff was successful.
-After such operation, an active Controller shall release control of the SCL line, therefore releasing control of the I3C Bus to the selected Secondary Controller.
+While the Legacy I2C protocol requires clock synchronization between each master and bus, I3C does not need such mechanism due to the handoff procedure.
+If the currently active Controller wants to pass Controller privileges to another device, it should run the handoff procedure and then it will issue a `GETACCR` command followed by a STOP condition, if the handoff was successful.
+After such an operation, the active Controller will release control of the SCL line, therefore releasing control of the I3C Bus to the selected Secondary Controller.
However, signals read from the I3C bus clock domain must be synchronized to the system clock domain before they are used internally.
As a reference, OpenTitan uses a 24MHz system clock to oversample data through [two flip flops](https://github.com/lowRISC/opentitan/blob/master/hw/ip/i2c/rtl/i2c_core.sv#L390-L409).
### Mixed I2C and I3C Bus (5.1.1.2.3)
-This project aims to create an I3C Primary Controller which means that we want to support all possible configurations specified by the I3C Bus specification:
+This project aims to create an I3C Primary Controller, which means that we want to support all possible configurations specified by the I3C Bus specification:
1. **Pure Bus**: Only I3C Devices are present on the Bus.
-2. **Mixed Fast Bus**: Both I3C Devices and Legacy I2C Devices are present on the Bus, such that the
-Legacy I2C Devices are restricted to ones that are generally permissible (i.e., Target-only, and no
-Target clock stretching), and that have a true I2C 50 ns Spike Filter on SCL. (I.e., I2C Devices that do not ‘see’ the SCL line as High when the High duration is less than 50 ns, across all temperatures and processes.)
-3. **Mixed Slow/Limited Bus**: Both I3C Devices and Legacy I2C Devices are present on the Bus, such that the Legacy I2C Devices are restricted to ones that are generally permissible (i.e., Target-only, and no Target clock stretching), but that do not have a true I2C 50 ns Spike Filter on SCL.
+2. **Mixed Fast Bus**: Both I3C Devices and Legacy I2C Devices are present on the Bus, in a way that the
+Legacy I2C Devices are restricted to the ones that are generally permissible (i.e., Target-only, and no
+Target clock stretching), and have a true I2C 50 ns Spike Filter on SCL. (I.e., I2C Devices that do not ‘see’ the SCL line as High when the High duration is less than 50 ns, across all temperatures and processes.)
+3. **Mixed Slow/Limited Bus**: Both I3C Devices and Legacy I2C Devices are present on the Bus, in a way that the Legacy I2C Devices are restricted to the ones that are generally permissible (i.e., Target-only, and no Target clock stretching), but do not have a true I2C 50 ns Spike Filter on SCL.
-While Mixed Fast Bus configuration can operate on both I2C and I3C protocols simultaneously (with certain speed limitations), Mixed Slow/Limited Bus is based on downgrading whole bus performance to the Legacy I2C protocol.
+While the Mixed Fast Bus configuration can operate on both I2C and I3C protocols simultaneously (with certain speed limitations), Mixed Slow/Limited Bus is based on downgrading the whole bus performance to the Legacy I2C protocol.
:::{note}
The Mixed Fast Bus scenario relies on the fact that Legacy I2C Devices are expected to support Legacy Virtual Register (LVR) through their **software drivers**.
:::
diff --git a/ci_queues.html b/ci_queues.html
index 2b94a89..0cc4587 100644
--- a/ci_queues.html
+++ b/ci_queues.html
@@ -327,7 +327,7 @@
Command and response queue thresholds are controlled via QUEUE_THLD_CTRL register.
+
Command and response queue thresholds are controlled via the QUEUE_THLD_CTRL register.
RX and TX data queue thresholds are controlled via DATA_BUFFER_THLD_CTRL.
The threshold for command queue is set by a write to the QUEUE_THLD_CTRL to the 8-bit CMD_EMPTY_BUF_THLD field.
-
The threshold N of range <1,255> (inclusive) will cause an CMD_QUEUE_READY_STAT interrupt when there’s N or more remaining empty entries left in the command queue.
-
If the N value is greater than the size of the command queue (CMD_FIFO_DEPTH) the full depth will be considered (the threshold will be set to CMD_FIFO_DEPTH).
+
The threshold for command queue is set by a write to the 8-bit CMD_EMPTY_BUF_THLD field of the QUEUE_THLD_CTRL register.
+
The N threshold of <1,255> range (inclusive) will cause an CMD_QUEUE_READY_STAT interrupt when there’s N or more remaining empty entries in the command queue.
+
If the N value is greater than the size of the command queue (CMD_FIFO_DEPTH), the full depth will be considered (the threshold will be set to CMD_FIFO_DEPTH).
The threshold for response queue is set by a write to QUEUE_THLD_CTRL to the 8-bit RESP_BUF_THLD field.
-
The threshold N of range <1,255> (inclusive) will cause an RESP_READY_STAT interrupt when there’s N or more responses enqueued in the response queue.
-
If the N value is greater or equal than the size of the response queue (RESP_FIFO_DEPTH) the full depth will be considered (the threshold will be set to RESP_FIFO_DEPTH-1)
+
The threshold for response queue is set by a write to the 8-bit RESP_BUF_THLD field of the QUEUE_THLD_CTRL register.
+
The N threshold of <1,255> range (inclusive) will cause an RESP_READY_STAT interrupt when there’s N or more responses enqueued in the response queue.
+
If the N value is greater or equal than the size of the response queue (RESP_FIFO_DEPTH), the full depth will be considered (the threshold will be set to RESP_FIFO_DEPTH-1)
The threshold for the TX queue is set by a write to DATA_BUFFER_THLD_CTRL to the 3-bit TX_BUF_THLD field.
-
The threshold N of range <0,7> (inclusive) will trigger an TX_THLD_STAT interrupt when 2^(N+1) (2 to the power of N+1) DWORD empty entries are available in the TX queue.
-
The software must provide an N value that corresponds to the threshold less or equal than TX_FIFO_DEPTH, otherwise the clog2(TX_FIFO_DEPTH)-1 will be applied.
+
The threshold for the TX queue is set by a write to the 3-bit TX_BUF_THLD field of the DATA_BUFFER_THLD_CTRL register.
+
The N threshold of <0,7> range (inclusive) will trigger an TX_THLD_STAT interrupt when 2^(N+1) (2 to the power of N+1) empty DWORD entries are available in the TX queue.
+
The software must provide an N value that corresponds to the threshold less or equal than TX_FIFO_DEPTH, otherwise clog2(TX_FIFO_DEPTH)-1 will be applied.
The threshold for the RX queue is set by a write to DATA_BUFFER_THLD_CTRL to the 3-bit RX_BUF_THLD field.
-
The threshold N of range <0,7> (inclusive) will trigger an RX_THLD_STAT interrupt when 2^(N+1) (2 to the power of N+1) DWORD entries are enqueued in the RX queue.
-
The software must provide an N value that corresponds to the threshold less than RX_FIFO_DEPTH, otherwise the clog2(RX_FIFO_DEPTH)-2 will be applied.
+
The threshold for the RX queue is set by a write to the 3-bit RX_BUF_THLD field of the DATA_BUFFER_THLD_CTRL register.
+
The N threshold of <0,7> range (inclusive) will trigger an RX_THLD_STAT interrupt when 2^(N+1) (2 to the power of N+1) DWORD entries are enqueued in the RX queue.
+
The software must provide an N value that corresponds to the threshold less than RX_FIFO_DEPTH, otherwise clog2(RX_FIFO_DEPTH)-2 will be applied.
MIPI Alliance Specification for I3C Basic, Version 1.1.1
MIPI Alliance Specification for I3C HCI, Version 1.2
MIPI Alliance Specification for I3C TCRI, Version 1.0
-
Specification documents can be obtained directly from MIPI website, however, a login with MIPI Alliance account is required.
+
The specification documents can be obtained directly from the MIPI website, however, a login with a MIPI Alliance account is required.
Some terminology of the MIPI Alliance Specifications carry over to this documentation and requires additional context:
-
ActiveControllerMode is the mode, in which the I3C Core initiates transfers on the I3C bus and is primarily responsible for bus initialization and management
+
ActiveControllerMode is the mode in which the I3C Core initiates transfers on the I3C bus and is primarily responsible for bus initialization and management
SecondaryControllerMode is the mode, in which the I3C Core joins the I3C Bus as a Target Device and is conditionally responsible for specific bus management tasks
SecondaryControllerMode and StandbyControllerMode are used interchangeably
ControllerInterface and HostControllerInterface are used interchangeably
The recovery flow is implemented according to OCP Secure Firmware Recovery standard v1.1-rc3.
+In recovery mode, the I3C Core acts as an I3C Target Device.
+In the Recovery Mode the Recovery Initiator Device (e.g. BMC) is primarily responsible for streaming the Firmware Recovery Image to the I3C Core.
+In order to facilitate this process, the I3C Core implements CSRs as specified in the Secure Firmware Recovery Interface.
+The firmware is responsible for implementing the recovery flow and transfering firmware data to the program memory.
+
The recovery flow adheres to the following steps:
+
+
Upon reset the hardware sets FIFO size and region type in the INDIRECT_FIFO_STATUS CSR
+
The device’s firmware configures the I3C core and sets appropriate bits in PROT_CAP CSR to indicate its recovery capabilities
+These must include the mandatory ones:
+
+
bit 0 (DEVICE_ID)
+
bit 4 (DEVICE_STATUS)
+
bit 6 (LocalC-imagesupport) or bit 7 (PushC-imagesupport)
+
bit 5 (INDIRECT_CTRL) only if bit 7 is set
+
+
+
Upon request for recovery mode entry, the firmware writes 0x3 (Recovery mode) to DEVICE_STATUS
+
+
Note
+
What actually triggers the recovery mode?
+
+
+
The Recovery Handler writes 0x1 (Awaiting recovery image) to RECOVERY_STATUS and sets recovery image index to 0
+
The Recovery Initiator writes to INDIRECT_FIFO_CTRL to inform the Recovery handler about the image size
+
+
Component Memory Space (CMS) field is set to 0
+
+
+
The Recovery Initiator writes a data chunk to the receive fifo via INDIRECT_FIFO_DATA CSR.
+The I3C core responds with a NACK in case when the FIFO is full.
+
The Recovery Handler updates FIFO pointers (Read Index and Write Index) presented in INDIRECT_FIFO_STATUS CSR
+
The device’s firmware reacts to a signal (interrupt, CSR poll?) that a data chunk has been written to the FIFO
+
The device’s firmware reads the data chunk from the FIFO and stores it in appropriate location in memory
+
Steps 5 to 8 are repeated until the Recovery handler detects that the whole firmware image has been transmitted
+
The device’s firmware polls RECOVERY_CONTROL register until it receives the “Activate image” command from the Recovery Initiator
+
The device’s firmware updates the RECOVERY_STATUS CSR to indicate that the uploaded firmware is being booted
Since the OCP Secure Firmware Recovery standard describes a set of CSRs that are the interface between the device being updated and the Recovery Initiator, I3C transactions that implement accessing them must be handled in logic instead of firmware which is the purpose of the Recovery Handler block.
+
When the recovery mode is active the handler takes over the TTI interface of the controller effectively detaching it from TTI CSRs.
+
+
The architecture of the Recovery Handler module is shown in the block diagram below:
+
+
The module’s backend is connected directly to the controller’s TTI interface.
+There are several muxes on RX and TX data paths which allow bypassing the module in normal operation mode and remove/inject data in recovery mode.
+There are two PEC (Packet Error Code) blocks responsible for calculating CRC for RX and TX data paths.
+The CRC algorithm operates on individual bytes and implements C(x) = x^8+x^2+x^1+1 polynomial (see MCTP I3C binding, section 5.3.1).
+The frontend is connected to I3C core CSRs accessible by software.
When recovery mode is inactive switches R4SW, T4SW are closed and all muxes are set to form a direct path between controller’s TTI interface, TTI queues and TTI CSRs.
In recovery mode switches R4SW and T4SW are open and muxes R4MUX and T4MUX connect TTI queues frontend to recovery CSRs (INDIRECT_FIFO). Apart from the muxes, there’s additional logic that controls when data can be accessed through INDIRECT_FIFO interface.
The Recovery Initiator sends command byte followed by 16-bit payload length LSB and MSB bytes using I3C private transfers.
+Payload data bytes follow ended by a Packet Error Code (PEC) checksum.
For CSR read the Recovery Initiator sends only the command byte and PEC checksum.
+Next, it issues a repeated start and begins a private read transaction.
+The device responds by sending data length LSB and MSB bytes followed by the data and PEC.
When the Recovery Initiator tries to write to a CSR through I3C it first sends the command byte followed by two length bytes which are received by the handler logic.
+If the length is non-zero the handler resets the PEC block and sets R2MUX to pass the remaining data to TTI RX data queue.
+The R2MUX disconnects the queue just before the last byte which is the PEC checksum.
+Finally, The last byte is compared with the checksum computed by the PEC block.
+
If the checksum matches the command handling part of the handler logic reads data from the TTI RX data queue and updates relevant CSR fields.
+
If the checksum does not match then the handler discards all the data in the queue.
+
In case of an INDIRECT_FIFO_DATA write command the handler does not process the data at all. Instead it opens R3MUX to make it available to the software.
+When the software reads data from INDIRECT_FIFO_DATA CSR the handler updates the queue pointer in INDIRECT_FIFO_STATUS CSR.
A CSR read begins similarly as write by receiving the command byte.
+Following that, the command handling part reads data from the CSR being read and passes it to the transmit part which formats the response I3C packet.
+
The transmit logic injects CSR length, resets TX PEC module, sends the CSR content to the I3C core and finally injects the calculated PEC checksum.
+
+
Note
+
TODO: Handle INDIRECT_FIFO_DATA read. This is not a priority as firmware write is more important than readback.
The I3C controller uses both Open-Drain and Push-Pull drivers and different timings are used for them.
+
The I3C controller uses both Open-Drain and Push-Pull drivers, and different timings are used for them.
The Open-Drain and Push-Pull drivers are both used within one I3C Frame.
Driver strength can be adjusted by setting correct values in the I3C Pad Attribute Configuration Register.
-The minimum allowed rise/fall times are: 150e6*bus_period, which is 12 ns for the 12.5 MHz bus.
-When calculating timings it is worth to include all falling edges in the LOW state.
+The minimum allowed rise/fall times are 150e6*bus_period, which is 12 ns for the 12.5 MHz bus.
+When calculating timings, it is worth including all falling edges in the LOW state.
Similarly, all the rising edges are part of the HIGH state.
This is because we will flip the bit in the internal implementation at the start of tCR,CF and then the actual rise/fall time will occur naturally.
Value of each of these registers expresses time delay, expressed in the I3C clock period.
-Default values are provided for the 500MHz clock.
-A python script timing.py is provided to recalculate values for higher clock frequencies.
+
The value of each of these registers expresses time delay, expressed in the I3C clock period.
+The default values are provided for the 500MHz clock.
+The timing.py Python script is provided to recalculate values for higher clock frequencies.
CI defines the CSR layout and how the host should interact with them to trigger desired I3C functions.
-The I3C core uses the PIO mode meaning that all interaction between it and the host happens through CSRs (as opposed to DMA mode where there’s a separate path for the core to access memory).
+
The CI defines the CSR layout and how the host should interact with them to trigger desired I3C functions.
+The I3C core uses the PIO mode, meaning that all interaction between the core and the host happens through CSRs (as opposed to the DMA mode where there’s a separate path for the core to access memory).
In an I3C (or multi-master I2C) system, it is possible that multiple devices connected to the bus will try to take over the bus control at the same time.
-Arbitration process must occur to resolve access.
-All devices that are concurrently transmitting an address follow the same rule:
+An arbitration process must occur to resolve access.
+All devices that are concurrently transmitting an address follow the same rules:
-
If the current bit to transmit is a 0, then the Device shall drive SDA Low after the falling edge of SCL and hold Low until the next falling edge of SCL.
+
If the current bit to transmit is a 0, then the Device will drive SDA Low after the falling edge of SCL and hold Low until the next falling edge of SCL.
Note
Other Devices may also be driving SDA Low, but that is acceptable.
-
If the current bit to transmit is a 1, then the Device shall not drive SDA, but rather shall High-Z SDA on the falling edge of SCL.
+
If the current bit to transmit is a 1, then the Device will not drive SDA, but rather High-Z SDA on the falling edge of SCL.
-
Additionally, the Device shall monitor the SDA on the rising edge of SCL to determine whether another Device has driven SDA Low.
-
If another Device has driven the SDA Low, then the Device has “lost” the Arbitration and shall not further participate in this Address Header.
-That is, the Device shall not transmit any more bits, but may wait for a future START (but not a Repeated START).
+
Additionally, the Device will monitor the SDA on the rising edge of SCL to determine whether another Device has driven SDA Low.
+
If another Device has driven the SDA Low, then the Device has “lost” the Arbitration and will not further participate in this Address Header.
+That is, the Device will not transmit any more bits, but may wait for a future START (but not a Repeated START).
The PHY is responsible for controlling external bus signals (SDA, SCL) and synchronizing them with an internal clock. It should also support bus arbitration.
-The I2C Core from the Opentitan project can be used as a reference design for basic features of the PHY.
+The I2C Core from the OpenTitan project can be used as a reference design for basic features of the PHY.
@@ -847,10 +862,10 @@
SDA and SCL lines (5.1.3.1)Virtual Open Drain functionality which seems like a good solution for implementing the desired behavior on FPGA devices while at the same time keeping it easy to use in silicon chips. Each bus line consists of 3 lines:
+
The OpenTitan I2C Core implements a Virtual Open Drain functionality which seems like a good solution for implementing the desired behavior on FPGA devices, while at the same time keeping it easy to use in silicon chips. Each bus line consists of 3 lines:
Signal input (scl_i, sda_i) - external input from the bus lines.
Signal output (scl_o, sda_o) - internal signal, it is tied to the GROUND.
Signal output enable (scl_en_o, sda_en_o) - internal signal enable, controlled by the core FSM.
This interface makes it easy to construct tri-state buffers.
-The controller will never assert external bus lines HIGH since it is assumed that these lines are pulled up to Vdd externally.
+The controller will never assert the external bus lines HIGH, since it is assumed that these lines are pulled up to Vdd externally.
Switching from output to input is enough to achieve signals asserted HIGH.
Verilator does not natively support x and z states and their handling is explained in the official documentation.
-Cocotb requires a wrapper to interact properly with an inout which is described in Cocotb discussion #3506.
+Cocotb requires a wrapper to interact properly with an inout, which is described in Cocotb discussion #3506.
Considering these limitations, PHY is being tested functionally using Cocotb and tri-state logic.
-Additionally, there is a RTL testbench run in Verilator and Icarus simulators that checks whether High-Z is set properly on I3C bus lines when the controller request high bus state.
+Additionally, there is an RTL testbench run in Verilator and Icarus simulators that checks whether High-Z is set properly on I3C bus lines when the controller requests a high bus state.
While Legacy I2C protocol requires clock synchronization between each master and bus, I3C does not need such mechanism due to the handoff procedure.
-If currently active Controller wants to pass Controller privileges to another device, it should run the handoff procedure and then it shall issue a GETACCR command followed by a STOP condition, if the handoff was successful.
-After such operation, an active Controller shall release control of the SCL line, therefore releasing control of the I3C Bus to the selected Secondary Controller.
+
While the Legacy I2C protocol requires clock synchronization between each master and bus, I3C does not need such mechanism due to the handoff procedure.
+If the currently active Controller wants to pass Controller privileges to another device, it should run the handoff procedure and then it will issue a GETACCR command followed by a STOP condition, if the handoff was successful.
+After such an operation, the active Controller will release control of the SCL line, therefore releasing control of the I3C Bus to the selected Secondary Controller.
However, signals read from the I3C bus clock domain must be synchronized to the system clock domain before they are used internally.
As a reference, OpenTitan uses a 24MHz system clock to oversample data through two flip flops.
This project aims to create an I3C Primary Controller which means that we want to support all possible configurations specified by the I3C Bus specification:
+
This project aims to create an I3C Primary Controller, which means that we want to support all possible configurations specified by the I3C Bus specification:
Pure Bus: Only I3C Devices are present on the Bus.
-
Mixed Fast Bus: Both I3C Devices and Legacy I2C Devices are present on the Bus, such that the
-Legacy I2C Devices are restricted to ones that are generally permissible (i.e., Target-only, and no
-Target clock stretching), and that have a true I2C 50 ns Spike Filter on SCL. (I.e., I2C Devices that do not ‘see’ the SCL line as High when the High duration is less than 50 ns, across all temperatures and processes.)
-
Mixed Slow/Limited Bus: Both I3C Devices and Legacy I2C Devices are present on the Bus, such that the Legacy I2C Devices are restricted to ones that are generally permissible (i.e., Target-only, and no Target clock stretching), but that do not have a true I2C 50 ns Spike Filter on SCL.
+
Mixed Fast Bus: Both I3C Devices and Legacy I2C Devices are present on the Bus, in a way that the
+Legacy I2C Devices are restricted to the ones that are generally permissible (i.e., Target-only, and no
+Target clock stretching), and have a true I2C 50 ns Spike Filter on SCL. (I.e., I2C Devices that do not ‘see’ the SCL line as High when the High duration is less than 50 ns, across all temperatures and processes.)
+
Mixed Slow/Limited Bus: Both I3C Devices and Legacy I2C Devices are present on the Bus, in a way that the Legacy I2C Devices are restricted to the ones that are generally permissible (i.e., Target-only, and no Target clock stretching), but do not have a true I2C 50 ns Spike Filter on SCL.
-
While Mixed Fast Bus configuration can operate on both I2C and I3C protocols simultaneously (with certain speed limitations), Mixed Slow/Limited Bus is based on downgrading whole bus performance to the Legacy I2C protocol.
+
While the Mixed Fast Bus configuration can operate on both I2C and I3C protocols simultaneously (with certain speed limitations), Mixed Slow/Limited Bus is based on downgrading the whole bus performance to the Legacy I2C protocol.
Note
The Mixed Fast Bus scenario relies on the fact that Legacy I2C Devices are expected to support Legacy Virtual Register (LVR) through their software drivers.