基于FPGA的OV7670摄像头实时检测

目录

前言:整体系统框图

一、OV7670摄像头简介

二、OV7670 SCCB协议简介

三、OV7670初始化寄存器配置

四、OV7670初始化代码编写

 五、什么是DVP?

六、摄像头写数据请求

七、顶层文件编写

八、效果


前言:整体系统框图

基于FPGA的OV7670摄像头实时检测_第1张图片

 如图所示,FPGA中主要模块包含:时钟模块、OV7670初始化模块、DVP协议数据流模块、写FIFO模块、写FIFO控制模块、SDRAM控制模块、读FIFO模块、读FIFO控制模块、VGA控制模块。

其整体流程为:启动时先对摄像头进行初始化设置,初始化完成后,FPGA从摄像头获取一帧一帧的图像数据,根据数据手册将ov7670数据流转换成我们需要的RGB565数据流,随后存入写FIFO模块;(写控制模块)当写FIFO模块中存储的数据大于等于8时,发出SDRAM写请求,SDRAM写请求通过后,读取FIFO数据存储起来;(读FIFO模块)当读FIFO数据小于等于8时,读取SDRAM中的数据经过读FIFO缓存后送入VGA显示模块进行显示。同时写控制模块和读控制模块控制SDRAM读写地址的增加。

1、时钟模块
     这里使用PLL的IP核,以50MHz时钟生成25MHz和100MHz时钟,其中摄像头初始化模块和VGA控制模块使用的是25MHz,SDRAM控制模块、写FIFO控制模块和读FIFO控制模块使用的是100MHz,写FIFO和读FIFO模块都是异步FIFO,使用25MHz和100MHz时钟。

一、OV7670摄像头简介

OV7670/OV7171 图像传感器,体积小、工作电压低,提供单片VGA摄像头和影像处理器的所有功能。通过SCCB 总线控制,可以输出整帧、子采样、取窗口等方式的各种分辨率8位影响数据。该产品VGA图像最高达到30帧/秒。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、饱和度、色度等都可以通过SCCB接口编程。OmmiVision 图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、托尾、浮散等,提高图像质量,得到清晰的稳定的彩色图像。

主要引出的信号引脚如下:

3.3V--输入电源电压(推荐使用3.3V,5V也可,但不推荐)

GND

SCL(SIOC):SCCB时钟口(注意:部分单片机需要上拉控制,和I2C接口类似)

SDA(SIOD):SCCB数据口(注意:部分单片机需要上拉控制,和I2C接口类似)

VSYNC:场同步(帧同步)信号(输出信号)

HREF:行同步信号(输出信号,一般可以不使用,特殊情况使用)

PCLK:像素时钟

XCLK:系统时钟输入

D0-D7:数据位(输出信号)

RESET:初始化所有寄存器到默认值 0:RESET 模式 1:一般模式

PWDN:POWER DOWN模式选择 0:工作 1:POWER DOWN

其中,对OV7670初始化配置只使用SCL和SDA两个信号线。

所用模块如图:

基于FPGA的OV7670摄像头实时检测_第2张图片

二、OV7670 SCCB协议简介

      对OV7670初始化使用的是SCCB协议,由数据线SDA和时钟线SCL组成,SCCB协议和I2C协议基本一样,是简化的I2C协议,前面博客中已经讲过I2C协议,需要可以去看看。

SCCB(SeriaI Camera ControlBus)是简化的I2C协议,SIO-l是串行时钟输入线,SIO-O是串行双向数据线,分别相当于I2C协议的SCL和SDA。SCCB的总线时序与I2C基本相同,它的响应信号ACK被称为一个传输单元的第9位,分为Don’t care和NA。Don’t care位由从机产生;NA位由主机产生,由于SCCB不支持多字节的读写,NA位必须为高电平。另外,SCCB没有重复起始的概念,因此在SCCB的读周期中,当主机发送完片内寄存器地址后,必须发送总线停止条件。不然在发送读命令时,从机将不能产生Don’t care响应信号。

这里采用的是100KHz的SCL。

