基于IIC协议的EEPROM读写测试

目录

一.EEPROM简介

二.IIC协议

 2.1物理层

 2.2协议层

2.3IIC器件地址 

2.4IIC读写操作种类

2.5IIC读写时序

三.系统整体模块设计 

四.代码解读 

4.1  I2C_dri模块代码解读

4.2E2PROM_rw模块代码解读

 4.3result_led灯模块

五.Modelsim仿真

5.1写操作分析

 5.2读操作分析

六.板级验证


一.EEPROM简介

           PROM:只能写一次数据;

           ROM:只读不写;

           EPROM:可写可擦除,但是需要固定编辑器对其改写。

           EEPROM:(Electrically Erasable Programmable Read Only Memory)带电可擦可编程只读存储器。

           本实验中用到的启明星开发板中所带的EEPROM是ATMEL 公司生产的 AT24C 系列的 AT24C64 这一型号,AT24C64 具有高可靠性,可对所存数据保存 100 年,并可多次擦写,擦写次数达一百万次。AT24C64 采用两线串行接口的双向数据传输协议——I2C 协议实现读写操作。

二.IIC协议

 2.1物理层

       I2C 即 Inter-Integrated Circuit(集成电路总线),是一种简单、双向、二线制总线标准,多用于主机和从机在数据量不大且传输距离短的场合下的主从通信。I2C 总线由数据线 SDA(双向) 和时钟线 SCL 构成通信线路,如下图所示。I2C 器件一般采用开漏结构与总线相连。开漏结构指的是低电平时照常拉低,高电平时由上拉电阻拉至高电平。

    

         

 2.2协议层

     2.2.1整体时序协议

         SCL是时钟线,SDA是数据线。

        当未传输数据时,SCL和SDA均为高电平,因为会被上拉电阻拉至高电平。

        当传输数据时,当SCL中的CLK为高电平时,不允许SDA上的数据发生变化;当SCL中的CLK为低电平时,允许SDA上的数据发生变化。

2.2.2具体时序图 

         首先我们需要知道两点,第一:SCL,SDA未传输数据为高电平;第二:SCL为高电平的时候SDA数据不能发生变化,但是,两点除外,起始信号和停止信号。

        当起始信号(低电平)来临时,在1~8个时钟的低电平处改变传输数据进行发送,当第9个clk的高电平下,SDA为低电平时代表1~8个clk下传输的8bit数据是有效完成的,随后发送停止信号。

  

2.3IIC器件地址 

           器件地址相当于从器件的专属ID号(这里假设这里EEPROM中的A2,A1,A0全为0)如2.1中的图所示,当主器件(ZYNQ)发出在某个从器件(EEPROM、RTC)读/写指令时,会指定器件地址,比如主器件指定器件地址为1010000,发送到从器件上,而EEPROM将A2,A1,A0传给IIC,IIC整合成1010000,回传给主器件的器件地址也为1010000,则此时主从器件就连接成功,下一步主器件就可以在从器件上进行读写数据了。

         一句话,器件地址就是EEPROM的身份证,找到身份证就能指定这个人了 ,同理可以指定从器件。

                                                             EEPROM引脚图

2.4IIC读写操作种类

          连续写操作(页写):例如指定从第32页开始写,从第一行写到第32行结束,若此时还没来停止信号,则会重新回到第32页的第1行开始写,一直循环到停止信号来临。

          顺序读操作:例如EEPROM只有1000个地址,指定从第100个地址开始读,若停止信号没来,则继续读一直读到第1000行地址,然后返回第100行继续开始读。

2.5IIC读写时序

2.5.1单次写时序

         起始信号:当SCL为高时,SDA来低电平,代表主机发送起始信号;

         期间地址:7位期间地址加1位读写命令,总共是8位,参考2.3中的图。

         从机应答:在第9个clk发送应答信号(低电平),代表前面是有效传输。

        以上步骤完成了主机发送寻址信号,从机发送器件地址,两者相同,则可以开启后面的读写操作。

        16位地址信号:该两个字节信号是在传递从机中需要读写的地址,将指针指向该地址方便后续读写操作。

         8位数据:表示向前面指定的16位地址位写入该8位数据。

         停止信号:当SCL为高电平时,SDA变化为1,代表主机发送停止信号。

 2.5.2连续写时序 

            在连续写时,只要主寻址,从器件地址匹配,则只用发送一次16位地址,后续就可以在停止信号来临之前重复发送8位数据。

