SMBus Components Overview¶
The SMBus (System Management Bus) components provide a complete verification environment for the SMBus/I2C protocol. These components implement passive monitoring, active master emulation, and active slave emulation using tristate (open-drain) signal interfaces, supporting all SMBus 2.0 transaction types including Packet Error Checking (PEC).
Architecture Overview¶
The SMBus components use a signal-level architecture that models the open-drain behavior of the physical SMBus/I2C interface:
graph TB
subgraph TestEnv["Test Environment"]
Tests[Tests]
Config[Configuration]
end
subgraph SMBusLayer["SMBus Protocol Layer"]
Master["SMBus Master<br/>(Initiator)"]
Monitor["SMBus Monitor<br/>(Observer)"]
Slave["SMBus Slave<br/>(Responder)"]
end
subgraph PacketLayer["Packet Layer"]
Packet["SMBus Packet<br/>(Transaction Data)"]
TransType["Transaction Types<br/>(Quick, Byte, Word, Block)"]
Condition["Bus Conditions<br/>(START, STOP, ACK, NAK)"]
end
subgraph Utility["Utilities"]
CRC["SMBus CRC<br/>(PEC Calculator)"]
end
subgraph Bus["Physical Bus Model"]
SCL["SCL<br/>(scl_i, scl_o, scl_t)"]
SDA["SDA<br/>(sda_i, sda_o, sda_t)"]
end
TestEnv --> SMBusLayer
SMBusLayer --> PacketLayer
SMBusLayer --> Bus
PacketLayer --> Utility
Component Categories¶
Protocol Implementation¶
Core SMBus protocol components that handle signal-level communication:
- SMBusMaster: Initiates SMBus transactions with bit-level bus control
- SMBusSlave: Responds to SMBus transactions with memory-mapped register model
- SMBusMonitor: Passively observes and captures bus transactions
Key Features: - Tristate (open-drain) signal interface for realistic bus modeling - All SMBus 2.0 transaction types supported - Bit-level bus control with configurable clock period - START, STOP, and repeated START condition generation and detection - ACK/NAK handling with proper bus release semantics - Clock stretching support (slave)
Packet & Transaction Management¶
Transaction representation and bus condition tracking:
- SMBusPacket: Complete transaction record with timing, data, and status
- SMBusTransactionType: Enumeration of all SMBus 2.0 transaction types
- SMBusCondition: Enumeration of bus conditions (START, STOP, ACK, NAK)
Key Features: - Dataclass-based packet with all transaction fields - Compact and detailed formatting for logging - Status tracking (ACK, timeout, arbitration lost, PEC verification) - Word data extraction with LSB-first byte ordering - Deep copy support for transaction queuing
CRC Utility¶
- SMBusCRC: CRC-8 calculator implementing the SMBus PEC polynomial
SMBus Protocol Support¶
Transaction Types¶
| Type | Enum Value | Description | Data Bytes |
|---|---|---|---|
| Quick Command | QUICK_CMD (0) | Address-only transaction | 0 |
| Send Byte | SEND_BYTE (1) | Master sends 1 byte, no command | 1 |
| Receive Byte | RECV_BYTE (2) | Master receives 1 byte, no command | 1 |
| Write Byte | WRITE_BYTE (3) | Command + 1 data byte | 1 cmd + 1 data |
| Read Byte | READ_BYTE (4) | Command + 1 data byte | 1 cmd + 1 data |
| Write Word | WRITE_WORD (5) | Command + 2 data bytes | 1 cmd + 2 data |
| Read Word | READ_WORD (6) | Command + 2 data bytes | 1 cmd + 2 data |
| Block Write | BLOCK_WRITE (7) | Command + count + N data bytes | 1 cmd + 1 count + N data |
| Block Read | BLOCK_READ (8) | Command + count + N data bytes | 1 cmd + 1 count + N data |
| Block Process Call | BLOCK_PROC (9) | Block write followed by block read | Variable |
Bus Conditions¶
| Condition | Value | Description |
|---|---|---|
| IDLE | 0 | Bus is idle |
| START | 1 | START condition (SDA falls while SCL high) |
| STOP | 2 | STOP condition (SDA rises while SCL high) |
| REPEATED_START | 3 | Repeated START within a transaction |
| ACK | 4 | Acknowledge (SDA low during 9th clock) |
| NAK | 5 | Not Acknowledge (SDA high during 9th clock) |
Tristate Signal Interface¶
The SMBus components use a tristate interface to model the open-drain behavior of the physical bus:
| Signal | Type | Description |
|---|---|---|
scl_i |
Input | SCL line state (read from bus) |
scl_o |
Output | SCL drive value (0 to pull low) |
scl_t |
Output | SCL tristate control (1=release/input, 0=drive) |
sda_i |
Input | SDA line state (read from bus) |
sda_o |
Output | SDA drive value (0 to pull low) |
sda_t |
Output | SDA tristate control (1=release/input, 0=drive) |
Open-drain semantics:
- To release a line (allow pull-up): set _t=1
- To drive low: set _t=0 and _o=0
- The monitor uses only _i signals for passive observation
Design Principles¶
1. Accurate Bus Modeling¶
- Tristate interface faithfully models open-drain behavior
- Proper START/STOP condition generation with correct timing
- ACK/NAK follows SMBus protocol with proper bus release
- Clock stretching support for slave-paced transactions
2. Complete Protocol Coverage¶
- All SMBus 2.0 transaction types implemented
- Repeated START for read-after-write operations
- PEC (Packet Error Checking) support via CRC-8 utility
- Transaction status tracking (ACK, timeout, arbitration loss)
3. Flexible Configuration¶
- Configurable slave address (7-bit)
- Configurable SCL clock period for master
- Configurable memory size for slave register model
- Configurable clock stretching delay
- Optional PEC support per component
4. Ease of Use¶
- High-level transaction methods (write_byte_data, read_byte_data, block_write, etc.)
- Automatic address byte construction with R/W bit
- Callback support for monitor notifications
- Start/stop lifecycle management for all components
Usage Patterns¶
Basic Master-Slave Communication¶
import cocotb
from CocoTBFramework.components.smbus import SMBusMaster, SMBusSlave, SMBusMonitor
@cocotb.test()
async def basic_smbus_test(dut):
# Create components
master = SMBusMaster(
entity=dut, title="Master",
scl_i='smb_scl_i', scl_o='smb_scl_o', scl_t='smb_scl_t',
sda_i='smb_sda_i', sda_o='smb_sda_o', sda_t='smb_sda_t',
clock_period_ns=10000
)
slave = SMBusSlave(
entity=dut, title="Slave",
scl_i='smb_scl_i', scl_o='smb_scl_o', scl_t='smb_scl_t',
sda_i='smb_sda_i', sda_o='smb_sda_o', sda_t='smb_sda_t',
slave_addr=0x50,
memory_size=256
)
monitor = SMBusMonitor(
entity=dut, title="Monitor",
scl_signal='smb_scl_i',
sda_signal='smb_sda_i'
)
# Start slave and monitor
slave.start()
monitor.start()
# Perform write
result = await master.write_byte_data(
slave_addr=0x50, command=0x10, data=0xAB
)
# Perform read
result = await master.read_byte_data(
slave_addr=0x50, command=0x10
)
Block Transfer Testing¶
@cocotb.test()
async def block_transfer_test(dut):
master = SMBusMaster(dut, "Master",
clock_period_ns=5000) # 200kHz
slave = SMBusSlave(dut, "Slave", slave_addr=0x50)
slave.start()
# Block write
data = [0x11, 0x22, 0x33, 0x44, 0x55]
result = await master.block_write(
slave_addr=0x50, command=0x00, data=data
)
# Block read
result = await master.block_read(
slave_addr=0x50, command=0x00, max_bytes=32
)
print(f"Read {len(result.data)} bytes: {result.data}")
Pre-loading Slave Memory¶
@cocotb.test()
async def preloaded_memory_test(dut):
slave = SMBusSlave(dut, "Slave", slave_addr=0x50)
# Pre-load register values
slave.write_memory(0x00, [0xAA, 0xBB, 0xCC, 0xDD])
slave.write_memory(0x10, [0x11, 0x22, 0x33])
slave.start()
# Master reads will return pre-loaded values
master = SMBusMaster(dut, "Master")
result = await master.read_byte_data(slave_addr=0x50, command=0x00)
# result.data[0] == 0xAA
Integration with Framework¶
Standalone Components¶
Unlike the APB and AXI components, the SMBus components are standalone implementations that do not inherit from cocotb_bus base classes. They directly manage signal handles and cocotb coroutines for bus interaction.
Packet System¶
- SMBusPacket: Dataclass-based (not derived from framework Packet base class)
- Transaction Types: IntEnum for type-safe transaction identification
- Bus Conditions: IntEnum for bus state tracking
Statistics and Monitoring¶
Each component tracks operational statistics:
- Monitor: transaction_count, recv_queue
- Slave: transaction_count, ack_count, nak_count
- Master: transaction_count
Key Features¶
Transaction Management¶
- High-level API: Methods for each SMBus transaction type
- Automatic Protocol: START, address, command, data, STOP handled internally
- Repeated START: Automatic for read transactions requiring command phase
- Status Tracking: ACK/NAK, timeout, arbitration, PEC results
Memory Integration¶
- Slave Memory Model: Dictionary-based memory with configurable size
- Address Auto-increment: Automatic address advancement during transfers
- Pre-loading: Write data into slave memory before test starts
- Memory Access: Read/write/clear methods for verification
Verification Support¶
- Passive Monitor: Non-interfering transaction capture
- Callback Support: Monitor notifies on transaction completion
- Packet Formatting: Compact and detailed display formats
- Transaction Parsing: Automatic type detection from byte patterns
Getting Started¶
Quick Setup¶
- Import Components:
from CocoTBFramework.components.smbus import * - Create Slave: Configure address and memory, call
start() - Create Monitor: Connect to input signals, call
start() - Create Master: Configure clock period
- Run Transactions: Use high-level methods (write_byte_data, read_byte_data, etc.)
Advanced Usage¶
- PEC Support: Enable
support_pec=Trueand use SMBusCRC for verification - Clock Stretching: Configure
clock_stretch_cycleson the slave - Custom Signal Names: Override default signal names to match your DUT
- Memory Pre-loading: Use
slave.write_memory()to set initial register state - Transaction Monitoring: Register callbacks on the monitor for real-time observation
Each component provides start/stop lifecycle management, allowing dynamic activation during different test phases.