没有合适的资源?快使用搜索试试~ 我知道了~
首页I2C-verilog-(非常详细的i2c学习心得)
I2C-verilog-(非常详细的i2c学习心得)

I2C-verilog-(非常详细的i2c学习心得),总结的非常详细。可以练手
资源详情
资源评论
资源推荐

I2C 学习心得
我最近刚做完 I2C 通信协议的编写与调试,下面介绍一下我从一开始理解夏老师的程序,
修改程序,直到下板调试整个的学习过程,希望对大家学习 I2C 有一定的帮助。
一、 分析源代码
学习 I2C,首先我们要知道 I2C 是一种串行总线协议。目前几种常用的串行总线有 UART、
SPI 和 I2C,先来简单了解一下这三种串行总线。
图 1.UART、SPI、I2C 总线对比
如图 1 所示,UART 的总线数只有两条,分别是 TX(发送)和 RX(接收),没有时钟信
号,所以 UART 需要固定的波特率,也就是两位数据的间隔要相等。而 SPI 的四条总线分别
为 SCLK(时钟)、MISO(主器件数据输入,从器件数据输出)、MOSI(主器件数据输出,
从器件数据输入)、SS(从器件使能信号),SPI 总线由主机提供时钟,为同步通信,并且
SPI 总线有两条总线进行数据传输,可以同时进行收发数据,为双工模式。SPI 有 3 线、4 线
两种模式,3 线模式一般代表没有 SS 信号,具体情况还要视器件手册而定。I2C 有两条总线
SCL(时钟)和 SDA(数据),I2C 用的线更少,因为 I2C 需要有双向 IO 的支持,而且使用上
拉电阻,抗干扰能力没有其他两种强,一般用于同一板卡上芯片之间的通信,较少用于远距
离通信。
具体到 FPGA 设计这一环节,我们需要搞清这三种总线上的信号是怎么走的,UART 很简
单,使用发送数据线 TXD 和接收数据线 RXD 来传送数据,接收和发送可以单独进行也可以
同时进行。它传送数据的格式有严格的规定,每个数据以相同的位串形式传送,每个串行数
据由起始位,数据位,奇偶校验位和停止位组成。从起始位到停止位为一个字符的完整通信
格式。SPI 情况就相对多一些,根据时钟极性(CPOL)和时钟相位(CPHA)两个参数的不同有四
种基本情况,传送数据的格式与 UART 差不多。而 I2C 总线的协议要比 UART 和 SPI 复杂,能
掌握 I2C,也就能掌握 UART 和 SPI。言归正传,回到我们的 I2C 设计实例。
第一步首先了解,这个 I2C 实例的功能。
这个实例实现了通过 I2C 总线对 EEPROM 写入数据,再将写入 EEPROM 中的数据读取出
来的一个过程。实例的重点在于对 I2C 总线协议时序的掌握,即用 I2C 总线要求的格式将数
据写入到 EEPROM 中,再读取出来。
什么是 EEPROM?EEPROM(ElectricallyErasableProgrammableRead‐OnlyMemory),电可
擦可编程只读存储器,一种掉电后数据不丢失的存储芯片。EEPROM 可以在电脑上或专用设
备上擦除已有信息,重新编程。所以,EEPROM 是可以写入数据也可以读取数据的,并且
EEPROM 掉电数据并不会丢失,在后面将程序烧写到开发板的过程中可以验证这一点。
第二步,简单地了解一下这个实例的各个模块。

在这个 I2C 实例中,为了实现两个器件的通信,我们需要一个主机和一个从机,如下图
2 所示,它们之间采用 I2C 协议进行串行通信,设计实例中的 signal 模块和 EEPROM_WR 模
块模拟主机,EEPROM 模块模拟从机。当写入数据时,EEPROM_WR 模块从 signal 模块中调
取数据,然后通过 I2C 的两条总线 SDA(数据总线)和 SCL(时钟总线)向 EEPROM 器件写
入数据。当读出数据时,EEPROM_WR 仍然通过 SDA 和 SCL 总线读出 EEPROM 中的数据,然
后输入给 signal 模块,比较读出的数据与当时写入的数据是否相同。验证读写的正确性。
在至芯科技 EP2C8‐2010 开发板上,是有 EEPRO M 器件的,而 signal 模块我们可以通
过创建一个 RAM 的 IP 核来实现其功能,所以图 2 中唯有 EE PROM_WR 模块是要写入 FPGA
中的可综合模块,所谓可综合模块就是可以转化为实际电路的模块,而 signa l 和 EEPROM
模块则是为了仿真而存在的,所以其代码不必可综合,只编写其行为级模型即可。读者
在后面会发现这三个模块的源代码编写风格不一样,这就是因为 EEPROM_WR 模块是可
综合的,要求比较严格,不能用一些 init ial、#50 之类的语句,而 si gnal 与 EEPROM 模块
则没有这个限制。
第三步,了解 I2C 总线特征。
在 I2C 总线中,只有在总线处于“非忙”状态时,才能开始数据传输。在数据传输期间,
只要时钟线为高电平,数据线都必须保持稳定,否则数据线上的任何变化都被当作“启动”
或“
停止”信号。图 3 是总线状态的定义。
eeprom_wr
Signal
eeprom
DATA[7:0] DATA[7:0]
ADDR[10:0] ADDR[10:0]
CLK CLK
RD RD
WR WR
RESET RESET
ACK
ACK
SDA
SCLSCL
SDA
图 2. EEPROM 读写电路和它的测试电路
SCL
SDA
(A) (B)
(D)
(D)
(C)
(A)
停止信号
数据的电平稳定
数据才有效
数据在此
期间变化
启动信号
图 3.I2C 双向二线制串行总线
数据在此
期间变化
数据在此
期间变化
1
/
0