2.5.3当前地址读操作

            当主寻址从地址一致时,只需发送8位数据,无需指定16位地址。

 2.5.4随机地址读操作

             因为该操作需要指定地址,因此需要先虚写再读。虚写的目的就是将指针指向需要读数据的地址。

  

2.5.5当前地址连读操作

          因为是当前地址,故不需要传入16位地址。

2.5.6随即地址连读 

             无需赘述。

三.系统整体模块设计 

       dri_clk:驱动I2C操作的驱动时钟,I2C_dri和E2prom_rw公用该驱动时钟。

       I2c_data_r[7:0]:读到的数据,这里没有返回写的数据是因为比较都读和写的数据是否一致时,是用地址和读数据作比较的,因为该实验地址和数据都是0~256,保持同步一致。

       I2c_done:代表一次I2C操作完成。

        I2c_ack:应答信号。0表示应答,1表示未应答。

        I2c_exec:状态机驱动信号。让状态机从空闲状态进入运转状态。

        bit_ctrl:控制字地址是16位还是8位。

       I2c_rh_wl:0代表写数据,1代表读数据。

       I2c_addr[15:0]:16位字地址。

        I2C_data_w[7:0]:8位要写的数据。

        Rw_done:读写比较完成,该实验代表256位读数据和写入的数据比较完成。

        Rw_result:读写比较结果,一致灯亮,不一致灯闪烁。

四.代码解读 

4.1  I2C_dri模块代码解读

4.1.1dri_clk

             以下代码的作用就是生成驱动I2C操作的驱动时钟dri_clk=1Mhz。而系统时钟是50MHz,因此对系统分频就需要记到25的计数器。

            assign语句得到clk_divide=50,这里的>>2'd2,是/4的作用。

            else if()中的语句是得到clk_cnt=25,这里的clk_divide[8:1]和上面的作用一样,是/2。这里得到计数器25,每0~24对系统时钟翻转一次,从而得到50分频的驱动时钟dri_clk用于后续操作。

  

 4.1.2不同状态机写法比较

         一段式:整个状态机写到一个always模块里面,在该模块中既要描述状态转移,又要描述状态的输入与输出。

         二段式:用两个always语句块来描述状态机,其中一个always模块采用同步时序描述状态转移;另一个模块采用组合逻辑判断状态转移条件,描述状态转移规律以及输出。

         三段式:采用三个always语句块,一个采用同步时序描述状态转移,一个采用组合逻辑判断状态转移条件,描述状态转移规律,另外一个采用时序电路描述状态输出。

         该实验采用三段式。

4.1.3同步时序描述状态转移

4.1.4组合逻辑判断状态转移条件

        由以下状态转换图可知,一共有8种状态。分别是

       空闲状态:                         st_idle;

       写控制命令:                      st_sladdr;

       发送16位字地址的高8位:  st_addr16;

       发送16位字地址的低8位:  st_addr8;

       写数据:                              st_data_wr;

       读控制命令:                      st_addr_rd;

       读数据:                             st_data_rd;

       停止状态:                         st_stop.

 4.1.5时序电路描述状态输出

4.1.5.1空闲状态

          当状态是初始状态时,所有值赋初值。

          scl:I2C中的SCL时钟,该实验中为25KHZ.

          sda_out:主机FPGA发送的数据。

          sda_dir: 表示I2C数据方向,为1时表示主机(FPGA)输出信号,为0时FPGA输出高阻态,表示释放控制权。接收从机发来的信号。

          i2c_done:I2C一次操作完成。

          cnt:帮助I2C一次操作中的索引值。

           当I2C触发执行信号来临时,e2prom_rw模块传来读/写控制位,16位字地址,8位写数据。即3系统整体模块设计中的以下数据。

 4.1.5.2写控制命令

            在4.1.5.1中已经描述过,I2C中的SCL的时钟是25Khz,也就是I2C的驱动时钟的四分频,因此,scl在cnt下,每隔两个数翻转一次,即可得到四分频的SCL。

  

                                                                写控制命令波形图 

                 每次在SCL的低电平时期传输器件地址,即cnt=4、8、12...时将器件地址赋值给sda_out,该实验的器件地址是1010000,在第8个SCL下,传送写控制信号。

                  在cnt=36时,即第9个SCL时钟信号,sda=0,释放控制权。接收从机发来的应答信号。sda_in代表从机发送来的应答信号,为1表示未应答,为0表示应答。

                  在cnt=39时,代表从机应答结束,一次I2C操作完毕,将SCL清零,同时帮助数据操作的索引值cnt也清零。

