FPGA基础协议二:I2C读写E²PROM

本文详细介绍了如何在FPGA中实现I2C协议,包括I2C的基础知识、逻辑设计、代码实现以及仿真测试。文中详细解析了I2C协议的起始位、应答信号、停止位等关键概念,并阐述了E2PROM的读写操作。逻辑设计部分包括按键消抖、UART模块、I2C接口模块和E2PROM读写控制模块。代码实现部分展示了状态机、计数器和串并转换的实现细节。最后,通过仿真测试验证了设计的正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

FPGA基础协议二:I2C读写E2PROM

一、I2C与E²PROM

I2C常用念法:I²C(读作"I-squared-C" ),还有可选的拼写方式是I2C(读作I-two-C)以及IIC(读作I-I-

C),在中国则多以**“I方C”**称之。

1. I2C

I2C:(Inter-Integrated Circuit)即集成电路总线,是一种两线式串行总线,由PHILIPS公司开发,用于连接微控制器及其外围设备。多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。

  • I2C总线由数据线SDA时钟线SCL构成双向可收发的通信线路

  • 是一种半双工通信协议

  • 总线上的主设备与从设备之间以字节(8bit)为单位进行双向的数据传输。(升级版UART?)

1.1 物理层

image-20220623234857007

  • 它是一个支持多设备的总线(支持多主机多从机)。

  • I2C总线只使用两条总线线路,一条双向串行数据线(SDA) 一条串行时钟线(SCL)。数据线即用来表示数据,时钟线用于数据收发同步。

  • 每个连接到I2C总线的设备都有一个独立的地址,主机可以利用设备独立地址访问不同设备

  • I2C总线通过上拉电阻接到电源。当I2C设备空闲时,设备会输出高阻态,当所有设备都空闲,都输出高阻态时,由上拉电阻把I2C总线拉成高电平。

  • I2C总线具有仲裁机制1

  • 具有三种传输模式:

    **标准模式:**传输速率为100kbit/s

    **快速模式:**传输速率为400kbit/s

    **高速模式:**传输速率为3.4Mbit/s(不支持E2PROM)

    老师说他们一般写200kbit/s

1.2 协议层
  • I2C协议空闲状态:SCL与SDA均保持高电平,并且此时无I2C设备工作。

  • I2C协议的起始信号 :SCL保持高电平的同时SDA拉低。

  • I2C协议的数据传输状态:在SCL低电平时更新SDA的数据信息。

    SCL高电平时改变SDA会误发送起始/停止信号。

  • 应答信号:发送端每发送一个字节,就必须在第9个SCL脉冲期间释放SDA,由接收端反馈一个应答信

    号。

    • ACK:有效应答,表示成功接收端接收了该字节,低电平表示

    • NACK:非应答,表示接受失败、传输结束,高电平表示。

  • I2C协议的停止信号:SCL高电平时拉高SDA。

image-20220623235813516

把起始位看作一个时钟周期,8位数据位8个时钟周期,应答位一个时钟周期,约为10个时钟周期。所以这里可以与UART协议进行比对,在不算校验位且每次传输1字节的uart数据帧也是10bit,冥冥之中感到了某种联系。

I2C到此为止,感觉像是一个强化以后的UART协议

2. E2PROM

EEPROM,或写作E2PROM,全称电可擦除可编程只读存储器 (英语:Electrically-Erasable Programmable Read-Only Memory),是一种可以通过电子方式多次复写的半导体存储设备。相比EPROM,EEPROM不需要用紫外线照射,也不需取下,就可以用特定的电压,来抹除芯片上的信息,以便写入新的数据。

我的C4开发板使用的是型号为24LC04B的EEPROM存储芯片。24LC04B的存储容量为512Bytes/4Kbits,其内部有两个Block,每个Block中有256个字节(一个字节为8bit)。其读写操作都是以字节(8bit)为基本单位。 24LC04B EEPROM 存储芯片的器件地址包括:

  • 厂商设置的高4位1010,这里表设备代码。
  • 用户需自主设置的低3位 x、x、B0 来选择块地址。
  • 字节存储地址,一共8bit。

在IIC主从设备通讯时,主机在发送了起始信号后,接着会向从机发送控制命令。控制命令长度为1个字节,它的高7位为上文讲解的 IIC设备的器件地址,最低位为读写控制位。EEPROM储存芯片控制命令格式示意图,具体见下图。

image-20220624103746329

因为只有两个块,所以只设置B0即可,前面两位不会对结果造成影响。

  • 读写控制位为 0 时,表示主机(FPGA)要对从机(EEPROM)进行数据写入操作:{7’b1010xxx,1’b0}
  • 读写控制位为 1 时,表示主机(FPGA)要对从机(EEPROM)进行数据读出操作:{7’b1010xxx,1’b1}
2.1 写操作

字节写(BYTE WRITE)操作:一次写入1个字节。在数据信号线SDA上,发起始位(START)->写写控制字(Control Byte)->接收ACK->写字节地址(Word Address)->接收ACK->写数据(Data) ->接收ACK->发停止位(STOP)。

image-20220710193558685