(1)总线非忙状态(A 段):数据线 SDA 和 时钟线 SCL 都保持高电平。
(2)启动数据传输(B 段):当时钟线(SCL)为高电平状态时,数据线(SDA)由
高电平变为低电平的下降沿被认为是“启动”信号。只有出现“启动”信号后,其它的命令
才有效。
(3)停止数据传输(C 段):当时钟线(SCL)为高电平状态时,数据线(SDA)由
低电平变为高电平的上升沿被认为是“停止”信号。随着“停在”信号出现,所有的外部操
作都结束。
(4)数据有效(D 段):在出现“启动”信号以后,在时钟线(SCL)为高电平状态时
数据线是稳定的,这时数据线的状态就要传送的数据。数据线(SDA)上的数据的改变
必须在时钟线为低电平期间完成,每位数据占用一个时钟脉冲。每个数传输都是由“启动”
信号开始,结束于“停止”信号。
(5)应答信号:每个正在接收数据的从机 EEPROM 在接到一个字节的数据后,通
常需要发出一个应答信号。而每个正在发送数据的 EEPROM 在发出一个字节的数据后,
通常需要接收一个应答信号。EEPROM
读写控制器必须产生一个与这个应答位相联系的
额外的时钟脉冲。在 EEPROM 的读操作中,EEPROM 读写控制器对 EEPROM 完成的最
后一个字节产生一个高的应答位,这叫做非应答信号,随后给 EEPROM 一个结束信号。
第四步,理解各个模块的代码。
首先介绍核心模块——EEPROM_WR 模块,这个模块就干一件事,严格控制 SD A 与 SCL
总线上的信号,使其满足 I2C 总线时序要求。这里要用到状态机来控制 SDA 与 SCL 上的信号,
所以难点就在于对状态机的编写。因为 EP2C8‐2010 开发板采用的 EEPROM 是 AT24C02,
所以该状态机控制的 SCL 与 SDA 时序就要满足 AT24C02 的写入和读取格式。图 4 、5 分别
是 AT24C02/4/8/16 字节写入帧格式和读指定地址存储单元的数据帧格式,简单分析一下字
节写入格式,如图 4 所示:第 1 位启动信号,接下来的第 2‐9 位是控制字节写入,其中 2‐5
位是固定的机器码 1010,6‐8 位是页地址,第 10 位是 EEPROM 给出的应答信号 0,第 11‐18
位是存储单元地址,19 位是 EEPROM 给出的应答信号 0,第 20‐27 位是写入的数据,28 位
应答信号,29 位停止信号。而
AT24C02/4/8/16 的字节读取格式也是大同小异,先写入控制
字和存储地址,然后是启动信号与控制字节信号,这时,控制字节的第 8 位变为了 1(读取),
最后读取数据,并且在读取完毕后,主机将 SDA 拉高作为非应答信号。最后是停止位。
可能有人还是对这种字节写入与读取格式不明白,其实这种格式是别人定好的,我们所
需要的就是要让 SDA 与 SCL 的信号满足这种格式要求即可,下面我们来看夏老师的
EEPROM_WR 程序。
图 4.AT24C02/4/8/16 字节写入帧格式
图 5.AT24C02/4/8/16 读指定地址存储单元的数据帧格式
启
动
控制字节 EEPROM存储单元地址
数据
停
止
写
SDA线
S 1 0 1 0 X X X
应
答
应
答
应
答
启
动
控制字节
EEPROM存储单元
指定地址(n)
写
SDA线
S 1 0 1 0 X X X
应
答
应
答
启
动
S 1 0 1 0 X X X
停
止
读
控制字节
数据(n)
应
答
非
应
答
P

