FPGA项目记录

一、Version 1: 在AD7606.v文件中采用复用8个通道数据变量的方法连续读取AD_1和AD_2

串口所使用的分频时钟clk约为 系统时钟clk50的325倍。

从状态IDLE到AD转换结束,可以开始读取数据,需要大于27个clk50;

从状态READ_CH1到READ_CH8结束,需要32个clk50;

等待ad_select从00切换到01需要20个clk50;

即:

  • 连续读取AD_1或AD_2的8个通道的数据需要32个clk50;
  • 如果单独读取一轮转换后的AD通道的数据需要大于:27+32=59个clk50;
  • 读取一轮转换后的AD_1和AD_2的8通道的数据需要大于:27+32+20+32=111个clk50;

把16位的通道数据转换为十进制的BCD码,是8个通道在一个clk50时钟下同时进行的;

然后uart模块使用分频后的时钟,在一个分频后的clk内将8个通道的数据放入一个数组内;

然后把数组内8个通道的数据一个字节一个字节的发送到串口,其中发送一个字节需要255个分频clk;

即:

数组每发送一个字节,数组就会更新至少255次,至少已经读取了255轮的AD_1和AD_2的各自8通道的数据。

所以经由串口发送到电脑的数据实际上是分不清是AD1的数据还是AD2的数据,只能分清具体属于哪个通道的数据。

二、在一的基础上,在ad7606.v、volt_cal.v、uart.v文件中修改,分离出AD1和AD2

在原来的基础上添加AD2模块的8个通道的状态,使得FPGA在数据总线上读取完AD1的数据后,再读AD2的数据,同时把数据存放再AD2的寄存器中。

注意:添加状态后需要修改state的变量类型大小,防止添加状态后超过state的表示范围。

三、二成功后,再利用FPGA板子上的J2扩展口,再接上一块一带二AD扩展板,等于同时接上四块AD模块

image-20211228201606685

现有的FPGA为EP4CE10,总的逻辑单元有10320个,最大用户I/O资源有179个;

  • uart.v 需要占用1192个逻辑单元
  • ad706_test.v需要占用6342个逻辑单元
  • ad_input.v相当于包含两个ad706_test.v需要占用13185个逻辑单元

即:现有的FPGA无法完成同时接入四个AD模块的任务。

摄像头测试

摄像头边缘检测项目总共需要2032个逻辑单元,75个IO引脚。

四个AD同时采样

image-20220106152353115

时钟为50MHZ,一个时钟周期为20ns

CONVST信号的上升沿启动对所有模拟输入通道的同步采样(V1至V8)。

两个CONVST上升沿信号之间的间隔为:

5+wait_busy+3*8(第一个AD模块8个通道依次读取数据总线的时间)+(1+3)(转换AD所需时间,实际应该比这个大)

+3*8(第二AD模块8个通道依次读取数据总线的时间)+1+20+2 >= 80个时钟周期(80 x 20ns = 1600ns = 1.6us)

把16位的通道数据转换为十进制的BCD码,是8个通道在一个clk50时钟下同时进行的;

AD7606采用+5V单电源供电, 可以处理±10V和±5V真双极性输入信号, 同时所有通道均以高达200KSPS的吞吐速率采样。即每秒钟采样200K次,每次采样时间为1/200K=0.000005s=5us

把16位的通道数据转换为十进制的BCD码,是8个通道在一个clk50时钟下同时进行的;

UART模块

采用9600波特率

然后uart模块使用分频后的时钟,在一个分频后的clk内将8个通道的数据放入一个数组内;

一个分频时钟是325个clk50,即325*20ns=6500ns = 6.5us;

一个AD模块的8通道数据存入一个以字节为单位的数组(字符数组)需要一个分频时钟。

两条发送字符数组之间的间隔时间为2的16次方个分频时钟周期,即65536个分频时钟周期,等于0.4259s,在此间隔内程序把下一个AD模块的8通道数据存入到字符数组中;

一个AD模块的8个通道数据对应一个字符数组。

综上所述:

更新字符数组

一个分频时钟周期6.5us内,可以进行最多三次所有通道的同步采样,每次至少1.6us.

但是一个分频时钟周期,才存入一次8个通道的数据到字符数组。由于有四个AD模块,都只能由一个串口tx发送,因此每个uart_ad字符数组的更新时间为3个分频时钟周期。 则本次更新的字符数组数据和上一次之间,已经经历了最多9次采样。

