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

目录

  • 一、IIC 原理
    • 1.1 概述
    • 1.2 写操作
    • 1.3 读操作
    • 1.4 总线数据传输时间
  • 二、项目设计
    • 2.1 概述
    • 2.2 状态机
    • 2.3 波形仿真
    • 2.3 效果演示

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

一、IIC 原理

1.1 概述

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

1.2 写操作

比特写:

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

页写:

  • 页写过程图:
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第11张图片
    相比较于比特写,无非就是多增加了几个数据而已,只有当从机发送了 ACK 信号之后,主机再发送 STOP 信号
    这样就完成了页写的操作
    如果写了超过 16 个比特的数据,那么就存储最后发送的 16 个比特到数据块中

1.3 读操作

当前地址读:

  • 读控制字节图:
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第12张图片
    流程:主机先发送一个 START,然后主机再发送一个控制字节,然后从机发送一个比特数据,然后主机再发送一个 NACK 信号,再发送一个 STOP 信号
    相比较于写控制字节,读控制字节只是 B0 后面的那个 bit 为 1,1 表示读操作,0表示写操作
    256×8 这么大的数据块,发送哪一个比特数据呢?
    比如说:前面写了 n 个字节数据,数据指针最后指向的是 n+1 的地址,现在再读一个字节数据,那么从机发送的数据,就是 n+1 地址的数据,然后指针再指向 n+2,等待下一次操作(上图中应该是 n+1 )

随机读:

  • 随机读结构:
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第13张图片
    流程:主机先发送一个 START,然后主机再发送一个控制字节,然后从机发送一个 ACK 信号,主机再发送一个地址字节,从机再发送一个 ACK 信号,主机再发送一个 START 信号,主机再发送一个控制信号,从机发送一个 ACK,从机发送一个比特数据,主机发送一个 NACK,最后主机发送一个 STOP 信号
    说明:这个过程必须搞清楚,前面两个字节是为了将地址写入 FPGA 中,赋值给地址指针,然后再发送一个读控制读取数据

顺序读:

  • 结构图:
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第14张图片
    和前面随机读的区别就在于,主机接收多个字节后,再发送 NACK 信号,也就顺序接收多个字节了

1.4 总线数据传输时间

  • 先来看看图,这表示 START 信号、一个 bit 数据的保持与变化以及 STOP 信号的时长约束
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第15张图片
    先讲讲每个部分的意义吧,自己再结合下面的表格对上相应的时长
  • 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 上升沿的时长
  • 上面每个序号所需的时长约束表(不要觉得是英文就头大哈,工作时读的手册大多都是英文的)
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第16张图片
  • 结合上面讲的部分,可以比较详细的知晓其中每一段的意义,再集合表格就知道每一个地方需要大概多大的时长,结合电气标准这里我们用红框内的部分
  • 举个例子: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 有整个工程,自行下载
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第17张图片

系统设计:

  • 模块设计图
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第18张图片

2.2 状态机

  • 这里我采用三段式状态机的方式实现,比较好理解一点
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第19张图片
  • 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                 ;

2.3 波形仿真

  • 安装了 ModelSim 后,双击 bat 文件即可开始仿真
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第20张图片
    基于 FPGA 使用 Verilog 实现 IIC(I2C) 协议回环数据传输_第21张图片

2.3 效果演示

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

  • 原始数据:
    17(16 进制表示,10 进制为 23)
    a01b0102030405060708090a0b0c0d0e0f101112131415
    a0为设备地址
    1b为数据块地址
    后面的都是数据
  • 当写入数据超过 16 个时,只存入了最后 16 个字节数据,数码管也在滚动显示这 16 个字节数据
  • 读数据时,先写入两个字节(一个写控制字节、一个地址字节),然后再输入需要读取的数据长度即可

你可能感兴趣的:(fpga开发,IIC)