I2C的RTL代码设计


👉:I2C协议介绍请看:I2C协议


一、简介

I2C是一个低速、多master多slave的单端串行数据总线,有两根线(SCL串行时钟线和SDA串行数据线)构成,高速模式可达到3.4MHz的传输速率,最高支持5MHz传输(utra-fast mode)。

应用的例子:

  • 可以用于EEPROM中
  • 控制小的OLED和LCD显示屏
  • 可以作为PCI 和 PCIe的配置接口
  • 用于常用的低速DACs和ADCs接口
  • 调节显示设备的色彩、对比度等配置
  • 音频设备的音量调节
  • 电源模块的管理等

二、设计架构

这是一个简单的I2C平台,如下图所示结构:
请添加图片描述

  • APB接口,接收来自APB总线的数据和地址;
  • Prescale寄存器,对系统时钟分频,控制产生SCL线的时钟模块;
  • 指令寄存器,控制读写方向,以及要访问的slave地址;
  • 状态寄存器;
  • 控制寄存器,控制中断产生和是否使能I2C;
  • Transmit寄存器,寄存从APB总线过来的传输数据;
  • Receive寄存器,寄存从I2C slave读取的数据;
  • 数据IO移位寄存器,连接到Transmit寄存器和Receive寄存器上,写操作时,将APB发送过来的并行数据转换成串行数据,读操作时,将I2C的SDA线上的串行数据转换成并行数据发送到APB线上。
  • Byte指令控制器,
  • bit 指令控制器,

PS:为什么UART有独立的 write_data_buffer 和 read_data_buffer,而 i2c 可以只用一个 shift_register 连接到接收和发送的数据寄存器上?因为UART是一个全双工的总线,可以读写同时进行,而 I2C 是一个半双工的总线,读写不能同时进行,要么是读操作,要么是写操作。

三、I2C的PAD设计

I2C是一个双向PAD,I2C上的设备是漏极开路,并通过上拉电阻接到SCL和SDA线上。如下图所示:
请添加图片描述
解释上图:

  • scl_o 和 sda_o 是接的 1’b0,scl_i 和 sda_i 是接的 1’bz,为高阻态
  • 当 scl_en_o 和 sda_en_o 为 1’b0 时,此时开关被打开,SCL线被置为低;
  • 当 scl_en_o 和 sda_en_o 为 1’b1 时,此时开关关闭,向SCL线输出一个高阻态,通过上拉电阻作用将SCL或SDA线置1;

PS:I2C上连接的设备是有上拉电阻的处理,具有线与的功能。协议上可以看:I2C为什么要线与?为什么要上拉?

四、寄存器的配置

如下是对寄存器的设计,

名称偏移地址位宽访问属性复位值描述
PRElo0x008RWprescale的低8位
PREhi0x018RWprescale的高8位
CTR0x028RW控制寄存器
TXR0x038W发送寄存器
RXR0x038R接收寄存器
CR0x048W指令寄存器
SR0x048R状态寄存器

1. Prescale 寄存器( PRElo、PREhi )

Prescale 寄存器对时钟的分频关系,如下:
用5倍的SCL时钟来进行分频,如果系统时钟是 32 MHz,期待的SCL时钟是 100 KHz,那么有公式:
分频系数 = 32 MHz/ (5 * 100 KHz) -1 = 63(dec) = 3F (Hex)
注:只有在I2C使能关闭时才能改变 prescale 的值

2. 控制寄存器(CTR)

Bits位命名访问属性描述
7I2C_ENRWI2C使能。当置为1,则启动 I2C;当置为0,则关闭 I2C;
6INTR_ENRWI2C中断使能。当置为1,则使能 I2C中断;当置为0,则关闭 I2C中断;
5:0RW保留域

3. Transmit寄存器(TXR)

Bits位命名访问属性描述
7:1DATAWAPB端写入的数据
0RWWRW位。当置为1,则从slave中读取;当置为0,则想slave中写入;