三、OV7670初始化寄存器配置

     OV7670摄像头共201个寄存器,需要配置的有一百六十几个,这个具体看数据手册吧,下边代码中会有配置寄存器的数据。

四、OV7670初始化代码编写

`timescale 1 ns / 1 ns
module system_ctrl
(
	input 		clk,		//50MHz
	input 		rst_n,		//global reset

	output 		sys_rst_n,	//system reset
	output 		clk_c0,		
	output 		clk_c1,
	output		clk_c2,	//-75deg
	output		clk_c3	//-75deg
);

//----------------------------------------------
//rst_n synchronism, is controlled by the input clk
reg     rst_nr1,rst_nr2;
always @(posedge clk or negedge rst_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;
		end
end

//----------------------------------
//component instantiation for system_delay
wire	delay_done;
system_delay	u_system_delay
(
	.clk		(clk),
	.rst_n		(rst_nr2),
	.delay_done	(delay_done)
);
wire	pll_rst = ~rst_nr2 & ~delay_done;	//active High

//----------------------------------------------
//Component instantiation
wire 	locked;	
sdram_pll	u_sdram_pll
(
	.inclk0	(clk),
	.areset	(pll_rst),
	.locked	(locked),
			
	.c0		(clk_c0),
	.c1		(clk_c1),
	.c2		(clk_c2),
	.c3		(clk_c3)
);



//----------------------------------------------
//sys_rst_n synchronism, is control by the highest output clk
  
wire	sysrst_nr0 = rst_nr2 & locked & delay_done;  
reg 	sysrst_nr1, sysrst_nr2; 
always @(posedge clk_c1 or negedge sysrst_nr0)
begin
	if(!sysrst_nr0) 
        begin
        sysrst_nr1 <= 1'b0;
        sysrst_nr2 <= 1'b0;
        end        
	else 
        begin
        sysrst_nr1 <= 1'b1;
        sysrst_nr2 <= sysrst_nr1;
        end
end
assign sys_rst_n = sysrst_nr2;	//active Low

endmodule

//################################################//
//################################################//

module system_delay
(
	input	clk,		//50MHz
	input	rst_n,
	output	delay_done
);

//------------------------------------------
// Delay 100ms for steady state
localparam	DELAY_CNT = 23'd100_0000;	//50ms
reg	[22:0] cnt;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		cnt <= 0;
	else
		begin
		if(cnt < DELAY_CNT) //1ms
			cnt <= cnt + 1'b1;
		else
			cnt <= cnt;
		end
end

//------------------------------------------
//sys_rst_n synchronism
assign	delay_done = (cnt == DELAY_CNT)? 1'b1 : 1'b0;

endmodule

摄像头检测代码

`timescale 1ns/1ns
module CMOS_Capture
(
	//Global Clock
	input				iCLK,			//25MHz
	input				iRST_N,

	//I2C Initilize Done
	input				Init_Done,		//Init Done
	
	//Sensor Interface
	output				CMOS_RST_N,		//cmos work state(5ms delay for sccb config)
	output				CMOS_PWDN,      //cmos power on	
	output				CMOS_XCLK,		//25MHz
	input				CMOS_PCLK,		//25MHz
	input	[7:0]		CMOS_iDATA,		//CMOS Data
	input				CMOS_VSYNC,		//L: Vaild
	input				CMOS_HREF,		//H: Vaild
	
	//Ouput Sensor Data
	output	reg			CMOS_oCLK,		//1/2 PCLK
	output	reg	[15:0]	CMOS_oDATA,		//16Bits RGB		
	output	reg			CMOS_VALID,		//Data Enable
	output	reg	[7:0]	CMOS_FPS_DATA	//cmos fps
);
assign	CMOS_RST_N = 1'b1;		//cmos work state(5ms delay for sccb config)
assign  CMOS_PWDN = 1'b0;		//cmos power on	
assign	CMOS_XCLK = iCLK;		//25MHz XCLK


