FPGA和USB3.0通信-UVC摄像机

2021-12-05 10:12:36 浏览数 (1)

FPGA和USB3.0通信-UVC摄像机

本次演示用的是USB3.0芯片-CYPRESS CYUSB3014(下称 FX3),该芯片是标准的USB3.0 PHY,可以大大简化使用USB通信时FPGA的设计,主需要使用状态机进行FIFO的读写控制即可,同时该芯片还具有ARM核 I2S、I2C、SPI、UART等接口,大大增加了该芯片的使用范围。

FX3应用中后半部分测试已经完成暨FX3和PC之间的通信:

接下来就是通过FX3这个“桥梁”实现FPGA与PC之间的通信。

上面基本把各个通信都打通了,本节将从零开始一步一步搭建一个工业摄像头(入门版本)。

其实不需要FPGA,使用单独的FX3即可实现一个UVC摄像头,具体代码及教程(中英文都有)可以查看官方:

AN75779 - How to Implement an Image Sensor Interface Using EZ-USB® FX3™ in a USB Video Class (UVC) Framework

官方的架构如下:

但是这不符合我们的设计要求,考虑到ISP等处理,我们还是需要FPGA参与(还是需要参考官方历程的),所以下面就开始我们UVC的设计之路。

方案设计

首先上电第一步需要通过SCCB(类I2C)接口对摄像头进行初始化操作,这里有两种方式:一种是使用FPGA以查找表方式逐个写入摄像头中;第二种方式就是通过软核(Xilinx MicroBlazeAltera NISO II)对摄像头进行配置,这里厂商都是推荐软核进行配置,不仅灵活还节省资源。我们还是“头铁”的使用RTL进行配置,配置完成后摄像头将输出RAW数据,接下来FPGA将信号采集到内部进行接下来的操作。

在内部,视频数据先要经过一个FIFO,进行时钟域转换,接着RAW数据经过一个Xilinx的IP核(RAW转RGB),然后在转换成YUV(RGB转YUV),最后通过FIFO写入到DDR中,最后通过FIFO读出来的数据转换成可以传输进FX3的固定格式视频,PC端就可以通过一些UVC摄像头软件采集到摄像头(OV5640)数据。

PS:关于上面的一些术语,像RAW数据、RGB、YUV等可以查看《ISP(图像信号处理)算法概述、工作原理、架构、处理流程》。

上面方案以FPGA为核心的话,需要三个个部分:1、FPGA和FX3之间通信;2、FPGA和OV5640;3、FPGA和DDR。

其中最简单的是FPGA和DDR,使用官方IP核即可;

FPGA和FX3通信我们参考官方:

AN75779 - How to Implement an Image Sensor Interface Using EZ-USB® FX3™ in a USB Video Class (UVC) Framework

文档即官方UVC摄像头应用,只不过把摄像头换成FPGA即可(后面会有详细框图)。

FPGA和OV5640通信也是比较简单的,网上很多配置寄存器的文件,参考一下即可。

重点就是FPGA和FX3通信。

数据流分析

很多人觉得上面的流程比较繁琐,直接RAW转RGB(常规的转换,RAW数据大部分都需要转换成RGB数据再进行后续的处理)进行传输就好了,何必还转换成YUV呢?

其实这种固定传输的接口数据流最好分析了,不论后续时SDI接口、CameraLink接口、HDMI接口,还是我们这次UVC传输的USB接口,这些接口都是非常标准的接口,需要输出的数据都是标准的,我们这次使用的UVC传输的USB接口,就是传输的YUV422非压缩颜色格式数据,所以我们最后传输的就是YUV422数据。

PS:这里需要的YUV数据格式如下:

亮度值 Y 是为所有像素采样的,而色度值 U 和 V 是仅针对偶像素进行采样的。也就是说,在解析端,每个像素都由独立的亮度值 Y,而每 2 个相邻像素需要共用 1 个色度值 U 和 V。例如,我们以数字代表第几个像素,那么头 6 个像素的数据采样值为:

代码语言:javascript复制
Y0、U0、Y1、V0 (头两个像素)
Y2、U2、Y3、V2 (接下两个像素)
Y4、U4、Y5、V4 (接下两个像素)

整个数据流最开始就是RAW数据-->XXX-->YUV422,而摄像头输出也是RAW RGB数据,所以第一步是:RAW RGB--> RGB,第二步就是RGB--> YUV422.

OV5640数据手册

FPGA和FX3通信

下面再把官网的应用摘抄下来:

修改一下:

FX3固件编译

固件参考 Cypress 的应用笔记 AN75779

GPIF II接口设置

打开桌面应用程序

打开工程

选择

XXXfirmwarecyfxuvc_an75779fx3_uvc.cydsn

在官方的文件基础上去掉I2C(官方是直接接摄像头,需要通过I2C对摄像头进行配置),我们的配置是通过FPGA进行配置的,所以就不需要I2C。其他都不变

Build--> Build setting

就设置OutPut Location(理论任何位置都可以,方便分类我们放到工程文件夹下):

Build--> Build Project

会在OutPut窗口提示编译成功:

会在设置的文件下产生我们需要的配置头文件

将上面的文件拷贝到《AN75779》SDK工程文件夹下,替换原来的文件。

产生所需要的FX3固件

打开SDK

右击--Import ,导入工程

按照下图设置,点击【Next】

点击【Browse】选择刚刚复制配置头文件的工程文件夹。

会识别到工程,然后勾选选择,点击【FINISH】

选中工程,Project-> Build All

等待编译完成,会输出下列打印信息。