发送字符数组

一个字节发送为168个分频时钟,这里等待255个分频时钟,保证一个数据发送完成。总共114个字符,则需要114 x 255 = 29070个分频时钟,等于0.188955s

发送一个字符数组再加上到下一个的间隔时间为 0.188955s + 0.4259s = 0.614855s;

四个字符数组发送完成需要: 0.614855s x 4 = 2.45942s ;

即在发送字符数组的过程中,字符数组在不断的进行更新,一个分频时钟周期内最多可以进行三次所有通道的同步采样,那么从一个字符数组发送开始到其发送最后一个字符,中间至少进行了 3 x 114 x 255 = 87210 次采样。

但是由于对字符数组的赋值是在同一个分频时钟内的同一个状态字下进行的,所以可以认为一个字符数组内的8通道数据都是同一次采样所得到的数据。

即电脑上接受到的第一个字符和最后一个字符是同一次采样的结果。

但是电脑上接收到的同一AD同一个通道的数据的更新时间为四个字符数组发送完成需要的时间,即2.45942s,则若以此数据来观察动态模拟量的输入变化是极为不准确的。

采用115200波特率

分频参数计算如下:
假设数据的波特率为p,则所需时钟的频率为16*p。以波特率p为9600为例,系统时钟为50MHz,则分频系数为50000000/(16 x 9600) = 325.52,取整为326。

50000000/(16 x 115200) = 27.126,取整为28;

115200是9600的12倍,即分频时钟变为9600的12分之一。

此时一个分频时钟是28个clk50,即28 x 20 ns = 560ns,等于0.56us

发送字符数组

一个字节发送为168个分频时钟,这里等待255个分频时钟,保证一个数据发送完成。总共114个字符,则需要114 x 255 = 29070个分频时钟,等于29070 x 0.56us = 0.0162792s, 等于16.2792ms

两条发送字符数组之间的间隔时间为2的16次方个分频时钟周期,即65536个分频时钟周期,等于65536 x 0.56us = 0.0367 s

发送一个字符数组再加上到下一个的间隔时间为 0.0162792s + 0.0367 s= 0.0529 s ;

四个字符数组发送完成需要: **0.0529s x 4 = 0.2119s ;

但是数据容易丢失

在波特率115200的基础上优化

50000000/(16 x 115200) = 27.126,取整为28;

115200是9600的12倍,即分频时钟变为9600的12分之一。

此时一个分频时钟是28个clk50,即28 x 20 ns = 560ns,等于0.56us

发送字符数组

一个字节发送为168个分频时钟,这里等待180个分频时钟,保证一个数据发送完成。总共114个字符,则需要114 x 255 = 29070个分频时钟,等于29070 x 0.56us = 0.0162792s, 等于16.2792ms

两条发送字符数组之间的间隔时间为2的16次方个分频时钟周期,即65536个分频时钟周期,等于65536 x 0.56us = 0.0367 s

发送一个字符数组再加上到下一个的间隔时间为 0.0162792s + 0.0367 s= 0.0529 s ;

四个字符数组发送完成需要: 0.0529s x 4 = 0.2119s

DDR2 SDRAM读写

​ AX530开发板板载了一片高速DDR2 DRAM,型号:MT47H128M16HR-3IT,容量:2Gbit(128M*16bit)16bit总线。开发板上FPGA和DDR2 DRAM相连的是BANK3,BANK4的IO,电平是1.8V。FPGA跟DDR2之间的读写的时钟频率最高166.7MHz,数据频率最高可达333MHz

​ 在AX515/AX530开发板上使用FPGA的Bank3和Bank4跟DDR2连接,所以这两个Bank的IO电压都为1.8V。我们这里使用Bank3的2个区域DQ3B和DQ5B来连接DDR2的数据,使用DQ3B连接DDR2数据的高8位,DQS1和DM1; 使用DQ5B连接DDR2数据的低8位,DQS0和DM0。

 DDR2,全称 Double Data Rate 2 SDRAM,即第二代双倍数据速率同步动态随机存取存储器。它属于 SDRAM 家族的存储器产品,提供了相较于 DDR SDRAM 更高的运行效能与更低的电压,是 DDR SDRAM 的后继者,虽然 DDR2 和 DDR 都采用了在时钟的.上升沿和下降沿同时进行数据传输的基本方式,但是 DDR2 拥有两倍于 DDR 的预读取系统命令数据的能力(DDR2 4bit预读,DDR 2bit预读)。也就是说,在同样100MHz 的工作频率下,DDR 的实际频率为 200MHz,而 DDR2 则可以达到 400MHz。

