【I2C】基于SystemVerilog的16比特I/O拓展芯片TCA6416A读写控制

功能简介

  本文基于Xilinx Virtex Ultrascale+HBM VCU128 FPGA开发板,通过利用开发板上的TCA6416A芯片,对I2C通信方式进行学习。
  根据VCU128用户手册,128中具有两条I2C总线,其中一条连接有4个I2C芯片,能够与系统监视器(SYSMON)、EEPROM、QSFP等硬件资源进行通信。
图片

  根据手册介绍,TCA6416A芯片为I/O拓展芯片,PCA9544A、PCA9548A芯片为1-4、1-8通道总线交换芯片。两块TCA9548A芯片的使用需要先保证TCA6416A芯片的ICC_MUX_RESET-B引脚为高阻态或高电平,因此本文对利用FPGA控制TCA6416A芯片的I2C通信进行介绍。
  在实际使用中,Xilinx配置TCA6416A芯片的ADDR引脚为0,在FPGA上访问TCA6416A芯片的SCL、SDA引脚可通过如下约束设置,对应BANK67的BL28、BM27引脚。

set_property BOARD_PART_PIN IIC0_SCL_MAIN [get_ports i2c_0_scl]
set_property BOARD_PART_PIN IIC0_SDA_MAIN [get_ports i2c_0_sda]

TCA6416A芯片介绍

  TCA6416A为TI公司生产的I2C转16比特I/O拓展芯片,芯片手册,该芯片能够利用I2C协议进行16个通用引脚(分为2组:P00-P07,P10-P17)的读写访问,每个引脚支持设置为输入、输出两种模式。
图片

  ADDR引脚用于设置TCA6416A的I2C通信地址,如下图所示,TCA6416A的地址包含一个可编程位,在VCU128中,该位被设置为0。
图片

  TCA6416A的I/O Port为2组8比特通用IO引脚,在通过I2C通信进行使用时会通过8种指令读写8个寄存器,进而实现IO引脚的间接访问。这些操作会通过组的形式对2组8比特IO引脚进行访问。
图片

  在使用时,TCA6416A的I2C总线包含标准模式、快速模式两种,其中标准模式下SCL的时钟频率不能超过100KHz,快速模式下SCL的时钟频率不能超过400KHz。本文使用标准模式,时钟频率100KHz。

I2C发送端逻辑实现

  I2C是一种采用报文方式传输的串行通信方式,每次发送过程包含一个发送端和一个接收端。从发送端角度看由输出引脚SCL与输入输出引脚SDA构成,其中SDA为每次传输的数据,SCL为代表每次传输数据有效的高电平有效选通信号(时钟信号)。除了报文的开始位和结束位以外,SDA只能在SCL为低电平时发生变化,在SCL为高电平时应保持不变。
图片

  I2C传输的报文格式如下,包含1个开始位(S)、8个数据位(1个字节)、1个确认位(ACK)、1个停止位(P)。开始位由发送端发送,在发送完成后,可以进行多次数据位、确认位的交替传输,在最终交互完成后,由发送端发送停止位表示本次通信结束。在发送端发送完8个字节数据后,接收端会占用SDA发送确认位用于表明当前状态,类似一种响应信号。发送端可以根据接收端发送的确认位决定下一步的行动。
图片

  对于TCA6416A芯片,I2C传输可分为两种类型的操作。

写操作

  根据手册,对于TCA6416A芯片的写操作格式如下,Target Address为TCA6416A芯片的地址,Command Byte为本次访问的操作名称,后续Data0、Data1为写入的数据。下图展示了利用0x20指令写端口0的指令。
