I2C Protocol
Master the I2C (Inter-Integrated Circuit) protocol and its addressing and acknowledgment mechanisms
What is I2C?
The I2C (Inter-Integrated Circuit) protocol was developed by Philips Semiconductors (now NXP) in 1982. It enables communication between multiple devices using only two wires.
Key characteristics:
- 2 wires: SDA (data) and SCL (clock)
- Open-drain: lines require external pull-up resistors
- Multi-master: hardware arbitration between multiple masters
- Addressing: each slave has a unique address (7 or 10 bits)
- ACK/NACK: acknowledgment after each byte
I2C Signals
| Signal | Type | Description |
|---|---|---|
| SDA | Bidirectional open-drain | Serial Data |
| SCL | Bidirectional open-drain | Serial Clock |
Both lines are pulled high by pull-up resistors. Any device on the bus can pull a line low (open-drain), but none can force it high — only the pull-up resistors do that.
Start and Stop Conditions
I2C uses two special conditions that violate normal data transitions (data stable while SCL high):

START condition: SDA falls while SCL is high. STOP condition: SDA rises while SCL is high.
SDA data must only change while SCL is low — except for START and STOP conditions.
I2C Frame
A typical I2C write transaction:
START | Address (7 bits) | R/W='0' | ACK | Data byte | ACK | STOP- START: initiated by the master
- Address: 7 bits MSB first, identifies the target slave
- R/W bit: 0 = write (master → slave), 1 = read (slave → master)
- ACK: slave pulls SDA low to acknowledge
- Data: bytes transmitted, each followed by ACK/NACK
- STOP: initiated by master to release the bus
ACK and NACK
After each 8-bit byte, the receiver sends:
- ACK (Acknowledge): SDA low during the 9th clock pulse — successful reception
- NACK (Not Acknowledge): SDA high (released) — error or end of read
In read mode, the master sends NACK after the last byte to signal it wants no more data.
VHDL Implementation — I2C Master State Machine
library ieee;
use ieee.std_logic_1164.all;
entity i2c_master is
generic (
g_SYS_CLK_HZ : positive := 100_000_000; -- 100 MHz
g_I2C_CLK_HZ : positive := 400_000 -- 400 kHz (Fast mode)
);
port (
i_clk : in std_logic;
i_rst : in std_logic;
i_start : in std_logic;
i_rw : in std_logic; -- '0'=write, '1'=read
i_addr : in std_logic_vector(6 downto 0);
i_data : in std_logic_vector(7 downto 0);
o_data : out std_logic_vector(7 downto 0);
o_busy : out std_logic;
o_ack_err : out std_logic;
io_sda : inout std_logic;
io_scl : inout std_logic
);
end entity i2c_master;A typical state machine includes states:
IDLE→START→ADDR→ACK_ADDR→DATA→ACK_DATA→STOP
The full implementation is available in the corresponding exercise.
Clock Stretching
A slave can "stretch" SCL by holding it low to slow down the master. The master must monitor SCL and wait for it to rise before continuing.
This feature requires SCL to be open-drain (bidirectional) on the master side as well.
Multi-Master Arbitration
If two masters start a transaction simultaneously, arbitration is resolved automatically:
- Each master compares what it drives on SDA with what it reads back
- If a master drives '1' but reads '0', it lost arbitration and stops
- The "winning" master continues uninterrupted
Standardized Speeds
| Mode | Max Speed |
|---|---|
| Standard Mode | 100 kbps |
| Fast Mode | 400 kbps |
| Fast Mode Plus | 1 Mbps |
| High Speed Mode | 3.4 Mbps |
Advantages and Disadvantages
| Advantages | Disadvantages |
|---|---|
| Only 2 wires | Slower than SPI |
| Native multi-master | Open-drain requires pull-up resistors |
| Addressing — no SS_N | More complex protocol |
| ACK/NACK for verification | Bus capacitance limit (400 pF) |