Easyi3C is a leading supplier of embedded system tools that simplify the development and debugging of various communication protocols. The company offers a range of products designed to help engineers and developers use I3C/I2C , USB and MIPI, JEDEC, MCTP and other protocols more efficiently.
In the context of DDR5 memory modules, the PMIC (Power Management Integrated Circuit) is managed via a sideband bus (I2C or I3C). "2-Byte Address" typically refers to the register addressing mechanism used to access the PMIC's internal configuration .
The following is a detailed explanation of how 2-byte addressing works in the DDR5 ecosystem:
1-Byte Address: Standard traditional I2C uses an 8-bit register offset ( 0x00to 0xFF).
2-Byte Address: Because the DDR5 PMIC and SPD Hub contain far more configuration data and vendor-specific registers than previous generations, they typically use 16-bit register addresses (2 bytes) to map the expanded memory space.
When using 2-byte addressing for write or read operations, the master device (memory controller or bus analysis tool) sends data in the following order:
| order | Components | describe |
| first step | Slave Address | The PMIC has a 7-bit I2C address plus write bits. |
| Step 2 | Address MSB (high-order bits) | The "most significant byte" of the register (for example 0x01). |
| Step 3 | Address LSB | The "least significant byte" of the register (e.g. 0x30). |
| Step 4 | Data | The actual value written to the register 0x0130. |
Depending on the specific PMIC vendor (such as Renesas, Rambus, or MPS), you may encounter two methods for accessing the "extended" registers:
Paging mode: You first write a 1-byte address to the "page select" register, which changes the memory "view" that subsequent 1-byte commands can see.
True 2-byte addressing mode: The device is configured in a specific mode in which each command is followed by two address bytes after the slave ID.
Note: In the JEDEC specification for DDR5 (such as JESD301 ), there is a bit in the configuration register (usually Register 11 ) that can switch the device between 1-byte addressing and 2-byte addressing modes.
Supplier-specific areas: PMIC has certain specific areas (often starting with on some pages 0x40) that are usually password protected and require specific offsets to calibrate the voltage rails (VDD, VDDQ, VPP).
Telemetry: The unique offset required to read real-time current, voltage, and temperature data exceeds the 256 register limit supported by 1-byte addressing.
Important security tip:0x73 If you intend to manually write to the DDR5 PMIC using a 2-byte address, ensure that you have "unlocked" the necessary vendor areas. Most PMICs require a specific sequence of keys (e.g., writing and to specific registers sequentially 0x94) before accepting modifications to voltage or current limits.

As defined above, to ensure correct communication between the Tower I3C Host Adapter and slave under a 2-byte address, the registers above must first be configured correctly.
from Official website Download the corresponding software package, Easyi3C Tower I3C Host Adapter DDR5 Device API. Using our provided API, you can easily test the PMIC's 2-byte address mode. See the sample code below.
# ==========================================================================
# Easyi3C Tower USB to I3C Host Adapter Interface Library
# --------------------------------------------------------------------------
# Copyright © 2026 by Easyi3C, Inc.
# All rights reserved.
# --------------------------------------------------------------------------
# ==========================================================================
import sys
from ezi3c.api import *
from ezi3c.utils import hex_string
from ddr5 import Pmic0
ez = ez_open()
if not ez:
print("Cannot open Adapter")
sys.exit(-1)
clk = ez_set_bus_clk_freq(ez, 1000, 4000)
print("Cur Clk Freq: {}".format(clk))
ret = ez_set_io_voltage(ez, 1.0)
assert ret == 0, "Faield to set IO voltage"
pmic = Pmic0(ez, hid=0x00)
reg = 28
try:
ret = pmic.ccc_rstdaa()
assert ret == 0, "Failed to reset DAA: addr:{:02X}".format(pmic.addr)
print("I2C address 2 byte test: address <= 0xFF")
# Enable addr 2 byte mode
ret, data = pmic.i2c_read_reg(0x30, 1)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
ret = pmic.i2c_write_reg(0x30, data | 0x1 << 2)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
ret, data = pmic.i2c_read_reg(0, 2, two_byte_addr=True)
assert ret == 0 and data == (0x04, 0x23), "Failed to read PMIC data: addr:{:02X}".format(pmic.addr)
print("PMIC Data: {}".format(hex_string(data)))
# Disable addr 2 byte mode
ret, data = pmic.i2c_read_reg(0x30, 1, two_byte_addr=True)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
ret = pmic.i2c_write_reg(0x30, data & 0xFB, two_byte_addr=True)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
pmic.switch_to_i3c(send_ccc=True)
print("Two Byte address Test")
ret = pmic.i3c_write_reg(0x30, 4) # slave enter two Byte mode, need change according your chip
assert ret == 0, "Failed to enter two Byte mode addr:{:02X}".format(pmic.addr)
ret, data = pmic.i3c_read_reg(0x300, 1)
assert ret == 0, "Failed to read two Byte mode: addr:{:02X}".format(pmic.addr)
print("PMIC two Byte addr: {:02X} Data: {}".format(0x300, hex_string(data)))
print("Two Byte address Test with PEC")
ret = pmic.enable_pec(send_ccc=True)
assert ret == 0, "Failed to enable PEC: addr:{:02X}".format(pmic.addr)
ret = pmic.i3c_write_reg(0x30, 4) # slave enter two Byte mode, need change according your chip
assert ret == 0, "Failed to enter two Byte mode addr:{:02X}".format(pmic.addr)
ret, data = pmic.i3c_read_reg(0x300, 1)
assert ret == 0, "Failed to read two Byte mode: addr:{:02X}".format(pmic.addr)
print("PMIC two Byte addr: {:02X} Data: {}".format(0x300, hex_string(data)))
ret = pmic.disable_pec(send_ccc=True)
assert ret == 0, "Failed to enable PEC: addr:{:02X}".format(pmic.addr)
print("I3C address 2 byte test: address <= 0xFF")
# Enable addr 2 byte mode
ret, data = pmic.i3c_read_reg(0x30, 1)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
ret = pmic.i3c_write_reg(0x30, data | 0x1 << 2)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
ret, data = pmic.i3c_read_reg(0, 2, two_byte_addr=True)
assert ret == 0 and data == (0x04, 0x23), "Failed to read PMIC data: addr:{:02X}".format(pmic.addr)
print("PMIC Data: {}".format(hex_string(data)))
# Disable addr 2 byte mode
ret, data = pmic.i3c_read_reg(0x30, 1, two_byte_addr=True)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
ret = pmic.i3c_write_reg(0x30, data & 0xFB, two_byte_addr=True)
assert ret == 0, "Failed to read reg {}".format(hex_string(0x30))
finally:
pmic.ccc_rstdaa()
ez_close(ez)
print("Adapter closed.")Engineers can easily test I3C/I2C read and write access of the DDR5 PMIC 2-byte address using the API provided by the Tower I3C Host Adapter, improving work efficiency.