1. 从零开始:为什么我们需要动态配置Si570?
如果你玩过FPGA,尤其是Xilinx的Zynq或者UltraScale+系列,大概率遇到过时钟问题。板子上那个小小的晶振,频率是固定的,比如100MHz或者125MHz。但你的设计可能需要一个非常特定的频率,比如156.25MHz用于以太网,或者148.5MHz用于视频处理。这时候,一个可编程的时钟芯片就成了救星,而Si570正是这类芯片中的明星选手。
Si570是一颗由Silicon Labs(现在属于Skyworks)生产的高精度、可编程的I2C时钟发生器。它的厉害之处在于,你可以通过I2C总线,在运行时动态地改变它的输出频率,而且精度非常高,这对于需要多速率切换或者频率微调的应用场景(比如软件定义无线电、高速数据采集)来说,简直是神器。想象一下,你的硬件平台是固定的,但通过软件配置Si570,就能让它适应不同的通信标准或处理任务,这种灵活性是固定晶振无法比拟的。
那么,怎么去配置它呢?最直接的方法就是用FPGA上的GPIO去模拟I2C时序。这个方法我早期也用过,写个状态机,控制SDA和SCL线,确实能工作。但问题也不少:时序要自己抠,稳定性要自己调,如果系统里还有其他AXI总线设备,这种“野路子”的I2C控制器很难集成到统一的系统管理框架里,调试起来也麻烦。
所以,Xilinx官方提供的AXI I2C IP核就成了更优雅的选择。它本质上是一个符合AXI4-Lite总线规范的I2C控制器,你可以像访问内存一样,通过读写它的寄存器来控制I2C总线。这样一来,配置Si570就变成了对一组特定地址的寄存器进行读写操作,逻辑清晰,易于集成,也方便用C语言在处理器(如ARM Cortex-A系列)上直接驱动。我们今天要聊的,就是如何用好这个AXI I2C IP,安全、高效、准确地对Si570进行动态频率配置,并分享一些我实践中踩过的坑和优化技巧。
2. 核心武器:深入理解Xilinx AXI I2C IP核
要想驾驭Si570,首先得把你手里的武器——AXI I2C IP核——摸透。这个IP核在Vivado的IP Catalog里就能找到,全称是“AXI IIC Bus Interface”。把它加到你的Block Design里,连接上AXI互联矩阵和外部I2C引脚,看起来很简单,但内部的寄存器操作才是关键。
这个IP核提供了两个主要的数据通路:控制寄存器(CR、SR等)和数据FIFO(TX_FIFO, RX_FIFO)。所有的I2C时序,起始(START)、停止(STOP)、重复起始(Repeated START)、发送数据、接收数据,都是通过配置这些寄存器来触发的。官方文档(PG090)写得比较全,但读起来可能有点枯燥,我结合自己的经验给你捋一捋最核心的几个点。
首先,IOBUF的使用是个小细节,但很重要。I2C总线是开漏(Open-Drain)的,这意味着总线上的设备只能把线拉低(输出0),而不能主动拉高(输出1)。高电平是靠外部的上拉电阻实现的。在FPGA里,对应的I/O引脚需要配置成开漏模式。AXI I2C IP核的接口里,通常会看到 iic_scl_i/o/t 和 iic_sda_i/o/t 这组信号。这里的 t 信号就是三态控制信号。当Master需要输出高电平时,它并不是驱动一个‘1’,而是将 t 置为1,让引脚处于高阻态(输入状态),这样外部上拉电阻就把总线拉高了。只有当需要输出低电平时,才将 t 置0,同时内部驱动‘0’到引脚上。理解这一点,能帮你避免很多总线电平冲突的诡异问题。
其次,操作流程的核心是FIFO和状态机。IP核内部有一个状态机来管理I2C协议,而我们作为使用者,主要任务就是把正确的数据按顺序塞进TX_FIFO,并适时地配置控制寄存器。比如一次典型的写操作,你大概需要做这几步:把7位I2C设备地址


93

被折叠的 条评论
为什么被折叠?