4.1.5.3 发送16位字地址的高8位

             同4.1.5.2中发送器件地址数据一样,只不过这里是发送高8为字地址。

 4.1.5.4发送8位字地址的低8位

 4.1.5.5写数据

 4.1.5.6读数据之读命令

          相当于下图中的红色框内的步骤,因为读数据在经历过虚写操作后,需要重新传入器件地址以及读命令。

 4.1.5.7读数据

        需要注意,读数据时,sda_dir=0,因为要从从器件中读取数据,故要释放总线,接收数据。

         注意:cnt=32时,sda_dir=1,sda_out=1,为主机非应答,因为看下图,如果主机应答,此时E2PROM会将指针继续指向下一个地址,从而继续读,防止继续读。

4.2E2PROM_rw模块代码解读

4.2.1写字节

          case前面两行:因为i2c_exec,rw_done信号只在某case语句中出现,发生改变,这里赋值为0是确保该值只在case中有效,也就是确保其为脉冲信号。

           wait_cnt:因为当E2PROM写数据时,每两个地址之间要间隔一会,这里间隔5ms。本模块中采用的时钟是dri_clk=1Mhz,Tclk=1us,5ms/1us=5000,故WR_WAIT_TIME=5000。

           2'd0中,每当间隔5ms后,判断写地址是否到达最大值256,当小于该值时,i2c_exec=1表示启动4.1模块中的状态机,跳转到2'd1.

           2'd1中,分别将写地址和写数据同步加1,并将这些控制信号传入到4.1.5.1模块中,控制E2PROM写入数据。

          i2c_addr==MAX_BYTE:表示256(0~255)个字节写入完成,到256时,将地址清零,读/写控制信号改为读信号,状态转换至2'd2。

 4.2.2读字节

       2’d2:  当256个字写完后,进入该状态,i2c_exec=1,启动4.1模块中的状态机转换,同时将读信号传给4.1模块,此时,状态机完成写器件地址,写字节地址(这里字节地址为0,因为4.2.1中当256个字节写完后地址赋值为0),读数据传给2'd3进一步操作。

       2’d3: 这里直接i2c_addr[7:0] != i2c_data_r是因为写数据和地址是同步赋值的,因此其值完全相等,所以就用地址代替写数据了。注意第一次比较只是比较了写入的第一个数据(总共256个),因为只要256个字中的任何一个不相同,整体的就不相同。但是当第1位相同时继续比较第二位直到第256位。当256位都相同时,rw_result=1.

 4.3result_led灯模块

        rw_done_flag:因为4.3模块中的rw_done信号是脉冲信号,不易处理,因此引入该信号。恒常值。

       led_cnt:125000x1us=125ms,灯闪烁时间是125ms。

       led:读写结果一致,灯常亮;不一致,灯闪烁。

五.Modelsim仿真

5.1写操作分析

           整体分析,仿真中进行了3次写操作,每次写操作间隔5ms。

           当写如第一个字节时,首先 4.2模块发出i2c_exec信号,以启动4.1模块中的状态机开始运转,同时向4.1模块传入以下信号,则4.1模块开始进行写操作,如图中标识的1、2、3、4所示,1中进行传输7位器件地址+一位写命令(i2c_rh_wl=0),2和3中传输16位字地址,因为这里是写第一个字,因此地址为00...00,写入的数据也为00..00。

                当写入第二个字节时,可以看出3中的地址变为00...01,4中的数据也变为00...01。

 5.2读操作分析

      首先读地址0里面的数据,1,2,3为需写步骤,4为传输7位器件地址+1位读操作(i2c_rh_wl=1),5为读数据,读出的数据为00..00,在5中的第9个scl下,sda拉高,这意味着主机非应答。结合2.5.4的图,一致。注意:3和4之间有一个scl空着,这里因为读操作在需写完成后要重新发送一次起始信号。

       接着读第三个数据,可以看出5中读出的数据为00..10,此时i2c_addr=2,意味着读和写数据一致,因此rw_result为高,与设计一致。

六.板级验证

      读写数据一致,led常亮。

  • 10
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值