别再怕IIC时序了!用Verilog状态机清晰图解LM75/AT24C128的读写全过程
用Verilog状态机彻底解析IIC协议从LM75温度读取到AT24C128存储操作实战IICInter-Integrated Circuit总线是嵌入式系统中最常用的串行通信协议之一但它的时序控制和状态跳转逻辑常常让开发者感到困惑。本文将用Verilog状态机的设计思路带你彻底理解IIC协议的核心机制并通过LM75温度传感器和AT24C128 EEPROM两个典型设备的操作实例展示如何构建一个稳健可靠的IIC控制器。1. IIC协议核心机制解析IIC协议的精髓在于其简洁的两线制SCL时钟线和SDA数据线设计和严格定义的时序规范。要真正掌握IIC必须理解以下几个关键概念基本信号类型起始条件STARTSCL为高电平时SDA从高到低的跳变停止条件STOPSCL为高电平时SDA从低到高的跳变数据有效性SDA数据在SCL高电平期间必须保持稳定应答机制ACK/NACK每个字节传输后接收方必须发送应答信号关键时序参数参数描述典型值(100kHz)典型值(400kHz)tSU;STA起始条件建立时间4.7μs0.6μstHD;STA起始条件保持时间4.0μs0.6μstSU;DAT数据建立时间250ns100nstHD;DAT数据保持时间0ns0nstSU;STO停止条件建立时间4.0μs0.6μs注意实际设计中应留有时序裕量避免因信号传输延迟导致通信失败2. Verilog状态机设计方法论设计一个稳健的IIC控制器需要采用分层状态机架构将复杂的通信过程分解为可管理的状态序列。2.1 顶层状态设计顶层状态控制整个通信流程parameter MAIN_IDLE d20; // 空闲状态 parameter MAIN_STAR d21; // 起始条件 parameter MAIN_DEV0 d22; // 发送设备地址(写) parameter MAIN_ADDR d23; // 发送内存地址 parameter MAIN_REST d24; // 重复起始条件 parameter MAIN_DEV1 d25; // 发送设备地址(读) parameter MAIN_R8BI d26; // 读取数据字节 parameter MAIN_W8BI d27; // 写入数据字节 parameter MAIN_STOP d28; // 停止条件2.2 底层比特级控制每个顶层状态又细分为底层状态精确控制每个时钟周期// 写数据状态序列 parameter W1BY_SCLL d6; // SCL低电平期间准备数据 parameter W1BY_SCLH d7; // SCL高电平期间保持数据 parameter W1AK_SCLL d8; // 等待ACK的SCL低电平 parameter W1AK_SCLH d9; // 采样ACK的SCL高电平 // 读数据状态序列 parameter R1BY_SCLL d11; // SCL低电平期间释放SDA parameter R1BY_SCLH d12; // SCL高电平期间采样数据 parameter R1AK_SCLL d13; // 发送ACK的SCL低电平 parameter R1AK_SCLH d14; // 发送ACK的SCL高电平2.3 状态跳转逻辑示例以下是写操作的状态跳转核心代码always (posedge clk or posedge rst) begin if(rst) begin cur_state MAIN_IDLE; end else begin case(cur_state) MAIN_IDLE: if(req) cur_state MAIN_STAR; MAIN_STAR: if(down_ack) cur_state MAIN_DEV0; MAIN_DEV0: if(down_ack) cur_state (err_ack) ? MAIN_STOP : MAIN_ADDR; MAIN_ADDR: if(down_ack) cur_state (err_ack) ? MAIN_STOP : (wr || ADDR_NUM0) ? MAIN_W8BI : MAIN_REST; // ...其他状态跳转逻辑 endcase end end3. LM75温度传感器操作实战LM75是一款广泛使用的数字温度传感器通过IIC接口提供9位到12位的温度数据。3.1 LM75关键特性温度测量范围-55°C 到 125°C精度±2°C-25°C 到 100°C温度寄存器格式16位高9位有效LSB0.125°C设备地址固定部分1001xxx可通过引脚配置低三位寄存器映射寄存器地址功能描述0x00温度值只读0x01配置寄存器0x02超温阈值0x03迟滞温度3.2 读取温度值的状态机流程发送设备地址写模式状态序列MAIN_STAR → MAIN_DEV0设备地址7b1001xxx 1b0写发送温度寄存器地址0x00状态序列MAIN_ADDR → W1BY_SCLL → W1BY_SCLH (循环8次)重复起始条件状态序列MAIN_REST → START_SCLL → START_SCLH发送设备地址读模式状态序列MAIN_DEV1设备地址7b1001xxx 1b1读读取温度数据状态序列MAIN_R8BI → R1BY_SCLL → R1BY_SCLH (循环8次)最后发送NACK表示读取结束停止条件状态序列MAIN_STOP → STOP_SCLL → STOP_SCLH提示LM75的温度数据格式为补码形式转换时需特别注意符号位处理4. AT24C128 EEPROM操作详解AT24C128是128Kbit(16K×8)的串行EEPROM具有页写和顺序读功能。4.1 设备特性与注意事项支持100kHz(1.8V)和400kHz(2.5V)两种速度页写模式最多64字节/页写入周期时间典型5ms设备地址1010xxx其中xxx由A2,A1,A0引脚决定重要限制两次写入操作之间必须留有足够时间通常5ms单字节写入和页写入的时序要求不同超过页边界时会回卷到页首4.2 写操作状态机设计单字节写入的状态序列开始 → 设备地址(写) → 应答 → 高字节地址 → 应答 → 低字节地址 → 应答 → 数据字节 → 应答 → 停止对应的Verilog状态跳转MAIN_STAR → MAIN_DEV0 → MAIN_ADDR → W1BY_SCLL → W1BY_SCLH → ... → MAIN_W8BI → W1BY_SCLL → W1BY_SCLH → MAIN_STOP4.3 读操作特殊处理顺序读操作需要特别注意伪写入阶段先以写模式发送内存地址发送重复起始条件切换为读模式并接收数据状态序列示例开始 → 设备地址(写) → 应答 → 地址高字节 → 应答 → 地址低字节 → 应答 → 重复开始 → 设备地址(读) → 应答 → 读取数据(带ACK/NACK) → ... → 停止5. 关键时序参数的Verilog实现精确控制时序是IIC可靠通信的核心。以下是400kHz模式下的典型实现parameter tSYSCLK 20; // 系统时钟周期20ns(50MHz) parameter tCLK 4000/tSYSCLK; // SCL周期2500ns(400kHz) parameter tLOW 2000/tSYSCLK; // SCL低电平时间1000ns parameter tHIGH tCLK-tLOW; // SCL高电平时间1500ns parameter tHDDAT 1000/tSYSCLK; // 数据保持时间 parameter tSUDAT tLOW-tHDDAT; // 数据建立时间 // 时序控制计数器 always (posedge clk or posedge rst) begin if(rst) delay_cnt 0; else if(state_change) delay_cnt 0; else delay_cnt delay_cnt 1; end总线释放时机主设备发送完最后一个ACK后应在50ns内释放SDA从设备切换方向时主设备应等待足够时间通常300-400ns// 总线释放实现示例 R1AK_SCLL: begin if(delay_cnttHDDAT) begin sda_is_out 1; // 准备发送ACK/NACK sda_o (data_cntDATA_NUM); // 最后一个字节发NACK end end在实际项目中调试IIC通信时最常遇到的问题往往与时序裕量不足或总线竞争有关。特别是在多主设备系统中必须严格遵循总线仲裁规则确保不会出现两个设备同时驱动总线的情况。