img

  DDR2 难度比 SDRAM 复杂,直接用 IP 核比较靠谱。本篇博客记录一下 QuartusII 13.0 软件下的 DDR2 IP 核的官方例程仿真。

对SDRAM中“突发(Burst)” 的理解

突发(Burst)是指在同一行中相邻的存储单元连续进行数据传输的方式,连续传输的周期数就是突发长度(Burst Lengths,简称BL)。

http://hard.zol.com.cn/2004/0330/90618.shtml

1. 认识内存相关工作流程与参数

首先,我们还是先了解一下内存的大体结构工作流程,这样会比较容量理解这些参数在其中所起到的作用。这部分的讲述以SDRAM为例,因为时序图看起来会简单一些,但相关概念与DDR SDRAM的基本相同。

SDRAM的内部是一个存储阵列,将数据“填”进去,你可以它想象成一张表格。和表格的检索原理一样,先指定一个行(Row),再指定一个列(Column),我们就可以准确地找到所需要的单元格,这就是内存芯片寻址的基本原理。对于内存,这个单元格可称为存储单元,那么这个表格(存储阵列)叫什么呢?它就是逻辑Bank(Logical Bank,下文简称L-Bank)

img

SDRAM内部L-Bank示意图,这是一个8X8的阵列,B代表L-Bank地址编号,C代表列地址编号,R代表行地址编号。如果寻址命令是B1、R2、C6,就能确定地址是图中红格的位置.

目前的内存芯片基本上都是4个L-Bank设计,也就是说一共有4个这样的“表格”。寻址的流程也就是——先指定L-Bank地址,再指定行地址,然后指列地址最终的确寻址单元。 目前内存的读写基本都是连续的,因为与CPU交换的数据量以一个Cache Line(即CPU内Cache的存储单位)的容量为准,一般为64字节。而现有的P-Bank位宽为8字节,那么就要一次连续传输8次,这就涉及到我们也经常能遇到的突发传输的概念。突发(Burst)是指在同一行中相邻的存储单元连续进行数据传输的方式,连续传输的周期数就是突发长度(Burst Lengths,简称BL)。

在进行突发传输时,只要指定起始列地址与突发长度,内存就会依次地自动对后面相应数量的存储单元进行读/写操作而不再需要控制器连续地提供列地址(SDRAM与DDR SDRAM的突发传输对列寻址的操作数量有所不同,在此不再细说)。这样,除了第一笔数据的传输需要若干个周期(主要是之前的延迟,一般的是tRCD+CL)外,其后每个数据只需一个周期的即可获得。

突发连续读取模式:只要指定起始列地址与突发长度,后续的寻址与数据的读取自动进行,而只要控制好两段突发读取命令的间隔周期(与BL相同)即可做到连续的突发传输.

突发长度

  在 DDR 中,突发长度只有 2、4、8 三种选择,没有了突发长度 1 和全页式突发。之所以去掉突发长度 1 主要是因为 DDR 预读取位数是 2,L_BANK 一次就存取两倍于芯片位宽的数据,所以芯片至少也要进行两次传输才可以,否则内部多出来的数据很难被处理。之所以去掉全页式突发主要是因为PC内存中很难用得上。

​ 数据转换成十进制之后,一个AD模块的8个通道数据组成的字符数组大小为114字节,2Gbit = 256MB。

256 x 2^20 / (4 x 114) = 588,674 ,即倘若所有空间都用来存储数据,可以存放 约58 万条左右 的 一次32 通道采样结果。

但是装满这个DRAM,需要多少时间呢?

本来采样32个通道只需要1.6us 左右,考虑到转换十进制所需要的时间(暂时不知道一个clk50行不行),以及存入一次DRAM需要的时间,以及AD模块本身的采样率才200KSPS,一秒钟采样200K次,每次5us。

假设我们5us 存入一次DRAM 32 通道的数据,一次 就有 4 x 114字节的数据,即DRAM可以装58万条4 x 114Byte,每次存入需要5us,那么总共需要 5us x 58 万 = 2.9 s

