From I2C Protocol to Temperature Sensing: How FPGA Elegantly Drives the LM75 Sensor
In embedded system design, the collaboration between FPGA and various sensors has become one of the key technologies for achieving high-performance data acquisition. The I2C protocol, as a concise and efficient two-wire serial communication standard, is widely used for data exchange between sensors and controllers. This article will delve into how to use FPGA to achieve precise driving of the LM75 temperature sensor, from protocol parsing to low-level hardware design, providing FPGA beginners and embedded communication protocol enthusiasts with a complete and practical solution.
1. Core Mechanisms of the I2C Communication Protocol and FPGA Implementation Challenges
The I2C (Inter-Integrated Circuit) protocol is a synchronous, multi-master-slave serial communication protocol that enables data transfer between devices using only two signal lines (SDA and SCL). Implementing an I2C controller in FPGA requires particular attention to timing precision and the reliability of state machine design.
In standard mode (100 kbit/s), the SCL clock frequency must be strictly maintained within 100kHz
Start Condition: SDA generates a falling edge while SCL is high
Stop Condition: SDA generates a rising edge while SCL is high
Data Validity: SDA data must remain stable during the high period of SCL
Tip: When implementing I2C in FPGA, special attention must be paid to cross-clock domain issues. It is recommended to use a state machine to clearly distinguish each communication phase
In the Verilog implementation, we need to build a precise state machine to manage the entire communication flow:
parameter IDLE = 4'b0000;
parameter START = 4'b0001;
parameter ADDR = 4'b0010;
parameter ACK1 = 4'b0011;
parameter REG_ADDR = 4'b0100;
parameter ACK2 = 4'b0101;
parameter DATA_READ = 4'b0110;
parameter ACK3 = 4'b0111;
parameter STOP = 4'b1000;
reg [3:0] current_state;
reg [7:0] shift_reg;
reg [2:0] bit_count;
This state partitioning ensures that each I2C operation phase has a clear corresponding state, avoiding timing confusion.
2. In-Depth Analysis of the LM75 Sensor and Register Configuration Techniques
The LM75 is a high-precision digital temperature sensor that provides 11-bit resolution temperature data (0.125°C accuracy) via the I2C interface. Understanding its internal register structure is the foundation for correct data acquisition.
Bit 0: Operating mode selection (0 - Normal mode, 1 - Shutdown mode)
Bit 1: OS output mode (0 - Comparator mode, 1 - Interrupt mode)
Bit 2: OS polarity selection (0 - Active low, 1 - Active high)
Bit 3-4: Fault queue length setting
Bit 5-7: Reserved bits, must be set to 0
In practical applications, the configuration register is typically set to 0x00 (default normal mode), but may need adjustment based on specific application requirements:
// LM75 configuration register setting example
task write_config;
input [7:0] config_data;
i2c_send_byte(8'h90); // Device address + write operation
i2c_send_byte(8'h01); // Configuration register address
i2c_send_byte(config_data); // Configuration data
Special attention must be paid to the format handling of temperature data: the 11-bit data is stored in two's complement form, with the upper 9 bits representing the integer part and the lower 2 bits representing the fractional part. The actual temperature value calculation formula is:
Temperature value = (16-bit data read >> 5) × 0.125°C
3. FPGA Internal State Machine Design and Implementation Details
Implementing an I2C controller in an FPGA requires a carefully designed state machine to ensure that each communication step is executed accurately. The following is the detailed design of the core state machine:
Idle state: Wait for the start signal and initialize the internal registers.
Start state: Generate the START condition (SDA falls while SCL is high).
Device address transmission: Send the 7-bit device address plus the read/write bit.
Acknowledge detection: Detect the acknowledge signal from the slave device.
Register address transmission: Specify the LM75 register to be accessed.
Data read/write operation: Perform the actual data read or write.
Stop state: Generate the STOP condition to end communication.
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
current_state <= IDLE;
sda_out <= 1'b1;
scl_out <= 1'b1;
case (current_state)
if (start_i2c) begin
current_state <= START;
bit_count <= 3'd0;
sda_out <= 1'b0;
current_state <= ADDR;
Each state requires enough clock cycles to ensure signal stability.
The high-to-low level ratio of SCL should be kept at approximately 1:1.
During the acknowledge detection phase, the SDA line needs to be released so that the slave device can respond.
Note: In actual hardware, both the SCL and SDA lines require external pull-up resistors (typically 4.7kΩ), which is required by the open-drain output characteristic of the I2C protocol.
4. Hardware platform adaptation and Vivado development practice
Based on the Xilinx Artix-7 FPGA platform and the Vivado development environment, we need to perform a series of hardware adaptation tasks. Artix-7 devices provide abundant logic resources and flexible I/O configuration capabilities, making them very suitable for implementing customized I2C controllers.
# Temperature sensor I2C interface pin definitions
set_property PACKAGE_PIN N2 [get_ports TEM_SCL]
set_property IOSTANDARD LVCMOS33 [get_ports TEM_SCL]
set_property PACKAGE_PIN M3 [get_ports TEM_SDA]
set_property IOSTANDARD LVCMOS33 [get_ports TEM_SDA]
set_property PACKAGE_PIN E3 [get_ports sys_clk]
set_property IOSTANDARD LVCMOS33 [get_ports sys_clk]
set_property PACKAGE_PIN D9 [get_ports rst_n]
set_property IOSTANDARD LVCMOS33 [get_ports rst_n]
create_generated_clock -name i2c_clk -source [get_pins clk_gen/CLK]
-divide_by 100 [get_pins i2c_ctrl/SCL]
set_input_delay -clock [get_clocks i2c_clk]
-max 2.5 [get_ports TEM_SDA]
In engineering practice, we usually adopt a modular design approach and divide the entire system into several functional modules:
top_module (temp_test.v)