页写(PAGE WRITE)操作:一次写入16个字节(每字节为8bit)数据。在数据信号线SDA上,发起始位(START)->写写控制字(Control Byte)->接收ACK->写字节地址(Word Address)->接收ACK->写数据(Data(n)) ->接收ACK->写数据(Data(n+1))->接收ACK->(一共发送16字节(Byte)数据,中间数据省略)->写数据(Data(n+15))->接收ACK->发停止位(STOP)。

image-20220710193641884

2.2 读操作

当前地址读(Current Address READ)操作:在数据信号线SDA上,发起始位(START)->写读控制字(Control Byte)->接收ACK->接收读数据(Data)->发No ACK->发停止位(STOP)。

image-20220710194523158

随机地址读(RANDOM READ)操作:在数据信号线SDA上,发起始位(START)->写写控制字(Control Byte)->写读地址(Word Address)->接收ACK->再发起始位(START)->写读控制字(Control Byte)->接收读数据(Data)->发No ACK->发停止位(STOP)。

image-20220710195724687

顺序地址读(SEQUENTIAL READ)操作:在数据信号线SDA上,发起始位(START)->写写控制字(Control Byte)->写读地址(Word Address)->接收ACK->再发起始位(START)->写读控制字(Control Byte)->接收读数据(Data(n)) ->接收ACK->接收读数据(Data(n+1)) ->接收ACK->…->接收读数据(Data(n+x)) ->发No ACK->发停止位(STOP)。

image-20220710195749285

我更愿意把它叫做 页读,对应页写都是一次性读取多个字节,只不过它可以从指定地址一直连续读完整个内存。

然后要注意的是No Ack,这代表着是由I2C向E2PROM发送应答位,高电平表示?

二、逻辑设计

1. 实验需求

  1. 使用按键,模拟读写请求信号

  2. 收到读写请求信号时,FPGA通过I2C协议向E2PROM芯片写入单字节数据或从E2PROM芯片读出单字节数据;

  3. 使用串口来接收需要写入的数据和显示被读出的数据

2. 设计思路

  1. 一提到按键就要想到按键消抖模块。
  2. 需要一个读写控制模块与I2C接口模块:
    • 读写控制模块负责指挥I2C接口模块发送读写命令、地址、数据,以及使用两个fifo分别寄存uart写入数据和E2PROM读出数据。
    • 2C接口模块负责将这些字节并串转换为I2C协议允许的格式再传输E2PROM中,并将接收到的信息翻译再反馈给FPGA(串并转换)。
  3. 串口收发模块以及收发分别对应的2个fifo。
2.1 模块:
  • key_debounce模块:按键消抖模块,没什么好说的。
  • uart模块:分为收发两个模块,分别配备写与读两个fifo,用以缓存等待写和发的数据。
  • e2prom_rwctrl模块:E2PROM读写控制模块,用来向E2PROM存储器发送读写控制命令,以及缓存写入E2PROM的数据和从E2PROM读取到的数据。
  • i2c_interface模块:i2c接口模块,用来把接收到的指令并串转换为I2C协议的格式然后传输到E2PROM存储器中,或将E2PROM传输回来的信息进行串并转换传回到fifo中。
  • i2c_ctrl模块:SDA总线控制模块,负责SDA这根inout双向数据总线的输入输出控制。

image-20220724025526259

image-20220724025547905

2.2 工作步骤:

写:

  1. 由上位机串行发送 x Bytes的数据到串口接收模块uart_rx中;
  2. uart_rx模块将接收到的串行信号进行串并转换然后发送到e2prom_rwctrl模块中;
  3. e2prom_rwctrl模块,每接收到一次rx_vld(数据接收有效信号)后,开启wrfifo的写请求,写入一个字节,直到接收完为止;
  4. wrfifo缓存完成后,e2prom_rwctrl模块向i2c_interface模块发送写请求和需要写入的数据,每次发送1个字节的数据,在收到done信号后再次发送1个字节,知道发送完3个字节为止;
  5. i2c_interface负责将接收到的写控制字写地址wr_data[7:0]进行一个符合I2C协议的并串转换,并在每转换传输完成1个字节后,向e2prom_rwctrl模块发送done信号,提醒它传输下一个字节。

读:

  1. 按下key,经过按键消抖模块后输出稳定的key信号到e2prom_rwctrl模块中;
  2. e2prom_rwctrl模块接收到key信号后向i2c_interface模块发送写控制字读地址读控制字
  3. i2c_interface模块接收到读请求后发送写控制字读地址读控制字,接着在一个应答信号后将接收到的SDA信号进行一个依据I2C协议的串并转换发送到e2prom_rwctrl模块中;
  4. e2prom_rwctrl模块接收到的所有rd_data[07:00]缓存到读fifo中,然后以先进先出的原则依次发送给uart_tx模块;
  5. uart_tx模块将接收到的每一个rd_data[07:00]进行并串转换,然后发送到上位机中,在发送途中拉高busy信号,表示tx线已被占用:等我发完这个字节你这个fifo再传下一个进来。

以上便是本次项目全部代码的真谛,🤯顿悟这个流程后再写代码就不难了。

3. 程序框图

image-20220724210433558

4. 状态机

根据主状态机产生时钟的原则,i2c_interface模块为主状态机,e2prom读写控制模块为从状态机。

4.1 从状态机

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值