I2C主控制器(VHDL)

代码下载

版本2.2:i2c_master.vhd (14.1 KB)
修复了事务结束时出现的SDA信号毛刺问题(该问题在2.1版本中引入)

版本2.1:i2c_master_v2_1.vhd (14.0 KB)
用时钟使能替代门控时钟
调整了起始和停止条件期间的SCL时序

版本2.0:i2c_master_v2_0.vhd (13.5 KB)
新增同一事务中与不同从设备交互的功能
修正了ack_error错误时输出’Z’而非’1’的bug
修正了ack_error信号清除的时序

版本1.0:i2c_master_v1_0.vhd (12.9 KB)
首次公开发布

特点

  • 集成电路总线(I2C或IIC)主控组件的VHDL源代码
  • 符合NXP UM10204 I2C总线规范(单主控总线)
  • 用户可定义系统时钟
  • 用户可定义I2C串行时钟频率
  • 可生成起始、停止、重复起始和应答条件
  • 采用7位从机地址寻址
  • 兼容从机时钟拉伸功能
  • 不推荐用于多主控总线(无仲裁或同步机制)
  • 向用户逻辑通知从机应答错误

介绍

本文详述了用于单主控总线的I2C主控组件,采用VHDL编写,适用于CPLD和FPGA。该组件通过并行接口与用户逻辑进行读写交互。使用Quartus II 11.1版本进行设计。资源需求取决于具体实现方式。图1展示了I2C主控集成到系统中的典型示例。此处提供采用该I2C主控构建SPI转I2C桥接器的设计方案。

1 实现示例

背景

I2C总线是由飞利浦(现NXP)发明并规范的双线半双工数据链路。I2C总线的两条线路SDA和SCL均为双向开漏结构,通过上拉电阻工作。SCL是串行时钟线,SDA是串行数据线。总线上的设备通过将线路拉至低电平发送逻辑0,释放线路(保持悬空)发送逻辑1。

更多信息请参阅下方附加信息章节中的I2C规范文档。该文档详细阐述了协议内容、电气规范、上拉电阻阻值计算等。

操作原理

I2C主设备采用图2所示状态机实现I2C总线协议。上电后,组件立即进入就绪状态。在此状态等待直至ena 信号锁存命令。起始状态I2C总线上生成起始条件,命令状态向总线传送地址和读写指令。随后slv_ack1 状态捕获并验证从设备的应答信号。根据读写指令,组件将执行向从设备写入数据(wr 状态)或从从设备读取数据(rd 状态)。操作完成后,主设备在写入时捕获验证从设备响应 ( slv_ack2 状态),在读取时发出自身响应(mstr_ack 状态)。若ena信号再次锁存相同指令,主设备将立即继续执行写入(wr 状态)或读取(rd 状态)。若新指令与先前不同(如写操作后接读操作、读操作后接写操作或变更从机地址),主设备将按照I2C规范发起重复起始条件(起始状态)。当主设备完成读写操作且ena 信号未锁存新指令时,将生成停止条件(停止状态)并返回就绪状态。

2 I2C主设备状态机

状态机时序由GENERIC参数input_clkbus_clk 决定,详见下文"设置串行时钟速度"章节。计数器生成驱动状态机的数据时钟,同时产生scl 信号。

端口描述

表1描述了I2C主设备的端口定义。

1. 端口描述

设置串行时钟速度

组件从ENTITY中声明的两个GENERIC参数input_clkbus_clk 派生串行时钟sclinput_clk 参数必须设置为输入系统时钟clk 的频率(Hz)。示例代码中的默认设置为50MHz(组件仿真测试所用频率)。bus_clk 参数需设置为期望的串行时钟scl 频率。示例代码中的默认设置为400 kHz,对应I2C规范中的快速模式比特率。

事务处理

busy 输出端口为低电平时,表示组件已准备好接收命令。要启动事务,用户逻辑需分别将目标从机地址、读写命令和写入数据置于addrrwdata_wr 端口,并置位ena 信号。命令不会在下一个系统时钟clk 时被采样。该组件已在内部生成I2C时序,并基于此时序对命令进行采样。因此,用户逻辑应等待busy 信号置位,以确认这些输入何时被锁存至I2C主控制器。

随后I2C主控制器执行该命令。完成后,busy 信号会解除置位,表示读取数据已在data_rd 端口就绪,错误信息将通过ack_error 端口标记。

