【正点原子FPGA连载】第三十六章 基于OV5640的PL以太网视频传输实验-摘自【正点原子】领航者ZYNQ之FPGA开发...
时间:2023-12-03 23:07:02
1)实验平台:正点原子领导者ZYNQ开发板
2)平台采购地址:https://item.taobao.com/item.htm?&id=606160108761
3)全套实验源码 手册 视频下载地址:http://www.openedv.com/thread-301505-1-1.html
4)正点原子FPGA感兴趣的同学可以加群讨论:99424016
5)关注正点原子微信官方账号,获取最新信息更新
第三十六章 基于OV5640的PL以太网视频传输实验
OV5640同OV7725一样,都是OmniVision公司生产的(豪威科技)CMOS图像传感器。不同的是,OV5640支持更高的分辨率和采集率,具有更高的图像处理性能,主要用于手机、数码相机、计算机多媒体等领域。
在“基于OV7725的PL在以太网视频传输实验中,摄像头采集的图像实时显示在上位机显示软件上。本章将用于ZYNQ实现正确的开发板OV通过开发板采集5640数字图像,PL将以太网接口发送到上位机实时显示。
本章分为以下章节:
36.1 简介
36.2 实验任务
36.3 硬件设计
36.4 程序设计
36.5 下载验证
36.1 简介
OV5640是1/4英寸单芯片图像传感器,其感光阵列达到25921944(即500W像素),最快15fps QSXVGA(25921944)或者90fps VGA(640*480)图像采集的分辨率。传感器采用OmniVision推出的OmniBSI高灵敏度、低串扰、低噪声等传感器技术。图像处理功能集成在传感器内,包括自动曝光控制(AEC)、自动白平衡(AWB)等。传感器支持LED补光、MIPI输出接口和(移动工业处理器接口)DVP输出界面选择(数字视频并行)ISP(图像信号处理)和AFC(自动聚焦控制)等功能。
OV如下图所示,5640功能框图:
图 7.5.13.1 OV5640功能框图
从上图可以看出,时序发生器(timing generator)控制感光阵列(image array)、放大器(AMP)、AD输出外部时序信号(VSYNC、HREF和PCLK),外部时钟XVCLK经过PLL锁相环后输出的时钟作为系统的控制时钟;感光阵列将光信号转换为模拟信号,增益放大器后进入10位AD转换器;AD转换器将模拟信号转换为数字信号,并通过ISP进行相关图像处理,最终输出所配置格式的10位视频数据流。控制和控制增益放大器ISP通过寄存器等(registers)配置寄存器的接口是SCCB接口协议与接口兼容IIC协议。
OV5640采用两线式SCCB接口总线,有关SCCB详细介绍总线可参考基于OV7725的PL以太网视频传输实验OV7725简介部分。虽然OV5640和OV7725都是采用SCCB接口总线配置寄存器,但同,OV7725用8位(1字节)表示寄存器地址OV寄存器地址用16位(两个字节)表示。
OV5640 SCCB如下图所示:
图 7.5.13.2 OV5640 SCCB写传输协议
上图中的ID ADDRESS由7位器件地址和1位读写控制位组成 1:读),OV5640器件地址为7’h3c,因此,在写传输协议时,ID Address(W)= 8’h78(设备地址左移1位,低位补0);Sub-address(H)高8位寄存器地址,Sub-address(L)在低8位寄存器地址OV在5640多个寄存器中,有些寄存器可以重写,有些寄存器只能阅读,只有可重写的寄存器才能正确写入;Write Data为8位写数据,每个寄存器地址对应8位配置数据。
在OV5640正常工作前,传感器必须初始化,即通过配置寄存器在预期的工作模式下工作,并获得更好的图像质量。因为SCCB写传输协议和IIC几乎一样,所以我们可以直接使用IIC配置摄像头的驱动程序。当然这么多寄存器也并非都需要配置,很多寄存器可以采用默认的值。OV公司提供了OV5640软件应用手册(OV5640 Software Application Note,附在开发板上的信息7_硬件资料/4_OV5640资料/OV5640_camera_module_software_application_notes.pdf”),如果有些寄存器不知道如何配置,请参考本手册。下表是本程序中使用的关键寄存器的配置说明。
表 36.1.1 OV5640关键寄存器配置说明
地址
(HEX) 寄存器 默认值
(HEX) 详细说明
0x3008 SYSTEM CTROL0 0x02 Bit[7]:软件复位
Bit[6]:软件电源休眠:
0x3016 PAD OUTPUT ENABLE 00 0x00 Bit[1]:闪光输出
0x3017 PAD OUTPUT ENABLE 01 0x00 输入/输出控制 1:输出)
Bit[7]:FREX输出使能
Bit[6]:VSYNC输出使能
Bit[5]:HREF输出使能
Bit[4]:PCLK输出使能
Bit[3:0]:D[9:6]输出使能
0x3018 PAD OUTPUT ENABLE 02 0x00 输入/输出控制 1:输出)
Bit[7:2]:D[5:0]输出使能
Bit[1]:GPIO1输出使能
Bit[0]:GPIO0输出使能
0x3019 PAD OUTPUT VALUE 00 0x00 Bit[1]: 闪光灯操作
关掉闪光灯
1:打开闪光灯
0x301C PAD SELECT 00 0x00 Bit[1]:闪光灯IO选择
0x3035 SC PLL CONTRL1 0x11 Bit[7:4]系统时钟分频用于降低所有时钟频率
Bit[3:0]:MIPI分频
0x3036 SC PLL CONTRL2 0x69 Bit[7:0]:PLL倍频器(4~252)
在4~在127范围内支持任何整数分频
在128~仅在252范围内支持偶数分频
0x3808 TIMING DVPHO 0x0A Bit[3:0]:DVP 输出水平像素点4
0x3809 TIMING DVPHO 0x20 Bit[7:0]:DVP 输出水平像素点8位
0x380A TIMING DVPVO 0x07 Bit[2:0]:DVP垂直像素点输出高3位
0x380B TIMING DVPVO 0x98 Bit[7:0]输出垂直像素点低8位
0x4300 FORMAT CONTROL 0xF8 Bit[7:4]:数据输出格式
0:RAW
1:Y8
2:YUV444/RGB888
3:YUV422
4:YUV420
5:YUV420(仅在MIPI输出接口有效)
6:RGB565
Bit[3:0]:输出顺序:
0:{b[4:0],g[5:3]},{g[2:0],r[4:0]}
1:{r[4:0],g[5:3]},{g[2:0],b[4:0]}
2:{g[4:0],r[5:3]},{r[2:0],b[4:0]}
3:{b[4:0],r[5:3]},{r[2:0],g[4:0]}
4:{g[4:0],b[5:3]},{b[2:0],r[4:0]}
5:{r[4:0],b[5:3]},{b[2:0],g[4:0]}
6~14:不允许
15:{g[2:0],b[4:0]},{r[4:0],g[5:3]}
7:RGB555格式1
8:RGB555格式2
9:RGB444格式1
10:RGB444格式2
11~14:不允许
15:Bypass formatter module
OV5640寄存器较多,可参考其他寄存器的描述OV5640数据手册。需要注意的是,OV5640的数据手册并没有提供所有的寄存器描述,而且大多数必要的寄存器配置在ov在5640软件应用手册中可以找到,可以结合这两本手册学习如何对待OV5640进行配置。
设置输出图像参数
接下来,让我们介绍一下OV5640的ISP输入窗设置、预缩放窗设置和输出大小窗设置与我们的正常使用密切相关。有必要了解它们的设置关系如下图所示:
图 7.5.13.3 设置图像窗口
ISP设置输入窗口(ISP Input Size)允许用户设置整个传感器显示区域(physical pixel size,26321951,其中25921944像素有效),开窗范围为00~26321951可任意设置。也就是上图中的X_ADDR_ST(寄存器地址0x3800、0x3801)、Y_ADDR_ST(寄存器地址0x3802、0x3803)、X_ADDR_END(寄存器地址0x3804、0x3805)和YADDR_END(寄存器地址0x3806、0x3807)寄存器。该窗口设置范围中的像素数据将进入ISP进行图像处理。
预缩放窗口设置(pre-scaling size)允许用户在ISP输入窗口的基础上进行裁剪,用于设置将进行缩放的窗口大小,该设置仅在ISP输入窗口内进行X/Y方向的偏移。可以通过X_OFFSET(寄存器地址0x3810、0x3811)和Y_OFFSET(寄存器地址0x3812、0x3813)进行配置。
输出大小窗口设置(data output size)是在预缩放窗口的基础上,经过内部DSP进行缩放处理,并将处理后的数据输出给外部的图像窗口,图像窗口控制着最终的图像输出尺寸。可以通过X_OUTPUT_SIZE(寄存器地址0x3808、0x3809)和Y_OUTPUT_SIZE(寄存器地址0x380A、0x380B)进行配置。注意:当输出大小窗口与预缩放窗口比例不一致时,图像将进行缩放处理(图像变形),仅当两者比例一致时,输出比例才是1:1(正常图像)。
图 7.5.13.3中,右侧data output size区域,才是OV5640输出给外部的图像尺寸,也就是显示在显示器或者液晶屏上面的图像大小。输出大小窗口与预缩放窗口比例不一致时,会进行缩放处理,在显示器上面看到的图像将会变形。
输出像素格式
OV5640支持多种不同的数据像素格式,包括YUV(亮度参量和色度参量分开表示的像素格式)、RGB(其中RGB格式包含RGB565、RGB555等)以及RAW(原始图像数据),通过寄存器地址0x4300配置成不同的数据像素格式。
由于数据像素格式常用RGB565,我们这里也将ov5640配置为RGB565格式。由上表(表 36.1.1)可知,将寄存器0x4300寄存器的Bit[7:4]设置成0x6即可。OV5640支持调节RGB565输出格式中各颜色变量的顺序,对于我们常见的应用来说,一般是使用RGB或BGR序列。我们在“基于OV7725的PL以太网视频传输实验”的章节中介绍过,OV7725摄像头按照RGB的顺序输出,本章我们将OV5640输出的RGB565的颜色顺序和OV7725保持一致,将寄存器0x4300寄存器的Bit[3:0]设置成0x1。因此,“基于OV7725的PL以太网视频传输实验”章节中的图像采集模块可以直接用来采集OV5640输出的图像。
彩条测试模式
图像传感器配置成彩条测试模式后,会输出彩色的条纹,方便测试图像传感器是否正常工作,通过配置寄存器0x503d的Bit[7]位打开和关闭彩条模式。当需要打开彩条模式时,寄存器0x503d配置成0x80,关闭时配置成0x00,下图为打开彩条模式后图像输出的条纹。
图 7.5.13.4 彩条模式下的图像条纹
LED闪光灯
当外界环境光较暗时,传感器采集图像会受到较大影响,此时可以通过打开LED补光灯来弥补光照不足所带来的影响,就像手机在夜晚拍照时也会打开闪光灯来提高图像质量。通过配置寄存器0x3016=0x02,0x301c=0x02来使能LED补光灯功能;配置寄存器0x3019=0x02打开闪光灯,0x3019=0x00关闭闪光灯。
图像输出时序
接下来,我们介绍一下OV5640的图像数据输出时序,首先我们简单介绍一些定义。
QSXGA,这里指:分辨率为25921944的输出格式,类似的还有:QXGA(20481536)、UXGA(16001200)、SXGA(12801024)、WXGA(1440900)、WXGA(1280800)、XGA(1024768)、SVGA(800600)、VGA(640480)、QVGA(320240)和QQVGA(160120)等。
PCLK:像素时钟,一个PCLK时钟输出一个像素或者半个像素(像素数据的高8位或者低8位)。
VSYNC:帧同步信号。
HREF/HSYNC:行同步信号。
D[9:0]:像素数据,在RGB565格式中,只有高8位是有效的。
tPclk:一个时钟周期 。
tp:一个像素点的周期,在RGB565和YUV422输出格式下,tp=2tPclk;Raw输出格式下,tp=tPclk。
下图为OV5640输出图像数据的行时序图。
图 7.5.13.5 OV5640行时序图
从上图可以看出,传感器在HREF为高电平的时候输出图像数据,当HREF变高后,每一个 PCLK时钟,输出一个8位或者10位像素数据。比如我们采用QSXGA时序,RGB565格式输出,tp=2tPclk,每2个字节组成一个像素的颜色,这样每行总共输出25922个PCLK,也就是25922个字节。
再来看看帧时序(QSXGA模式,分辨率25921944),如下图所示:
图 7.5.13.6 OV5640 QSXGA帧时序
由上图可知,VSYNC的上升沿作为一帧的开始,高电平同步脉冲的时间为5688tp,紧接着等待48276tp时间后,HREF开始拉高,此时输出有效数据;HREF由2592tp个高电平和252tp个低电平构成;最后一行图像数据输出完成之后等待14544tp时间,一帧数据传输结束。所以输出一帧图像的时间实际上是tFrame = 5596992tp。
从OV5640的行时序图和帧时序图可以发现,其输出时序和OV7725是非常相似的,只是时间参数不同而已,大家可以参考“基于OV7725的PL以太网视频传输实验”中帧时序的介绍来学习OV5640的输出时序。
36.2 实验任务
本节实验任务是使用ZYNQ开发板及OV5640摄像头实现图像采集,并通过开发板上的以太网接口发送给上位机实时显示。
36.3 硬件设计
本次实验的硬件电路和“基于OV7725的PL以太网视频传输实验”中的硬件电路是基本相同的,都使用了领航者Zynq开发板上的摄像头扩展接口,IO管脚位置的配置也是一样的。
唯一的不同点在于,原先在“基于OV7725的PL以太网视频传输实验”中的Zynq输出给摄像头扩展接口的“cam_sgm_ctrl”信号,在本实验中变为了Zynq输出给OV5640的“电源休眠模式选择”信号cam_pwdn;且原来的cam_sgm_ctrl是我们需要一直赋值为高电平,但对于OV5640,cam_pwdn我们需要将其一直赋值为低电平,表示不休眠即正常工作模式。
OV5640摄像头的管脚分配如下表所示:
表 36.3.1 OV5640摄像头管脚分配
信号名 方向 管脚 端口说明
cam_pclk input W14 cmos 数据像素时钟
cam_vsync input U12 cmos 场同步信号
cam_href input T12 cmos 行同步信号
cam_rst_n output P14 cmos 复位信号,低电平有效
cam_pwdn output V15 cmos 电源休眠模式选择信号
cam_data[0] input R14 cmos 数据
cam_data[1] input U13 cmos 数据
cam_data[2] input V13 cmos 数据
cam_data[3] input U15 cmos 数据
cam_data[4] input U14 cmos 数据
cam_data[5] input W13 cmos 数据
cam_data[6] input V12 cmos 数据
cam_data[7] input Y14 cmos 数据
emio_sccb_tri_io [0] inout T10 cmos SCCB_SCL线
emio_sccb_tri_io [1] inout T11 cmos SCCB_SDA线
相关的管脚约束如下所示:
create_clock -period 20.000 -name sys_clk [get_ports sys_clk]
create_clock -period 8.000 -name eth_rxc [get_ports eth_rxc]
set_property -dict {
PACKAGE_PIN U18 IOSTANDARD LVCMOS33} [get_ports sys_clk]
set_property -dict {
PACKAGE_PIN N16 IOSTANDARD LVCMOS33} [get_ports sys_rst_n]
set_property -dict {
PACKAGE_PIN G15 IOSTANDARD LVCMOS33} [get_ports eth_rst_n]
set_property -dict {
PACKAGE_PIN K17 IOSTANDARD LVCMOS33} [get_ports eth_rxc]
set_property -dict {
PACKAGE_PIN E17 IOSTANDARD LVCMOS33} [get_ports eth_rx_ctl]
set_property -dict {
PACKAGE_PIN B19 IOSTANDARD LVCMOS33} [get_ports {
eth_rxd[0]}]
set_property -dict {
PACKAGE_PIN A20 IOSTANDARD LVCMOS33} [get_ports {
eth_rxd[1]}]
set_property -dict {
PACKAGE_PIN H17 IOSTANDARD LVCMOS33} [get_ports {
eth_rxd[2]}]
set_property -dict {
PACKAGE_PIN H16 IOSTANDARD LVCMOS33} [get_ports {
eth_rxd[3]}]
set_property -dict {
PACKAGE_PIN B20 IOSTANDARD LVCMOS33} [get_ports eth_txc]
set_property -dict {
PACKAGE_PIN K18 IOSTANDARD LVCMOS33} [get_ports eth_tx_ctl]
set_property -dict {
PACKAGE_PIN D18 IOSTANDARD LVCMOS33} [get_ports {
eth_txd[0]}]
set_property -dict {
PACKAGE_PIN C20 IOSTANDARD LVCMOS33} [get_ports {
eth_txd[1]}]
set_property -dict {
PACKAGE_PIN D19 IOSTANDARD LVCMOS33} [get_ports {
eth_txd[2]}]
set_property -dict {
PACKAGE_PIN D20 IOSTANDARD LVCMOS33} [get_ports {
eth_txd[3]}]
#CAMERA
create_clock -period 40.000 -name cmos_pclk [get_ports cam_pclk]
set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets cam_pclk_IBUF]
set_property -dict {
PACKAGE_PIN W14 IOSTANDARD LVCMOS33} [get_ports cam_pclk]
set_property -dict {
PACKAGE_PIN P14 IOSTANDARD LVCMOS33} [get_ports cam_rst_n]
set_property -dict {
PACKAGE_PIN V15 IOSTANDARD LVCMOS33} [get_ports cam_sgm_ctrl]
set_property -dict {
PACKAGE_PIN R14 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[0]}]
set_property -dict {
PACKAGE_PIN U13 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[1]}]
set_property -dict {
PACKAGE_PIN V13 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[2]}]
set_property -dict {
PACKAGE_PIN U15 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[3]}]
set_property -dict {
PACKAGE_PIN U14 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[4]}]
set_property -dict {
PACKAGE_PIN W13 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[5]}]
set_property -dict {
PACKAGE_PIN V12 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[6]}]
set_property -dict {
PACKAGE_PIN Y14 IOSTANDARD LVCMOS33 IOB TRUE} [get_ports {
cam_data[7]}]
set_property -dict {
PACKAGE_PIN U12 IOSTANDARD LVCMOS33} [get_ports cam_vsync]
set_property -dict {
PACKAGE_PIN T12 IOSTANDARD LVCMOS33} [get_ports cam_href]
set_property -dict {
PACKAGE_PIN T10 IOSTANDARD LVCMOS33} [get_ports cam_scl]
set_property -dict {
PACKAGE_PIN T11 IOSTANDARD LVCMOS33} [get_ports cam_sda]
36.4 程序设计
图 7.5.13.1是根据本章实验任务画出的系统框图。对比“基于OV7725的以太网视频传输实验”的系统框图可以发现,我们只是把外设OV7725模块替换成了OV5640模块,其余模块基本相同(IIC配置模块有差异)。时钟IP核模块用于为IIC驱动模块、以太网顶层模块和开始传输控制模块提供驱动时钟。I2C驱动模块和I2C配置模块用于初始化OV5640图像传感器;摄像头采集模块负责采集摄像头图像数据,并且把图像数据连接至图像数据封装模块,图像数据封装模块将输入的图像数据进行位拼接,并添加图像的帧头和行场分辨率;以太网顶层模块实现以太网数据的收发;开始传输控制模块控制以太网顶层模块开始/停止发送数据。
图 7.5.13.1 系统框图
顶层模块的原理图如下图所示:
图 7.5.13.2 顶层模块原理图
FPGA顶层模块(ov5640_udp_pc)例化了以下七个模块:时钟IP核模块(clk_wiz_0)、I2C驱动模块(i2c_dri)、I2C配置模块(i2c_ov5640_rgb565_cfg)、摄像头图像采集模块(cmos_capture_data)、开始传输控制模块(start_transfer_ctrl)、图像数据封装模块(img_data_pkt)和以太网顶层模块模块(eth_top)。
时钟模块(clk_wiz_0):时钟IP核模块通过调用MMCM IP核来实现,总共输出2个时钟,频率分别为50Mhz和200Mhz时钟。50Mhz时钟作为IIC驱动模块的操作时钟;200Mhz时钟作为IDELAYCTRL源语的参考时钟。
I2C驱动模块(i2c_dri):I2C驱动模块负责驱动OV5640 SCCB接口总线,用户可根据该模块提供的用户接口可以很方便的对OV5640的寄存器进行配置,该模块和“EEPROM读写实验”章节中用到的I2C驱动模块为同一个模块,有关该模块的详细介绍请大家参考“EEPROM读写实验”章节。
I2C配置模块(i2c_ov5640_rgb565_cfg):I2C配置模块的驱动时钟是由I2C驱动模块输出的时钟提供的,这样方便了I2C驱动模块和I2C配置模块之间的数据交互。该模块寄存需要配置的寄存器地址、数据以及控制初始化的开始与结束,同时该模块输出OV5640的寄存器地址和数据以及控制I2C驱动模块开始执行的控制信号,直接连接到I2C驱动模块的用户接口,从而完成对OV5640传感器的初始化。
摄像头图像采集模块(cmos_capture_data):摄像头采集模块在像素时钟的驱动下将传感器输出的场同步信号、行同步信号以及8位数据转换成16位数据信号,完成对OV5640传感器图像的采集。
开始传输控制模块(start_transfer_ctrl):该模块解析以太网顶层模块接收到的数据,如果收到1个字节的ASCII码“1”,则表示以太网开始传输图像数据;如果收到1个字节的ASCII码“0”,则表示以太网停止传输图像数据。
图像数据封装模块(img_data_pkt):图像数据封装模块负责将输入16位的图像数据,拼接成32位数据,以及添加图像数据的帧头和行场分辨率。该模块控制着以太网发送模块发送的字节数,单次发送一行图像数据的字节数,模块内部例化了一个异步FIFO模块,用于缓存待发送的图像数据。
以太网顶层模块(eth_top):以太网顶层模块实现以太网通信的收发功能,有关该模块的详细介绍请大家参考“以太网UDP测试实验”章节。
顶层模块部分代码如下:
1 module ov5640_udp_pc(
2 input sys_clk , //系统时钟
3 input sys_rst_n , //系统复位信号,低电平有效
4 //以太网接口
5 input eth_rxc , //RGMII接收数据时钟
6 input eth_rx_ctl , //RGMII输入数据有效信号
7 input [3:0] eth_rxd , //RGMII输入数据
8 output eth_txc , //RGMII发送数据时钟
9 output eth_tx_ctl , //RGMII输出数据有效信号
10 output [3:0] eth_txd , //RGMII输出数据
11 output eth_rst_n , //以太网芯片复位信号,低电平有效
12
13 //摄像头接口
14 input cam_pclk , //cmos 数据像素时钟
15 input cam_vsync , //cmos 场同步信号
16 input cam_href , //cmos 行同步信号
17 input [7:0] cam_data , //cmos 数据
18 output cam_rst_n , //cmos 复位信号,低电平有效
19 output cam_pwdn , //电源休眠模式选择 0:正常模式 1:电源休眠模式
20 output cam_scl , //cmos SCCB_SCL线
21 inout cam_sda //cmos SCCB_SDA线
22 );
23
24 //parameter define
25 //开发板MAC地址 00-11-22-33-44-55
26 parameter BOARD_MAC = 48'h00_11_22_33_44_55;
27 //开发板IP地址 192.168.1.10
28 parameter BOARD_IP = {
8'd192,8'd168,8'd1,8'd10};
29 //目的MAC地址 ff_ff_ff_ff_ff_ff
30 parameter DES_MAC = 48'hff_ff_ff_ff_ff_ff;
31 //目的IP地址 192.168.1.102
32 parameter DES_IP = {
8'd192,8'd168,8'd1,8'd102};
33
34 parameter H_CMOS_DISP = 11'd640; //CMOS分辨率--行
35 parameter V_CMOS_DISP = 11'd480; //CMOS分辨率--列
36 parameter TOTAL_H_PIXEL = H_CMOS_DISP + 12'd1216; //水平总像素大小
37 parameter TOTAL_V_PIXEL = V_CMOS_DISP + 12'd504; //垂直总像素大小
38
39 parameter SLAVE_ADDR = 7'h3c ; //OV5640的器件地址7'h3c
40 parameter BIT_CTRL = 1'b1 ; //OV5640的字节地址为16位 0:8位 1:16位
41 parameter CLK_FREQ = 27'd50_000_000 ; //i2c_dri模块的驱动时钟频率
42 parameter I2C_FREQ = 20'd250_000 ; //I2C的SCL时钟频率,不超过400KHz
在代码的第24至32行定义了四个参量:开发板MAC地址BOARD_MAC,开发板IP地址 BOARD_IP,目的MAC地址DES_MAC(这里指PC MAC地址),目的IP地址 DES_IP(PC IP地址)。开发板的MAC地址和IP地址是我们随意定义的,只要不和目的MAC 地址和目的IP地址一样就可以,否则会产生地址冲突。目的MAC地址这里写的是公共MAC 地址(48’hff_ff_ff_ff_ff_ff),也可以修改成电脑网口的MAC地址,DES_IP是对应电脑以太网的IP地址,这里定义的四个参数是向下传递的,需要修改MAC地址或者IP地址时直接在这里修改即可,而不用在以太网顶层模块里面修改。
在代码的第34行至37行定义了CMOS水平/垂直方向像素个数和水平/垂直总像素个数,本次实验设置的摄像头分辨率为640*480。
在代码的第39行定义了OV5640的器件地址,其器件地址为7’h3c;第40行定义了寄存器地址的位宽,BIT_CTRL=0表示地址位宽为8位,BIT_CTRL=1表示地址位宽为16位。因为OV5640的地址位宽为16位,所以BIT_CTRL设置为1。
76 assign rst_n = sys_rst_n & locked;
77 //电源休眠模式选择 0:正常模式 1:电源休眠模式
78 assign cam_pwdn = 1'b0;
79 assign cam_rst_n = 1'b1;
80
81 //例化时钟IP核
82 clk_wiz_0 u_clk_wiz_0
83 (
84 .clk_out1 (clk_50m),
85 .clk_out2 (clk_200m),
86 .reset (~sys_rst_n),
87 .locked (locked),
88 .clk_in1 (sys_clk)
89 );
90
91 //I2C配置模块
92 i2c_ov5640_rgb565_cfg u_i2c_cfg(
93 .clk (i2c_dri_clk),
94 .rst_n (rst_n),
95 .i2c_done (i2c_done),
96 .i2c_data_r (i2c_data_r),
97 .cmos_h_pixel (H_CMOS_DISP),
98 .cmos_v_pixel (V_CMOS_DISP),
99 .total_h_pixel (TOTAL_H_PIXEL),
100 .total_v_pixel (TOTAL_V_PIXEL),
101 .i2c_exec (i2c_exec),
102 .i2c_data (i2c_data),
103 .i2c_rh_wl (i2c_rh_wl),
104 .init_done (cam_init_done)
105 );
106
107 //I2C驱动模块
108 i2c_dri
109 #(
110 .SLAVE_ADDR (SLAVE_ADDR), //参数传递
111 .CLK_FREQ (CLK_FREQ ),
112 .I2C_FREQ (I2C_FREQ )
113 )
114 u_i2c_dri(
115 .clk (clk_50m ),
116 .rst_n (rst_n ),
117 //i2c interface
118 .i2c_exec (i2c_exec ),
119 .bit_ctrl (BIT_CTRL ),
120 .i2c_rh_wl (i2c_rh_wl ),
121 .i2c_addr (i2c_data[23:8]),
122 .i2c_data_w (i2c_data[7:0]),
123 .i2c_data_r (i2c_data_r),
124 .i2c_done (i2c_done ),
125 .i2c_ack (),
126 .scl (cam_scl ),
127 .sda (cam_sda ),
128 //user interface
129 .dri_clk (i2c_dri_clk) //I2C操作时钟
130 );
131
132 //摄像头数据采集模块
133 cmos_capture_data u_cmos_capture_data(
134
135 .rst_n (rst_n & cam_init_done),
136 .cam_pclk (cam_pclk),
137 .cam_vsync (cam_vsync),
138 .cam_href (cam_href),
139 .cam_data (cam_data),
140 .cmos_frame_vsync (cmos_frame_vsync),
141 .cmos_frame_href (),
142 .cmos_frame_valid (img_data_en),
143 .cmos_frame_data (img_data)
144 );
OV5640摄像头配置模块和IIC驱动模块实现对OV5640摄像头的初始化,在初始化完成后拉高cam_init_done信号,此时开始通过摄像头数据采集模块接收摄像头输出的图像数据(如程序中第135行代码所示),将输入的8位数据转换成16位RGB565数据。
146 //开始传输控制模块
147 start_transfer_ctrl u_start_transfer_ctrl(
148 .clk (eth_rx_clk),
149 .rst_n (rst_n),
150 .udp_rec_pkt_done (udp_rec_pkt_done),
151 .udp_rec_en (udp_rec_en ),
152 .udp_rec_data (udp_rec_data ),
153 .udp_rec_byte_num (udp_rec_byte_num),
154
155 .transfer_flag (transfer_flag) //图像开始传输标志,1:开始传输 0:停止传输
156 );
157
158 //图像封装模块
159 img_data_pkt u_img_data_pkt(
160 .rst_n (rst_n),
161
162 .cam_pclk (cam_pclk),
163 .img_vsync (cmos_frame_vsync),
164 .img_data_en (img_data_en),
165 .img_data (img_data),
166 .transfer_flag (transfer_flag),
167 .eth_tx_clk (eth_tx_clk ),
168 .udp_tx_req (udp_tx_req ),
169 .udp_tx_done (udp_tx_done ),
170 .udp_tx_start_en (udp_tx_start_en),
171 .udp_tx_data (udp_tx_data ),
172 .udp_tx_byte_num (udp_tx_byte_num)
173 );
174
175 //以太网顶层模块
176 eth_top #(
177 .BOARD_MAC (BOARD_MAC), //参数例化
178 .BOARD_IP (BOARD_IP ),
179 .DES_MAC (DES_MAC ),
180 .DES_IP (DES_IP )
181 )
182 u_eth_top(
183 .sys_rst_n (rst_n ), //系统复位信号,低电平有效
184 .clk_200m (clk_200m),
185 //以太网RGMII接口
186 .eth_rxc (eth_rxc ), //RGMII接收数据时钟
187 .eth_rx_ctl (eth_rx_ctl), //RGMII输入数据有效信号
188 .eth_rxd (eth_rxd ), //RGMII输入数据
189 .eth_txc (eth_txc ), //RGMII发送数据时钟
190 .eth_tx_ctl (eth_tx_ctl),