• 基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输


    本文内容:本文主要基于一篇外文手册 24AA04/24LC04B 设备,采用 IIC 协议进行数据传输,用 FPGA 模拟从机 24AA04/24LC04B,PC 为主机进行数据传输,深入学习 IIC 协议

    一、IIC 原理

    1.1 概述

    • 根据 24AA04/24LC04B 手册,可以知晓该设备采用 100kHz 或者 400 kHz 的速度进行数据传输,同时有一个 16 字节的缓存器,所以项目中要定义一个 16 字节的缓存器
      在这里插入图片描述
    • 同时需要定义两块 256×8 的数据块
      在这里插入图片描述
    • 管脚种类:VCC、GND、SCL、SDA
      VCC:电源
      GND:接地
      SCL:时钟线
      SDA:数据传输单总线
    • IIC 协议采用同步时钟半双工的方式运行
      在这里插入图片描述
    • 从上图可以看出,用 FPGA 模拟从机时,同步时钟信号由 PC 上位机传输过来
    • SDA 数据传输为单总线的方式,当主机发送数据时,SDA 单总线由主机占用,当从机发送数据时,SDA 单总线由从机占用

    1.2 写操作

    比特写:

    • 比特写的方式如下,记住这个图,下面逐段讲解
      在这里插入图片描述
    • 首先由主机发送一个 START 信号给从机,让从机知道主机要送数据过来了
    • START 信号
      在这里插入图片描述
      当 SCL 为高电平的时候,SDA 从高电平跳变为低电平,则标志着有 START 信号
      从机就进入接收主机发送的数据的状态
    • Control Byte 字节
      在这里插入图片描述
      IIC 协议传输数据时,先发送字节的高位,再发送字节的低位,先高后低
      先发送 1010 ,这四个 bit 表示 24AA04/24LC04B 设备地址,固定的
      再发送 xxB0,这三个 bit 前两个无所谓,B0 表示哪一个数据块,0 表示第 0 个 256×8 数据块,1 表示第 1 个 256×8 数据块
    • ACK 信号
      在这里插入图片描述
      前面所有的 bit 都是由主机发过来的
      而 ACK 由接收设备发出,现在主机是发送设备,FPGA 为接收设备,所以现在是由 FPGA 发出 ACK 信号
      如果 FPGA 作为发送设备,PC 作为接收设备,那么就由 PC 发出 ACK 信号
      接收设备每接受到一个字节,就要发送一个 ACK 信号,它是低电平
    • Word Address 字节
      在这里插入图片描述
      写控制字节后面一定是跟上一个地址字节
      这个字节表示,256×8 数据块的地址,范围为 0——255
    • Data 字节
      在这里插入图片描述
      一个 8 bit 的数据,先高后低
    • STOP 信号
      在这里插入图片描述
      当 SCL 为高电平的时候,SDA 从低电平跳变为高电平,则标志着有 STOP 信号
      从机就进入空闲状态,没数据接收了

    页写:

    • 页写过程图:
      在这里插入图片描述
      相比较于比特写,无非就是多增加了几个数据而已,只有当从机发送了 ACK 信号之后,主机再发送 STOP 信号
      这样就完成了页写的操作
      如果写了超过 16 个比特的数据,那么就存储最后发送的 16 个比特到数据块中

    1.3 读操作

    当前地址读:

    • 读控制字节图:
      在这里插入图片描述
      流程:主机先发送一个 START,然后主机再发送一个控制字节,然后从机发送一个比特数据,然后主机再发送一个 NACK 信号,再发送一个 STOP 信号
      相比较于写控制字节,读控制字节只是 B0 后面的那个 bit 为 1,1 表示读操作,0表示写操作
      256×8 这么大的数据块,发送哪一个比特数据呢?
      比如说:前面写了 n 个字节数据,数据指针最后指向的是 n+1 的地址,现在再读一个字节数据,那么从机发送的数据,就是 n+1 地址的数据,然后指针再指向 n+2,等待下一次操作(上图中应该是 n+1 )

    随机读:

    • 随机读结构:
      在这里插入图片描述
      流程:主机先发送一个 START,然后主机再发送一个控制字节,然后从机发送一个 ACK 信号,主机再发送一个地址字节,从机再发送一个 ACK 信号,主机再发送一个 START 信号,主机再发送一个控制信号,从机发送一个 ACK,从机发送一个比特数据,主机发送一个 NACK,最后主机发送一个 STOP 信号
      说明:这个过程必须搞清楚,前面两个字节是为了将地址写入 FPGA 中,赋值给地址指针,然后再发送一个读控制读取数据

    顺序读:

    • 结构图:
      在这里插入图片描述
      和前面随机读的区别就在于,主机接收多个字节后,再发送 NACK 信号,也就顺序接收多个字节了

    1.4 总线数据传输时间

    • 先来看看图,这表示 START 信号、一个 bit 数据的保持与变化以及 STOP 信号的时长约束
      在这里插入图片描述
      先讲讲每个部分的意义吧,自己再结合下面的表格对上相应的时长
    • 7 与 6 的交界处就是一个 START 信号的产生,7 表示 SCL 上升沿来了后,必须保持 7 对应的时长才产生 START 信号,再保持 6 对应时长的低电平
      10 与 12 的交界处就是一个 STOP 信号的产生,10 表示 SCL 上升沿来了后,必须保持 10 对应时长才产生 STOP 信号,再保持 12 对应时长的高电平
      5 与 4 表示 SCL 信号边沿的持续时长
      3 表示 SCL 低电平的保持时长
      2 表示 SCL 高电平保持时长
      8 表示 SDA 电平变化点距离SCL 下降沿的时长
      9 表示 SDA 电平变化点距离 SCL 上升沿的时长
    • 上面每个序号所需的时长约束表(不要觉得是英文就头大哈,工作时读的手册大多都是英文的)
      在这里插入图片描述
    • 结合上面讲的部分,可以比较详细的知晓其中每一段的意义,再集合表格就知道每一个地方需要大概多大的时长,结合电气标准这里我们用红框内的部分
    • 举个例子:7 与 6 的交界处就是一个 START 信号的产生,其中 7 必须 > 600 ns,6 必须 > 600 ns,其它的就不一一例举了

    二、项目设计

    说明:时间不太充裕,就写这么多了,源码也有些注释,信号的命令也中规中矩,语块分明,也比较容易理解哈

    2.1 概述

    功能需求:

    • 主机可以发送一个或多个 byte 数据,从机能成功缓存,并写入 2×256×8 的数据块中
    • 主机发送超过 16 byte 的数据,则只将最后 16 byte 数据写入数据块中
    • 主机发送读控制信号后,从机能发送相应长度的数据
    • 从机写入数据块中的所有数据,能够在数码管上滚动显示出来

    器件需求:

    • 硬件:USB 转 IIC 模块
    • 软件:USB2I2C_CN.exe 用于 PC 发送 IIC 协议数据给 FPGA

    项目工程:https://github.com/zcj-debug/IIC_2_256_8_data_blocks

    • 我的 github 有整个工程,自行下载
      在这里插入图片描述

    系统设计:

    • 模块设计图
      在这里插入图片描述

    2.2 状态机

    • 这里我采用三段式状态机的方式实现,比较好理解一点
      在这里插入图片描述
    • IDLE:从机没有干任何事,空闲状态
    • START:从机检测到 SDA 中的 START 信号后,进入 START 状态
    • CTRL_BYTE:从机开始接收一个 byte 的控制字节
    • ADDRESS_BYTE:控制字节为写控制,则进入接收地址字节状态
    • SEND_DATA:控制字节为读控制,则进入发送数据状态
    • RECEIVE_DATA:接收完地址字节后进入接收数据状态
    • STOP:从机接收到 NACK 或者 STOP 信号后进入 STOP 状态

    独热码:

    parameter           IDLE            =   7'b000_0001                 ,
                        START           =   7'b000_0010                 ,
                        CTRL_BYTE       =   7'b000_0100                 ,
                        ADDRESS_BYTE    =   7'b000_1000                 ,
                        SEND_DATA       =   7'b001_0000                 ,
                        RECEIVE_DATA    =   7'b010_0000                 ,
                        STOP            =   7'b100_0000                 ;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    2.3 波形仿真

    • 安装了 ModelSim 后,双击 bat 文件即可开始仿真
      在这里插入图片描述
      在这里插入图片描述

    2.3 效果演示

    FPGA从机实现IIC协议数据传输

    • 原始数据:
      17(16 进制表示,10 进制为 23)
      a01b0102030405060708090a0b0c0d0e0f101112131415
      a0为设备地址
      1b为数据块地址
      后面的都是数据
    • 当写入数据超过 16 个时,只存入了最后 16 个字节数据,数码管也在滚动显示这 16 个字节数据
    • 读数据时,先写入两个字节(一个写控制字节、一个地址字节),然后再输入需要读取的数据长度即可
  • 相关阅读:
    zookeeper+kafka消息队列群集部署
    ChatGPT高级数据分析功能
    Codeforces Round #813 (Div. 2)A-E1
    42.集群调优策略—Index 写调优-1
    webhook--详解(gitee 推送)
    【计算机视觉 | 图像模型】常见的计算机视觉 image model(CNNs & Transformers) 的介绍合集(九)
    线性代数学习笔记4-5:求解线性方程组
    uniapp H5生成画布,插入网络图片。下载画布
    【面试题精讲】Java包装类缓存机制
    GitLab CI/CD 持续集成/部署 SpringBoot 项目
  • 原文地址:https://blog.csdn.net/ssj925319/article/details/126427237