单个事务中可执行多次读写操作(及其任意组合)。若当前命令完成时ena信号仍保持置位,I2C主控制器将锁存新的addrrwdata_wr 值,并立即执行新命令。busy信号仍会解除置位一个scl 周期以指示读取数据已在data_rd 就绪,随后重新置位表示新命令已锁存并开始执行。

事务处理示例

图3展示了典型事务处理的时序图。用户逻辑给出地址"1010101"、表示写入的rw命令’0’,以及写入数据"10011001"。通过置位ena 信号锁存这些值。当busy 信号置位后,用户逻辑发出新命令。地址保持"1010101",但后续命令改为读取(rw = ‘1’),ena 信号保持置位。I2C主控制器完成第一条命令后,解除busy信号置位表示操作完成。由于ena 保持置位,主控制器锁存新命令并重新置位busy 信号。当busy 信号再次置位时,用户逻辑确认第二条命令正在执行,并解除ena 信号以结束该命令后的事务。I2C主控制器完成读取命令,将读取数据"11001100"输出至data_rd 端口,并再次解除busy 信号置位。

3 典型事务处理时序图

若需用新命令延续事务,ena 信号 和新输入必须在当前命令最后数据位结束前就绪。因此建议在当前命令锁存后立即发出新命令。ena 信号可以持续保持有效状态,直到事务中的最后一条命令被锁存。

控制 I2C 主设备的用户逻辑示例

下方用户逻辑代码片段展示了一种管理多读写事务的简单技术。该示例实现通过统计busy 信号跳变次数,在适当时机向I2C主设备发送命令。"get_data"状态会执行I2C总线上单次事务内所需的所有操作,包括一次写入、一次读取、第二次写入和第二次读取,例如从从设备多个寄存器中获取数据时可能采用的操作序列。

应答错误

每传输完一个字节后,I2C总线接收端必须发出应答或非应答信号。若I2C主设备收到从设备的错误响应,会通过ack_error 端口标记错误来通知用户逻辑。I2C主设备不会自动尝试重发信息,因此用户逻辑需决定是否重新发送命令和/或采取其他措施。ack_error 端口会在下一事务开始时自动清零。

时钟拉伸

I2C规范第3.1.9节定义的可选功能允许从设备通过保持**scl 低电平来暂停事务。某些从设备在需要更多时间存储接收数据等情况下会启用此功能。本I2C主设备组件兼容支持该特性的从设备。控制I2C主设备的用户逻辑无需执行任何操作。

复位

reset_n 输入端口必须保持逻辑高电平才能使I2C主设备组件正常工作。该端口的低电平将异步复位组件。复位期间,组件会保持busy 端口为高电平,表示I2C主设备不可用。sclsda 端口进入高阻态,data_rdack_error 输出端口被清零。退出复位状态后,当I2C主设备准备就绪时,busy 端口会解除有效状态。

结论

该I2C主设备是可编程逻辑组件,通过简单并行接口实现与I2C从设备的通信。其遵循NXP I2C规范中关于单主总线的要求,并支持时钟拉伸可选功能。

附加信息

UM10204, I2C-bus specification and user manual, NXP Semiconductors N.V. (1.3 MB)

相关主题

SPI转I2C桥接器(VHDL) - 本设计采用上述I2C主设备实现SPI到I2C的协议转换。

温度传感器TCN75A Pmod控制器(VHDL) - 本设计使用上述I2C主设备对Microchip TCN75A温度传感器进行配置和数据采集。

温度传感器ADT7420 Pmod控制器(VHDL) - 该设计使用上述I2C主控配置并采集Analog Devices ADT7420温度传感器的数据。

电容传感AD7156 Pmod控制器(VHDL) - 该设计使用上述I2C主控配置并采集Analog Devices AD7156电容数字转换器的数据。

颜色传感器Pmod控制器(VHDL) - 该设计使用上述I2C主控配置并采集AMS TCS3472颜色光数字转换器的数据。

罗盘Pmod控制器(VHDL) - 该设计使用上述I2C主控配置并采集Memsic MMC34160PJ磁力计的数据。

ADC AD7991 Pmod控制器(VHDL) - 该设计使用上述I2C主控采集Analog Devices AD7991四通道12位模数转换器的数据。

温湿度传感器Pmod控制器(VHDL) - 该设计使用上述I2C主控配置并采集德州仪器HDC1080湿度计的温湿度数据。

实时时钟MCP79410 Pmod控制器(VHDL) - 该设计使用上述I2C主控控制Microchip MCP79410实时时钟/日历。