FPGA运动目标识别系统_第1页
FPGA运动目标识别系统_第2页
FPGA运动目标识别系统_第3页
FPGA运动目标识别系统_第4页
FPGA运动目标识别系统_第5页
已阅读5页,还剩46页未读 继续免费阅读

付费下载

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

基于FPGA的运动目标识别系统设计系统硬件设计 基于FPGA的运动目标识别系统总体结构VGA显示器SDRAM芯片图像处理模块摄像头采集模块图像传感器VGA显示器SDRAM芯片图像处理模块摄像头采集模块图像传感器OV7670图像传感器初始化配置模块OV7670图像传感器初始化配置模块VGA控制模块SDRAM控制模块VGA控制模块SDRAM控制模块FPGAFPGA基于FPGA的运动目标识别系统主要包括以下几个模块:OV7670图像传感器初始化配置模块、摄像头数据采集模块、基于SDRAM视频处理显示模块等。整个系统流程如下:首先,在FPGA中OV7670图像传感器初始化配置模块对图像传感器OV7670中寄存器进行数据写入,摄像头可以按照数字输出数据流的要求输出,FPGA中数据采集模块再采集数据流,然后通过视频数据格式转换和目标识别模块即图像处理模块,再在SDRAM中缓存,最后再送到VGA显示器显示。FPGA开发板阿尔特拉公司的“飓风”四代系列FPGA器件继承了Cyclone系列产品成本低廉、功耗小的优良传统,本平台所用的是其中的飓风四代E系列器件,其优点是以最低的功耗,通过最低的成本实现较高的功能性,其资源包括66个18*18的乘法器,是可以实现DSP处理密集型应用,嵌入式存储器有594Kbits,逻辑单元有22320LE,还支持包括串行数字接口的多种协议。 开发板电路包括FPGA的电源模块、FPGA的配置模块(即JTAG和ASP等)、时钟电路及复位模块和SDRAM模块。开发板实物图 OV7670摄像头接收640*480像素,每秒30fps的数据。VGA显示640*480分辨率高达60fps,每秒共30M带宽的图像。这点处理要求理论上对于FPGA来说绰绰有余,但这要求放至任意一块常见的MCU,甚至是ARM核,都是有点难以想象的。实现单片机做不到的事情,才是FPGA的优势所在。图像传感器图像传感器,是组成数字摄像头的重要组成部分。根据元件的不同,可分为CCD(ChargeCoupledDevice,电荷耦合元件)和CMOS(ComplementaryMetal-OxideSemiconductor,金属氧化物半导体元件)两大类。CCD提供的图像质量可以非常好,抗噪能力高和设计灵活。虽然由于增加了外围电路使系统的尺寸变大,复杂性变高,但提高了电路设计的灵活性,可以随设计者要求特意提高某方面性能。CCD更适合于注重性能而不太注重成本的应用领域,如天文,医疗X光影像和对图像的噪声要求高的应用领域。CMOS是使用了现代大规模半导体集成电路生产工艺来生产出的图像传感器,因技术成熟,有成品率高、集成度高和成本低等特点。CMOS技术早就成为图像传感器企业关注的重点,希望可以兼有CCD图像传感器的特点。经过不懈的尝试,CMOS图像传感器可以兼有CCD图像传感器的优点了,甚至可以与之媲美,使CMOS图像传感器成为主流产品。CMOS的工艺特点使它们更适用于要求体积小和功耗低而不需要图像噪声和质量特别高的场合。像大多数安全防护应用和大多数消费型数码产品应用。本课题使用的摄像头是来自是OvmniVision公司的摄像头,型号是OV7670,属于CMOS摄像头,支持I2C接口,自带的AD转换精度为10位,VGA图像最高达到30帧每秒,像素面积为3.6um*3.6um,是逐行扫描模式,像素是30W,支持自动曝光控制、自动增益控制、自动白平衡、自动消除灯光条纹、图像缩放,工作模式下的工号为60mw,输出格式支持RawRGB(将每一个像素的数据直接输出)、RGB565\555\444(三原色红绿蓝模式,后面数字分别代表红绿蓝的位数)、YUV\YCbCr4:2:2(亮度信号Y和两个色差信号B-Y(即U)、R-Y(即V),数字代表数据为Y-U-Y-V次序输出的),输出数据都为8位D{7...0},其它输出的数据还包括CMOS_HREF(行同步信号),CMOS_VSYNC(场同步信号),CMOS_PCLK(输出像素时钟信号),当然还有对OV7670配置的I2C相关引脚CMOS_SCLK和CMOS_SDATA。摄像头里的功能模块包括有感光阵列、模拟信号处理、AD转换、测试图案发生器、数字信号处理器、图像缩放、时序发生器、数字视频端口、SCCB接口(即I2C接口)、LED和闪光灯输出控制。由此可见,有很大一部分数据转换都在内部处理完成了。VGA显示接口VGA接口是一种D型接口,上面共有15针,分成三排,每排五个,VGA接口针脚定义如图2-3所示。接口有2根NC(NotConnect)信号针,3根显示数据总线针,5个GND信号针,另外比较重要的是3根RGB彩色分量信号和2根扫描同步信号HSYNC和VSYNC针。VGA接口中彩色分量采用RS343电平标准。RS343电平标准的峰值电压为1V。VGA接口是显卡上应用最为广泛的接口类型,多数的显卡都带有此种接口。本系统使用了一个外设VGA接口,自带一个DAC转换芯片,可以直接将输出的数字信号转换为VGA能接受的零到七伏特电平,输出给显示器显示图像。第三章运动目标识别系统模块化设计运动目标识别系统顶层设计图3-1运动目标识别系统顶层结构图整个系统软件设计主要为以上几个模块:时钟及复位模块、 OV7670图像传感器初始化配置模块、摄像头数据采集模块和基于SDRAM的视频处理显示模块。其中基于SDRAM的视频处理显示模块又包括SDRAM缓存模块,VGA驱动程序模块、视频数据格式转换程序和目标识别模块即图像处理模块。时钟及复位模块主要是为整个系统提供时钟和复位信号。OV7670图像传感器初始化配置模块是对图像传感器寄存器进行初始化配置。摄像头数据采集模块是将摄像头的传入的初始数据采集并整合。SDRAM缓存模块是控制SDRAM实现对数据缓存,为实时显示提供可能。VGA驱动程序是控制驱动VGA显示器正常显示。视频数据格式转换程序是将视频数据RGB565格式转换为灰度图像以便后续处理。目标识别模块是实现运动目标识别,对相邻帧的像素之和后相减,大于阈值即判断有运动目标。整个的工作过程为:先通过FPGA中I2C总线模块对图像传感器OV7670中的寄存器进行配置即数据写入,摄像头才能按照要求输出数字数据流,在FPGA中采集数据模块的数据流,然后发送到图像处理模块进行处理,在SDRAM缓存,然后发送到VGA显示。时钟及复位模块 开发板自带晶振振荡器为25MHz,由PLL锁相环分频或倍频出适合的频率提供给各模块 CLK是开发板自带的晶振时钟输入引脚。rst_n是复位引脚。sys_rst_n是接到各模块的异步复位引脚。但是有一些模块对这个时钟频率要求分频或倍频,所以要经过时钟模块进行分频或倍频。此外系统还需要一个复位设置,将这两个功能整合在一个模块中。在quartusII中直接调用PLL(锁相环(PhaseLockedLoop))来完成我们的时钟分频或倍频。PLL时钟设置界面由图可知从c0,c1和c2与自带晶振的相对频率、相位。c0为全局时钟。c1是乒乓模块和存储控制模块的时钟信号。c2直接接到SDRAM中作为时钟信号。摄像头数据采集模块 摄像头采集的像素时钟信号CMOS_PCLK,场同步信号CMOS_VSYNC,行同步信号CMOS_HREF和8位像素数据CMOS_iDATA[7:0]去通过这个模块采集,再送入下个显示处理模块。Init_Done接受来自I2C总线模块的config_done信号,高电平有效表示I2C初始化完成。CMOS_oclk是数据同步输出时钟。CMOS_VALID是数据输出有效位。CMOS_XCLK等于全局时钟。 要想对输入数据进行处理,就要首先知道进来的数据是怎么样的。所以通过quartusII平台上的SignalTapII仿真得到摄像头进来的cmos_pclk像素时钟信号、cmos_vsync场信号、cmos_href行信号和8位cmos_data像素数据信号的时序图。由图可以看出,在场信号(默认低有效),和行信号有效的同时,摄像头开始输出8位数据。因此就在此时要开始拼接数据:先保存第一个8位数据,拼接到第二8位个数据,实现一个完整16位像素数据的输出。然后要实现这16位数据在SDRAM的缓存,在拼接完成的同时,给一个信号给FIFO使能,场同步信号作为SDRAM的地址清零信号,这样就能缓存这16位数据了。值得注意的是在此模块中因为在OV摄像头手册中提到,前300ms数据会不稳定,所以在本模块设计中还特意丢弃了前10帧。OV7670图像传感器初始化配置模块 I2C总线是用来初始化的OV7670图像传感器的设置,分辨率和PCLK像素时钟设置和传感器的输出数据格式等等也可以这样设置。I2C总线概况 I2C(InterIntegratedCircuit,内部集成电路)总线是在上世纪80年代由PHILIPS公司为音视频设备发明的两线式串行总线,用于连接微控制器和外围设备虽然总线没有并行总线的吞吐率,效率明显不足,但是因其只有两条双向信号线,分别为SCLKS和SDATA信号线,接口直接接在组件之上,硬件结构十分简单,这两条双向信号线通过上拉电阻接到正电源电压,初始状态下两线均为高电平,连接到总线的设备都有唯一的地址来发送或接收数据,这个地址一般是设备出厂时就分配好的,也可以通过软件设定。[7]原本OV摄像头使用的是它自己公司的SerialCameraControlBus(SCCB)总线,然而与I2C总线的时序并没有差别,所以下面就都介绍I2C总线了。I2C总线控制程序设计 I2C总线控制程序设计原理图如下首先介绍各引脚功能定义。管脚GO是传送数据开始标志位,管脚I2C_CLK就是为I2C总线提供的数据传输的工作时钟,管脚I2C_SCLK就是加在两条总线上其中的SCLK时钟信号线,管脚I2C_SDAT是加在两条总线上其中的SDAT数据信号线,管脚iCLK是全局时钟,管脚iRST_N是复位引脚,管脚I2C_WDATA[23..0]是主端口发送给从端口的配置数据,包括7位从端口设备地址、1位数据方向、8位寄存器地址和要8位写入寄存器的设定数据,管脚ACK为应答位,管脚END是传送数据结束标志位,I2C_RDATA为读取数据这里不作介绍。接下来介绍I2C总线传输过程为:主端口发送1位起始位,紧跟主端口发送的是从端口设备的8位地址即出厂分配的地址或可通过软件设定,地址的最后一位表示该请求是写入还是读取,为“0”表示请求写入,为“1”表示请求读取,在从端口设备核对地址无误后,向主端口发送一位应答信号。图大概介绍一下几个重要过程:开始条件:当SCL为高电平期时,SDA由高电平到低电平的跳变,即下降沿。 结束条件:当SCL为高电平期时,SDA由低电平到高电平的跳变,即上升沿。 开始和结束信号都是由主机发出的,在开始信号产生后,总线就是被占用的状态;在结束信号产生后,总线就是空闲状态。 应答位:主器件每发送一个字节后,即第九个时钟脉冲时,从器件释放SDA数据线为表示应答。 非应答位:主器件每发送一个字节后,即第九个时钟脉冲时,从器件保持SDA数据线表示非应答。从端口设备地址:8位地址,由7位地址和1位数据传输方向位组成。最低位为“0”表写入模式,为“1”表示读取模式。写入过程:从端口设备地址:8位地址,由7位地址和1位数据传输方向位组成。最低位为"0”表写入模式,为"1”表示读取模式。写入过程:(1)发送从器件的地址和读写选择位,等到从器件拉低SCL进行应答;如果从器件接收成功,则进行应答;如果握手不成功或从设备发送到错误的数据不产生响应,则请求重发或终止。(2)发送想要写入的寄存器地址;从器件对其发出应答;(3)发送数据。(4)发送停止位。然后介绍该程序设计的思路结构流程图如下:起始起始SCLK和SDAT保持高电平SCLK和SDAT保持高电平否开始条件(SCLK保持高电平和SDAT下降沿)否开始条件(SCLK保持高电平和SDAT下降沿)开始条件(SCLK开始条件(SCLK高电平和SDAT下降沿)是写入从设备地址是写入从设备地址否是否应答否是否应答是是否是否应答写入寄存器地址否是否应答写入寄存器地址是是写入配置数据写入配置数据否是否应答否是否应答是配置的寄存器数是否超过阈值否是配置的寄存器数是否超过阈值否是是结束结束全程序的大概思路是以全局时钟为频率,设置了SD_COUNTER计数器,以此为基础把写入操作分为部分:空闲、起始、写入和终止。计数器为0时为空闲部分,空闲部分时,SCLK和SDAT都为高电平,ACK1、ACK2和ACK3都为高电平。计数器为1到3时,为起始部分,计数器为2时,使SDAT为低电平,计数器为3时,使SCLK 为低电平,这样就满足了写入过程的开始条件。 计数器4到14,为写入从设备地址部分,4到11时,从高位开始,把7位从设备地址和1位读写设置位,一位一位写入到SDAT。12到14时,从SDAT读取 ACK1,表示从设备地址写入完成。读到的ACK1如果不是高阻态,则计数器从0开始重新计数。 计数器15到25,为写入寄存器地址,15到22时,从高位开始,把8位寄存器地址,一位一位写入到SDAT。23到25时,,从SDAT上读取ACK2,表示寄存器地址写入完成。如果读到的ACK2不是高阻态,则计数器从0开始重新计数。 计数器26到36,为写入要配置的数据部分,26到33时,从高位开始,把8位数据写入,从高位开始,一位一位写入到SDAT。34到36时,从SDAT读取ACK3,表示配置数据写入完成。读到的ACK3如果不是高阻态,则计数器从0开始重新计数。 至此24位数据写入完成,传输成功。以上的子程序完成了对SCLK和SDAT信号线的具体分配,然而对各个信号的判断和子程序的例化,需要在2级顶层程序里完成。 在2级顶层程序里,用的时钟频率有FPGA开发板的25MHz自带频率,在程序中分频为10KHz。在这个程序里设置了一个状态机,有三个状态,分别为“0、1和2”。0代表空闲状态,先判断当前写入的寄存器数是否超过了图像传感器的寄存器数的阈值,这里设置的阈值LUT_SIZE为168,数值由图像传感器决定。如果没超过阈值的话再由END信号线判断是否进入1状态即写入状态,表示开始写入操作,如果24位数据都写入完成的话,即ACK1、2、3都为高阻态,则进入2状态即寄存器地址加1,再转到0状态空闲状态。I2C总线对OV7670寄存器的配置 本系统的开发板作为主端口设备通过I2C总线来配置OV7670的寄存器,从端口设备只有OV7670图像传感器,虽然I2C总线协议与其他总线协议相对没有那么复杂,但还是有一定的难度的,所以在本课题中只需要完成写入操作,无需读取操作。 因本课题只有对图像传感器的写入操作,主端口先发送位设备地址Ox42(7位地址和1位数据方向,为设备出厂默认设置),然后发送8位寄存器地址和8位配置数据,每发送一个字节,从端口收到后给出应答信号ACK1、ACK2和ACK3。最后主端口发送结束标志位,停止写操作。I2C总线写入时序图 I2C总线8位写入操作时序如图3-9所示。开始时,主端口首先发送1位开始标志位,即I2C_sclk保持高电平,I2C_sdat线下降沿。首先主端口在I2C_sdat数据线上发送从端口设备地址Ox42二进制表示为(01000010),最后一位是“0”,代表写入操作,从高位到低位一位一位发送,发完8位之后,读取到ACK1为三态(三态无法使用ModeisIM仿真),代表从器件收到数据并发送应答位。接着主端口再发送要配置的寄存器地址表示寄存器Ox32二进制为(00110010),Ox32是OV7670内寄存器地址,从高位发到低位,然后重复上述操作。然后主端口设备发送要配置的数据Oxb2二进制数为(10110010),也是重复上述操作。最后,主端口再发送一位结束标志位即I2C_sclk保持高电平,I2C_sdat线上升沿,代表16位数据已经写完,OV7670内部的寄存器Ox32里的数值为Oxb2。 以上介绍如何配置了一个寄存器数据的详细过程。本设计要配置的寄存器有164个,就不一一赘述了。下面通过表列出几个重要的寄存器。除了表3-1中列出这几个寄存器,其它寄存器采用默认值。几个重要的寄存器数据配置寄存器地址功能描述设定值设定功能12选择图像输出格式04RGB565格式输出11时钟输入设置80使用外部时钟6BPLL寄存器设置00选择0分频3EPCLK像素时钟设置00选择0分频全屏最大基于SDRAM的视频处理显示模块VGA驱动程序设计经过处理之后的YUV格式的视频要经过VGA驱动程序才能真正显示在VGA显示器上,该程序RTL原理图VGA驱动程序原理图原理图各引脚功能介绍:CLK是接的全局时钟取反。rst_n是复位信号。lcd_data[15..0]是要显示的经过处理的存储在SDRAM里的YUV格式数据。lcd_dclk是像素时钟信号。lcd_hs是行扫描。lcd_vs是场扫描。lcd_en是显示屏使能信号,高电平输出输入数据lcd_data。lcd_rgb[15..0]是输出信号。lcd_xpos是显示水平坐标。lcd_ypos是显示垂直坐标。lcd_request是输出坐标请求信号,高电平时输出坐标。lcd_framesync就是场扫描。lcd_blank是行扫描与场扫描,空白信号。这个模块凡是需要VGA显示的,都会用到,程序不再详细分析。只要根据分辨率设置场消隐期场、消隐后肩、场显示期和域场消隐前肩的四个时期的时间就可以了。行扫描和场扫描时序图 如上图所示。VGA显示一直在扫描,每一场的扫描由若干行扫描组成,如此循环下去。将场扫描分为四个阶段由图3-12得出场扫描可以分为a、b、c、d,4个阶段。这四个阶段定义如下:a~b:场消隐期。b~c:场消隐后肩。c~d:场显示期。d~e:场消隐前肩。 分辨率640*480的时间参数设置如下`define H_FRONT 11'd16`define H_SYNC 11'd96`define H_BACK 11'd48`define H_DISP 11'd640`define H_TOTAL 11'd800 `define V_FRONT 11'd10`define V_SYNC 11'd2`define V_BACK 11'd33`define V_DISP 11'd480`define V_TOTAL 11'd525视频数据格式转换程序设计经过摄像头采集模块之后,输出的是RGB565格式的视频,因为相比于彩色视频灰度视频比较好处理。所以要把RGB565格式视频转化为YUV的灰度视频,还得先在两者之间加入RGB888格式的转化。而这一转换只需要通过简单的高位补低位或者低位补零就可以实现。为保障数据的精确度采取高位补低位的方法进行处理。实现编码如下: RGB888_R<={cmos_indata[15:11],cmos_indata[15:13]} RGB888_G<={cmos_indata[10:5],cmos_indata[10:9]} RGB888_B<={cmos_indata[4:0],cmos_indata[4:2]} RGB颜色格式转YUV格式,实际上是色度空间的转换,RGB是三基色度空间,YUV是亮度与色度的表达,具体的公式如下:Y=0.299R+0.587G=0.114B(1-a)Cb=0.568B-Y+128=-0.172R-0.339G+0.511B+128(Cr=0.713B-Y+128=0.511R-0.428G-0.083B+128 但是FPGA是0和1的世界,Verilog语言是不能对浮点数进行计算,所以我们先把这些乘数等值扩大256倍,再向右移位8位,来实现同样的计算结果,转换后的公式如下:Y=77*R+150*G+29*B≫8Cb=-43*R-85*G+128*B≫8+128Cr=128*R-107*G-21*B≫8 虽然FPGA有着资源丰富的乘法器和移位寄存器,如果直接用直白的公式按上面的运算来编码,也是可以计算出最后想要的结果。但是这样执行的效率就低、资源消耗巨大;并且在表达式为负数的时候,运算结果容易出错。因此,我们在把算法实际表达写进FPGA程序的时候,我们需要把运算进行拆分。本设计先进行了各个乘数的运算,再进行相加减。并且为了避免运算过程出现负数而徒增麻烦的情况,先把得到的加减数加上128,也就是提到括号运算内,再进行移位。这样大大避免了结果溢出的风险。公式如下。Y=77*R+150*G+29*B≫8 Cb=-43*R-85*G+128*B+32768≫8 Cr=128*R-107*G-21*B+32768≫8 最后的移位我们直接采取提取首八位数据输出的方法,编码如下。 Y_r1 <= Y_r0[15:8]; Cb_r1 <= Cb_r0[15:8]; Cr_r1 <= Cr_r0[15:8]; 经过如上各个步骤的计算后即可得到灰度信号,实际上需要处理及输出的仅一项8Bit的灰度信号Y。SDRAM缓存模块设计因为实时的视频采集系统所要处理的数据量十分大,而且对实时性要求高,最重要的是采集视频的速度和处理数据的速度可能会不匹配,所以就需要高速、容量大的存储器来缓存实时的视频数据,实现数据的缓存和处理速度尽可能匹配。SDRAM(SynchronousDynamicRandomAccessMemory,同步动态随机存储器),同步是指内存工作需要同步时钟,内部的命令的发送与数据的传输都以它为基准;动态是指存储阵列需要不断的刷新来保证数据不丢失;随机是指数据不是线性依次存储,而是自由指定地址进行数据读写。内部本质是一个存储阵列,把对应数据一个一个放入格子内。参照定位原理的形式,先选择一行(行),然后选择列(列),使存储单元确定。以内存的角度说,那些单元格被称为存储单元,每一个存储单元最大能装载大小为8、16、32的数据。而对于整个行列组成的块而言,整个存储阵列在SDRAM中被称为逻辑Bank(LogicalBank)。SDRAM存储阵列 在介绍了基本硬件构成之后,再来介绍本设计顶层控制模块。其原理图如下。SDRAM顶层控制模块SDRAM各引脚说明引脚说明clk_refSDRAM控制器时钟输入clk_refoutSDRAM驱动时钟输入rst_nSDRAM控制器复位信号输入sdram_clkSDRAM驱动时钟信号接口sdram_ckeSDRAM驱动时钟使能信号接口sdram_cs_nSDRAM芯片片选使能信号接口sdram_we_nSDRAM数据写入使能信号接口sdram_cas_nSDRAM列地址选通信号接口sdram_ras_nSDRAM行地址选通信号接口sdram_init_doneSDRAM初始化完成信号,作为外部数据输入的前提wr_loadSDRAM写地址置位信号wr_addrSDRAM写入地址最小值wr_max_addrSDRAM写入地址最大值wr_lengthSDRAM写入数据长度rd_addrSDRAM读取地址最小值rd_max_addrSDRAM读取地址最大值rd_lengthSDRAM读取数据长度sys_weWRFIFO数据输入信号clk_writeWRFIFO输入端时钟信号sys_rdRDFIFO输出端时钟信号clk_readRDFIFO数据读取信号对于用户的操作而言,只需要关心WRFIFO写入端口,与RDFIFO读取端

口。每个端口的时序均一样,主要分为连续写入/读取,与使能写入/读取。写入SDRAM时序图但是实际上我们是在同一个Bank当中读写SDRAM缓存,这会使得当前正在进行的图像数据与上一次存入的图像数据之间存在重叠。为了解决这个问题,需要在实现乒乓操作,使得在一段时间内,SDRAM存储块进行读写的乒乓操作:乒乓读写操作图 在编码中添加了2个先入先出队列,通过数据缓存模块实现了1+2Bank与3+4Bank数据在一定时间内,SDRAM储存块读写的乒乓操作。同时还通过控制使能信号的高低电平,来实现控制是否执行SDRAM控制器乒乓操作。目标识别模块设计 本设计在比较了上面的三种方法之后,决定采用帧间差分法实现本设计。一帧图像分辨率为640*480,如果要将每一像素相加,假如每位像素都为8位1的,即最大值为78643200,FPGA开发板内部寄存器是可以接受的。 模块的功能是计算每一帧里所有像素的和,将相邻两帧的和比较大小,然后用比较大的数据减去相对小的数据,最后将相减后的数与固定阈值比较,最后将相减后的数和固定阈值比较,这里设置阈值是e5ffff。当大于阈值时,输出0,使LED灯亮,表示有运动目标。当小于时,输出1,LED灯灭,表示静止。图3-17目标识别模块附录附录附录 总系统顶层程序:`timescale1ns/1psmodulesdram_ov7670_vga( //globalclock50MHz //input clk_27, //27MHz input CLOCK, //sdramcontrol output S_CLK, //sdramclock output S_CKE, //sdramclockenable output S_NCS, //sdramchipselect output S_NWE, //sdramwriteenable output S_NCAS, //sdramcolumnaddressstrobe output S_NRAS, //sdramrowaddressstrobe output[1:0] S_DQM, //sdramdataenable output [1:0] S_BA, //sdrambankaddress output [11:0] S_A, //sdramaddress inout [15:0] S_DB, //sdramdata //VGAport output VGA_HSYNC, //horizontalsync output VGA_VSYNC, //verticalsync output [15:0] VGAD, //VGAdata //cmosinterface output CMOS_SCLK, //cmosi2cclock inout CMOS_SDAT, //cmosi2cdata input CMOS_VSYNC, //cmosvsync input CMOS_HREF, //cmoshsyncrefrence input CMOS_PCLK, //cmospxielclock output CMOS_XCLK, //cmosexternlclock input [7:0] CMOS_DB, //cmosdata outputled_o, output [3:0] LED //leddatainput );assignrst_n=1'b1;//wire clk_vga; //vgaclockwire clk_ref; //sdramctrlclockwire clk_refout; //sdramclockoutputwire sys_rst_n; //globalresetsystem_ctrl u_system_ctrl( .clk (CLOCK), //globalclock50MHZ .rst_n (rst_n), //externalreset .sys_rst_n (sys_rst_n), //globalreset .clk_c0 (clk_vga), //25MHz .clk_c1 (clk_ref), //100MHz-45deg .clk_c2 (clk_refout) //100MHz);//wire [7:0] I2C_RDATA; //i2cregisterdatawire [7:0] LUT_INDEX; //lutindexwire Config_Done; //I2Cconfigdone I2C_AV_Config u_I2C_AV_Config( //Globalclock .iCLK (clk_vga), //25MHz .iRST_N (sys_rst_n), //GlobalReset //I2CSide .I2C_SCLK (CMOS_SCLK), //I2CCLOCK .I2C_SDAT (CMOS_SDAT), //I2CDATA //CMOSSignal .Config_Done (Config_Done), //I2CConfigdone .I2C_RDATA (I2C_RDATA), //CMOSID .LUT_INDEX ()//(LUT_INDEX) //IDIndex);assign led_data=I2C_RDATA; //diaplayI2C_RDATA//wire frame_valid; //datavalid,oraddressrestartwire [7:0] cmos_fps_data; //cmosframerateCMOS_Capture u_CMOS_Capture( //GlobalClock .iCLK (clk_vga), //25MHz .iRST_N (sys_rst_n), //globalreset //I2CInitilizeDone .Init_Done (Config_Done&sdram_init_done), //InitDone //SensorInterface .CMOS_RST_N (),//(cmos_rst_n), //cmosworkstate .CMOS_PWDN (),//(cmos_pwdn), //cmospoweron .CMOS_XCLK (CMOS_XCLK), //cmos .CMOS_PCLK (CMOS_PCLK), //25MHz .CMOS_iDATA (CMOS_DB), //CMOSData .CMOS_VSYNC (CMOS_VSYNC), //L:Vaild .CMOS_HREF (CMOS_HREF), //H:Vaild //OuputSensorData .CMOS_oCLK (cmos_iclk), //DataPCLK .CMOS_oDATA (cmos_indata), //16BitsRGB .CMOS_VALID (cmos_VALID), //DataEnable .CMOS_FPS_DATA ()//(cmos_fps_data) //cmosframerate);wirecmos_VALID;wire [15:0] cmos_indata;wirecmos_iclk;//VIP_RGB888_YCbCr444VIP_RGB888_YCbCr444_inst( //globalclock .clk(clk_vga), //cmosvideopixelclock .rst_n(sys_rst_n), //globalreset .cmos_indata(cmos_indata), .cmos_iclk(cmos_iclk),.cmos_valid(cmos_VALID), .CMOS_oCLK(sys_we), //1/2PCLK .CMOS_oDATA(sys_data_in), //16BitsRGB .img_y(img_y), .CMOS_VALID(frame_valid) //DataEnable);wire [7:0]img_y;detectdetect_inst( .sclk (clk_vga), .cmos_iclk (sys_we), .rst_n (sys_rst_n), .image_y (img_y), .cmos_valid(frame_valid), .led_o(led_o));//sdramvgactrlsystemwire sys_we; //systemdatawriteenablewire [15:0] sys_data_in; //systemdatainputwire sdram_init_done; //sdraminitdonesdram_vga_top u_sdram_vga_top( //globalclock .clk_vga (clk_vga), //vgaclock .clk_ref (clk_ref), //sdramctrlclock .clk_refout (clk_refout), //sdramclockoutput .rst_n (sys_rst_n), //globalreset //sdramcontrol .sdram_clk (S_CLK), //sdramclock .sdram_cke (S_CKE), //sdramclockenable .sdram_cs_n (S_NCS), //sdramchipselect .sdram_we_n (S_NWE), //sdramwriteenable .sdram_cas_n (S_NCAS), //sdramcolumnaddressstrobe .sdram_ras_n (S_NRAS), //sdramrowaddressstrobe .sdram_udqm (S_DQM[1]), //sdramdataenable(H:8) .sdram_ldqm (S_DQM[0]), //sdramdataenable(L:8) .sdram_ba (S_BA), //sdrambankaddress .sdram_addr (S_A), //sdramaddress .sdram_data (S_DB), //sdramdata //lcdport .lcd_dclk (), //lcdpixelclock .lcd_hs (VGA_HSYNC), //lcdhorizontalsync .lcd_vs (VGA_VSYNC), //lcdverticalsync .lcd_sync (),//(lcd_sync), //lcdsync .lcd_blank (), //lcdblank(L:blank) .lcd_red (VGAD[15:11]), //lcdreddata .lcd_green (VGAD[10:5]), //lcdgreendata .lcd_blue (VGAD[4:0]), //lcdbluedata //userinterface .clk_write (clk_vga), //fifowriteclock .sys_we (sys_we), //fifowriteenable .sys_data_in (sys_data_in), //fifodatainput .sdram_init_done (sdram_init_done), //sdraminitdone .frame_valid (frame_valid) //framevalid);endmodule时钟及复位模块程序:`timescale1ns/1nsmodulesystem_ctrl( input clk, //50MHz input rst_n, //globalreset output sys_rst_n, //systemreset output clk_c0, output clk_c1, output clk_c2 //-75deg);////rst_nsynchronism,iscontrolledbytheinputclkregrst_nr1,rst_nr2;always@(posedgeclkornegedgerst_n)begin if(!rst_n) begin rst_nr1<=1'b0; rst_nr2<=1'b0; end else begin rst_nr1<=1'b1; rst_nr2<=rst_nr1; endend////componentinstantiationforsystem_delaywire delay_done;system_delay u_system_delay( .clk (clk), .rst_n (rst_nr2), .delay_done (delay_done));wire pll_rst=~rst_nr2&~delay_done; //activeHigh////Componentinstantiationwire locked; sdram_pll u_sdram_pll( .inclk0 (clk), .areset (pll_rst), .locked (locked), .c0 (clk_c0), .c1 (clk_c1), .c2 (clk_c2));////sys_rst_nsynchronism,iscontrolbythehighestoutputclkwire sysrst_nr0=rst_nr2&locked&delay_done;reg sysrst_nr1,sysrst_nr2;always@(posedgeclk_c1ornegedgesysrst_nr0)begin if(!sysrst_nr0)beginsysrst_nr1<=1'b0;sysrst_nr2<=1'b0;end elsebeginsysrst_nr1<=1'b1;sysrst_nr2<=sysrst_nr1;endendassignsys_rst_n=sysrst_nr2; //activeLowendmodulemodulesystem_delay( input clk, //50MHz input rst_n, output delay_done);////Delay100msforsteadystatelocalparam DELAY_CNT=23'd100_0000; //50msreg [22:0]cnt;always@(posedgeclkornegedgerst_n)begin if(!rst_n) cnt<=0; else begin if(cnt<DELAY_CNT)//1ms cnt<=cnt+1'b1; else cnt<=cnt; endend////sys_rst_nsynchronismassign delay_done=(cnt==DELAY_CNT)?1'b1:1'b0;endmodule摄像头数据采集模块程序:`timescale1ns/1nsmoduleCMOS_Capture( //GlobalClock input iCLK, //25MHz input iRST_N,//I2CInitilizeDoneinput Init_Done, //InitDone //SensorInterface output CMOS_RST_N, //cmosworkstate(5msdelayforsccbconfig) output CMOS_PWDN,//cmospoweron output CMOS_XCLK, //25MHz input CMOS_PCLK, //25MHz input [7:0] CMOS_iDATA, //CMOSData input CMOS_VSYNC, //L:Vaild input CMOS_HREF, //H:Vaild //OuputSensorData output reg CMOS_oCLK, //1/2PCLK output reg [15:0] CMOS_oDATA, //16BitsRGB output reg CMOS_VALID, //DataEnable output reg [7:0] CMOS_FPS_DATA //cmosfps);assign CMOS_RST_N=1'b1; //cmosworkstate(5msdelayforsccbconfig)assignCMOS_PWDN=1'b0; //cmospoweron assign CMOS_XCLK=iCLK; //25MHzXCLK//reg mCMOS_HREF; //行同步:高电平有效always@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) mCMOS_HREF<=0; else mCMOS_HREF<=CMOS_HREF; endwire CMOS_HREF_over=({mCMOS_HREF,CMOS_HREF}==2'b10)?1'b1:1'b0; //HREF下降沿结束*///reg mCMOS_VSYNC;always@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) mCMOS_VSYNC<=1; else mCMOS_VSYNC<=CMOS_VSYNC; //场同步:低电平有效endwire CMOS_VSYNC_over=({mCMOS_VSYNC,CMOS_VSYNC}==2'b01)?1'b1:1'b0; //VSYNC上升沿结束////CountertheHS&VSPixellocalparam H_DISP = 12'd640;localparam V_DISP = 12'd480;reg [11:0] X_Cont; //640reg [11:0] Y_Cont; //480always@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) X_Cont<=0; elseif(~CMOS_VSYNC&CMOS_HREF) //场信号有效 X_Cont<=(byte_state==1'b1)?X_Cont+1'b1:X_Cont; else X_Cont<=0;endalways@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) Y_Cont<=0; elseif(CMOS_VSYNC==1'b0) begin if(CMOS_HREF_over==1'b1) //HREF下降沿一行结束 Y_Cont<=Y_Cont+1'b1; end else Y_Cont<=0;end*/////Changethesensordatafrom8bitsto16bits.reg byte_state; //bytestatecountreg[7:0] Pre_CMOS_iDATA;always@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) begin byte_state<=0; Pre_CMOS_iDATA<=8'd0; CMOS_oDATA<=16'd0; end else begin if(~CMOS_VSYNC&CMOS_HREF) //行场有效,{first_byte,second_byte} begin byte_state<=byte_state+1'b1; //(RGB565={first_byte,second_byte}) case(byte_state) 1'b0: Pre_CMOS_iDATA[7:0]<=CMOS_iDATA; 1'b1: CMOS_oDATA[15:0]<={Pre_CMOS_iDATA[7:0],CMOS_iDATA[7:0]}; endcase end else begin byte_state<=0; Pre_CMOS_iDATA<=8'd0; CMOS_oDATA<=CMOS_oDATA; end endend////WaitforSensoroutputDatavalid,10Franmereg [3:0] Frame_Cont;reg Frame_valid;always@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) begin Frame_Cont<=0; Frame_valid<=0; end elseif(Init_Done) //CMOSI2C初始化完毕 begin if(CMOS_VSYNC_over==1'b1) //VS上升沿,1帧写入完毕 begin if(Frame_Cont<12) begin Frame_Cont <= Frame_Cont+1'b1; Frame_valid<=1'b0; end else begin Frame_Cont <= Frame_Cont; Frame_valid<=1'b1; //数据输出有效 end end endend////CMOS_DATA数据同步输出使能时钟always@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) CMOS_oCLK<=0; elseif(Frame_valid==1'b1&&byte_state)//(X_Cont>=12'd1&&X_Cont<=H_DISP)) CMOS_oCLK<=~CMOS_oCLK; else CMOS_oCLK<=0;end////数据输出有效CMOS_VALIDalways@(posedgeCMOS_PCLKornegedgeiRST_N)begin if(!iRST_N) CMOS_VALID<=0; elseif(Frame_valid==1'b1) CMOS_VALID<=~CMOS_VSYNC; else CMOS_VALID<=0;end//// 2s延时函数reg [25:0] delay_cnt; //25_000000*2always@(posedgeiCLKornegedgeiRST_N)begin if(!iRST_N) delay_cnt<=0; elseif(Frame_valid) begin if(delay_cnt<26'd50_000000) delay_cnt<=delay_cnt+1'b1; else delay_cnt<=0; end else delay_cnt<=0;endwire delay_2s=(delay_cnt==26'd50_000000)?1'b1:1'b0;////帧率采样计算reg fps_state;reg [7:0] fps_data;always@(posedgeiCLKornegedgeiRST_N)begin if(!iRST_N) begin fps_data<=0; fps_state<=0; CMOS_FPS_DATA<=0; end elseif(Frame_valid) begin case(fps_state) 0: begin CMOS_FPS_DATA<=CMOS_FPS_DATA; if(delay_2s==0) begin fps_state<=0; if(CMOS_VSYNC_over==1'b1) //VS上升沿,1帧写入完毕 fps_data<=fps_data+1'b1; end else fps_state<=1; end 1: begin fps_state<=0; fps_data<=0; CMOS_FPS_DATA<=fps_data>>1; end endcase end else begin fps_data<=0; fps_state<=0; CMOS_FPS_DATA<=0; endendendmodule视频数据格式转换模块程序:`timescale1ns/1nsmoduleVIP_RGB888_YCbCr444( //globalclock input clk, //cmosvideopixelclock input rst_n, //globalreset inputwire[15:0]cmos_indata, inputwirecmos_iclk, inputwirecmos_valid,output wire CMOS_oCLK, //1/2PCLK output wire [15:0] CMOS_oDATA, //16BitsRGB output wire CMOS_VALID //DataEnable);///*********************************************//Referto<OV7725CameraModuleSoftwareApplicatonNote>page5 Y = (77*R + 150*G + 29*B)>>8 Cb = (-43*R - 85*G + 128*B)>>8+128 Cr = (128*R - 107*G - 21*B)>>8+128> Y = (77*R + 150*G + 29*B)>>8 Cb = (-43*R - 85*G + 128*B+32768)>>8 Cr = (128*R - 107*G - 21*B+32768)>>8**********************************************///Step1reg [15:0] img_red_r0, img_red_r1, img_red_r2; reg [15:0] img_green_r0, img_green_r1, img_green_r2;reg [15:0] img_blue_r0, img_blue_r1, img_blue_r2;always@(posedgeclkornegedgerst_n)begin if(!rst_n) begin img_red_r0 <= 0; img_red_r1 <= 0; img_red_r2 <= 0; img_green_r0 <= 0; img_green_r1 <= 0; img_green_r2 <= 0; img_blue_r0 <= 0; img_blue_r1 <= 0; img_blue_r2 <= 0; end else begin img_red_r0 <= {cmos_indata[15:11],cmos_indata[15:13]} * 8'd77; img_red_r1 <= {cmos_indata[15:11],cmos_indata[15:13]} * 8'd43; img_red_r2 <= {cmos_indata[15:11],cmos_indata[15:13]} * 8'd128; img_green_r0 <= {cmos_indata[10:5],cmos_indata[10:9]} * 8'd150; img_green_r1 <= {cmos_indata[10:5],cmos_indata[10:9]} * 8'd85; img_green_r2 <= {cmos_indata[10:5],cmos_indata[10:9]} * 8'd107; img_blue_r0 <= {cmos_indata[4:0],cmos_indata[4:2]} * 8'd29; img_blue_r1 <= {cmos_indata[4:0],cmos_indata[4:2]} * 8'd128; img_blue_r2 <= {cmos_indata[4:0],cmos_indata[4:2]} * 8'd21; endend////Step2reg [15:0] img_Y_r0; reg [15:0] img_Cb_r0;reg [15:0] img_Cr_r0;always@(posedgeclkornegedgerst_n)begin if(!rst_n) begin img_Y_r0 <= 0; img_Cb_r0 <= 0; img_Cr_r0 <= 0; end else begin img_Y_r0 <= img_red_r0 + img_green_r0 + img_blue_r0; img_Cb_r0 <= img_blue_r1- img_red_r1 - img_green_r1 + 16'd32768; img_Cr_r0 <= img_red_r2 + img_green_r2 + img_blue_r2 + 16'd32768; endend////Step3reg [7:0] img_Y_r1; reg [7:0] img_Cb_r1;reg [7:0] img_Cr_r1;always@(posedgeclkornegedgerst_n)begin if(!rst_n) begin img_Y_r1 <= 0; img_Cb_r1 <= 0; img_Cr_r1 <= 0; end else begin img_Y_r1 <= img_Y_r0[15:8]; img_Cb_r1 <= img_Cb_r0[15:8]; img_Cr_r1 <= img_Cr_r0[15:8]; endend////lag3clockssignalsyncreg [2:0] cmos_iclk_r;reg [2:0] cmos_valid_r; always@(posedgeclkornegedgerst_n)begin if(!rst_n) begin cmos_iclk_r<=0; cmos_valid_r<=0; end else begin cmos_iclk_r <= {cmos_iclk_r[1:0], cmos_iclk}; cmos_valid_r <= {cmos_valid_r[1:0], cmos_valid}; endendassign CMOS_oCLK = cmos_iclk_r[2];assign CMOS_VALID = cmos_valid_r[2];assignCMOS_oDATA={img_Y_r1[7:3],img_Y_r1[7:2],img_Y_r1[7:3]};endmodule目标识别模块:moduledetect( input wire sclk, input wire cmos_iclk, input wire rst_n, input wire [7:0] image_y, input wire cmos_valid, output wire led_o);parameterYUZHI = 28'he5fffff;reg [27:0] cnt_1;reg[27:0] cnt_2;reg [27:0] cnt_3;reg led_o_r;//reg [27:0] cnt_4;reg cmos_valid_r1,cmos_valid_r2;wirenegedge_valid;always@(posedgesclkornegedgerst_n) if(rst_n==1'b0)begin cmos_valid_r1<='b0; cmos_valid_r2<='b0; end elsebegin cmos_valid_r1<=cmos_valid; cmos_valid_r2<=cmos_valid_r1; end assignnegedge_valid=~cmos_valid_r1&cmos_valid_r2;assignposedge_valid=cmos_valid_r1&~cmos_valid_r2; always@(posedgecmos_iclkornegedgerst_n) if(rst_n==1'b0) cnt_1<='b0; elseif(cmos_valid==1'b1) cnt_1<=cnt_1+image_y; else cnt_1<=cnt_1;always@(posedgesclkornegedgerst_n) if(rst_n==1'b0) cnt_2<='b0; elseif(posedge_valid==1'b1) cnt_2<=cnt_1; always@(posedgesclkornegedgerst_n) if(rst_n==1'b0) cnt_3<='b0; elseif(negedge_valid==1'b1)begin if(cnt_1>cnt_2) cnt_3<=cnt_1-cnt_2; else cnt_3<=cnt_2-cnt_1; end always@(posedgesclkornegedgerst_n) if(rst_n==1'b0) led_o_r<=1'b1; elseif(cnt_3>YUZHI) led_o_r<=1'b0; else led_o_r<=1'b1; assignled_o=led_o_r;endmoduleOV7670图像传感器初始化配置模块`timescale1ns/1nsmoduleI2C_AV_Config( //Globalclock input iCLK, //25MHz input iRST_N, //GlobalReset //I2CSide output I2C_SCLK, //I2CCLOCK inout I2C_SDAT, //I2CDATA output reg Config_Done,//ConfigDone output reg [7:0] LUT_INDEX, //LUTIndex output [7:0] I2C_RDATA //I2CReadData);// LUTDataNumberparameter LUT_SIZE = 168;///////////////////// I2CControlClock ////////////////////////// ClockSettingparameter CLK_Freq = 25_000000; //25MHzparameter I2C_Freq = 10_000; //10KHzreg [15:0] mI2C_CLK_DIV; //CLKDIVreg mI2C_CTRL_CLK; //I2CControlClockalways@(posedgeiCLKornegedgeiRST_N)begin if(!iRST_N) begin mI2C_CLK_DIV <= 0; mI2C_CTRL_CLK <= 0; end else begin if(mI2C_CLK_DIV <(CLK_Freq/I2C_Freq)/2) mI2C_CLK_DIV <= mI2C_CLK_DIV+1'd1; else begin mI2C_CLK_DIV <= 0; mI2C_CTRL_CLK <= ~mI2C_CTRL_CLK; end endend//reg i2c_en_r0,i2c_en_r1;always@(posedgeiCLKornegedgeiRST_N)begin if(!iRST_N) begin i2c_en_r0<=0; i2c_en_r1<=0; end else begin i2c_en_r0<=mI2C_CTRL_CLK; i2c_en_r1<=i2c_en_r0; endendwire i2c_negclk=(i2c_en_r1&~i2c_en_r0)?1'b1:1'b0; //negedgei2c_sclktransferdata////////////////////// ConfigControl //////////////////////////////InternalRegisters/Wires//reg [23:0] mI2C_DATA; //I2CDatawire mI2C_END; //I2CTransferEndwire mI2C_ACK; //I2CTransfer

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论