倘若转换十进制需要的时间比较大,但是如果这个时间超过5us ,就意味着采样数据会有丢失(即第一个发送的字节数据和最后一个发送的字节数据已经不是同一时刻采样得到的数据了)。

倘若将数据装入SD卡呢?

因为SD卡有不同的速度等级,不同的速度等级SD卡的读写速度也有所不同,在本实验中将使用最高的25Mhz的SPI时钟来实现SD卡的数据读写。25MHZ的时钟意味着SD卡的时钟周期只有40ns. sd_clk=40ns

写SD卡步骤:

发送CMD24命令 (single Block write)需要48个sd_clk;

写数据之前等待8个sd_clk;

发送Start Block Taken需要8个sd_clk;

写456个字节(0~255,0~255)到SD卡需要8*456个sd_clk,456 x 8 x 40 ns = 145920ns = 145.92 us;

写crc需要16个sd_clk;

write_done需要15个sd_clk;

(48 + 8 +8 x 456 + 16 +15) x 40 ns = 149400 ns = 149.4 us

1MB = 2^20 B

发送1MB数据,需要的时间为:2^20 / 456 x 149.4 us = 343546.6 us = 0.343546 s

即一秒钟只能发送不超过3MB数据。

然而在以太网通信中把4个AD模块的数据全部写入RAM变量需要至少9.12us

远远比写入SD卡快得多,所以写入SD卡这种方案不可行。


串口发送数据

倘若使用发送数据到电脑,每次发送完四个AD模块,32个通道的数据大概需要2.5s。如果先存储完整个DRAM,然后读取DRAM数据使用串口发送,则需要2.5 * 58 万 = 大于一百万秒, 大于11天

但是装满这个DRAM,需要多少时间呢?

本来采样32个通道只需要1.6us 左右,考虑到转换十进制所需要的时间(暂时不知道一个clk50行不行),以及存入一次DRAM需要的时间,以及AD模块本身的采样率才200KSPS,一秒钟采样200K次,每次5us。

假设我们5us 存入一次DRAM 32 通道的数据,一次 就有 4 x 114字节的数据,即DRAM可以装58万条4 x 114Byte,每次存入需要5us,那么总共需要 5us x 58 万 = 2.9 s

倘若转换十进制需要的时间比较大,但是如果这个时间超过5us ,就意味着采样数据会有丢失(即第一个发送的字节数据和最后一个发送的字节数据已经不是同一时刻采样得到的数据了)。

USB2.0

开发板上通过Cypress CY7C68013A USB2.0控制器芯片实现PC与FPGA间的高速数据通信,CY7C68013A控制器完全符合通用串行总线协议2.0版规范,支持全速(12Mbit/s)以及低速(480Mbit/s)模式。用户通过用USB线连接PC的USB口和开发板的MINI型的USB口(J6)就可以进行USB2.0的数据通信。

CY7C68013A的内部8051 处理器的工作频率可以为48Mhz, 24Mhz, 12Mhz, AX515/AX530开发板中使用了24Mhz晶体作为时钟输入

CY7C68013A内部集成四个FIFO,大小共为4K字节,用户可以通过设置让其工作在Master或Slave模式

CY7C68013A与其它器件间的通信很简单,它提供的GPIF于FIFO两种模式可以与FPGA, DSP, ATA, UTOPIA, EPP, PCMCIA等实现无缝的数据交换。

CY7C68013A收发器由一个24MHz的晶振提供时钟。

开发板在出厂前已经下载了CY7C68013的固件程序,固件里设置CY7C68013的EP2和EP4为输出(PC端发送,FPGA端接收), **EP6和EP8为输入(FPGA端发送,PC端接收)**。

FPGA和USB芯片CY7C68013A的数据通信是通过异步读写CY7C68013A的四个端口(EP2,EP4,EP6,EP8)的FIFO的数据来实现的,其中FPGA为主设备CY7C68013的端口为从设备

CY7C68013A FIFO异步读:

外部系统控制FIFOADDR0和FIFOADDR1地址线的电平选择端口,拉低SLOE信号后,选择的端口会把FIFO的数据输出到数据总线。外部系统拉低SLRD读取数据。

image-20220107191426078

CY7C68013A FIFO异步写:

