基于OV2640/ OV5640 的图像采集显示系统系列文章目录:
(1)基于 OV5640 摄像头理论知识讲解-成像和采样原理
(2)基于 OV5640 摄像头理论知识讲解-数字接口和控制接口
(3)基于 OV5640 摄像头理论知识讲解-典型工作模式配置
(4)基于OV2640/ OV5640 的图像采集显示系统
文章目录
- 前言
- 一、图像采集显示系统原理及结构
- 二、各模块的定义
- 三、顶层模块ov2640_ddr3_tft
- 四、ov2640_ddr3_tft_tb文件
前言
本节将在实验“基于 DDR3 的串口传图帧缓存系统设计”实现一个图像采集显示应用系统,来设计 OV2640 / OV5640应用系统中所需的基本应用逻辑电路。
提示:以下是本篇文章正文内容,下面案例可供参考
一、图像采集显示系统原理及结构
整个系统最终的目的是要在 TFT 显示屏上显示图像数据,由于 TFT 显示屏采用的是RGB565 接口,为了让图像正常的显示在显示屏的指定位置,需要有相应的时序发生逻辑,这就是上图中的 Disp_Driver。该模块会按照 TFT 显示屏的接口时序产生对应的控制时序(HS、VS、DE、RGB data),实质上就是我们已经学习过的 TFT/VGA 控制器。
由于 TFT 显示屏显示时候,是按照 60 帧率的速率进行刷新,也就是每秒刷新 60 张图像,为了保证图像的正常显示,一般需要有一个图像缓冲区,TFT 控制器实时从该图像缓冲区中读取数据并送往 TFT 屏上显示。所以在上述系统中,设计了一个 DDR3 用来存储需要显示的图像数据。
从设计的框图可以看出,整个系统与基于 DDR3 的串口传图帧缓存系统的差异在于串口传图是电脑通过串口将数据传输给 FPGA,而本实验是通过 OV2640 摄像头采集数据传给FPGA 处理。本节重点是如何让驱动 OV2640,让 FPGA 正确采集到图像数据。
二、各模块的定义
(1)Camera_Init 模块:OV2640 要想能够正常的输出图像数据,必须经 SCCB 接口对其寄存器进行配置,所以整个系统首要的工作是使用控制逻辑经由 SCCB 接口对其进行初始化,在上图中,对 OV2640进行初始化的功能模块为 Camera_Init。该模块会在系统开始工作时,对 OV2640 中各个寄存器写入指定值以实现初始化操作(参考Camera_Init )。
(2)DVP Capture 模块:负责将 DVP 接口输出的数据按照每两个一组合,得到符合 RGB565 图像格式的 16 位数据,之后数据处理过程与串口传图是一样,所以需要使用 SCCB 接口对OV2640 进行设置,让其图像输出格式为 RGB565(参考DVP Capture )。
(3)disp_driver 模块:tft 屏显示驱动控制,对缓存在 DDR3 中的图像数据进行显示(可参考VGA成像原理)。
(4)wr_ddr3_fifo 模块:使用的 FIFO IP ,主要用于写入 DDR3 数据的缓存、解决数
据跨时钟域以及数据位宽的转换(IP生成参考 IP生成 )。
(5)rd_ddr3_fifo 模块:使用的 FIFO IP ,主要用于读出 DDR3 数据的缓存、解决数据
跨时钟域以及数据位宽的转换(IP生成参考 IP生成 )。
(6)fifo_ddr3_native_fifo 模块:主要是用于接口的转换,将 MIG IP 的Native接口换成与 FIFO
对接的接口(可参考第五节 )。
(7)mig_7series_native 模块: DDR3 控制器,使用的 Memory Interface Generator(MIG 7
Series)IP(可参考 DDR3 控制器 MIG IP 详解完整版 )。
(8)pll 模块:上述各个模块所需时钟的产生,使用 PLL IP。除去使用 IP 和前面章节讲过的模块外,还需要设计的模块包括Camera_Init 模块和DVP Capture模块。
(9)顶层模块ov2640_ddr3_tft,用于实现上述模块的转换与连接(参考第三节)。
三、顶层模块ov2640_ddr3_tft
/
// Module Name : ov2640_ddr3_tft
// Description : 摄像头采集数据,DDR3缓存,TFT显示
// Name :小王在努力...
// Revision : Vivado 2018.3
// Revision 0.01 - File Created
/
module ov2640_ddr3_tft(
//System clock reset
input clk50m , //系统时钟输入,50MHz
input reset_n , //复位信号输入
//LED
output [3:0] led ,
//TFT Interface
output [15:0] TFT_rgb , //TFT数据输出
output TFT_hs , //TFT行同步信号
output TFT_vs , //TFT场同步信号
output TFT_clk , //TFT像素时钟
output TFT_de , //TFT数据使能
output TFT_pwm , //TFT背光控制
//HDMI Internal
//hdmi1 interface
output hdmi1_clk_p,
output hdmi1_clk_n,
output [2:0]hdmi1_dat_p,
output [2:0]hdmi1_dat_n,
output hdmi1_oe,
//hdmi2 interface
output hdmi2_clk_p,
output hdmi2_clk_n,
output [2:0] hdmi2_dat_p,
output [2:0] hdmi2_dat_n,
output hdmi2_oe,
//camera interface
output camera_sclk ,
inout camera_sdat ,
input camera_vsync ,
input camera_href ,
input camera_pclk ,
output camera_xclk ,
input [7:0] camera_data ,
output camera_rst_n ,
//DDR3 Interface
// Inouts
inout [15:0] ddr3_dq ,
inout [1:0] ddr3_dqs_n ,
inout [1:0] ddr3_dqs_p ,
// Outputs
output [13:0] ddr3_addr ,
output [2:0] ddr3_ba ,
output ddr3_ras_n ,
output ddr3_cas_n ,
output ddr3_we_n ,
output ddr3_reset_n ,
output [0:0] ddr3_ck_p ,
output [0:0] ddr3_ck_n ,
output [0:0] ddr3_cke ,
output [0:0] ddr3_cs_n ,
output [1:0] ddr3_dm ,
output [0:0] ddr3_odt
);
//*********************************
//Internal connect
//*********************************
//clock
wire pll_locked;
wire loc_clk50m;
wire loc_clk200m;
wire loc_clk24m;
wire loc_clk33m;
wire loc_clk165m;
//reset
wire g_rst_p;
//camera interface
wire camera_init_done;
wire pclk_bufg_o;
wire [15:0] image_data;
wire image_data_valid;
wire image_data_hs;
wire image_data_vs;
//wr_fifo Interface
wire wrfifo_clr;
wire wrfifo_wren;
wire [15:0] wrfifo_din;
//rd_fifo Interface
wire rdfifo_clr;
wire rdfifo_rden;
wire [15 :0] rdfifo_dout;
//mig Interface
wire ui_clk ;
wire ui_clk_sync_rst ;
wire mmcm_locked;
wire init_calib_complete;
//tft
wire clk_disp;
wire frame_begin;
wire disp_hs;
wire disp_vs;
wire disp_de;
wire [4:0]disp_blue;
wire [5:0]disp_green;
wire [4:0]disp_red;
//兼容小梅哥TFT5.0寸和TFT4.3寸显示屏,可根据实际进行配置选择
/*
parameter IMAGE_WIDTH = 480;
parameter IMAGE_HEIGHT = 272;
assign clk_disp = loc_clk9m;
*/
parameter CAMERA_WIDTH = 800;
parameter CAMERA_HEIGHT = 600;
parameter IMAGE_WIDTH = 800;
parameter IMAGE_HEIGHT = 480;
assign clk_disp = loc_clk33m;
assign ddr3_init_done = mmcm_locked && init_calib_complete;
assign g_rst_p = ~ddr3_init_done;
assign led = {camera_init_done,camera_rst_n,ddr3_init_done,pll_locked};
pll pll
(
// Clock out ports
.clk_out1 (loc_clk50m ), // output clk_out1
.clk_out2 (loc_clk200m ), // output clk_out2
.clk_out3 (loc_clk24m ), // output clk_out3
.clk_out4 (loc_clk33m ), // output clk_out4
.clk_out5 (loc_clk165m ), // output clk_out5
// Status and control signals
.resetn (reset_n ), // input reset
.locked (pll_locked ), // output locked
// Clock in ports
.clk_in1 (clk50m ) // input clk_in1
);
assign camera_xclk = loc_clk24m;
camera_init
#(
.CAMERA_TYPE ( "ov2640" ),//"ov2640" or "ov7725"
.IMAGE_TYPE ( 0 ),// 0: RGB; 1: JPEG
.IMAGE_WIDTH ( IMAGE_WIDTH ),// 图片宽度
.IMAGE_HEIGHT ( IMAGE_HEIGHT ),// 图片高度
.IMAGE_FLIP_EN ( 1'b0 ),// 0: 不翻转,1: 上下翻转
.IMAGE_MIRROR_EN( 1'b0 ) // 0: 不镜像,1: 左右镜像
)camera_init
(
.Clk (loc_clk50m ),
.Rst_n (~g_rst_p ),
.Init_Done (camera_init_done ),
.camera_rst_n(camera_rst_n ),
.camera_pwdn ( ),
.i2c_sclk (camera_sclk ),
.i2c_sdat (camera_sdat )
);
BUFG BUFG_inst (
.O(pclk_bufg_o ), // 1-bit output: Clock output
.I(camera_pclk ) // 1-bit input: Clock input
);
DVP_Capture DVP_Capture(
.Rst_p (~camera_init_done ),//input
.PCLK (pclk_bufg_o ),//input
.Vsync (camera_vsync ),//input
.Href (camera_href ),//input
.Data (camera_data ),//input [7:0]
.ImageState ( ),//output reg
.DataValid (image_data_valid ),//output
.DataPixel (image_data ),//output [15:0]
.DataHs (image_data_hs ),//output
.DataVs (image_data_vs ),//output
.Xaddr ( ),//output [11:0]
.Yaddr ( ) //output [11:0]
);
//---------------------------------------------
//仅仿真用,正常功能时,将下面sim_dat_gen模块进行屏蔽
//仿真时,取消屏蔽sim_dat_gen模块,将DVP_Capture模块屏蔽
//---------------------------------------------
// sim_dat_gen #(
// .DISP_WIDTH (IMAGE_WIDTH ),
// .DISP_HEIGHT (IMAGE_HEIGHT ),
// .DATA_WIDTH (16 )
// )
// sim_dat_gen(
// .clk (pclk_bufg_o ),
// .reset (g_rst_p ),
// .gen_en (camera_init_done),
// .sim_dat (image_data ),
// .sim_dat_vaild(image_data_valid)
// );
//-------------------------------------------
assign wrfifo_wren = image_data_valid;
assign wrfifo_din = image_data;
assign wrfifo_clr = ~camera_init_done;
assign rdfifo_clr = frame_begin;
fifo_mig_axi_fifo
#(
. WR_DDR_ADDR_BEGIN ( 0 ) ,
. WR_DDR_ADDR_END ( IMAGE_WIDTH*CAMERA_HEIGHT*2 ) ,
. RD_DDR_ADDR_BEGIN ( 0 ) ,
. RD_DDR_ADDR_END ( IMAGE_WIDTH*IMAGE_HEIGHT*2 ) ,
. AXI_ID ( 4'b0000 )
)fifo_mig_axi_fifo
(
//wr_ddr3_fifo ports
. wrfifo_rst (wrfifo_clr ) ,
. loc_clk50M (pclk_bufg_o ) ,
. wrfifo_din (wrfifo_din ) ,
. wrfifo_wren (wrfifo_wren ) ,
//rd_ddr3_fifo ports
. rdfifo_rst (rdfifo_clr ) ,
. loc_clk33M (loc_clk33m ) ,
. rdfifo_rden (rdfifo_rden ) ,
. rdfifo_dout (rdfifo_dout ) ,
//DDR3 Interface
//input
. loc_clk200M (loc_clk200m ) ,
. xx_sys_rst (pll_locked ) , //用于连接 pll_locked
. xx_aresetn (pll_locked ) , //用于连接 pll_locked
//output
. ui_clk (ui_clk ) ,
. ui_clk_sync_rst (ui_clk_sync_rst ) ,
. mmcm_locked (mmcm_locked ) ,
. init_calib_complete(init_calib_complete) ,
//DDR3 Interface
// Inouts
. ddr3_dq (ddr3_dq ) ,
. ddr3_dqs_n (ddr3_dqs_n ) ,
. ddr3_dqs_p (ddr3_dqs_p ) ,
// Outputs
. ddr3_addr (ddr3_addr ) ,
. ddr3_ba (ddr3_ba ) ,
. ddr3_ras_n (ddr3_ras_n ) ,
. ddr3_cas_n (ddr3_cas_n ) ,
. ddr3_we_n (ddr3_we_n ) ,
. ddr3_reset_n (ddr3_reset_n) ,
. ddr3_ck_p (ddr3_ck_p ) ,
. ddr3_ck_n (ddr3_ck_n ) ,
. ddr3_cke (ddr3_cke ) ,
. ddr3_cs_n (ddr3_cs_n ) ,
. ddr3_dm (ddr3_dm ) ,
. ddr3_odt (ddr3_odt )
);
disp_driver disp_driver
(
.ClkDisp (clk_disp ),
.Rst_p (g_rst_p ),
.Data (rdfifo_dout ),
.DataReq (rdfifo_rden ),
.H_Addr ( ),
.V_Addr ( ),
.Disp_HS (disp_hs ),
.Disp_VS (disp_vs ),
.Disp_Red (disp_red ),
.Disp_Green (disp_green ),
.Disp_Blue (disp_blue ),
.Frame_Begin (frame_begin ),
.Disp_DE (disp_de ),
.Disp_PCLK (TFT_clk )
);
assign TFT_hs = disp_hs;
assign TFT_vs = disp_vs;
assign TFT_de = disp_de;
assign TFT_rgb = {disp_red,disp_green,disp_blue};
assign TFT_pwm = 1'b1;
//HDMI1
dvi_encoder dvi_encoder1(
.pixelclk (loc_clk33m ),
.pixelclk5x (loc_clk165m ),
.rst_p (g_rst_p ),
.blue_din ({disp_blue ,3'b000} ),
.green_din ({disp_green,2'b00 } ),
.red_din ({disp_red ,3'b000} ),
.hsync (disp_hs ),
.vsync (disp_vs ),
.de (disp_de ),
.tmds_clk_p (hdmi1_clk_p ),
.tmds_clk_n (hdmi1_clk_n ),
.tmds_data_p (hdmi1_dat_p ),
.tmds_data_n (hdmi1_dat_n )
);
assign hdmi1_oe = 1'b1;
//HDMI2
dvi_encoder dvi_encoder2(
.pixelclk (loc_clk33m ),
.pixelclk5x (loc_clk165m ),
.rst_p (g_rst_p ),
.blue_din ({disp_blue ,3'b000} ),
.green_din ({disp_green,2'b00 } ),
.red_din ({disp_red ,3'b000} ),
.hsync (disp_hs ),
.vsync (disp_vs ),
.de (disp_de ),
.tmds_clk_p (hdmi2_clk_p ),
.tmds_clk_n (hdmi2_clk_n ),
.tmds_data_p (hdmi2_dat_p ),
.tmds_data_n (hdmi2_dat_n )
);
assign hdmi2_oe = 1'b1;
endmodule
四、ov2640_ddr3_tft_tb文件
`timescale 1ns / 1ps
//
// Module Name : ov2640_ddr3_tft_tb
// Description : 摄像头采集数据,DDR3缓存,TFT显示
// Name :小王在努力...
// Revision : Vivado 2018.3
// Revision 0.01 - File Created
//
module ov2640_ddr_tft_tb( );
reg clk50m;
reg reset_n;
wire [3:0 ] led;
wire [15:0] TFT_rgb ; //TFT数据输出
wire TFT_hs ; //TFT行同步信号
wire TFT_vs ; //TFT场同步信号
wire TFT_clk ; //TFT像素时钟
wire TFT_de ; //TFT数据使能
wire TFT_pwm ; //TFT背光控制
wire hdmi1_clk_p;
wire hdmi1_clk_n;
wire [2:0]hdmi1_dat_p;
wire [2:0]hdmi1_dat_n;
wire hdmi1_oe;
wire hdmi2_clk_p;
wire hdmi2_clk_n;
wire [2:0] hdmi2_dat_p;
wire [2:0] hdmi2_dat_n;
wire hdmi2_oe;
//camera interface
wire camera_sclk ;
wire camera_sdat ;
reg camera_vsync ;
reg camera_href ;
reg camera_pclk ;
wire camera_xclk ;
wire [7:0] camera_data ;
wire camera_rst_n ;
wire [15:0] ddr3_dq ;
wire [1:0 ] ddr3_dqs_n ;
wire [1:0 ] ddr3_dqs_p ;
wire [13:0] ddr3_addr ;
wire [2:0 ] ddr3_ba ;
wire ddr3_ras_n ;
wire ddr3_cas_n ;
wire ddr3_we_n ;
wire ddr3_reset_n ;
wire [0:0] ddr3_ck_p ;
wire [0:0] ddr3_ck_n ;
wire [0:0] ddr3_cke ;
wire [0:0] ddr3_cs_n ;
wire [1:0] ddr3_dm ;
wire [0:0] ddr3_odt ;
initial clk50m = 1;
always #10 clk50m = ~clk50m;
initial camera_pclk = 1;
always #12 camera_pclk = ~camera_pclk;
initial begin
reset_n = 0;
#201;
reset_n = 1;
#500000000;
$stop;
end
ov2640_ddr3_tft ov2640_ddr3_tft(
clk50m , //系统时钟输入,50MHz
reset_n , //复位信号输入
led ,
TFT_rgb , //TFT数据输出
TFT_hs , //TFT行同步信号
TFT_vs , //TFT场同步信号
TFT_clk , //TFT像素时钟
TFT_de , //TFT数据使能
TFT_pwm , //TFT背光控制
hdmi1_clk_p,
hdmi1_clk_n,
hdmi1_dat_p,
hdmi1_dat_n,
hdmi1_oe,
hdmi2_clk_p,
hdmi2_clk_n,
hdmi2_dat_p,
hdmi2_dat_n,
hdmi2_oe,
camera_sclk ,
camera_sdat ,
camera_vsync ,
camera_href ,
camera_pclk ,
camera_xclk ,
camera_data ,
camera_rst_n ,
ddr3_dq ,
ddr3_dqs_n ,
ddr3_dqs_p ,
ddr3_addr ,
ddr3_ba ,
ddr3_ras_n ,
ddr3_cas_n ,
ddr3_we_n ,
ddr3_reset_n ,
ddr3_ck_p ,
ddr3_ck_n ,
ddr3_cke ,
ddr3_cs_n ,
ddr3_dm ,
ddr3_odt
);
ddr3_model ddr3_model
(
.rst_n (ddr3_reset_n ),
.ck (ddr3_ck_p ),
.ck_n (ddr3_ck_n ),
.cke (ddr3_cke ),
.cs_n (ddr3_cs_n ),
.ras_n (ddr3_ras_n ),
.cas_n (ddr3_cas_n ),
.we_n (ddr3_we_n ),
.dm_tdqs(ddr3_dm ),
.ba (ddr3_ba ),
.addr (ddr3_addr ),
.dq (ddr3_dq ),
.dqs (ddr3_dqs_p ),
.dqs_n (ddr3_dqs_n ),
.tdqs_n ( ),
.odt (ddr3_odt )
);
endmodule