← Back to list

I2C Protocol in FPGA Design: A Beginner’s Guide to Inter-Integrated Circuit

If you’ve ever wondered how chips talk to each other inside a smartphone, a sensor module, or an FPGA development board, you’ve already met…

csjo logicion · 2026-05-31 00:14 · 0 claps · 4.1 min read
#fpga #verilog #i2c #hardware #embedded-systems
Open on Medium ↗
Wiki topics: 📟 · Gadgets & IoT

I2C Protocol in FPGA Design: A Beginner’s Guide to Inter-Integrated Circuit

If you’ve ever wondered how chips talk to each other inside a smartphone, a sensor module, or an FPGA development board, you’ve already met I2C — even if you didn’t know its name. I2C (pronounced “I-squared-C” or “I-two-C”) is one of the most common ways to connect a controller to sensors, displays, EEPROMs, and configuration registers using just two wires.

In this beginner’s guide, we’ll explore what I2C is, how it works, why it’s so popular in embedded and FPGA systems, and how you might start implementing it in Verilog.

What Is I2C?

I2C, short for Inter-Integrated Circuit, is a synchronous, multi-controller, multi-target serial communication bus originally developed by Philips Semiconductor (now NXP) in the 1980s. It was designed to let multiple integrated circuits on the same PCB communicate using a minimal number of pins.

I2C uses only two bidirectional lines:

SDA (Serial Data Line) — carries the actual data bits.

SCL (Serial Clock Line) — carries the clock signal generated by the controller.

Both lines are open-drain, meaning devices can only pull them low. External pull-up resistors keep the lines high by default. This open-drain design is what enables multiple devices to share the bus safely without short-circuiting one another.

Why I2C Matters in FPGA Design

FPGAs frequently interface with the outside world through sensors and small peripheral chips: temperature sensors, accelerometers, OLED displays, real-time clocks, EEPROMs, and audio codecs all commonly speak I2C. Because I2C only needs two wires, it’s perfect for designs where pin count is limited — a frequent constraint in compact FPGA-based products.

Implementing I2C in an FPGA also gives you full control over timing, supports multiple targets on the same bus, and can be tailored to specific clock rates from standard mode (100 kHz) all the way up to fast mode plus (1 MHz).

I2C vs SPI vs UART: Quick Comparison

All three are popular serial protocols, but each has trade-offs:

Wires: I2C uses 2, SPI typically uses 4 or more, UART uses 2.

Speed: SPI is fastest (10+ MHz). I2C reaches up to 5 MHz in high-speed mode but typically runs at 100 kHz or 400 kHz. UART is slowest (usually under 1 Mbps).

Multi-device: I2C addresses many targets natively; SPI needs a separate chip-select per target; UART is strictly point-to-point.

Complexity: UART is simplest; I2C is moderate; SPI requires careful pin and timing planning.

How an I2C Transaction Works

Every I2C transaction follows the same basic structure. Understanding this pattern is the key to debugging I2C in any system, FPGA or otherwise.

  1. START condition: SDA goes from high to low while SCL stays high. This signals the bus is now in use.
    1. Address frame: The controller sends a 7-bit target address followed by a single read/write bit (0 = write, 1 = read).
    1. ACK/NACK: The addressed target pulls SDA low for one clock cycle to acknowledge. No ACK means no device responded.
    1. Data frames: 8-bit data bytes are exchanged, each followed by an ACK/NACK bit.
    1. STOP condition: SDA goes from low to high while SCL stays high. The bus is released.
  2. One subtle but important rule: SDA is only allowed to change while SCL is low. The only legal exceptions are the START and STOP conditions — which is exactly how the bus distinguishes them from regular data bits.
  3. A Simple Verilog Sketch: I2C Controller State Machine
  4. Below is a simplified skeleton of an I2C controller (master) written in Verilog. It shows the core states and how SDA and SCL are driven using tri-state-style logic.
  5. // Simplified I2C controller skeleton (not synthesizable as-is)
  6. module i2c_master (
  7. input wire clk,
  8. input wire rst_n,
  9. input wire start,
  10. input wire [6:0] target_addr,
  11. input wire rw, // 0=write, 1=read
  12. input wire [7:0] data_in,
  13. output reg busy,
  14. inout wire sda,
  15. output reg scl
  16. );

typedef enum logic [3:0] {

IDLE, START_S, ADDR, ACK1, WRITE_DATA, ACK2, STOP_S

} state_t;

state_t state;

reg sda_drive; // 1 = drive low, 0 = release (high-Z)

assign sda = sda_drive ? 1'b0 : 1'bz;

// Each state transitions on a divided clock so SCL toggles at

// 100 kHz (or whichever I2C speed you target).

// Real designs add a clock divider, bit counter, ACK sampling,

// and clock stretching detection.

endmodule

This sketch is intentionally minimal. A production controller would also handle restart conditions, multi-master arbitration, configurable bit rates, and timing checks against the I2C specification (setup time, hold time, bus-free time).

Common Beginner Pitfalls

Forgetting pull-ups: Without external pull-up resistors, SDA and SCL float and nothing works. Typical values are 4.7 kΩ for standard mode and 1–2 kΩ for faster speeds.

Driving SDA high: I2C devices never actively drive the lines high. Always model SDA as open-drain (use ‘z’ in simulation, IOBUF or open-drain IO buffers in synthesis).

Confusing 7-bit vs 8-bit addresses: Datasheets sometimes list the 8-bit address (address + R/W bit shifted in) instead of the 7-bit address. Misreading this is the most common reason a target doesn’t ACK.

Ignoring clock stretching: A slow target may hold SCL low to buy itself processing time. A robust controller must detect this and pause the clock instead of forcing the next edge.

Skipping a logic analyzer: I2C looks simple on paper, but timing bugs are subtle. A cheap USB logic analyzer that decodes I2C will save hours.

Practical Takeaways

Reach for I2C when pin count matters and you need to talk to many small peripherals. Reach for SPI when you need high throughput. And always read the target datasheet’s I2C timing section before writing a single line of Verilog — each device has quirks around setup time, repeated start, and clock stretching.

If you’re just starting out, try implementing a simple I2C write-only controller that talks to an EEPROM or an OLED display on your dev board. Once you can reliably write a byte and see the ACK, the rest of the protocol falls into place.

What's Next

In the next article, we’ll look at AXI — the on-chip protocol that ties IP blocks together inside modern FPGA SoCs. If you understand I2C and SPI, AXI will feel like the natural “inside the chip” cousin of those protocols, scaled up for high-speed memory and peripheral access.

Follow for more FPGA content — we publish a beginner-friendly FPGA and ASIC verification article every day.


메타데이터
post_id
c6cacd4ea3ff
slug
i2c-protocol-in-fpga-design-a-beginners-guide-to-inter-integrated-circuit-c6cacd4ea3ff
url
https://medium.com/@ahe24mobile/i2c-protocol-in-fpga-design-a-beginners-guide-to-inter-integrated-circuit-c6cacd4ea3ff
canonical_url
https://medium.com/@ahe24mobile/i2c-protocol-in-fpga-design-a-beginners-guide-to-inter-integrated-circuit-c6cacd4ea3ff
author_url
https://medium.com/@ahe24mobile
status
ok
fetched_at
2026-06-11 15:16:29