图片

  下面展示了进行I2C写操作的状态机:

  always_comb begincase (fsm_r)RESET: beginif (itf_rst_done) beginfsm_s = IDLE;end else beginfsm_s = RESET;endendIDLE: beginif (single_bit_hold_flag_r) beginif (START_flag_r) beginfsm_s = ADDR_START;end else beginfsm_s = IDLE;endend else beginfsm_s = IDLE;endendADDR_START: beginif (single_bit_hold_flag_r) beginfsm_s = ADDR_DATA;end else beginfsm_s = ADDR_START;endendADDR_DATA: beginif (single_bit_hold_flag_r && pos_cnt_r == 4'd7) beginfsm_s = ADDR_ACK;end else beginfsm_s = ADDR_DATA;endendADDR_ACK: beginif (single_bit_hold_flag_r) begin// if (STOP_flag_r) beginif (1'b0) beginfsm_s = ADDR_STOP;end else beginfsm_s = CMD_DATA; // ADDR_STOP;endend else beginfsm_s = ADDR_ACK;endendADDR_STOP: beginif (single_bit_hold_flag_r) beginfsm_s = IDLE;end else beginfsm_s = ADDR_STOP;endendCMD_DATA: beginif (single_bit_hold_flag_r && pos_cnt_r == 4'd7) beginfsm_s = CMD_ACK;end else beginfsm_s = CMD_DATA;endendCMD_ACK: beginif (single_bit_hold_flag_r) begin// if (STOP_flag_r) beginif (1'b0) beginfsm_s = CMD_STOP;end else beginif (RWn_flag_r) beginfsm_s = SECADDR_START; // ADDR_STOP;end else beginfsm_s = WR_DATA; // ADDR_STOP;endendend else beginfsm_s = CMD_ACK;endendCMD_STOP: beginif (single_bit_hold_flag_r) beginfsm_s = IDLE;end else beginfsm_s = CMD_STOP;endendWR_DATA: beginif (single_bit_hold_flag_r && pos_cnt_r == 4'd7) beginfsm_s = WR_ACK;end else beginfsm_s = WR_DATA;endendWR_ACK: beginif (single_bit_hold_flag_r) beginif (STOP_flag_r) beginfsm_s = WR_STOP;end else beginfsm_s = WR_DATA;endend else beginfsm_s = WR_ACK;endendWR_STOP: beginif (single_bit_hold_flag_r) beginfsm_s = IDLE;end else beginfsm_s = WR_STOP;endenddefault: beginfsm_s = RESET;endendcaseend
读操作

  TCA6416A芯片的读操作格式如下,在进行读操作前,需要先通过写操作设置指令。使得TCA6416A芯片得知后续对哪个寄存器进行读操作。之后再利用开始位(S)重启读操作。下图展示了利用0x20指令读端口0的I2C格式。
  在读操作中,在FPGA进行I2C读操作时,后续I2C总线将由TCA6416A芯片发送8个数据位,由FPGA发送确认位(ACK),如下图所示。
图片

  下面展示了进行I2C读操作的状态机:

   always_comb begincase (fsm_r)RESET: beginif (itf_rst_done) beginfsm_s = IDLE;end else beginfsm_s = RESET;endendIDLE: beginif (single_bit_hold_flag_r) beginif (START_flag_r) beginfsm_s = ADDR_START;end else beginfsm_s = IDLE;endend else beginfsm_s = IDLE;endendADDR_START: beginif (single_bit_hold_flag_r) beginfsm_s = ADDR_DATA;end else beginfsm_s = ADDR_START;endendADDR_DATA: beginif (single_bit_hold_flag_r && pos_cnt_r == 4'd7) beginfsm_s = ADDR_ACK;end else beginfsm_s = ADDR_DATA;endendADDR_ACK: beginif (single_bit_hold_flag_r) begin// if (STOP_flag_r) beginif (1'b0) beginfsm_s = ADDR_STOP;end else beginfsm_s = CMD_DATA; // ADDR_STOP;endend else beginfsm_s = ADDR_ACK;endendADDR_STOP: beginif (single_bit_hold_flag_r) beginfsm_s = IDLE;end else beginfsm_s = ADDR_STOP;endendCMD_DATA: beginif (single_bit_hold_flag_r && pos_cnt_r == 4'd7) beginfsm_s = CMD_ACK;end else beginfsm_s = CMD_DATA;endendCMD_ACK: beginif (single_bit_hold_flag_r) begin// if (STOP_flag_r) beginif (1'b0) beginfsm_s = CMD_STOP;end else beginif (RWn_flag_r) beginfsm_s = SECADDR_START; // ADDR_STOP;end else beginfsm_s = WR_DATA; // ADDR_STOP;endendend else beginfsm_s = CMD_ACK;endendCMD_STOP: beginif (single_bit_hold_flag_r) beginfsm_s = IDLE;end else beginfsm_s = CMD_STOP;endendSECADDR_START: beginif (single_bit_hold_flag_r) beginfsm_s = SECADDR_DATA;end else beginfsm_s = SECADDR_START;endendSECADDR_DATA: beginif (single_bit_hold_flag_r && pos_cnt_r == 4'd7) beginfsm_s = SECADDR_ACK;end else beginfsm_s = SECADDR_DATA;endendSECADDR_ACK: beginif (single_bit_hold_flag_r) begin// if (STOP_flag_r) beginif (1'b0) beginfsm_s = SECADDR_STOP;end else beginfsm_s = RD_DATA; // ADDR_STOP;endend else beginfsm_s = SECADDR_ACK;endendSECADDR_STOP: beginif (single_bit_hold_flag_r) beginfsm_s = IDLE;end else beginfsm_s = SECADDR_STOP;endendRD_DATA: beginif (single_bit_hold_flag_r && pos_cnt_r == 4'd7) beginfsm_s = RD_ACK;end else beginfsm_s = RD_DATA;endendRD_ACK: beginif (single_bit_hold_flag_r) beginif (STOP_flag_r) beginfsm_s = RD_STOP;end else beginfsm_s = RD_DATA;endend else beginfsm_s = RD_ACK;endendRD_STOP: beginif (single_bit_hold_flag_r) beginfsm_s = IDLE;end else beginfsm_s = RD_STOP;endenddefault: beginfsm_s = RESET;endendcaseend