外部系统控制FIFOADDR0和FIFOADDR1地址线的电平选择端口,再输出要写的数据到数据总线,拉高SLWR信号SLWR的上升沿把数据存入FIFO中。

image-20220107191949253

开发板中使用Cyclone IV FPGA的Bank6的IO口和CY7C68013A的总线连接。

在开发板中,我们已经为用户配置了CY7C68013固件程序,其中设置EP2,EP4的FIFO为数据输出EP6,EP8的FIFO为数据输入,每个端口含有两个512字节的FIFO,如果一个512字节FIFO被读空或写满,硬件会自动切换到另一个512字节FIFO。另外FLAGA~C引脚的功能也是在固件程序中配置,其中控制信号和状态信号都是低电平有效。如果用户需要改变CY7C68013A的工作模式,端口或信号的配置,可以修改CY7C68013A的固件来实现。

USB通信软件的开发包含两部分,一部分为CY7C6803A的固件设计,另一部分为在FPGA的verilog测试程序。


FPGA Verilog程序设计

在本USB2.0测试程序案例中中,会循环查询CY7C68013A的端口2的FIFO是否有数据,如果CY7C68013A的端口2的FIFO不空(PC发送数据到端口2),程序会读取端口2的FIFO数据然后把它发送回到CY7C68013A端口6的FIFO中。

以太网通信

本实验将实现FPGA 芯片和PC 之间进行千兆以太网数据通信, 通信协议采用EthernetUDP 通信协议。 FPGA 通过GMII 总线和开发板上的Gigabit PHY 芯片通信, Gigabit PHY芯片把数据通过网线发给PC。以太网数据通信的示意图如下:

image-20220107220526854

在AX515/AX530开发板我们采用了Realtek千兆GPHY芯片RTL8211E来实现千兆以太网数据通信。当网口Link到千兆以太网时, FPGA通过GMII总线和PHY芯片进行数据通信,当网口Link到百兆以太网时, PGA通过MII总线和PHY芯片进行数据通信。另外FPGA可以通过MDI/MDIO管理接口来配置或读取PHY芯片内部的寄存器。

千兆的GMII通信模式下, 发送数据时**,发送时钟为125Mhz的GTXC信号, 数据为TXD0TXD7, 数据有效信号为TXEN, TXC信号没有使用; 接收数据时,接收时钟为125Mhz的RXC信号, 数据为RXD0RXD7, 数据有效信号为RXDV。
百兆的MII通信模式**下, 发送数据时,发送时钟为25Mhz的TXC信号, 此25Mhz的TXC时钟是PHY输入给FPGA的,数据为TXD0TXD3, 数据有效信号为TXEN, GTXC信号没有使用; 接收数据时,接收时钟为25Mhz的RXC信号, 数据为RXD0RXD3, 数据有效信号为RXDV。

本案例实验以千兆以太网GMII通信为例来设计verilog程序,程序功能为FPGA检测网口发来的UDP的数据包,如果接收到网口发来的数据包后会把接收到的数据包存储在FPGA内部的RAM中,再不断的把RAM中的数据包通过网口发回到ethernet网络

TOP顶层程序一个功能是实例化udp模块;另外也调用了一个双口RAM,读写的数据宽度为32bit, RAM的地址深度为512。双口RAM用于存储以太网接收到的数据, 程序在没有接收到以太网数据包的时候,一直往外发送存储在RAM中的”HELLO ALINX AX530”的字符,如果接收到以太网数据包,接收到的以太网数据包会覆盖RAM中的数据,程序会不断向网口发送接收到的数据包。

可以用memory类型来定义RAM,ROM等存储器,其结构为reg [n-1:0] 存储器名[m-1:0],意义为m个n位宽度的寄存器。例如,reg [7:0] ram [255:0]表示定义了256个8位寄存器,256也即是存储器的深度,8为数据宽度。

UDP发送模块实现把RAM里的数据组成UDP IP包格式通过GMII总线发给PHY芯片,PHY芯片再把数据发送到开发板的网口
以太网数据包发送之前需要先发送IP数据包的包头,IP包头由8个字节的前导码,目标MAC Address,源MAC地址和两个字节的IP包类型组成。前导码是由7个0x55, 1个0xD5字节组成表示一个IP数据包传输的开始; 目标MAC Address为数据要发送对象的MAC地址,如果开发板的网口是和您的PC机相连,那目标MAC Address的值为你PC机的MAC地址。源MAC Address是指开发板本地的MAC地址。IP包类型值为0x0800。
发完IP包头之后开始发送IP 数据报首部,IP 数据报首部的格式我们在前面已经讲过,接着发送UDP报文段的首部和数据,最后发送4个字节的CRC32的值。

