新闻中心

EEPW首页 > 汽车电子 > 设计应用 > I2C总线控制器的VHDL设计及实现

I2C总线控制器的VHDL设计及实现

作者:■ 迈瑞医疗电子公司 郑俭锋时间:2005-05-05来源:eaw

摘    要:本文用设计了一个简洁而实用的控制器,介绍了详细的设计思路和在中的实现,并给出了在嵌入式系统设计中的使用方法。
关键词:

引言
以其接口简单、使用灵活等突出优点在数字系统中获得了广泛的应用。尤其在嵌入式系统中,I2C总线被普遍用来连接CPU/MCU和外围器件。I2C总线规范经过十几年的实践,发展了多层标准。从传输速率上划分,有标准模式(100Kbit/s),快速模式(400Kbit/s),高速模式(3.4Mbit/s);从寻址范围上划分有7位地址模式和10位地址模式。本文使用语言设计的控制器模块采用标准速率、7位地址的模式,主要应用在嵌入式系统中,给CPU/MCU提供一个操作I2C器件的简易平台,以弥补某些CPU/MCU功能的不足。

功能定义
I2C总线的接口非常简单,只需一根数据线(SDA)和一根时钟线(SCL)。I2C器件可以工作于主件(Master)模式和从件(Slaver)模式,但I2C总线上同时只能有一个主件和多个从件,每次传输规定由主件发起,通过从件地址(Slaver Address)访问从件。设计时本着简单实用的原则,限定本模块只工作于Master模式。
端口定义
entity I2C_CTRL is
 port(
 -- 系统信号
 nReset: in STD_LOGIC;-- 系统复位信号端
 CLK: in STD_LOGIC; -- 内部系统时钟端
 -- 控制信号
 ADRS: in STD_LOGIC_ VECTOR(4 downto 2); -- 地址线,3位(8个32位地址)
 Din: in STD_LOGIC_ VECTOR(7 downto 0); -- 数据输入线,8位
 Dout: out STD_LOGIC_ VECTOR(7 downto 0); -- 数据输出线,8位
 nCS: in STD_LOGIC; --片选使能端
 nWR: in STD_LOGIC; --写使能端
 -- I2C总线信号
 SDA: inout STD_LOGIC; --串行数据输入输出端,输出有三态
 SCL: out STD_LOGIC --时钟输出端,三态输出
 );
end I2C_CTRL;
寄存器定义
本模块的寄存器定义参照Motorola公司ColdFire系列MCU MCF5307的I2C控制器,共定义了3个寄存器,长度均为8位,采用32位编址,如表1所示。
时序状态机
本模块根据I2C总线规范的时序标准(见图1),划分一个传输周期为8个状态,状态转换如图2所示。

进程设计
本模块全部采用同步时序设计。VHDL时序仿真见图3,限于篇幅,不提供VHDL原程序。下面只对每个进程的关键点进行说明。
时钟进程
本模块设定FPGA分配给I2C模块的系统时钟(CLK)为20MHz,而标准模式的I2C总线操作速率(SCL的速率)为100KHz,需要对系统时钟进行分频。基于VHDL的同步设计需要,本地时钟频率必须为SCL速率的整数倍,本模块取两倍值,因此本地时钟频率设为200KHz。定义6bit定时器timer,对系统时钟的上升沿进行计数。
系统复位时timer清零。当CLK上升沿时,timer值减1。当timer=0时赋值100,对20MHz的系统输入时钟进行100分频产生200KHz的本地时钟。
为满足对总线的运行状态进行进一步的细分,使用一个5bit的step信号对运行进度进行计数,每个本地时钟到达时,step加1。
CPU读寄存器进程
系统复位时Dout端口清零。在片选信号nCS有效的情况下,当CLK上升沿时,对地址总线ADRS译码,把指定地址的寄存器内容送到Dout端口。
CPU写寄存器进程
系统复位时,初始化I2CR和I2DO。在片选信号nCS和nWR同时有效的情况下,当CLK上升沿时,读取Din端口的信号,存入被ADRS译码选中的寄存器。
状态标志改写进程
系统复位时,初始化状态标志。运行时根据状态机和step的值改写状态标志。其中I2SR[IIF]因为同时可以由CPU改写,安排另外一个独立的进程。
状态机赋值进程和状态机转换进程
系统复位时,状态为IDEL。当检测到MSTA=1时,进入START状态,保持4个本地时钟周期,进入READY状态,根据MTX的值,进入SENDING或RECEVING状态,等待ICF=1时,表明传输结束,进入WAITING状态。根据IIF或者MSTA是否被清除,决定继续下一个传输或者退到STOP状态。STOP状态保持3个本地时钟周期,返回IDEL状态。
SCL线进程和SDA线进程
系统复位时SCL线输出高阻,运行时按照状态机和step的值改写SCL线。当进入传输状态(SENDING或RECEIVING)时,step[0]=0输出高阻,step[0]=1输出低电平。
系统复位时SDA线输出高阻,运行时按照状态机和step的值读写SDA线。