仿真测试

  仿真模拟了利用VIO输入0x02端口0引脚读写指令后FPGA的工作过程 。其中蓝色高阻态用于TCA6416A发来的响应信息。

    initial begin // write to Output Port Registerforce i2c_top_inst.CMD_vec_r    = 8'b00000010;   force i2c_top_inst.wrDATA_vec_r   = 8'h6a;force i2c_top_inst.START_flag_r = 1'b1;force i2c_top_inst.RWn_flag_r   = 1'b1;force i2c_top_inst.wrACK_flag_r   = 1'b0;force i2c_top_inst.STOP_flag_r  = 1'b1;end

图片

上板测试

  这里以0x02端口0引脚读写指令为例,进行I2C通信测试,初始状态下端口0的8个引脚值为0x77。
图片

  通过设置读写模式选择RWn_flag_r为0,指令CMD_vec_r为0x20,写数据wrDATA_vec_r为0x6A,点击START_flag_r控制FPGA发送I2C写端口0的8bit为6A。
图片

  通过设置RWn_flag_r为1,其余保持不变,点击START_flag_r控制FPGA发送I2C读端口0的8bit,得到rdDATA_vec_r结果为6A。
图片

完整代码

  工程代码可于同名公众号回复I2C_TCA6416A下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/3813.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java Web 网页设计(3)

3.servlet JavaWeb——Servlet(全网最详细教程包括Servlet源码分析)-CSDN博客 servlet java不支持 只有Tomcat支持 使用时添加一下 servlet中最常用的两个(固定)方法: 下面我们创建一个servlet类 package com.oracle…

汽车组装3D电子说明书更通俗易懂

激光打印机由于造价高、技术更先进,因此在使用和维护上需要更专业的手法,而对于普通客户来说并不具备专业操作激光打印机的技能,为了通俗易懂地让客户理解激光打印机,我们为企业定制了激光打印机3D产品说明书,将为您带…

《QT实用小工具·三十五》基于PathView,Qt/QML做的一个可以无限滚动的日历控件

1、概述 源码放在文章末尾 改项目实现了基于PathView,Qt/QML做的一个可以无限滚动的日历控件,下面是demo演示: 项目部分代码如下所示: import QtQuick 2.7 import QtQuick.Controls 1.4 import QtQuick.Controls.Styles 1.4Bu…

【最优化】牛顿法、高斯-牛顿法

一、牛顿法 1、牛顿法在一维搜索中的应用 在一维搜索中我们所要解决的问题是如何找函数f(x)的最小值。 牛顿法的核心思想是用二次函数拟合函数f(x)的某一邻域区间,用二次函数的极小值点作为下一次的迭代点。通过多次迭代使得二次函数的极小值逼近函数f(x)的极小值 …

Trivy离线扫描:容器安全实践指南

一、Trivy简介 1.1 Trivy 概述 Trivy 是一款全面多功能的安全扫描器。Trivy具有寻找安全问题和目标的扫描器。现已经被 Github Action、Harbor 等主流工具集成,Trivy支持大多数流行的编程语言、操作系统和平台的扫描,应该是该领域目前目前采用最广的开…

【React】CSS 局部样式

书写 CSS 的时候,如果 CSS 文件名包含 module,那么说明该 CSS 是一个局部 CSS 样式文件,类似于 vue 中的 scoped。 .avatarContainer {width: 40px;height: 40px;border-radius: 50%;background: rgb(213, 226, 226); }import styles from ..…

android脱壳:一种使用native进行抽取壳脱壳的方法,native版本的frida-fart

前言 写rxposed的时候,搞了很多模块,其中有一个远程调用脱壳的,但是当时使用的是rmi远程调用,因为一些问题无法使用,可能是对抗问题,也有可能是技术问题,所以我又换了一种远程调用方式。 概述…