rx_total_length 实际上是IP 数据报首部中的总长度字段,指首部和数据之和的长度;

**rx_data_length **是UDP数据包的长度,这里是UDP报头中的UDP数据报字段,包括UDP首部8个字节和数据。

UDP数据接收程序和UDP数据发送是一样的,先判断是否接收到前导码,如果接收到前导码,开始接收目标MAC Address并判断是否和本开发板的MAC地址一致,一致的话再接收剩余的UDP包头和数据。接收数据的时候把接收到的8bit数据转化成32bit的数据宽度写入到内部的RAM中。

发送一个以太网数据包到电脑,需要先发送8BytesIP前导码报头,12Bytes Mac地址,2Bytes IP类型,发送7个32bit的IP 数据报头;

然后发送数据,假设每个AD模块的数据为114个字节,但是由于RAM地址是32位的,我们总共四个AD模块,114 x 4 = 456,恰好是32位的倍数,不需要额外补充0,即每个AD模块114个字节,总共4个AD模块,即456个字节。

最后发送4个字节的CRC校验码。

总共8+14+28+456+4=510Bytes

若要发送四个AD模块的数据,从start状态到sendcrc状态总共需要1+3+8+14+28+456+4= 514 个clk125;

514 x 8 ns= 4112 ns = 4.112 us,

即发送四个AD模块的书需要4.112us,再加上两个以太网数据包之间发送的时间间隔(待定),才是数据发送的周期。

假设写入RAM的时钟使用的是50MHZ,20ns每个时钟。

114 x 20 ns + 114 x 20 ns (data_o_valid==1’b0时需要一个clk) = 4560 ns = 4.56 us

4个AD模块的数据全部写入RAM需要至少4.56us

四、每个模块单独采样

CONVST信号的上升沿启动对所有模拟输入通道的同步采样(V1至V8)。

image-20220106152353115

FPGA的两个扩展口,经过我设计的数据扩展板后,接到两个AD模块上,AD0和AD1,每个AD模块有自己单独的convst、CS/RD、BUSY、FIRSTDATA信号。根据老师要求,四个AD模块需要分别采样,即不需要再像之前一样,同时给四个AD模块发送CONVST采样信号,每个AD模块采样设置一些采样间隔,以用来增大信号的采样频率(即这种情况是四个AD模块接收得到信号是同一个信号)。

由于AN7606的采样率最高200KSPS,即5us。在这5us内让其他三个AN7606等间隔开启采样,以减少同一个信号的采样间隔。

以下对应项目代码: J1_J2_AD_Ethernet_Version2

由于四个AD模块间隔采样遇到了问题,所以这里只使用了两个AD模块间隔采样同一信号。即采样间隔在两个AD模块都测量同一信号的条件下,从5us变成了2.5us。这里说的2.5 us和5us是对AD模块而言的,而对数据采集来说,我采用的方法是,两个AD模块的数据采集使能到读取数据,是紧贴着的。

ad7606.v中:

从AD1采集使能到采集数据结束需要: 2+5+1+3*8 = 32 clk50 = 32 *20ns = 640 ns =0.64 us

然后紧接着的就是AD的采集使能到采集数据结束需要: 1+2+ 3*8 = 27 clk = 27 *20 ns = 540 ns = 0.54 us

即一轮AD1 和AD2的采集需要 0.64 +0.54 = 1.18 us,即5us内,AD1和AD2的采样到数据收集 可以进行4轮,虽然后面三轮都是相同的数据。

AD模块的物理特性是最快200KPS,即5us采集一次。我们使用两个AD模块来间隔采样同一信号,采样率可以提升一倍。

使用wireshark抓包软件作为上位机接收数据,可接收间隔时间为2us的UDP数据包。(还可以设置更短如1us,但是丢失包数量会增多)。

要发送四个AD模块的数据,从start状态到sendcrc状态总共需要1+3+8+14+28+456+4= 514 个clk125;

514 x 8 ns= 4112 ns = 4.112 us,即:

发送的数据包之间的间隔总的为: 2 + 4.112 us = 6.112 us;