会在Debug文件下产生我们所需要的固件。

下载固件

选择FX3启动模式从【USB启动 】,插入PC的USB3.0接口:

设备管理器的信息。

启动Control Center

选中需要下载的设备,Program-->FX3-->SPI Flash

选择刚刚生成的固件

查看进度:

看到下图的提示,表示下载成功。

断电重启,设备管理器里就可以看到摄像头设备:

关于SDK中的一些修改及配置,请参考Cypress官方AN75779 - UVC图像采集应用笔记。

内有中文版详细说明,篇幅有限请自行查看。

FPGA端RTL设计

这部分主要参考《FPGA和USB3.0通信-联合测试(一)》中的同步时序,这里贴一下:

对于这次应用主要使用写应用,写应用的时序如下:

  • 1.FIFO地址稳定且SLCS#信号被激活。
  • 2.外部主设备/外设将数据输出到数据总线上。
  • 3.SLWR#被激活。
  • 4.当SLWR#被激活时,数据将被写入到FIFO内,并且,FIFO指针将在PCLK的上升沿上递增。
  • 5.从时钟的上升沿起,经过tCFLG的延迟后,FIFO标志将被更新。

突发写入时将发生相同的事件序列。

注意:在突发模式下,SLWR#和SLCS#在整个突发写入过程中保持激活状态。在突发写入模式下,SLWR#被激活 后,每当PCLK的上升沿到来时,都会将数据总线上的值写入到FIFO内。此外,FIFO指针也在PCLK的每个上升沿 上得到更新。

短数据包:通过PKTEND#信号可将某个短数据包发送到USB主机。需要设计外部器件/处理器,使之在传输最后数据 字时同时激活与该字相应的SLWR#脉冲和PKTEND#。PKTEND#激活期间,FIFOADDR需要保持不变。同时激活 PKTEND#和SLWR#时,GPIFII状态机会将数据包视为短数据包,并将其发送到USB接口。如果协议不要求传输任 何短数据包,则PKTEND#信号可被置高。

请注意,执行读操作时,没有任何具体信号表示已从USB获取了短数据包。空标志必须由外部主设备监控,以确定读 取完所有数据的时间。

零长度数据包:外部器件/处理器可仅通过激活PKTEND#,而没有激活SLWR#来传输一个零长度数据包(ZLP)。必须驱动SLCS#和地址,如图5所示。

标志使用情况:外部处理器监控标志信号来控制流量。标志信号由EZ-USBFX3器件输出。通过配置各标志,可显示 专用线程或当前寻址线程的空/满/局部状态。

上面是针对写FIFO时序进行说明,针对UVC使用时还需要注意视频帧格式传输,我们上面分析了FX3 UVC是属于YUV422格式,格式的具体分析上面也有了。

通过上面图片我们知道这次应用FPGA和FX3的引脚关系,具体说明如下:

信号名

功能描述

FX3 引脚

FV

帧有效(表示帧的开始和结束)

GPIO[29]

LV

行有效(表示行的开始和结束)

GPIO[28]

PCLK

像素时钟(即同步接口的时钟)

GPIO[16]

Data[7:0]

8bit位宽的图像数据

DQ[7:0]

具体时序如下:

PS:大家记住FV LV等信号定义,这在视频处理领域是非常常见的。

FPGA和摄像头通信

摄像头配置

上电第一步就是配置摄像头,这次设计使用寄存器进行配置,配置参数参考《CrazyBingo》曾经的OV5640寄存器配置:

这部分整体思路就是通过查找表上电后将寄存器通过SCCB接口一个一个写入OV5640中,其他的摄像头网上也有配置好的寄存器文件,自行查找替换即可。

读取摄像头数据

配置完成摄像头就需要读取摄像头数据,我们只需要按照下面的时序写进FIFO即可。

FPGA主要RTL模块说明

RGB 转 YUV 说明

这部分在之前分享的《视频技术手册》中有详细说明,这里截图一下:

如果R'B'G'数据的取值范围为0~255(计算机体系中是这样),公式需要在后面 128,经过一些测试及更改,目前的公式变成:

FPGA实现时,无法对小数进行操作,所以要对计算进行放大,然后计算结果再缩小即可:

工程使用说明

连接相应的硬件,下载程序到FPGA中,通过VIO选择相应的输出源(1:输出16阶灰色;0:摄像头输出。为了对比方便看摄像头输出)。

PC端打开AMCap(收费,好用), VirtualDUB(开源,地址:http://virtualdub.sourceforge.net/):

AMCap:

只需要在Devices-->FX3就可以显示我们输出到PC端视频了。

VirtualDUB:

运行上图中的程序;

菜单 Fil --> Capture AVI…

菜单 Device-->FX3 (DirectShow)

视频效果:

VIO选择1:输出16阶灰色

VIO选择0:输出摄像头数据

PS:如果上述两个软件选择不了FX3,请先检查设备管理器里有没有识别到FX3,如果没有请查看之前的文章把硬件测试做一下。

总结

最后在说明一下上面的操作其实是没必要的,摄像头是直接可以输出YUV422的(这种应用就是为什么摄像头可以直接和FX3对接的原因),我们是为了后续的视频处理才选择RGB(很多算法都是基于RGB颜色空间)。

这一些列文章就结束了,由于作者水平有限,不免有些错误,大家可以留言说明,谢谢大家支持。

所有的资料及工程都在下面的链接里:

https://github.com/suisuisi/FPGAandUSB3.0

相应的系列文章都在WIKI里。

https://github.com/suisuisi/FPGAandUSB3.0/wiki

0 人点赞