局部多项式近似与 AMPM 算法

kappa3; %已在您的代码中定义% 定义窗口大小 windowSize (2*kappa1);% 初始化梯度估计值 [rows, cols] size(wrappedPhase); phi_y zeros(rows, cols); phi_x zeros(rows, cols);% 遍历每个窗口 for m 1kappa:rows-kappafor n 1kappa:cols-kappa% 提取局部窗口Z_mn wrap…

逆数对(树状数组的方法)

本题链接:登录—专业IT笔试面试备考平台_牛客网 题目: 样例: 输入 5 4 5 1 3 2 输出 7 思路: 根据题意,求逆序对总数。 逆序对含义:如果数组中的两个不同位置,前面的数字比后面的数字严格大&…

新建云仓库

1.GitHub新建云仓库: LICENSE:开源许可证;README.md:仓库说明文件;开源项目;cocoaPodsName.podspec: CocoaPods项目的属性描述文件。 2.Coding新建云仓库: 备注: Coding新建项目:

中文句子在线改写 2024 新版发布

句子改写在线功能上线有 1 年多了,最近上线了新版本,主要包含以下三个功能: 增加主题切换功能,提供亮色、暗黑两种模式 简化句子输入界面 句子改写记录的保存和分享 中文句子改写首页-结果页面 句子改写功能目前支持严谨、普通…

简单的jmeter脚本自动化

1、创建线程组,定义自定义变量,保存请求默认值 2、用csv编写测试用例 备注:如果单元格内本身就有引号,则格式会有点小问题,不能直接修改为csv 用txt打开后 有引号的需要在最外层多包一层引号,每个引号前…

AI 语音机器人系统怎么搭建

搭建AI语音机器人系统通常包括以下几个关键步骤: 确定需求和技术选型:首先要明确AI语音机器人需要实现的功能,选择合适的技术框架和工具,如自然语言处理工具、语音识别工具等。 搜集和准备数据:收集和整理与业务相关…

Linux 底软开发——对CAN的详细操作(周期发送,异常检测,过滤报文)

Linux底软开发—对CAN发送接收详细操作 文章目录 Linux底软开发—对CAN发送接收详细操作1.保证多条CAN数据发送的周期性2.解析CAN报文数据3.CAN总线异常机制应对4.对CAN报文进行过滤操作5.完整的接收报文代码(过滤,心跳检测,解析)…

Java之复制图片

从文件夹中复制图片 从这个文件夹: 复制到这个空的文件夹: 代码如下: import java.io.*; import java.util.Scanner;/*** 普通文件的复制*/public class TestDome10 {public static void main(String[] args) {// 输入两个路径// 从哪里(源路…

MySQL随便聊-----之认识MySQL

本专栏,用作复习,不建议小白,建议者勿看 一、了解MySQL 二、MySQL的客户端/服务器架构 以我们平时使用的微信为例,它其实是由两部分组成的,一部分是客户端程序,一部分是服务器程序。客户端可 能有很多种形…

适合弱电行业用的项目管理系统,找企智汇项目管理系统!

弱电行业,是指通信、计算机、监控、安防、智能家居等一系列与现代生活息息相关的行业。在这个行业,项目管理的重要性不言而喻。企智汇项目管理系统在弱电行业的应用中,展现出了其独特的优势和价值。该系统能够充分满足弱电工程项目的复杂需求…

基于arcpro3.0.2版的使用深度学习检测对象之椰子树

基于arcpro3.0.2版的使用深度学习检测对象之椰子树 GPU显卡Nivda 1080 训练模型图 (四)检测对象之椰子树 使用深度学习检测对象 打开 detect objects using deep learning,参数 输入栅格为要检测的影像 模型定位为上一步输出的.emd文件 cpu模式Max Overlap Ratio0.4 运行时间…

C语言----单链表的实现

前面向大家介绍了顺序表以及它的实现,今天我们再来向大家介绍链表中的单链表。 1.链表的概念和结构 1.1 链表的概念 链表是一种在物理结构上非连续,非顺序的一种存储结构。链表中的数据的逻辑结构是由链表中的指针链接起来的。 1.2 链表的结构 链表…

ROM修改进阶教程------如何去除安卓机型系统的开机向导 几种操作步骤解析

在和很多工作室定制化系统中。手机在第一次启动的时候系统都会进入设置向导,虽然可以设置手机的基本配置。但有很多客户需要去除手机的开机向导来缩短开机时间。确保手机直接进入工作状态。那么今天的教程针去除对开机向导的几种方法做个解析。机型很多版本不同。操作也有不同…