资讯详情

【正点原子FPGA连载】第三十九章OV7725摄像头RGB-LCD显示实验 -摘自【正点原子】新起点之FPGA开发指南_V2.1

1)实验平台:正点原子新起点V2开发板 2)平台采购地址:https://detail.tmall.com/item.htm?id=609758951113 2)全套实验源码 手册 视频下载地址:http://www.openedv.com/thread-300792-1-1.html 3)正点原子FPGA感兴趣的同学可以加群讨论:99424016 4)关注正点原子微信官方账号,获取最新信息更新 在这里插入图片描述

第三十九章OV7725摄像头RGB-LCD显示实验

OV7725是OmniVision(豪威科技)公司生产的一个CMOS图像传感器主要用于玩具、安全监控、计算机多媒体等领域、安全监控、计算机多媒体等领域。本章将使用FPGA实现正确的开发板OV通过收集和收集7725的数字图像LCD实时显示。 本章包括以下几个部分: 3838.1简介 38.2实验任务 38.3硬件设计 38.4程序设计 38.5下载验证

39.1简介 OV7725是一种1/4英寸单芯片图像传感器,其感光阵列达到640*480,最快60fps VGA图像采集的分辨率。图像处理功能集成在传感器内,包括自动曝光控制(AEC)、自动增益控制(AGC)与自动白平衡(AWB)等。同时,传感器具有较高的感光灵敏度,适用于低照度的应用下图为OV功能框图7725。

图 39.1.1 OV7725功能框图 由上图可知,感光阵列(image array)在XCLK图像采样由时钟驱动,输出640*480阵列的模拟数据;然后在时序发生器中模拟信号处理器(video timing generator)在控制下,算法处理模拟数据(analog processing);模拟数据处理完成后分成G(绿色)和R/B(红/蓝)两条通道经过AD转换器转换成数字信号后,并且通过DSP对相关图像进行处理,最终输出配置格式的10位视频数据流。模拟信号处理和DSP通过寄存器等(registers)配置寄存器的接口是SCCB接口协议与接口兼容IIC协议。 SCCB(Serial Camera Control Bus,串行摄像头控制总线OV(OmniVision公司定义和开发的三线串行总线控制着摄像头的大部分功能,包括图像数据格式、分辨率和图像处理参数。OV为了减少传感器引脚的包装,公司现在SCCB大多数总线采用两线接口总线。 OV7725采用两线接口总线,包括SIO_C串行时钟输入线和SIO_D串行双向数据线相当于IIC协议的SCL信号线和SDA信号线。我们前面提到过SCCB协议兼容IIC因为协议SCCB协议和IIC协议非常相似,相关IIC详细介绍协议请参考EEPROM读写实验章节。 SCCB如下图所示:

图 39.1.2 SCCB写传输协议 上图中的ID ADDRESS由7位器件地址和1位读写控制位组成 1:读),OV7725器件地址为7‘h因此,在写传输协议时,ID Address(W) = 8’h42(设备地址左移1位,低位补0);Sub-address为8位寄存器地址,在OV0725的数据手册定义为0x00~0xAC共有173个寄存器,有的寄存器可以重写,有的只读,只有可重写的寄存器才能正确写;Write Data为8位写数据,每个寄存器地址对应8位配置数据。上图中的第9位X表示Don’t Care(不用担心)OV7725)发出响应信号响应主机ID Address、Sub-address和Write Data是否传输完成,但从机可能不会发出响应信号,因此主机(此处指FPGA)不需要判断这里是否有回应,直接默认完成当前传输。 我们可以发现,SCCB和IIC写传输协议很像,只是在SCCB在写传输协议时,第九个不需要关心,IIC写传输协议作为响应位。SCCB阅读传输协议和IIC有些差异,在IIC在阅读传输协议时,将会有寄存器地址restart也就是重复开始的操作;而SCCB读取传输协议中没有重复开始的概念。写完寄存器地址后,启动总线停止信号。SCCB读传输协议。