在FPGA中的实现
本I2C控制器模块全部采用可综合的VHDL语言设计,通过Mentor公司的Leonardo Spectrum工具综合,并在Altera公司的Cyclone FPGA中实现布线。
Leonardo Spectrum 2003b65综合的结果是:
Device Utilization for EP1C6Q240C
Resource                Used    Avail   Utilization
IOs                     25      181      13.81%
LCs                     171     5980      2.86%
Memory Bits         0       92160     0.00%
          Clock Frequency Report
 Clock                : Frequency
 CLK                  : 211.8 MHz
此处作为一个单独的模块进行综合,因此上述结果I/O口占用率包括了地址、数据总线和时钟线等,实际使用时作为一个子模块,这些信号线都在FPGA内部。

模块的使用说明
本模块适合应用在嵌入式系统中,作为CPU/MCU连接I2C器件的一个桥接器,使得CPU可以像操作普通存储器一样控制I2C器件。下面补充说明CPU/MCU操作本模块的使用方法。
1) 每发起一次传输都必须先对I2C器件进行寻址。不管是要从I2C器件里接收还是发送数据,都必须先设置I2CR[MTX]以标明是一个发送任务,并在I2DR中填入要寻址的I2C器件的Slaver地址,再发送“开始传输”指令。只有在传输完地址之后,再按需要改写I2CR[MTX]位来实现接收或者发送。如果发送地址之前就试图读写I2C总线将得不到预期的结果。
2) 在一次传输完成之后,将置位中断标记I2SR[IIF]。中断标记必须由软件清除,在标记被清除之后,控制器将自动读取I2CR,进行下一轮传输。如果要改变传输方式,应该在清除中断标记I2SR[IIF]之前改写I2CR寄存器。
3) 对reSTART指令的执行与I2C总线协议规范不尽相同。只有在传输指令没有被结束(即在发送reSTART指令之后没有发送过STOP指令)的状态下设置I2CR[RSTA]才能产生一个reSTART指令,否则无效。而且每次需要reSTART操作时,必须再次重复设置I2CR[RSTA]才能生效。这样解释reSTART指令的目的是,可以方便实现一些EEPROM器件的“选择/任意读数”模式。

结语
本文设计的I2C控制器非常适用于以“MCU+FPGA”为模式的嵌入式系统中。当MCU不具有I2C控制功能,而使用I/O口模拟又占用较多资源时,用FPGA实现对I2C器件的控制成为最理想的选择。通常这种情况下,针对在I2C总线的地位来说,MCU只需担当主件(Master模式),I2C器件只充当从件(Slaver模式),而且一般的器件都只工作于标准速率。因此,若采用FPGA厂商提供的标准I2C控制器IP,会造成资源浪费。而自行设计一个控制器就显得更为经济实用了。■

参考文献
1 The I2C-Bus Specification, Version 2.1, Philips Semiconductors, 2000.1
2 MCF5307 ColdFire Integrated Microprocessor User誷 Manual, Rev 2.0, Motorola, Inc., 2000.8



关键词: FPGA I2C总线 VHDL

评论

技术专区

关闭