4.1 两个AD模块对同一信号接替采样

由于使用两个AD模块对同一信号接替采样,故实际上对同一信号的接收间隔时间为 : 6.112 / 2 = 3.056 us

4.2 四个AD模块对同一信号接替采样

AD1: 从发送采样信号到接受完8个通道的数据所需时间:

(3+6+1+4 x8 +1 ) x 20 ns = 860 ns = 0.86 us

AD2: 从发送采样信号到接受完8个通道的数据所需时间:

(3 + 4 x 8 + 1) x 20 ns = 720 ns = 0.72 us

J1扩展口 过渡 J2 扩展口 所需时间:

(20 +1 ) x 20 ns = 420 ns =0.42 us

AD3: 从发送采样信号到接受完8个通道的数据所需时间:

(3+6+1+4 x8 +1 ) x 20 ns = 860 ns = 0.86 us

AD4: 从发送采样信号到接受完8个通道的数据所需时间:

(3 + 4 x 8 + 1) x 20 ns = 720 ns = 0.72 us

故一次四个AD模块交替采样的完成时间是:0.86+0.72+0.42+0.86+0.72=3.58us

故5us内可完成一次四个AD模块的交替采样;

收集数据时间间隔实际上只看发送数据所消耗的时间,由于每次都是4个AD模块的数据一起发送,故计算同一接收数据间隔可以直接除以4;

由于使用四个AD模块对同一信号接替采样,故实际上对同一信号的接收间隔时间为 : 6.112 / 4 = 1.528 us


摄像头

本实验将采用500万像素的OV5640摄像头模组(模块型号:AN5640)为大家显示更高分辨率的视频画面。OV5640摄像头模组最大支持QSXGA (2592x1944)的拍照功能,支持1080P、720P、VGA、QVGA视频图像输出。本实验将OV5640配置为RGB565输出,先将视频数据写入外部存储器,再从外部存储器读取送到VGA、LCD等显示模块

OV5640摄像头模组采用美国OmniVision(豪威)CMOS芯片图像传感器OV5640,支持自动对焦的功能。OV5640芯片支持DVP 和MIPI 接口,本实验所用 OV5640摄像头模组通过DVP接口和FPGA连接实现图像的传输

OV5640的参数说明

像素:硬件像素500W;
感光芯片:OV5640;
感光尺寸:1/4;
功能支持:自动对焦, 自动曝光控制(AEC),自动白平衡(AWB);
图像格式 : RAW RGB, RGB565/555/444, YUV422/420和JPEG压缩;
捕获画面:QSXGA(2592x1944), 1080p, 1280x960, VGA(640x480), QVGA(320x240);
工作温度:-3070℃, 稳定工作温度为050℃

OV5640寄存器配置

OV5640的寄存器配置是通过FPGA的I2C接口来配置。用户需要配置正确的寄存器值让OV5640输出我们需要的图像格式,实验中我们把摄像头输出分辨率和显示设备分辨率配置成一样的, OV5640的摄像头输出的数据格式在以下的0x4300的寄存器里配置,在我们的例程中OV5640配置成RGB565的输出格式

OV5640的RGB565输出格式

OV5640在HREF信号为高时输出一行的图像数据,输出数据在PCLK的上升沿的时候有效。因为RGB565显示每个像数为16bit, 但OV75640每个PCLK输出的是8bit,所以每个图像的像数分两次输出,第一个Byte输出为R4~R0和G5G3, 第二个Byte输出为G2\G0和B4~B0,将前后2个字节拼接起来就是16Bit RGB565数据。

image-20220124222629777

程序设计

本程序一个比较关键的地方在于视频同时读写,如何做到读写不冲突?在设计帧读写模块时就已经考虑到这点,所以有帧基地址选择,最大4帧选择,每次读视频帧地址和正在写的帧地址是不同的,而是上次写入的帧地址,这样就可以避免读写冲突,避免视频画面裂开错位。
cmos_8_16bit模块完成输入8bit数据到16bit数据,数据位宽变成2倍,时钟频率不变,所以16bit数据是隔一个时钟周期有效,并不是一直有效。

image-20220124113454333

cmos_write_req_gen模块完成ov5640数据写入请求,生成write_addr_index写地址选择和read_addr_index读地址选择。

image-20220124113750660

  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2022-2024 lk
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~

支付宝
微信