图 39.1.3 SCCB读传输协议 从上图可以看出,SCCB阅读传输协议分为两部分。第一部分是编写设备地址和寄存器地址,即首先进行虚写操作。通过这种虚写操作,地址指针指向虚写操作中寄存器地址的位置。当然,虚写操作也可以通过上述写作传输协议来完成。第二部分是读取器件地址和数据。此时读取的数据是寄存器地址对应的数据。ID Address(R) = 8’h43(设备地址左移1位,低位补1位)。上图中的NA位于主机(这里指FPGA)产生,由于SCCB总线不支持连续读写,所以NA位置必须为高电平。 在OV在7725正常工作之前,传感器必须初始化,即在预期的工作模式下工作,并通过配置寄存器获得更好的图像质量。因为SCCB写传输协议和IIC几乎一样,所以我们可以直接使用IIC配置摄像头的驱动程序。当然,并非所有的寄存器都需要配置,许多寄存器可以使用默认值。OV公司提供了OV7725软件使用手册(OV7725 Software Application Note,附在开发板上的信息7_硬件资料/6_OV7725资料/OV7725 Software Application Note.pdf若某些寄存器不知道如何配置,可参考本手册,下表是本程序使用的关键寄存器的配置说明。 表 39.1.1 OV7725关键寄存器配置说明

OV7725寄存器较多,其他寄存器的描述可参考OV数据手册7725。 下图为OV7725的一些特性。

图 39.1.4 OV7725的特性 从上图可以看出,OV7725的输入时钟频率为10Mhz~48Mhz,实验摄像头的输入时钟为12 Mhz;SCCB总线的SIO_C最大时钟频率为400KHz;配置寄存器软件复位(寄存器地址0x12 Bit[7]位)和硬件复位(cam_rst_n引脚后需要等待最大1ms配置其他寄存器;每次配置寄存器后,最大需要300ms时间延迟,也就是说,10帧图像输出时间可以输出稳定的视频流。 OV7725支持各种不同分辨率图像的输出,包括VGA(640480)、QVGA(320240)以及CIF(分辨率为352的常用标准化图像格式288)到4030等任何尺寸。寄存器地址0x12(COM7)、0x17(HSTART)、0x18(HSIZE)、0x19(VSTRT)、0x1A(VSIZE)、0x32(HREF)、0x29(HoutSize)、0x2C(VOutSize)、0x2A(EXHCH)配置输出图像的分辨率。 OV7725支持多种不同的数据像素格式,包括YUV(像素格式分别表示亮度参数和色度参数),RGB(其中RGB格式包含RGB565、RGB555等)和8位RAW(原始图像数据)和10位RAW,通过寄存器地址0x12(COM7)配置不同的数据像素格式。 因为相机采集的图像最终必须在LCD上显示,新起点开发板上的数据接口为RGB详见888格式LCD因此,我们将展示彩条实验的章节)OV7725摄像头输出的图像素数据配置成RGB然后将565格式转换为565格式RGB888格式。下图为摄像头输出VGA帧模式时序图。

图 39.1.5 VGA帧模式输出时序图br> 在介绍时序图之前先了解几个基本的概念。 VSYNC:场同步信号,由摄像头输出,用于标志一帧数据的开始与结束。上图中VSYNC的高电平作为一帧的同步信号,在低电平时输出的数据有效。需要注意的是场同步信号是可以通过设置寄存器0x15 Bit[1]位进行取反的,即低电平同步高电平有效,本次实验使用的是和上图一致的默认设置; HREF/HSYNC:行同步信号,由摄像头输出,用于标志一行数据的开始与结束。上图中的HREF和HSYNC是由同一引脚输出的,只是数据的同步方式不一样。本次实验使用的是HREF格式输出,当HREF为高电平时,图像输出有效,可以通过寄存器0x15 Bit[6]进行配置。本次实验使用的是HREF格式输出; D[9:0]:数据信号,由摄像头输出,在RGB格式输出中,只有高8位D[9:2]是有效的; tPCLK:一个像素时钟周期; tp:单个数据周期,这里需要注意的是上图中左下角红框标注的部分,在RGB模式中,tp代表两个tPCLK(像素时钟)。以RGB565数据格式为例,RGB565采用16bit数据表示一个像素点,而OV7725在一个像素周期(tPCLK)内只能传输8bit数据,因此需要两个时钟周期才能输出一个RGB565数据; tLine:摄像头输出一行数据的时间,共784个tp,包含640tp个高电平和144tp个低电平,其中640tp为有效像素数据输出的时间。以RGB565数据格式为例,640tp实际上是6402=1280个tPCLK; 由图 39.1.5可知,VSYNC的上升沿作为一帧的开始,高电平同步脉冲的时间为4tLine,紧接着等待18tLine时间后,HREF开始拉高,此时输出有效数据;HREF由640tp个高电平和144tp个低电平构成;输出480行数据之后等待8tLine时间一帧数据传输结束。所以输出一帧图像的时间实际上是tFrame =(4 + 18 + 480 + 8)tLine = 510tLine。 本次实验采用OV7725支持的最大分辨率640480,摄像头的输入时钟为12 Mhz,摄像头的输出时钟为24 Mhz(详细公式请看表 39.1.1),由此我们可以计算出摄像头的输出帧率,以PCLK=24Mhz(周期为42ns)为例,计算出OV7725输出一帧图像所需的时间如下: 一帧图像输出时间:tFrame = 510tLine = 510784tp = 5107842tPCLK = 799680*42ns =33.5866ms; 摄像头输出帧率:1000ms/33.5866ms ≈ 30Hz。 如果把像素时钟频率提高到摄像头的最大时钟频率48Mhz,通过上述计算方法,摄像头的输出帧率约为60Hz。 下图为OV7725输出RGB565格式的时序图:

图 39.1.6 RGB565模式时序图 上图中的PCLK为OV7725输出的像素时钟,HREF为行同步信号,D[9:2]为8位像素数据。OV7725最大可以输出10位数据,在RGB565输出模式中,只有高8位是有效的。像素数据在HREF为高电平时有效,第一次输出的数据为RGB565数据的高8位,第二次输出的数据为RGB565数据的低8位,first byte和second byte组成一个16位RGB565数据。由上图可知,数据是在像素时钟的下降沿改变的,为了在数据最稳定的时刻采集图像数据,所以我们需要在像素时钟的上升沿采集数据。 39.2实验任务 本节实验任务是使用新起点开发板及OV7725摄像头实现图像采集,并通过RGB-LCD接口驱动RGB-LCD液晶屏(支持目前正点原子推出的所有RGB-LCD屏),并实时显示出图像。 39.3硬件设计 新起点FPGA开发板上有一个摄像头扩展接口,该接口可以用来连接OV7725/OV5640等摄像头模块,摄像头扩展接口原理图如图 39.3.1所示:

图 39.3.1 摄像头扩展接口原理图 ATK-OV7725是正点原子推出的一款高性能30W像素高清摄像头模块。该模块通过2*9排针(2.54mm间距)同外部连接,我们将摄像头的排针直接插在开发板上的摄像头接口即可,如下图所示:

图 39.3.2 OV7725摄像头连接开发板图 前面说过,OV7725在RGB565模式中只有高8位数据是有效的即D[9:2],而我们的摄像头排针上数据引脚的个数是8位。实际上,摄像头排针上的8位数据连接的就是OV7725传感器的D[9:2],所以我们直接使用摄像头排针上的8位数据引脚即可。 需要注意的是,由图 39.3.1可知,摄像头扩展口的第18个引脚定义为CMOS_PWDN,而我们的OV7725摄像头模块的PWDN引脚固定为低电平,也就是一直处于正常工作模式。OV7725摄像头模块的第18个引脚定义为SGM_CTRL(CMOS_PWDN),这个引脚是摄像头驱动时钟的选择引脚。OV7725摄像头模块内部自带晶振的,当SGM_CTRL引脚为低电平时,选择使用摄像头的外部时钟,也就是FPGA需要输出时钟给摄像头;当SGM_CTRL引脚为高电平时,选择使用摄像头的晶振提供时钟。本次实验将SGM_CTRL引脚驱动为高电平,这样就不用为摄像头提供驱动时钟,即不用在CMOS_XCLK引脚上输出时钟。 由于LCD接口和SDRAM引脚数目较多且在前面相应的章节中已经给出它们的管脚列表,这里只列出摄像头相关管脚分配,如下表所示: 表 39.3.1 OV7725摄像头管脚分配

摄像头TCL约束文件如下: set_location_assignment PIN_M2 -to sys_clk set_location_assignment PIN_M1 -to sys_rst_n set_location_assignment PIN_B14 -to sdram_clk set_location_assignment PIN_G11 -to sdram_ba[0] set_location_assignment PIN_F13 -to sdram_ba[1] set_location_assignment PIN_J12 -to sdram_cas_n set_location_assignment PIN_F16 -to sdram_cke set_location_assignment PIN_K11 -to sdram_ras_n set_location_assignment PIN_J13 -to sdram_we_n set_location_assignment PIN_K10 -to sdram_cs_n set_location_assignment PIN_J14 -to sdram_dqm[0] set_location_assignment PIN_G15 -to sdram_dqm[1] set_location_assignment PIN_F11 -to sdram_addr[0] set_location_assignment PIN_E11 -to sdram_addr[1] set_location_assignment PIN_D14 -to sdram_addr[2] set_location_assignment PIN_C14 -to sdram_addr[3] set_location_assignment PIN_A14 -to sdram_addr[4] set_location_assignment PIN_A15 -to sdram_addr[5] set_location_assignment PIN_B16 -to sdram_addr[6] set_location_assignment PIN_C15 -to sdram_addr[7] set_location_assignment PIN_C16 -to sdram_addr[8] set_location_assignment PIN_D15 -to sdram_addr[9] set_location_assignment PIN_F14 -to sdram_addr[10] set_location_assignment PIN_D16 -to sdram_addr[11] set_location_assignment PIN_F15 -to sdram_addr[12] set_location_assignment PIN_P14 -to sdram_data[0] set_location_assignment PIN_M12 -to sdram_data[1] set_location_assignment PIN_N14 -to sdram_data[2] set_location_assignment PIN_L12 -to sdram_data[3] set_location_assignment PIN_L13 -to sdram_data[4] set_location_assignment PIN_L14 -to sdram_data[5] set_location_assignment PIN_L11 -to sdram_data[6] set_location_assignment PIN_K12 -to sdram_data[7] set_location_assignment PIN_G16 -to sdram_data[8] set_location_assignment PIN_J11 -to sdram_data[9] set_location_assignment PIN_J16 -to sdram_data[10] set_location_assignment PIN_J15 -to sdram_data[11] set_location_assignment PIN_K16 -to sdram_data[12] set_location_assignment PIN_K15 -to sdram_data[13] set_location_assignment PIN_L16 -to sdram_data[14] set_location_assignment PIN_L15 -to sdram_data[15] set_location_assignment PIN_R1 -to lcd_bl set_location_assignment PIN_T2 -to lcd_de set_location_assignment PIN_T3 -to lcd_hs set_location_assignment PIN_P3 -to lcd_vs set_location_assignment PIN_R3 -to lcd_pclk set_location_assignment PIN_L1 -to lcd_rst set_location_assignment PIN_T4 -to lcd_rgb[4] set_location_assignment PIN_R4 -to lcd_rgb[3] set_location_assignment PIN_T5 -to lcd_rgb[2] set_location_assignment PIN_R5 -to lcd_rgb[1] set_location_assignment PIN_T6 -to lcd_rgb[0] set_location_assignment PIN_R6 -to lcd_rgb[10] set_location_assignment PIN_T7 -to lcd_rgb[9] set_location_assignment PIN_R7 -to lcd_rgb[8] set_location_assignment PIN_T8 -to lcd_rgb[7] set_location_assignment PIN_R8 -to lcd_rgb[6] set_location_assignment PIN_T9 -to lcd_rgb[5] set_location_assignment PIN_R9 -to lcd_rgb[15] set_location_assignment PIN_T10 -to lcd_rgb[14] set_location_assignment PIN_R10 -to lcd_rgb[13] set_location_assignment PIN_T11 -to lcd_rgb[12] set_location_assignment PIN_R11 -to lcd_rgb[11] set_location_assignment PIN_T14 -to cam_data[7] set_location_assignment PIN_R14 -to cam_data[6] set_location_assignment PIN_N6 -to cam_data[5] set_location_assignment PIN_P6 -to cam_data[4] set_location_assignment PIN_M8 -to cam_data[3] set_location_assignment PIN_N8 -to cam_data[2] set_location_assignment PIN_P8 -to cam_data[1] set_location_assignment PIN_K9 -to cam_data[0] set_location_assignment PIN_M9 -to cam_href set_location_assignment PIN_R13 -to cam_pclk set_location_assignment PIN_L9 -to cam_rst_n set_location_assignment PIN_N9 -to cam_scl set_location_assignment PIN_L10 -to cam_sda set_location_assignment PIN_P9 -to cam_vsync set_location_assignment PIN_R12 -to cam_sgm_ctrl 39.4程序设计 OV7725在VGA帧模式下,以RGB565格式输出最高帧率可达60Hz,LCD屏的刷新频率也可以达到60Hz,那么是不是直接将采集到的图像数据连接到LCD屏的输入数据端口就行了呢?答案是不可以。我们在前面说过,OV7725帧率如果要达到60Hz,那么像素时钟频率必须为48Mhz,而LCD屏根据屏的分辨率不同时钟也不同,首先就有时钟不匹配的问题,其次是时序方面的不匹配,LCD屏驱动对时序有着严格的要求。我们在“RGB-LCD彩条显示实验”的章节中可以获知,LCD一行或一场分为四个部分:低电平同步脉冲、显示后沿、有效数据段以及显示前沿,各个部分的时序参数很显然跟OV7725并不是完全一致的。因此必须先把一帧图像缓存下来,然后再把图像数据按照LCD的时序发送到LCD屏上显示。OV7725在VGA帧模式输出下,一帧图像的数据量达到64048016bit = 4915200bit = 4800kbit = 4.6875Mbit,带宽为4.6875Mbit45Hz(帧率)=210.9375 Mbit/S,我们新起点FPGA开发板芯片型号为EP4CE10F17C8,器件手册可以发现,EP4CE10F17C8的片内存储资源为414Kbit,远不能达到存储要求。因此我们只能使用板载的外部存储器SDRAM来缓存图像数据,新起点板载的SDRAM容量为256Mbit,最大带宽为2.66Gbit/S(16bit166M),足以满足缓存图像数据的需求。 OV7725在正常工作之前必须通过配置寄存器进行初始化,而配置寄存器的SCCB协议和I2C协议在写操作时几乎一样,所以我们需要一个I2C驱动模块。为了使OV7725在期望的模式下运行并且提高图像显示效果,需要配置较多的寄存器,这么多寄存器的地址与参数需要单独放在一个模块,因此还需要一个寄存配置信息的I2C配置模块。在摄像头配置完成后,开始输出图像数据,因此需要一个摄像头图像采集模块来采集图像;外接SDRAM存储器当然离不开SDRAM控制器模块的支持,最后LCD顶层模块读取SDRAM缓存的数据以达到最终实时显示的效果。

图 39.4.1 程序结构框图 由上图可知,时钟模块(pll_clk)为LCD顶层模块、SDRAM控制模块以及I2C驱动模块提供驱动时钟。I2C配置模块和I2C驱动模块控制着传感器初始化的开始与结束,传感器初始化完成后图像采集模块将采集到的数据写入SDRAM控制模块,LCD顶层模块从SDRAM控制模块中读出数据,完成了数据的采集、缓存与显示。需要注意的是图像数据采集模块是在SDRAM和传感器都初始化完成之后才开始输出数据的,避免了在SDRAM初始化过程中向里面写入数据。 顶层模块的原理图如下图所示:

图 39.4.2 RTL视图 FPGA顶层模块(ov7725_rgb565_lcd)例化了以下六个模块:时钟模块(pll_clk)、I2C驱动模块(i2c_dri)、I2C配置模块(i2c_ov7725_rgb565_cfg)、图像采集顶层模块(cmos_data_top)、SDRAM控制模块(sdram_top)和LCD顶层模块(lcd_rgb_top)。 时钟模块(pll_clk):时钟模块通过调用PLL IP核实现,共输出3个时钟,频率分别为100Mhz(SDRAM参考时钟)、100M偏移-75度时钟(SDRAM芯片输入时钟)和50Mhz时钟。100Mhz时钟作为SDRAM控制模块的参考时钟,100M偏移-75度时钟用来输出给外部SDRAM芯片使用,50Mhz时钟作为I2C驱动模块和LCD顶层模块的驱动时钟。 I2C驱动模块(i2c_dri):I2C驱动模块负责驱动OV7725 SCCB接口总线,用户可根据该模块提供的用户接口可以很方便的对OV7725的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节。 I2C配置模块(i2c_ov7725_rgb565_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址、数据以及控制初始化的开始与结束,同时该模块输出OV7725的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对OV7725传感器的初始化。 图像采集顶层模块(cmos_data_top):摄像头采集模块在像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据转换成SDRAM控制模块的写使能信号和16位写数据信号,完成对OV7725传感器图像的采集。如果LCD屏的分辨率小于OV7725的分辨率,还要对OV7725采集的数据进行裁剪,以匹配LCD屏的分辨率。 SDRAM读写控制模块(sdram_top):SDRAM读写控制器模块负责驱动SDRAM片外存储器,缓存图像传感器输出的图像数据。该模块将SDRAM复杂的读写操作封装成类似FIFO的用户接口,非常方便用户的使用。在“SDRAM读写测试实验”的程序中,读写操作地址都是SDRAM的同一存储空间,如果只使用一个存储空间缓存图像数据,那么同一存储空间中会出现两帧图像叠加的情况,为了避免这一情况,我们在SDRAM的其它BANK中开辟一个相同大小的存储空间,使用乒乓操作的方式来写入和读取数据,所以本次实验在“SDRAM读写测试实验”的程序里做了一个小小的改动,有关该模块的详细介绍请大家参考“SDRAM读写测试实验”章节,本章只对改动的地方作介绍。 LCD顶层模块(lcd_rgb_top):LCD顶层模块负责驱动LCD屏的驱动信号的输出,同时为其他模块提供屏体参数、场同步信号和数据请求信号。 顶层模块的代码如下:

1   module ov7725_rgb565_lcd(    
2       input                 sys_clk     ,  //系统时钟
3       input                 sys_rst_n   ,  //系统复位,低电平有效
4       //摄像头接口
5       input                 cam_pclk    ,  //cmos 数据像素时钟
6       input                 cam_vsync   ,  //cmos 场同步信号
7       input                 cam_href    ,  //cmos 行同步信号
8       input        [7:0]    cam_data    ,  //cmos 数据
9       output                cam_rst_n   ,  //cmos 复位信号,低电平有效
10      output                cam_sgm_ctrl,  //cmos 时钟选择信号, 1:使用摄像头自带的晶振
11      output                cam_scl     ,  //cmos SCCB_SCL线
12      inout                 cam_sda     ,  //cmos SCCB_SDA线
13      //SDRAM接口
14      output                sdram_clk   ,  //SDRAM 时钟
15      output                sdram_cke   ,  //SDRAM 时钟有效
16      output                sdram_cs_n  ,  //SDRAM 片选
17      output                sdram_ras_n ,  //SDRAM 行有效
18      output                sdram_cas_n ,  //SDRAM 列有效
19      output                sdram_we_n  ,  //SDRAM 写有效
20      output       [1:0]    sdram_ba    ,  //SDRAM Bank地址
21      output       [1:0]    sdram_dqm   ,  //SDRAM 数据掩码
22      output       [12:0]   sdram_addr  ,  //SDRAM 地址
23      inout        [15:0]   sdram_data  ,  //SDRAM 数据 
24      //lcd接口 
25      output                lcd_hs      ,  //LCD 行同步信号
26      output                lcd_vs      ,  //LCD 场同步信号
27      output                lcd_de      ,  //LCD 数据输入使能
28      inout        [15:0]   lcd_rgb     ,  //LCD RGB565颜色数据
29      output                lcd_bl      ,  //LCD 背光控制信号
30      output                lcd_rst     ,  //LCD 复位信号
31      output                lcd_pclk       //LCD 采样时钟
32      );
33  
34  //parameter define
35  parameter  SLAVE_ADDR = 7'h21 ; //OV7725的器件地址7'h21
36  parameter  BIT_CTRL   = 1'b0          ;  //OV7725的字节地址为8位 0:8位 1:16位
37  parameter  CLK_FREQ   = 26'd50_000_000;  //i2c_dri模块的驱动时钟频率 33.3MHz
38  parameter  I2C_FREQ   = 18'd250_000   ;  //I2C的SCL时钟频率,不超过400KHz
39  
40  //wire define
41  wire                  clk_100m        ;  //100mhz时钟,SDRAM操作时钟
42  wire                  clk_100m_shift  ;  //100mhz时钟,SDRAM相位偏移时钟
43  wire                  clk_50m         ;  //50mhz时钟,提供给lcd驱动时钟
44  wire                  locked          ;
45  wire                  rst_n           ;
46                                      
47  wire                  i2c_exec        ;  //I2C触发执行信号
48  wire   [15:0]         i2c_data        ;  //I2C要配置的地址与数据(高8位地址,低8位数据) 
49  wire                  cam_init_done   ;  //摄像头初始化完成
50  wire                  i2c_done        ;  //I2C寄存器配置完成信号
51  wire                  i2c_dri_clk     ;  //I2C操作时钟 
52  wire                  wr_en           ;  //sdram_ctrl模块写使能
53  wire   [15:0]         wr_data         ;  //sdram_ctrl模块写数据
54  wire                  rd_en           ;  //sdram_ctrl模块读使能
55  wire                  sdram_init_done ;  //SDRAM初始化完成
56  wire                  rdata_req       ;  //SDRAM控制器模块读使能
57  wire   [15:0]         rd_data             ;  //SDRAM控制器模块读数据
58  wire                  cmos_frame_valid    ;  //数据有效使能信号
59  wire                  init_calib_complete ;  //SDRAM初始化完成init_calib_complete
60  wire                  sys_init_done       ;  //系统初始化完成(SDRAM初始化+摄像头初始化)
61  wire                  clk_200m            ;  //SDRAM参考时钟
62  wire                  cmos_frame_vsync    ;  //输出帧有效场同步信号 
63  wire                  cmos_frame_href     ;  //输出帧有效行同步信号 
64  wire    [7:0]         wr_bust_len         ;  //从SDRAM中读数据时的突发长度
65  wire    [9:0]         pixel_xpos_w        ;  //像素点横坐标
66  wire    [9:0]         pixel_ypos_w        ;  //像素点纵坐标 
67  wire                  lcd_clk             ;  //分频产生的LCD 采样时钟
68  wire    [10:0]        h_disp              ;  //LCD屏水平分辨率
69  wire    [10:0]        v_disp              ;  //LCD屏垂直分辨率 
70  wire    [10:0]        h_pixel             ;  //存入SDRAM的水平分辨率 
71  wire    [10:0]        v_pixel             ;  //存入SDRAM的屏垂直分辨率 
72  wire    [15:0]        lcd_id              ;  //LCD屏的ID号
73  wire    [27:0]        sdram_addr_max      ;  //存入SDRAM的最大读写地址
74  
75  //*****************************************************
76  //** main code
77  //*****************************************************
78  
79  assign  rst_n = sys_rst_n & locked;
80  //系统初始化完成:SDRAM和摄像头都初始化完成
81  //避免了在SDRAM初始化过程中向里面写入数据
82  assign  sys_init_done = sdram_init_done & cam_init_done;
83  //不对摄像头硬件复位,固定高电平
84  assign  cam_rst_n = 1'b1;
85  //cmos 时钟选择信号, 1:使用摄像头自带的晶振
86  assign  cam_sgm_ctrl = 1'b1;
87  
88  //相环
89  pll_clk u_pll_clk(
90      .areset       (~sys_rst_n),
91      .inclk0       (sys_clk),
92      .c0           (clk_100m),
93      .c1           (clk_100m_shift),
94      .c2           (clk_50m),
95      .locked       (locked)
96      );
97  
98  //I2C配置模块 
99  i2c_ov7725_rgb565_cfg u_i2c_cfg(
100     .clk           (i2c_dri_clk),
101     .rst_n         (rst_n),
102     .i2c_done      (i2c_done),
103     .i2c_exec      (i2c_exec),
104     .i2c_data      (i2c_data),
105     .init_done     (cam_init_done)
106     );    
107 
108 //I2C驱动模块
109 i2c_dri 
110 #(
111     .SLAVE_ADDR  (SLAVE_ADDR),               //参数传递
112     .CLK_FREQ    (CLK_FREQ  ),              
113     .I2C_FREQ    (I2C_FREQ  )                
114     ) 
115 u_i2c_dri(
116     .clk         (clk_50m   ),   
117     .rst_n       (rst_n     ),   
118     //i2c interface
119     .i2c_exec    (i2c_exec  ),   
120     .bit_ctrl    (BIT_CTRL  ),   
121     .i2c_rh_wl   (1'b0),                     //固定为0,只用到了IIC驱动的写操作 
122     .i2c_addr    (i2c_data[15:8]),   
123     .i2c_data_w  (i2c_data[7:0]),   
124     .i2c_data_r  (),   
125     .i2c_done    (i2c_done  ),   
126     .scl         (cam_scl   ),   
127     .sda         (cam_sda   ),   
128     //user interface
129     .dri_clk     (i2c_dri_clk)               //I2C操作时钟
130 );
131 
132 //CMOS图像数据采集模块
133 cmos_data_top u_cmos_data_top(
134     .rst_n                 (rst_n & sys_init_done), //系统初始化完成之后再开始采集数据 
135     .cam_pclk              (cam_pclk),
136     .cam_vsync             (cam_vsync),
137     .cam_href              (cam_href),
138     .cam_data              (cam_data),
139     .lcd_id                (lcd_id),  
140     .h_disp                (h_disp),
141     .v_disp                (v_disp),  
142     .h_pixel               (h_pixel),
143     .v_pixel               (v_pixel),
144     .sdram_addr_max        (sdram_addr_max),    
145     .cmos_frame_vsync      (cmos_frame_vsync),
146     .cmos_frame_href       (cmos_frame_href),
147     .cmos_frame_valid      (cmos_frame_valid),      //数据有效使能信号
148     .cmos_frame_data       (wr_data)                //有效数据 
149     );
150 
151 //SDRAM 控制器顶层模块,封装成FIFO接口
152 //SDRAM 控制器地址组成: {bank_addr[1:0],row_addr[12:0],col_addr[8:0]}
153 sdram_top u_sdram_top(
154 .ref_clk      (clk_100m),                   //sdram 控制器参考时钟
155 .out_clk      (clk_100m_shift),             //用于输出的相位偏移时钟
156 .rst_n        (rst_n),                      //系统复位
157                                             
158 //用户写端口 
159 .wr_clk       (cam_pclk),                   //写端口FIFO: 写时钟
160 .wr_en        (cmos_frame_valid),           //写端口FIFO: 写使能
161 .wr_data      (wr_data),                    //写端口FIFO: 写数据
162 .wr_min_addr  (24'd0),                      //写SDRAM的起始地址
163 .wr_max_addr  (sdram_addr_max),             //写SDRAM的结束地址
164 .wr_len       (10'd512),                    //写SDRAM时的数据突发长度
165 .wr_load      (~rst_n),                     //写端口复位: 复位写地址,清空写FIFO
166                                             
167 //用户读端口 
168 .rd_clk       (lcd_clk),                    //读端口FIFO: 读时钟
169 .rd_en        (rdata_req),                  //读端口FIFO: 读使能
170 .rd_data      (rd_data),                    //读端口FIFO: 读数据
171 .rd_min_addr  (24'd0),                      //读SDRAM的起始地址
172 .rd_max_addr  (sdram_addr_max),             //读SDRAM的结束地址
173 .rd_len       (10'd512),                    //从SDRAM中读数据时的突发长度
174 .rd_load      (~rst_n),                     //读端口复位: 复位读地址,清空读FIFO
175                                             
176 //用户控制端口 
177 .sdram_read_valid  (1'b1),                  //SDRAM 读使能
178 .sdram_pingpang_en (1'b1),                  //SDRAM 乒乓操作使能
179 .sdram_init_done (sdram_init_done),         //SDRAM 初始化完成标志
180                                             
181 //SDRAM 芯片接口 
182 .sdram_clk    (sdram_clk),                  //SDRAM 芯片时钟
183 .sdram_cke    (sdram_cke),                  //SDRAM 时钟有效
184 .sdram_cs_n   (sdram_cs_n),                 //SDRAM 片选
185 .sdram_ras_n  (sdram_ras_n),                //SDRAM 行有效
186 .sdram_cas_n  (sdram_cas_n),                //SDRAM 列有效
187 .sdram_we_n   (sdram_we_n),                 //SDRAM 写有效
188 .sdram_ba     (sdram_ba),                   //SDRAM Bank地址
189 .sdram_addr   (sdram_addr),                 //SDRAM 行/列地址
190 .sdram_data   (sdram_data),                 //SDRAM 数据

        标签: c2h6传感器7p8pin连接器m8接近开关传感器e2e3055d5t加速度传感器05n直流三线传感器21pin翻盖连接器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台