注:

  • 如果是传输的是数据,这8位合在一起刚好是一个byte的数据;
  • 如果传输的是地址,则前高7位是地址,最低位R/W位(读写方向位);
  • 关于I2C使用10bit地址访问可以看:10bit地址读写

4. Recieve寄存器(RXR)

Bits位访问属性描述
7:0R从I2C读取的数据

5. 状态寄存器(SR)

Bits位命名访问属性描述
7ACKR接收数据时回复
6BUSYRI2C 总线处于busy状态。当I2C总线发出 START条件时,为1;当I2C总线发出 STOP条件时,为0;
5ARB_LSRmaster仲裁失败,未获取总线权限。仲裁失败的原因:1.总线产了STOP条件,但没有请求; 2.master驱动SDA为高,但是发现SDA为低;
4:2R保留域
1TRANS_STATUSR传输状态。为1表示传输正在进行;为0表示传输完成
0INTR_STATUSR中断指示。只有当CTR寄存器的中断使能打开,中断信号拉起的条件:1.1个byte的数据传输完成;2.仲裁失败

6.指令寄存器(CR)

Bits位命名访问属性描述
7ACKR接收数据时回复
6BUSYRI2C 总线处于busy状态。当I2C总线发出 START条件时,为1;当I2C总线发出 STOP条件时,为0;
5ARB_LSRmaster仲裁失败,未获取总线权限。仲裁失败的原因:1.总线产了STOP条件,但没有请求; 2.master驱动SDA为高,但是发现SDA为低;
4R保留域
3R保留域
2R保留域
1TRANS_STATUSR传输状态。为1表示传输正在进行;为0表示传输完成
0INTR_STATUSR中断指示。只有当CTR寄存器的中断使能打开,中断信号拉起的条件:1.1个byte的数据传输完成;2.仲裁失败

四、RTL代码

【持续更新中…】

最近一个项目需要做I2C的slave,在opencores.org上面找到了一个I2C代码,不过是master的。 下载来看看,发现里面有一个I2C slave的行为级代码。 于是自己根据这个代码改写了一个I2C slave RTL代码,并修改了原来那个设计的testbench,将rtl的Slave替换了原来的behavior的Slave,在modelsim里面作了前仿,完全通过。还有一个myram.v文件,是一个register file,和slave相连,存储数据用的。 用synplify做综合,使用x3s400-4的器件,占用LUT<100,速度接近200MHz。性能比较优化。 代码做了详尽的注释,语言采用verilog,并且写了仿真的脚本。解压了直接运行simbehav.bat就可以了。如果modelsim安装的时候注册了环境变量(path),脚本调用modelsim,输入run -all即可看到仿真结果。 虽然不是很复杂,不过对于广大需要做I2CRTL slave的工程师来说,还是很有参考价值的。 1、 设计流程 将I2C slave的行为模型改为rtl模型。 进行等效仿真,直到波形一致,通过timing check,数据正确。 再进行rtl优化设计 2、 注意要点 a) 时钟的设计 b) 对于restart condition的时序是否正确 c) 3、 进度 a) 11-12:initial状态的bitcnt不对,需要认真比对/设计 b) 11-13:initial基本解决(sda_in的问题)。Sda三态冲突,原因不明。比对原设计 c) 11-14:sda三态冲突解决,原因为sda在初始化时没有将sda_oen赋值(由sm赋值,但是sm没有做async reset)。同时注意verilog的大小写敏感。 d) 11-15:仿真出现错误:read出来的数据非期望值。写入逻辑完全正确。Read时由于sda_oe在sm中有一个cycle_pulse的延迟,导致了mem_do[7]串行移出时错位。在更改了sm的代码风格后再研究解决方法。 e) 11-16:仿真完全匹配波形。计划:优化结构,提高稳定性sm改为每个时钟打一下。 关于I2C的SDA三态转换: Master在发送完第8个bit后随后将sda释放(posedge后大概1/4 scl周期),此时slave需要在第九个bit对应的scl的posedge拉低sda。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小verifier

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值