//-----------------------------------------------------
//同步输入//Sensor HS & VS Vaild Capture
/**************************************************
________							       ________
VS		|_________________________________|
HS			  _______	 	   _______
_____________|       |__...___|       |____________
**************************************************/

/*
//----------------------------------------------
reg		mCMOS_HREF;		//行同步:高电平有效
always@(posedge CMOS_PCLK or negedge iRST_N)
begin
	if(!iRST_N)
		mCMOS_HREF <= 0;
	else
		mCMOS_HREF <= CMOS_HREF;		
end
wire	CMOS_HREF_over = ({mCMOS_HREF,CMOS_HREF} == 2'b10) ? 1'b1 : 1'b0;		//HREF 下降沿结束
*/

//----------------------------------------------
reg		mCMOS_VSYNC;
always@(posedge CMOS_PCLK or negedge iRST_N)
begin
	if(!iRST_N)
		mCMOS_VSYNC <= 1;
	else
		mCMOS_VSYNC <= CMOS_VSYNC;		//场同步:低电平有效
end
wire	CMOS_VSYNC_over = ({mCMOS_VSYNC,CMOS_VSYNC} == 2'b01) ? 1'b1 : 1'b0;	//VSYNC上升沿结束


/*
//--------------------------------------------
//Counter the HS & VS Pixel
localparam		H_DISP	=	12'd640;
localparam		V_DISP	=	12'd480;
reg		[11:0]	X_Cont;	//640
reg		[11:0]	Y_Cont;	//480
always@(posedge CMOS_PCLK or negedge iRST_N)
begin
	if(!iRST_N)
		X_Cont <= 0;
	else if(~CMOS_VSYNC & CMOS_HREF)			//场信号有效
		X_Cont <= (byte_state == 1'b1) ?  X_Cont + 1'b1 : X_Cont;
	else
		X_Cont <= 0;
end

always@(posedge CMOS_PCLK or negedge iRST_N)
begin
	if(!iRST_N)
		Y_Cont <= 0;
	else if(CMOS_VSYNC == 1'b0)
		begin
		if(CMOS_HREF_over == 1'b1)		//HREF下降沿 一行结束
			Y_Cont <= Y_Cont + 1'b1;
		end
	else
		Y_Cont <= 0;
end
*/

//-----------------------------------------------------
//Change the sensor data from 8 bits to 16 bits.
reg			byte_state;		//byte state count
reg [7:0]  	Pre_CMOS_iDATA;
always@(posedge CMOS_PCLK or negedge iRST_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
		end
end


//--------------------------------------------
//Wait for Sensor output Data valid, 10 Franme
reg	[3:0] 	Frame_Cont;
reg 		Frame_valid;
always@(posedge CMOS_PCLK or negedge iRST_N)
begin
	if(!iRST_N)
		begin
		Frame_Cont <= 0;
		Frame_valid <= 0;
		end
	else if(Init_Done)					//CMOS I2C初始化完毕
		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
		end
end

//-----------------------------------------------------
//CMOS_DATA数据同步输出使能时钟
always@(posedge CMOS_PCLK or negedge iRST_N)
begin
	if(!iRST_N)
		CMOS_oCLK <= 0;
	else if(Frame_valid == 1'b1 && byte_state)//(X_Cont >= 12'd1 && X_Cont <= H_DISP))
		CMOS_oCLK <= ~CMOS_oCLK;
	else
		CMOS_oCLK <= 0;
end

//----------------------------------------------------
//数据输出有效CMOS_VALID
always@(posedge CMOS_PCLK or negedge iRST_N)
begin
	if(!iRST_N)
		CMOS_VALID <= 0;
	else if(Frame_valid == 1'b1)
		CMOS_VALID <= ~CMOS_VSYNC;
	else
		CMOS_VALID <= 0;
end


/************************************************************
	Caculate Frame Rate per second
*************************************************************/
//-----------------------------------------------------
//	2s 延时函数
reg	[25:0]	delay_cnt;	//25_000000 * 2
always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N)
		delay_cnt <= 0;
	else if(Frame_valid)
		begin
		if(delay_cnt < 26'd50_000000)
			delay_cnt <= delay_cnt + 1'b1;
		else
			delay_cnt <= 0;
		end
	else
		delay_cnt <= 0;
end
wire	delay_2s = (delay_cnt == 26'd50_000000) ? 1'b1 : 1'b0;

//-------------------------------------------
//帧率采样计算
reg			fps_state;
reg	[7:0]	fps_data;
always@(posedge iCLK or negedge iRST_N)
begin
	if(!iRST_N)
		begin
		fps_data <= 0;
		fps_state <= 0;
		CMOS_FPS_DATA <= 0;
		end
	else if(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;
		end
end


endmodule

摄像头开机定时要求

//camera power on timing requirement
module power_on_delay(clk_50M,reset_n,camera_rstn,camera_pwnd,initial_en);                  
input clk_50M;
input reset_n;
output camera_rstn;
output camera_pwnd;
output initial_en;
reg [18:0]cnt1;
reg [15:0]cnt2;
reg [19:0]cnt3;
reg initial_en;
reg camera_rstn_reg;
reg camera_pwnd_reg;

assign camera_rstn=camera_rstn_reg;
assign camera_pwnd=camera_pwnd_reg;

//5ms, delay from sensor power up stable to Pwdn pull down
always@(posedge clk_50M)
begin
  if(reset_n==1'b0) begin
	    cnt1<=0;
		 camera_pwnd_reg<=1'b1;  
  end
  else if(cnt1<18'h40000) begin
       cnt1<=cnt1+1'b1;
       camera_pwnd_reg<=1'b1;
  end
  else
     camera_pwnd_reg<=1'b0;         
end

//1.3ms, delay from pwdn low to resetb pull up
always@(posedge clk_50M)
begin
  if(camera_pwnd_reg==1)  begin
	    cnt2<=0;
		 camera_rstn_reg<=1'b0;  
  end
  else if(cnt2<16'hffff) begin
       cnt2<=cnt2+1'b1;
       camera_rstn_reg<=1'b0;
  end
  else
     camera_rstn_reg<=1'b1;         
end

//21ms, delay from resetb pul high to SCCB initialization
always@(posedge clk_50M)
begin
  if(camera_rstn_reg==0) begin
         cnt3<=0;
         initial_en<=1'b0;
  end
  else if(cnt3<20'hfffff) begin
        cnt3<=cnt3+1'b1;
        initial_en<=1'b0;
  end
  else
       initial_en<=1'b1;    
end

endmodule

sdram_vga_top 

module sdram_vga_top
(
	//global clock
	input			clk_vga,		//vga clock
	input			clk_ref,		//sdram ctrl clock
	input			clk_refout,		//sdram clock output
	input			rst_n,			//global reset

	//sdram control
	output			sdram_clk,		//sdram clock
	output			sdram_cke,		//sdram clock enable
	output			sdram_cs_n,		//sdram chip select
	output			sdram_we_n,		//sdram write enable
	output			sdram_cas_n,	//sdram column address strobe
	output			sdram_ras_n,	//sdram row address strobe
	output			sdram_udqm,		//sdram data enable (H:8)
	output			sdram_ldqm,		//sdram data enable (L:8)
	output	[1:0]	sdram_ba,		//sdram bank address
	output	[11:0]	sdram_addr,		//sdram address
	inout	[15:0]	sdram_data,		//sdram data
		
	//lcd port
	output			lcd_dclk,		//lcd pixel clock			
	output			lcd_hs,			//lcd horizontal sync 
	output			lcd_vs,			//lcd vertical sync
	output			lcd_sync,		//lcd sync
	output			lcd_blank,		//lcd blank(L:blank)
	output	[4:0]	lcd_red,		//lcd red data
	output	[5:0]	lcd_green,		//lcd green data
	output	[4:0]	lcd_blue,		//lcd blue data
	
	//user interface
	input			clk_write,		//fifo write clock
	input			sys_we,			//fifo write enable
	input	[15:0]	sys_data_in,	//fifo data input
	output			sdram_init_done,//sdram init done
	input			frame_valid		//frame valid
);


//----------------------------------------------
wire			sys_rd;        		//fifo read enable
wire	[15:0]	sys_data_out;  		//fifo data output
wire			lcd_framesync;		//lcd frame sync
wire			frame_write_done;	//sdram write frame done
wire			frame_read_done;	//sdram read frame done
wire	[1:0]	wr_bank;			//sdram write bank
wire	[1:0]	rd_bank;			//sdram read bank
wire			wr_load;			//sdram write address reset
wire			rd_load;			//sdram read address reset
sdram_2fifo_top	u_sdram_2fifo_top
(
	//global clock
	.clk_ref			(clk_ref),			//sdram	reference clock
	.clk_refout			(clk_refout),		//sdram clk	input 
	.clk_write			(clk_write),		//fifo data write clock
	.clk_read			(clk_vga),			//fifo data read clock
	.rst_n				(rst_n),			//global reset
	
	//sdram interface
	.sdram_clk			(sdram_clk),		//sdram clock	
	.sdram_cke			(sdram_cke),		//sdram clock enable	
	.sdram_cs_n			(sdram_cs_n),		//sdram chip select	
	.sdram_we_n			(sdram_we_n),		//sdram write enable	
	.sdram_ras_n		(sdram_ras_n),		//sdram column address strobe	
	.sdram_cas_n		(sdram_cas_n),		//sdram row address strobe	
	.sdram_ba			(sdram_ba),			//sdram data enable (H:8)    
	.sdram_addr			(sdram_addr),		//sdram data enable (L:8)	
	.sdram_data			(sdram_data),		//sdram bank address	
	.sdram_udqm			(sdram_udqm),		//sdram address	
	.sdram_ldqm			(sdram_ldqm),		//sdram data
	
	//user interface
	//burst and addr
	.wr_length			(9'd256),			//sdram write burst length
	.rd_length			(9'd256),			//sdram read burst length
	.wr_addr			({wr_bank,20'd0}),			//sdram start write address
	.wr_max_addr		({wr_bank,20'd307200}),		//sdram max write address
	.wr_load			(wr_load),			//sdram write address reset
	.rd_addr			({rd_bank,20'd0}),			//sdram start read address
	.rd_max_addr		({rd_bank,20'd307200}),		//sdram max read address
	.rd_load			(rd_load),			//sdram read address reset
	
	//dcfifo interface
	.sdram_init_done	(sdram_init_done),	//sdram init done
	.frame_write_done	(frame_write_done),	//sdram write one frame
	.frame_read_done	(frame_read_done),	//sdram read one frame
	.sys_we				(sys_we),			//fifo write enable
	.sys_data_in		(sys_data_in),		//fifo data input
	.sys_rd				(sys_rd),			//fifo read enable
	.sys_data_out		(sys_data_out),		//fifo data output
	.data_valid			(lcd_framesync)		//system data output enable
);

//-----------------------------
sdbank_switch	u_sdbank_switch
(
	.clk				(clk_write),
	.rst_n				(rst_n),
	
	.bank_valid			(frame_valid),
	.frame_write_done	(frame_write_done),
	.frame_read_done	(frame_read_done),
	
	.wr_bank			(wr_bank),
	.rd_bank			(rd_bank),
	.wr_load			(wr_load),
	.rd_load			(rd_load)
);

//---------------------------------
//display on lcd
wire	[10:0]	lcd_xpos;
wire	[10:0]	lcd_ypos;
wire	[15:0]	lcd_data;
assign lcd_data = sys_data_out;
/*
lcd_display	U_lcd_display
(
	.clk			(clk_vga),
	.rst_n			(rst_n),
    
    .alpha_data		(9'hC8),
	.lcd_xpos		(lcd_xpos),
	.lcd_ypos		(lcd_ypos),
	.lcd_data_in	(sys_data_out),	
	.lcd_data		(lcd_data)
);
*/
//-----------------------------
//lcd driver top module
lcd_top	u_lcd_top
(
	//global clock
	.clk			(clk_vga),	
	.rst_n			(rst_n),	

	//lcd interface
	.lcd_blank		(lcd_blank),
	.lcd_sync		(lcd_sync),
	.lcd_dclk		(lcd_dclk),
	.lcd_hs			(lcd_hs),		
	.lcd_vs			(lcd_vs),	
	.lcd_en			(),	
	.lcd_rgb		({lcd_red, lcd_green ,lcd_blue}),

	//user interface
	.lcd_request	(sys_rd),
	.lcd_framesync	(lcd_framesync),
	.lcd_data		(lcd_data),
	.lcd_xpos		(lcd_xpos),
	.lcd_ypos		(lcd_ypos)
);

endmodule

 五、什么是DVP?

       DVP(Digital Video Port) 是传统的sensor输出接口,采用并行输出方式,d数据位宽有8bit、10bit、12bit、16bit,是CMOS电平信号(重点是非差分信号),PCLK最大速率为96MHz,接口如下图:

基于FPGA的OV7670摄像头实时检测_第3张图片

 DVP协议是摄像头中常用的协议,除了DVP协议摄像头中还有其他常用的协议如:MIPI、LVDS等协议,以实现标准图像数据流转换,其中摄像头8位数据转16位代码如下

module cmos_8_16bit(
	input              rst,
	input              pclk,
	input [7:0]        pdata_i,
	input              de_i,
	output reg[15:0]   pdata_o,//转换成16位RGB565图像数据
	output reg         hblank,
	output reg         de_o
);
reg[7:0] pdata_i_d0;
reg[11:0] x_cnt;
always@(posedge pclk)
begin
	pdata_i_d0 <= pdata_i;
end

always@(posedge pclk or posedge rst)
begin
	if(rst)
		x_cnt <= 12'd0;
	else if(de_i)
		x_cnt <= x_cnt + 12'd1;
	else
		x_cnt <= 12'd0;
end

always@(posedge pclk or posedge rst)
begin
	if(rst)
		de_o <= 1'b0;
	else if(de_i && x_cnt[0])
		de_o <= 1'b1;
	else
		de_o <= 1'b0;
end

always@(posedge pclk or posedge rst)
begin
	if(rst)
		hblank <= 1'b0;
	else
		hblank <= de_i;
end

always@(posedge pclk or posedge rst)
begin
	if(rst)
		pdata_o <= 16'd0;
	else if(de_i && x_cnt[0])
		pdata_o <= {pdata_i_d0,pdata_i};
	else
		pdata_o <= 16'd0;
end

endmodule 

六、摄像头写数据请求

module cmos_write_req_gen(
	input              rst,
	input              pclk,
	input              cmos_vsync,
	output reg         write_req,
	output reg[1:0]    write_addr_index,
	output reg[1:0]    read_addr_index,
	input              write_req_ack
);
reg cmos_vsync_d0;
reg cmos_vsync_d1;
always@(posedge pclk or posedge rst)
begin
	if(rst == 1'b1)
	begin
		cmos_vsync_d0 <= 1'b0;
		cmos_vsync_d1 <= 1'b0;
	end
	else
	begin
		cmos_vsync_d0 <= cmos_vsync;
		cmos_vsync_d1 <= cmos_vsync_d0;
	end
end
always@(posedge pclk or posedge rst)
begin
	if(rst == 1'b1)
		write_req <= 1'b0;
	else if(cmos_vsync_d0 == 1'b1 && cmos_vsync_d1 == 1'b0)
		write_req <= 1'b1;
	else if(write_req_ack == 1'b1)
		write_req <= 1'b0;
end
always@(posedge pclk or posedge rst)
begin
	if(rst == 1'b1)
		write_addr_index <= 2'b0;
	else if(cmos_vsync_d0 == 1'b1 && cmos_vsync_d1 == 1'b0)
		write_addr_index <= write_addr_index + 2'd1;
end

always@(posedge pclk or posedge rst)
begin
	if(rst == 1'b1)
		read_addr_index <= 2'b0;
	else if(cmos_vsync_d0 == 1'b1 && cmos_vsync_d1 == 1'b0)
		read_addr_index <= write_addr_index;
end
endmodule 

七、顶层文件编写

`timescale 1ns / 1ps
module sdram_ov7670_vga
(
	//global clock 50MHz
	//input			clk_27,			//27MHz
	input			CLOCK,	
	//input			rst_n,			//global reset
	
	//sdram control
	output			S_CLK,		//sdram clock
	output			S_CKE,		//sdram clock enable
	output			S_NCS,		//sdram chip select
	output			S_NWE,		//sdram write enable
	output			S_NCAS,	//sdram column address strobe
	output			S_NRAS,	//sdram row address strobe
	output[1:0] 	S_DQM,		//sdram data enable 
	output	[1:0]	S_BA,		//sdram bank address
	output	[12:0]	S_A,		//sdram address
	inout	[15:0]	S_DB,		//sdram data
	
	//VGA port			
	output			VGA_HSYNC,			//horizontal sync 
	output			VGA_VSYNC,			//vertical sync
	output	[15:0]	VGAD,		//VGA data
	
	//cmos interface
	output			CMOS_SCLK,		//cmos i2c clock
	inout			CMOS_SDAT,		//cmos i2c data
	input			CMOS_VSYNC,		//cmos vsync
	input			CMOS_HREF,		//cmos hsync refrence
	input			CMOS_PCLK,		//cmos pxiel clock
	output			CMOS_XCLK,		//cmos externl clock
	input	[7:0]	CMOS_DB,		//cmos data
//	output			cmos_rst_n,		//cmos reset
//	output			cmos_pwdn,		//cmos pwer down

	output	[3:0]	LED		//led data input	
);
assign rst_n = 1'b1;
//---------------------------------------------
wire  clk_camera;
wire	clk_vga;		//vga clock
wire	clk_ref;		//sdram ctrl clock
wire	clk_refout;		//sdram clock output
wire	sys_rst_n;		//global reset
system_ctrl	u_system_ctrl
(
	.clk				(CLOCK),			//global clock  50MHZ
	.rst_n				(rst_n),		//external reset
	
	.sys_rst_n			(sys_rst_n),	//global reset
	.clk_c0				(clk_camera),	//13MHz
	.clk_c1				(clk_vga),		//25MHz
	.clk_c2				(clk_ref),	   //100MHz
	.clk_c3				(clk_refout)	//100MHz
);
 

//-----------------------------
wire	[7:0]	I2C_RDATA;		//i2c register data
wire	[7:0]	LUT_INDEX;		//lut index
wire			Config_Done;	//I2C config done		
I2C_AV_Config	u_I2C_AV_Config 
(
	//Global clock
	.iCLK				(clk_vga),		//25MHz
	.iRST_N				(sys_rst_n),	//Global Reset
	
	//I2C Side
	.I2C_SCLK			(CMOS_SCLK),	//I2C CLOCK
	.I2C_SDAT			(CMOS_SDAT),	//I2C DATA
	
	//CMOS Signal
	.Config_Done		(Config_Done),	//I2C Config done
	.I2C_RDATA			(I2C_RDATA),	//CMOS ID
	.LUT_INDEX			()//(LUT_INDEX)		//ID Index
);
assign	led_data = I2C_RDATA;				//diaplay I2C_RDATA
//-----------------------------------------------
//Seg7_lut	u5	(	LUT_INDEX[7:4],	oSEG5	);	
//Seg7_lut	u4	(	LUT_INDEX[3:0],	oSEG4	);
//Seg7_lut	u1	(	I2C_RDATA[7:4],	oSEG1	);
//Seg7_lut	u0	(	I2C_RDATA[3:0],	oSEG0	);

//-----------------------------------------------               
wire			frame_valid;		//data valid, or address restart
wire	[7:0]	cmos_fps_data;		//cmos frame rate
CMOS_Capture	u_CMOS_Capture
(
	//Global Clock
	.iCLK				(clk_camera),		//24MHz
	.iRST_N				(sys_rst_n),	//global reset
	
	//I2C Initilize Done
	.Init_Done			(Config_Done & sdram_init_done),	//Init Done
	
	//Sensor Interface
	.CMOS_RST_N			(),//(cmos_rst_n),	//cmos work state 
	.CMOS_PWDN			(),//(cmos_pwdn),	//cmos power on	
	.CMOS_XCLK			(CMOS_XCLK),		//cmos
	.CMOS_PCLK			(CMOS_PCLK),		//25MHz
	.CMOS_iDATA			(CMOS_DB),    	//CMOS Data
	.CMOS_VSYNC			(CMOS_VSYNC),  	 	//L: Vaild
	.CMOS_HREF			(CMOS_HREF), 		//H: Vaild
	                                    
	//Ouput Sensor Data                 
	.CMOS_oCLK			(sys_we),			//Data PCLK
	.CMOS_oDATA			(sys_data_in),  	//16Bits RGB
	.CMOS_VALID			(frame_valid),		//Data Enable
	.CMOS_FPS_DATA		()//(cmos_fps_data)		//cmos frame rate
);

//Seg7_lut	u7	(	cmos_fps_data[7:4],	oSEG7	);	//fsp rate
//Seg7_lut	u6	(	cmos_fps_data[3:0],	oSEG6	);	//fps rate


//wire	[8:0]	alpha_data;					//alpha adjust data
//assign	led_data = alpha_data;				//diaplay alpha data
//alpha_control	u_alpha_control
//(
//	.clk				(clk_vga),			//vga clock
//	.rst_n				(sys_rst_n),		//global reset
//	
//	.key_data			(key_data),			//key data
//	.alpha_data			(alpha_data)		//aplha adjust data
//);

//-------------------------------------
//sdram vga ctrl system
wire			sys_we;						//system data write enable
wire	[15:0]	sys_data_in;				//system data input
wire			sdram_init_done;			//sdram init done
sdram_vga_top	u_sdram_vga_top
(
	//global clock
	.clk_vga			(clk_vga),			//vga clock
	.clk_ref			(clk_ref),			//sdram ctrl clock
	.clk_refout			(clk_refout),		//sdram clock output
	.rst_n				(sys_rst_n),		//global reset

	//sdram control
	.sdram_clk			(S_CLK),		//sdram clock
	.sdram_cke			(S_CKE),		//sdram clock enable
	.sdram_cs_n			(S_NCS),		//sdram chip select
	.sdram_we_n			(S_NWE),		//sdram write enable
	.sdram_cas_n		(S_NCAS),		//sdram column address strobe
	.sdram_ras_n		(S_NRAS),		//sdram row address strobe
	.sdram_udqm			(S_DQM[1]),		//sdram data enable (H:8)
	.sdram_ldqm			(S_DQM[0]),		//sdram data enable (L:8)
	.sdram_ba			(S_BA),			//sdram bank address
	.sdram_addr			(S_A),		//sdram address
	.sdram_data			(S_DB),		//sdram data
		
	//lcd port
	.lcd_dclk			(),			//lcd pixel clock			
	.lcd_hs				(VGA_HSYNC),			//lcd horizontal sync 
	.lcd_vs				(VGA_VSYNC),			//lcd vertical sync
	.lcd_sync			(),//(lcd_sync),			//lcd sync
	.lcd_blank			(),		//lcd blank(L:blank)
	.lcd_red			(VGAD[15:11]),			//lcd red data
	.lcd_green			(VGAD[10:5]),		//lcd green data
	.lcd_blue			(VGAD[4:0]),			//lcd blue data
	
	//user interface
	.clk_write			(CMOS_PCLK),			//fifo write clock
	.sys_we				(sys_we),			//fifo write enable
	.sys_data_in		(sys_data_in),		//fifo data input
	.sdram_init_done	(sdram_init_done),	//sdram init done
	.frame_valid		(frame_valid)		//frame valid
);


endmodule

八、效果

基于FPGA的OV7670摄像头实时检测_第4张图片基于FPGA的OV7670摄像头实时检测_第5张图片

你可能感兴趣的:(FPGA,fpga开发)