首先是一堆输入输出、寄存器的定义,我们读程序的时候大可先不看这些,等到后面有
需要的时候再回过头来看这些定义,这里需要注意的是 SDA 与 DATA 的类型,都是 inout 型,
SDA 我们很容易理解,因为主机和从机都会给 SDA 线上发信号,比如字节写入格式时,主机
先给 SDA 发了 1 个 8 位数据,然后作为应答位,从机要把 SDA 拉低,表示我已经接受到你
的信号了,在应答位时主机是不能操作 SDA 线的。然而 DATA 设定为 inout 型,我们可以看
到图 2,其实在字节写入格式时,DATA 是 signal 模块传输给 EEPROM_WR 模块,作为要写入
的数据。而在字节读取格式时, EEPROM_WR 通过 SDA 从 EEPROM 中读取数据,其实跟 DA TA
是没有关系的,这里可以只将 DATA 设定为 input 型,设定为 inout 型是因为后续的程序会将
EEPROM_WR 读取到的数据发给 signal,与 signal 当初发送的数据进行比较,检验通信是否
正确。如果将比较数据这程序操作放在 EEPROM_WR 模块中,就可以将 DATA 设为 input。
提到 inout 类型,还得再多补充两句,inout,顾名思义,双向口既能作为输入又能作为
输出,可以节省管脚,在具体实现上一般是用三态门来实现,图 6 就是用三态门实现的 sda
总线的示意图。
图 6.sda 总线示意图
link_sda 和 out_flag 分别为 EEPROM_WR 和 EEPROM 控制三态门输出的开关,当 link_sda
打开,out_flag 关闭时,EEPROM_WR 向 SDA 传输数据,EEPROM 接收 SDA 的数据,此时,
SDA 对于 EEPROM_WR 来说就是 output,对于 EEPROM 来说就是 input。反之,当 link_sda
关闭,out_flag 打开时,EEPROM_WR 通过 SDA 从从 EEPROM 中读取数据。当 link_sda 与
out_flag 都关闭时,SDA 就被置为高阻状态。
下面来看程序中对于 SDA 和 DATA 三态门的描述。
assignsda1 =(link_head) ?head_buf[1] :1'b0;
assignsda2=(link_write) ?sh8out_buf[7] :1'b0;
assignsda3=(link_stop)
?stop_buf[1] :1'b0;
assignsda4=(sda1|sda2|sda3);
assignSDA=(link_sda) ?sda4:1'bz;
assignDATA=(link_read) ?data_from_rm :8'hzz;
这是程序中应用三态门对双向口的实现,我们可以看到引入了多个开关,link_head、
link_write、link_stop、link_sda、link_read,其中 link_sda 和 link_read 这两个开关是最主要的,
当 link_sda =1,即 link_sda 打开时,将 sda4 输出,SDA=sda4。当 link_sda =0 时,将 SDA 置
为高阻。同时 sda4 也是由三个开关控制的,为 sda1、sda2、sda3 三个信号相或的结果,这
里是将
EEPROM_WR 的状态分为了三个基本的状态,分别是启动状态、写入状态以及停止状

态,这是根据 EEPROM 对 SDA 总线输出的值区分的。对照图 3、图 4,其实意思就是在启动
的时候给 SDA 一个下降沿,停止时给 SDA 一个上升沿,传输数据时给 SDA 一个有效数据。
引入这些开关是为了看得更加直观。当然,我们也可以不引入这么多开关,只需要 link_sda
和 link_read,在每次 link_sda 打开的时候我们都给 sda4 赋新值即可。
下面我们来看产生串行时钟 SCL 的程序:
always@(negedgeCLK)
if(RESET)
SCL<=0;
else
SCL<=~SCL;
这条产生 SCL 的程序也是十分巧妙的,本文中的程序是用 CLK 的下降沿来触发 SCL 时钟,
用 CLK 的上升沿来触发 SDA,这样 SDA 与 SCL 就相差了半个 SCL 周期,目的是为了满足 I2C
总线上的传输协议,具体见图 7.
图 7.SCL 与 SDA 基本时序关系
从图 7 中,我们可以看出,启动位占了一个 SCL 时钟周期,1 时刻拉高,2 时刻拉低,
保证在 SCL 高电平时 SDA 有下降沿,这样就是启动信号,同理,如果我们要传输数据时,3
时刻将传输的数据赋给 SDA,比如要传输的数是 1010,3 时刻将 SDA 拉高,直到完成 1 个 SCL
周期时再把下一个值 0 赋给 SDA。这样就是一个 SCL 与 SDA 基本的时序关系,我个人的理解
是这样的:首先,要保证图 3、4 中字节读写格式的每一位都要占一个 SCL 时钟周期。其次,
每个 CLK 上升沿时将数据传给 SDA,比如 1:SDA<=1;2:SDA<=0。这样才能保证时序的一
致性。
接下来我们看到的就是主状态机程序,由图 3、4 列出的字节读写格式,我们可以将读
写操作分为一共 11 个状态,状态图如下。
剩余81页未读,继续阅读
















lvhf2008
- 粉丝: 2
- 资源: 4
上传资源 快速赚钱
我的内容管理 收起
我的资源 快来上传第一个资源
我的收益
登录查看自己的收益我的积分 登录查看自己的积分
我的C币 登录后查看C币余额
我的收藏
我的下载
下载帮助

会员权益专享
安全验证
文档复制为VIP权益,开通VIP直接复制

评论2