基于 ZYNQ 的双目视觉图像采集系统设计(二)

       Image_controller模块包含2个子模块,如图1所示。I2C_OV5640_Init_RGB565.v 模块实现 IIC的接口协议和初始化配置,其下有两个子模块:I2C_Controller.v 模块实现IIC的读写控制时序,I2C_OV5640_RGB565_Config.v 模块则产生IIC寄存器初始化配置的地址和数据;image_capture.v 模块实现图像采集和缓存功能。  

图1. Image_controller模块架构

1.I2C_OV5640_Init_RGB565.v模块设计
       如图2所示,I2C_OV5640_RGB565_Config.v模块存储着CMOS Sensor的I2C寄存器初始化配置的地址和数据;I2C_Controller.v 模块主要是最底层的IIC协议实现;而I2C_OV5640_Init_RGB565.v模块中设计了一个I2C初始化配置状态机,在上电后,该状态机从I2C_OV5640_RGB565_Config.v 模块中依次读取 311个地址和数据,然后分别通过I2C_Controller.v模块实现I2C写数据时序,完成CMOS Sensor的上电初始化配置。

图2. IIC配置产生逻辑功能框图

       I2C_OV5640_Init_RGB565.v模块产生I2C初始化配置的控制信号,通过状态机实现311次的I2C操作。config_done信号在完成I2C初始化配置后拉高;i2c_sclk为连接CMOS Sensor 的I2C时钟信号,i2c_sdat为连接CMOS Sensor的I2C数据信号,这两个信号都连接到 I2C_Controller.v模块实现控制。

module I2C_OV5640_Init_RGB565
(
	//Global clock
	input		clk,		//100MHz
	input		rst_n,		//Global Reset
	
	//I2C Side
	output		i2c_sclk,	//I2C CLOCK
	inout		i2c_sdat,	//I2C DATA
	
	output reg	config_done//Config Done
);

 以下代码对输入时钟信号做分频,产生100KHz的I2C时钟i2c_ctrl_clk。

parameter	CLK_Freq	=	100_000000;	//100 MHz
parameter	I2C_Freq	=	100_000;		//400 KHz
reg	[15:0]	i2c_clk_div;				//CLK DIV
reg			i2c_ctrl_clk;				//I2C Control Clock
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		i2c_clk_div	<=	0;
		i2c_ctrl_clk	<=	0;
		end
	else
		begin
		 if( i2c_clk_div	< (CLK_Freq/I2C_Freq)/2)
			 i2c_clk_div	<=	i2c_clk_div + 1'd1;
		 else
			 begin
			 i2c_clk_div	<=	0;
			i2c_ctrl_clk	<=	~i2c_ctrl_clk;
			end
		end
end

       以下代码检测I2C时钟i2c_ctrl_clk的下降沿,产生脉冲信号i2c_negclk作为I2C数据变更的使能信号。

reg	i2c_en_r0, i2c_en_r1;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		i2c_en_r0 <= 0;
		i2c_en_r1 <= 0;
		end
	else
		begin
		i2c_en_r0 <= i2c_ctrl_clk;
		i2c_en_r1 <= i2c_en_r0;
		end
end
wire	i2c_negclk = (i2c_en_r1 & ~i2c_en_r0) ? 1'b1 : 1'b0;		//negedge i2c_sclk transfer data

       下面的状态机,将lut_index信号从0到310(一共311)递增,分别读取I2C_OV5640_RGB565_Config.v模块中存储的I2C配置寄存器的地址和数据,逐个的实现I2C 的访问(读或写)时序。这里的状态机setup_state分3个状态,即状态0,空闲状态;状态 1,写数据状态;状态2,lut_index递增。状态切换的逻辑是这样的:状态0判断当前i2c_end 为低电平,会立即进入状态1(实际上状态0只会停留1个I2C时钟周期);状态1在i2c_end拉高后进入状态2(即状态1会一直停留到1次I2C写操作完成);状态2直接切换到状态0。在状态机之外,会判断if(lut_index < LUT_SIZE)来决定是否进入状态机中执行I2C操作,也就是说。当所有311次I2C操作完成后,将不再进入状态机中执行I2C读或写操作。 

always@(posedge clk or negedge rst_n)		//25MHz	i2c_ctrl_clk
begin
	if(!rst_n)
		begin
		config_done <= 0;
		lut_index	<=	0;
		setup_state	<=	0;
		i2c_trans		<=	0;
		i2c_wr     <=	0;	
		end
	else if(i2c_negclk)
		begin
		if(lut_index < LUT_SIZE)
			begin
			config_done <= 0;
			case(setup_state)
			0:	begin						//IDLE State
				if(~i2c_end)				//END Transfer
					setup_state	<=	1;		
				else						//Transfe ing
					setup_state	<=	0;				
					i2c_trans		<=	1;			//Go Transfer
				if(lut_index < 12'd2)
					begin
					i2c_wr <= 0;			//Read Data
					i2c_data<={8'h79,8'h78,lut_data};
					end
				else
				begin
					i2c_wr <= 1;			//Write Data
					i2c_data<={8'h00,8'h78,lut_data};
				end
				end
			1:	
				begin						//Write data
				if(i2c_end)
					begin
					i2c_wr <= 0;
					i2c_trans <= 0;
					if(~i2c_ack)			//ACK ACTIVE
						setup_state	<=	2;	//INDEX ++
					else
						setup_state	<=	0;	//Repeat Transfer						
					end
				end
			2:	begin						//Address Add
				lut_index	<= lut_index + 1'd1;
				setup_state	<= 0;
				i2c_trans	<= 0;
				i2c_wr      <= 0;
				end
			endcase
			end
		else
			begin
			config_done <= 1'b1;
			lut_index 	<= lut_index;
			setup_state	<= 0;
			i2c_trans	<= 0;
			i2c_wr      <= 0;
			end
	end
end

I2C_OV5640_Init_RGB565.v模块完整代码如下:

`timescale 1ns/1ns
module I2C_OV5640_Init_RGB565
(
	//Global clock
	input		clk,		//100MHz
	input		rst_n,		//Global Reset
	
	//I2C Side
	output		i2c_sclk,	//I2C CLOCK
	inout		i2c_sdat,	//I2C DATA
	
	output reg	config_done//Config Done
);


/	I2C Control Clock	
//	Clock Setting
parameter	CLK_Freq	=	100_000000;	//100 MHz
parameter	I2C_Freq	=	100_000;		//400 KHz
reg	[15:0]	i2c_clk_div;				//CLK DIV
reg			i2c_ctrl_clk;				//I2C Control Clock
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		i2c_clk_div	<=	0;
		i2c_ctrl_clk	<=	0;
		end
	else
		begin
		 if( i2c_clk_div	< (CLK_Freq/I2C_Freq)/2)
			 i2c_clk_div	<=	i2c_clk_div + 1'd1;
		 else
			 begin
			 i2c_clk_div	<=	0;
			i2c_ctrl_clk	<=	~i2c_ctrl_clk;
			end
		end
end


//-------------------------------------
reg	i2c_en_r0, i2c_en_r1;
always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		begin
		i2c_en_r0 <= 0;
		i2c_en_r1 <= 0;
		end
	else
		begin
		i2c_en_r0 <= i2c_ctrl_clk;
		i2c_en_r1 <= i2c_en_r0;
		end
end
wire	i2c_negclk = (i2c_en_r1 & ~i2c_en_r0) ? 1'b1 : 1'b0;		//negedge i2c_sclk transfer data

//	Config Control	
// Internal Registers/Wires
wire		i2c_end;		//I2C Transfer End
wire		i2c_ack;		//I2C Transfer ACK
reg	[8:0]	lut_index;		//LUT Index
reg	[1:0]	setup_state;		//State Machine
reg			i2c_trans;			//I2C Transfer Start
reg			i2c_wr;			//I2C Write / Read Data
wire	[23:0]	lut_data;		//ID-Address,SUB-Address,Data}
reg	[39:0]	i2c_data;

wire	[8:0]	LUT_SIZE;
always@(posedge clk or negedge rst_n)		//25MHz	i2c_ctrl_clk
begin
	if(!rst_n)
		begin
		config_done <= 0;
		lut_index	<=	0;
		setup_state	<=	0;
		i2c_trans		<=	0;
		i2c_wr     <=	0;	
		end
	else if(i2c_negclk)
		begin
		if(lut_index < LUT_SIZE)
			begin
			config_done <= 0;
			case(setup_state)
			0:	begin						//IDLE State
				if(~i2c_end)				//END Transfer
					setup_state	<=	1;		
				else						//Transfe ing
					setup_state	<=	0;				
					i2c_trans		<=	1;			//Go Transfer
				if(lut_index < 12'd2)
					begin
					i2c_wr <= 0;			//Read Data
					i2c_data<={8'h79,8'h78,lut_data};
					end
				else
				begin
					i2c_wr <= 1;			//Write Data
					i2c_data<={8'h00,8'h78,lut_data};
				end
				end
			1:	
				begin						//Write data
				if(i2c_end)
					begin
					i2c_wr <= 0;
					i2c_trans <= 0;
					if(~i2c_ack)			//ACK ACTIVE
						setup_state	<=	2;	//INDEX ++
					else
						setup_state	<=	0;	//Repeat Transfer						
					end
				end
			2:	begin						//Address Add
				lut_index	<= lut_index + 1'd1;
				setup_state	<= 0;
				i2c_trans	<= 0;
				i2c_wr      <= 0;
				end
			endcase
			end
		else
			begin
			config_done <= 1'b1;
			lut_index 	<= lut_index;
			setup_state	<= 0;
			i2c_trans	<= 0;
			i2c_wr      <= 0;
			end
	end
end


I2C_Controller 	u_I2C_Controller	
(	
	.clk			(clk),
	.rst_n			(rst_n),
							
	.i2c_clk		(i2c_ctrl_clk),	//	Controller Work Clock
	.i2c_en			(i2c_negclk),		//	I2C DATA ENABLE
	.i2c_wdata		(i2c_data),//	DATA:[SLAVE_ADDR,SUB_ADDR,DATA]
	.i2c_sclk		(i2c_sclk),			//	I2C CLOCK
	.i2c_sdat		(i2c_sdat),			//	I2C DATA
	
	.trans			(i2c_trans),			//	Go Transfer
	.wr				(i2c_wr),      	//	END transfor
	.ack			(i2c_ack),			//	ACK
	.i2c_end		(i2c_end),			//	END transfor 
	.i2c_rdata		(/*I2C_RDATA*/)			//	ID
);

		

I2C_OV5640_RGB565_Config	u_I2C_OV5640_RGB565_Config
(
	.LUT_INDEX		(lut_index	),
	.LUT_DATA		(lut_data	),
	.LUT_SIZE		(LUT_SIZE	)
);


endmodule

2. I2C_OV5640_RGB565_Config.v模块设计
        该模块相当于一个 LUT或者ROM,存储着对ov5640初始化配置的地址和数据(这些数据来源于《OV5640 camera module software application notes 1.3_Actions》),输入LUT_INDEX信号可以取值0~310(LUT_SIZE-1),对应不同的输出LUT_DATA。这个LUT_DATA的bit23-8为I2C访问地址,bit7-0为I2C写入数据。输出LUT_SIZE表示这个LUT(ROM)的有效数据数量。 
代码如下:

`timescale 1ns/1ns
module	I2C_OV5640_RGB565_Config
(
	input		[8:0]	LUT_INDEX,
	output	reg	[23:0]	LUT_DATA,
	output		[8:0]	LUT_SIZE
);
assign		LUT_SIZE = 9'd311;


localparam	SET_OV5640	=	2;			//SET_OV LUT Adderss

//-----------------------------------------------------------------
/	Config Data LUT	  //	
always@(*)
begin
	case(LUT_INDEX)
	OV5640 : VGA 640*480
	SET_OV5640 +  0:   	LUT_DATA	= 	24'h3008_42;
	SET_OV5640 +  1:   	LUT_DATA	= 	24'h3103_03;
	SET_OV5640 +  2:   	LUT_DATA	= 	24'h4005_1a;
	SET_OV5640 +  3:   	LUT_DATA	= 	24'h4740_21;
	SET_OV5640 +  4:   	LUT_DATA	= 	24'h3017_ff;
	SET_OV5640 +  5:   	LUT_DATA	= 	24'h3018_ff;
	SET_OV5640 +  6:   	LUT_DATA	= 	24'h3034_1a;
	SET_OV5640 +  7:   	LUT_DATA	= 	24'h3035_11;	//PLL
	SET_OV5640 +  8:   	LUT_DATA	= 	24'h3036_69;	//PLL
	SET_OV5640 +  9:   	LUT_DATA	= 	24'h3037_13;
	SET_OV5640 + 10:   	LUT_DATA	= 	24'h3108_01;
	SET_OV5640 + 11:   	LUT_DATA	= 	24'h3630_36;
	SET_OV5640 + 12:   	LUT_DATA	= 	24'h3631_0e;
	SET_OV5640 + 13:   	LUT_DATA	= 	24'h3632_e2;
	SET_OV5640 + 14:   	LUT_DATA	= 	24'h3633_12;
	SET_OV5640 + 15:   	LUT_DATA	= 	24'h3621_e0;
	SET_OV5640 + 16:   	LUT_DATA	= 	24'h3704_a0;
	SET_OV5640 + 17:   	LUT_DATA	= 	24'h3703_5a;
	SET_OV5640 + 18:   	LUT_DATA	= 	24'h3715_78;
	SET_OV5640 + 19:   	LUT_DATA	= 	24'h3717_01;
	SET_OV5640 + 20:   	LUT_DATA	= 	24'h370b_60;
	SET_OV5640 + 21:   	LUT_DATA	= 	24'h3705_1a;
	SET_OV5640 + 22:   	LUT_DATA	= 	24'h3905_02;
	SET_OV5640 + 23:   	LUT_DATA	= 	24'h3906_10;
	SET_OV5640 + 24:   	LUT_DATA	= 	24'h3901_0a;
	SET_OV5640 + 25:   	LUT_DATA	= 	24'h3731_12;
	SET_OV5640 + 26:   	LUT_DATA	= 	24'h3600_08;
	SET_OV5640 + 27:   	LUT_DATA	= 	24'h3601_33;
	SET_OV5640 + 28:   	LUT_DATA	= 	24'h302d_60;
	SET_OV5640 + 29:   	LUT_DATA	= 	24'h3620_52;
	SET_OV5640 + 30:   	LUT_DATA	= 	24'h371b_20;
	SET_OV5640 + 31:   	LUT_DATA	= 	24'h471c_50;
	SET_OV5640 + 32:   	LUT_DATA	= 	24'h3a13_43;
	SET_OV5640 + 33:   	LUT_DATA	= 	24'h3a18_00;
	SET_OV5640 + 34:   	LUT_DATA	= 	24'h3a19_b0;
	SET_OV5640 + 35:   	LUT_DATA	= 	24'h3635_13;
	SET_OV5640 + 36:   	LUT_DATA	= 	24'h3636_03;
	SET_OV5640 + 37:   	LUT_DATA	= 	24'h3634_40;
	SET_OV5640 + 38:   	LUT_DATA	= 	24'h3622_01;
	SET_OV5640 + 39:   	LUT_DATA	= 	24'h3c01_34;
	SET_OV5640 + 40:   	LUT_DATA	= 	24'h3c00_00;
	SET_OV5640 + 41:   	LUT_DATA	= 	24'h3c04_28;
	SET_OV5640 + 42:   	LUT_DATA	= 	24'h3c05_98;
	SET_OV5640 + 43:   	LUT_DATA	= 	24'h3c06_00;
	SET_OV5640 + 44:   	LUT_DATA	= 	24'h3c07_08;
	SET_OV5640 + 45:   	LUT_DATA	= 	24'h3c08_00;
	SET_OV5640 + 46:   	LUT_DATA	= 	24'h3c09_1c;
	SET_OV5640 + 47:   	LUT_DATA	= 	24'h3c0a_9c;
	SET_OV5640 + 48:   	LUT_DATA	= 	24'h3c0b_40;
	SET_OV5640 + 49:   	LUT_DATA	= 	24'h3820_40;
	SET_OV5640 + 50:   	LUT_DATA	= 	24'h3821_01;
	SET_OV5640 + 51:   	LUT_DATA	= 	24'h3814_31;
	SET_OV5640 + 52:   	LUT_DATA	= 	24'h3815_31;
														
	SET_OV5640 + 53:   	LUT_DATA	= 	24'h3800_00;		
	SET_OV5640 + 54:   	LUT_DATA	= 	24'h3801_00;		
	SET_OV5640 + 55:   	LUT_DATA	= 	24'h3802_00;		
	SET_OV5640 + 56:   	LUT_DATA	= 	24'h3803_04;		
	SET_OV5640 + 57:   	LUT_DATA	= 	24'h3804_0a;		
	SET_OV5640 + 58:   	LUT_DATA	= 	24'h3805_3f;		
	SET_OV5640 + 59:   	LUT_DATA	= 	24'h3806_07;		
	SET_OV5640 + 60:   	LUT_DATA	= 	24'h3807_9b;	//	VGA		QVGA	SVGA	CIF		720P
	SET_OV5640 + 61:   	LUT_DATA	= 	24'h3808_02;	//	02		01		03		01		05
	SET_OV5640 + 62:   	LUT_DATA	= 	24'h3809_80;	//	80		40		20		60		00
	SET_OV5640 + 63:   	LUT_DATA	= 	24'h380a_01;	//	01		00		02		01		02	
	SET_OV5640 + 64:   	LUT_DATA	= 	24'h380b_e0;	//	e0		f0		58		20		d0
	SET_OV5640 + 65:   	LUT_DATA	= 	24'h380c_07;	//参看手册P39	
	SET_OV5640 + 66:   	LUT_DATA	= 	24'h380d_68;		
	SET_OV5640 + 67:   	LUT_DATA	= 	24'h380e_03;		
	SET_OV5640 + 68:   	LUT_DATA	= 	24'h380f_d8;		
		
	SET_OV5640 + 69:   	LUT_DATA	= 	24'h3810_00;
	SET_OV5640 + 70:   	LUT_DATA	= 	24'h3811_10;
	SET_OV5640 + 71:   	LUT_DATA	= 	24'h3812_00;
	SET_OV5640 + 72:   	LUT_DATA	= 	24'h3813_06;
	SET_OV5640 + 73:   	LUT_DATA	= 	24'h3618_00;
	SET_OV5640 + 74:   	LUT_DATA	= 	24'h3612_29;
	SET_OV5640 + 75:   	LUT_DATA	= 	24'h3708_64;
	SET_OV5640 + 76:   	LUT_DATA	= 	24'h3709_52;
	SET_OV5640 + 77:   	LUT_DATA	= 	24'h370c_03;
	SET_OV5640 + 78:   	LUT_DATA	= 	24'h3a02_03;
	SET_OV5640 + 79:   	LUT_DATA	= 	24'h3a03_d8;
	SET_OV5640 + 80:   	LUT_DATA	= 	24'h3a08_01;
	SET_OV5640 + 81:   	LUT_DATA	= 	24'h3a09_27;
	SET_OV5640 + 82:   	LUT_DATA	= 	24'h3a0a_00;
	SET_OV5640 + 83:   	LUT_DATA	= 	24'h3a0b_f6;
	SET_OV5640 + 84:   	LUT_DATA	= 	24'h3a0e_03;
	SET_OV5640 + 85:   	LUT_DATA	= 	24'h3a0d_04;
	SET_OV5640 + 86:   	LUT_DATA	= 	24'h3a14_03;
	SET_OV5640 + 87:   	LUT_DATA	= 	24'h3a15_d8;
	SET_OV5640 + 88:   	LUT_DATA	= 	24'h4001_02;
	SET_OV5640 + 89:   	LUT_DATA	= 	24'h4004_02;
	SET_OV5640 + 90:   	LUT_DATA	= 	24'h3000_00;
	SET_OV5640 + 91:   	LUT_DATA	= 	24'h3002_1c;
	SET_OV5640 + 92:   	LUT_DATA	= 	24'h3004_ff;
	SET_OV5640 + 93:   	LUT_DATA	= 	24'h3006_c3;
	SET_OV5640 + 94:   	LUT_DATA	= 	24'h300e_58;
	SET_OV5640 + 95:   	LUT_DATA	= 	24'h302e_00;
	SET_OV5640 + 96:   	LUT_DATA	= 	24'h4300_61;// RGB565:61 YUV422YUYV:30  
	SET_OV5640 + 97:   	LUT_DATA	= 	24'h501f_01;// 00: ISP:YUV22 01:ISP:RGB 
	SET_OV5640 + 98:   	LUT_DATA	= 	24'h3016_02;
	SET_OV5640 + 99:   	LUT_DATA	= 	24'h301c_02;
	SET_OV5640 + 100:  	LUT_DATA	= 	24'h3019_02;
	SET_OV5640 + 101:  	LUT_DATA	= 	24'h3019_00;
	SET_OV5640 + 102:  	LUT_DATA	= 	24'h4713_03;
	SET_OV5640 + 103:  	LUT_DATA	= 	24'h4407_04;
	SET_OV5640 + 104:  	LUT_DATA	= 	24'h440e_00;
	SET_OV5640 + 105:  	LUT_DATA	= 	24'h460b_35;
	SET_OV5640 + 106:  	LUT_DATA	= 	24'h460c_20;
	SET_OV5640 + 107:  	LUT_DATA	= 	24'h4837_22;
	SET_OV5640 + 108:  	LUT_DATA	= 	24'h3824_02;
	SET_OV5640 + 109:  	LUT_DATA	= 	24'h5000_a7;
	SET_OV5640 + 110:  	LUT_DATA	= 	24'h5001_a3;
	SET_OV5640 + 111:  	LUT_DATA	= 	24'h5180_ff;
	SET_OV5640 + 112:  	LUT_DATA	= 	24'h5181_f2;
	SET_OV5640 + 113:  	LUT_DATA	= 	24'h5182_00;
	SET_OV5640 + 114:  	LUT_DATA	= 	24'h5183_14;
	SET_OV5640 + 115:  	LUT_DATA	= 	24'h5184_25;
	SET_OV5640 + 116:  	LUT_DATA	= 	24'h5185_24;
	SET_OV5640 + 117:  	LUT_DATA	= 	24'h5186_10;
	SET_OV5640 + 118:  	LUT_DATA	= 	24'h5187_12;
	SET_OV5640 + 119:  	LUT_DATA	= 	24'h5188_10;
	SET_OV5640 + 120:  	LUT_DATA	= 	24'h5189_74;
	SET_OV5640 + 121:  	LUT_DATA	= 	24'h518a_5e;
	SET_OV5640 + 122:  	LUT_DATA	= 	24'h518b_ac;
	SET_OV5640 + 123:  	LUT_DATA	= 	24'h518c_83;
	SET_OV5640 + 124:  	LUT_DATA	= 	24'h518d_3b;
	SET_OV5640 + 125:  	LUT_DATA	= 	24'h518e_35;
	SET_OV5640 + 126:  	LUT_DATA	= 	24'h518f_4f;
	SET_OV5640 + 127:  	LUT_DATA	= 	24'h5190_42;
	SET_OV5640 + 128:  	LUT_DATA	= 	24'h5191_f8;
	SET_OV5640 + 129:  	LUT_DATA	= 	24'h5192_04;
	SET_OV5640 + 130:  	LUT_DATA	= 	24'h5193_70;
	SET_OV5640 + 131:  	LUT_DATA	= 	24'h5194_f0;
	SET_OV5640 + 132:  	LUT_DATA	= 	24'h5195_f0;
	SET_OV5640 + 133:  	LUT_DATA	= 	24'h5196_03;
	SET_OV5640 + 134:  	LUT_DATA	= 	24'h5197_01;
	SET_OV5640 + 135:  	LUT_DATA	= 	24'h5198_04;
	SET_OV5640 + 136:  	LUT_DATA	= 	24'h5199_87;
	SET_OV5640 + 137:  	LUT_DATA	= 	24'h519a_04;
	SET_OV5640 + 138:  	LUT_DATA	= 	24'h519b_00;
	SET_OV5640 + 139:  	LUT_DATA	= 	24'h519c_07;
	SET_OV5640 + 140:  	LUT_DATA	= 	24'h519d_56;
	SET_OV5640 + 141:  	LUT_DATA	= 	24'h519e_38;
	SET_OV5640 + 142:  	LUT_DATA	= 	24'h5381_1e;
	SET_OV5640 + 143:  	LUT_DATA	= 	24'h5382_5b;
	SET_OV5640 + 144:  	LUT_DATA	= 	24'h5383_08;
	SET_OV5640 + 145:  	LUT_DATA	= 	24'h5384_0a;
	SET_OV5640 + 146:  	LUT_DATA	= 	24'h5385_7e;
	SET_OV5640 + 147:  	LUT_DATA	= 	24'h5386_88;
	SET_OV5640 + 148:  	LUT_DATA	= 	24'h5387_7c;
	SET_OV5640 + 149:  	LUT_DATA	= 	24'h5388_6c;
	SET_OV5640 + 150:  	LUT_DATA	= 	24'h5389_10;
	SET_OV5640 + 151:  	LUT_DATA	= 	24'h538a_01;
	SET_OV5640 + 152:  	LUT_DATA	= 	24'h538b_98;
	SET_OV5640 + 153:  	LUT_DATA	= 	24'h5300_08;
	SET_OV5640 + 154:  	LUT_DATA	= 	24'h5301_30;
	SET_OV5640 + 155:  	LUT_DATA	= 	24'h5302_10;
	SET_OV5640 + 156:  	LUT_DATA	= 	24'h5303_00;
	SET_OV5640 + 157:  	LUT_DATA	= 	24'h5304_08;
	SET_OV5640 + 158:  	LUT_DATA	= 	24'h5305_30;
	SET_OV5640 + 159:  	LUT_DATA	= 	24'h5306_08;
	SET_OV5640 + 160:  	LUT_DATA	= 	24'h5307_16;
	SET_OV5640 + 161:  	LUT_DATA	= 	24'h5309_08;
	SET_OV5640 + 162:  	LUT_DATA	= 	24'h530a_30;
	SET_OV5640 + 163:  	LUT_DATA	= 	24'h530b_04;
	SET_OV5640 + 164:  	LUT_DATA	= 	24'h530c_06;
	SET_OV5640 + 165:  	LUT_DATA	= 	24'h5480_01;
	SET_OV5640 + 166:  	LUT_DATA	= 	24'h5481_08;
	SET_OV5640 + 167:  	LUT_DATA	= 	24'h5482_14;
	SET_OV5640 + 168:  	LUT_DATA	= 	24'h5483_28;
	SET_OV5640 + 169:  	LUT_DATA	= 	24'h5484_51;
	SET_OV5640 + 170:  	LUT_DATA	= 	24'h5485_65;
	SET_OV5640 + 171:  	LUT_DATA	= 	24'h5486_71;
	SET_OV5640 + 172:  	LUT_DATA	= 	24'h5487_7d;
	SET_OV5640 + 173:  	LUT_DATA	= 	24'h5488_87;
	SET_OV5640 + 174:  	LUT_DATA	= 	24'h5489_91;
	SET_OV5640 + 175:  	LUT_DATA	= 	24'h548a_9a;
	SET_OV5640 + 176:  	LUT_DATA	= 	24'h548b_aa;
	SET_OV5640 + 177:  	LUT_DATA	= 	24'h548c_b8;
	SET_OV5640 + 178:  	LUT_DATA	= 	24'h548d_cd;
	SET_OV5640 + 179:  	LUT_DATA	= 	24'h548e_dd;
	SET_OV5640 + 180:  	LUT_DATA	= 	24'h548f_ea;
	SET_OV5640 + 181:  	LUT_DATA	= 	24'h5490_1d;
	SET_OV5640 + 182:  	LUT_DATA	= 	24'h5580_02;
	SET_OV5640 + 183:  	LUT_DATA	= 	24'h5583_40;
	SET_OV5640 + 184:  	LUT_DATA	= 	24'h5584_10;
	SET_OV5640 + 185:  	LUT_DATA	= 	24'h5589_10;
	SET_OV5640 + 186:  	LUT_DATA	= 	24'h558a_00;
	SET_OV5640 + 187:  	LUT_DATA	= 	24'h558b_f8;
	SET_OV5640 + 188:  	LUT_DATA	= 	24'h5800_23;
	SET_OV5640 + 189:  	LUT_DATA	= 	24'h5801_15;
	SET_OV5640 + 190:  	LUT_DATA	= 	24'h5802_10;
	SET_OV5640 + 191:  	LUT_DATA	= 	24'h5803_10;
	SET_OV5640 + 192:  	LUT_DATA	= 	24'h5804_15;
	SET_OV5640 + 193:  	LUT_DATA	= 	24'h5805_23;
	SET_OV5640 + 194:  	LUT_DATA	= 	24'h5806_0c;
	SET_OV5640 + 195:  	LUT_DATA	= 	24'h5807_08;
	SET_OV5640 + 196:  	LUT_DATA	= 	24'h5808_05;
	SET_OV5640 + 197:  	LUT_DATA	= 	24'h5809_05;
	SET_OV5640 + 198:  	LUT_DATA	= 	24'h580a_08;
	SET_OV5640 + 199:  	LUT_DATA	= 	24'h580b_0c;
	SET_OV5640 + 200:  	LUT_DATA	= 	24'h580c_07;
	SET_OV5640 + 201:  	LUT_DATA	= 	24'h580d_03;
	SET_OV5640 + 202:  	LUT_DATA	= 	24'h580e_00;
	SET_OV5640 + 203:  	LUT_DATA	= 	24'h580f_00;
	SET_OV5640 + 204:  	LUT_DATA	= 	24'h5810_03;
	SET_OV5640 + 205:  	LUT_DATA	= 	24'h5811_07;
	SET_OV5640 + 206:  	LUT_DATA	= 	24'h5812_07;
	SET_OV5640 + 207:  	LUT_DATA	= 	24'h5813_03;
	SET_OV5640 + 208:  	LUT_DATA	= 	24'h5814_00;
	SET_OV5640 + 209:  	LUT_DATA	= 	24'h5815_00;
	SET_OV5640 + 210:  	LUT_DATA	= 	24'h5816_03;
	SET_OV5640 + 211:  	LUT_DATA	= 	24'h5817_07;
	SET_OV5640 + 212:  	LUT_DATA	= 	24'h5818_0b;
	SET_OV5640 + 213:  	LUT_DATA	= 	24'h5819_08;
	SET_OV5640 + 214:  	LUT_DATA	= 	24'h581a_05;
	SET_OV5640 + 215:  	LUT_DATA	= 	24'h581b_05;
	SET_OV5640 + 216:  	LUT_DATA	= 	24'h581c_07;
	SET_OV5640 + 217:  	LUT_DATA	= 	24'h581d_0b;
	SET_OV5640 + 218:  	LUT_DATA	= 	24'h581e_2a;
	SET_OV5640 + 219:  	LUT_DATA	= 	24'h581f_16;
	SET_OV5640 + 220:  	LUT_DATA	= 	24'h5820_11;
	SET_OV5640 + 221:  	LUT_DATA	= 	24'h5821_11;
	SET_OV5640 + 222:  	LUT_DATA	= 	24'h5822_15;
	SET_OV5640 + 223:  	LUT_DATA	= 	24'h5823_29;
	SET_OV5640 + 224:  	LUT_DATA	= 	24'h5824_bf;
	SET_OV5640 + 225:  	LUT_DATA	= 	24'h5825_af;
	SET_OV5640 + 226:  	LUT_DATA	= 	24'h5826_9f;
	SET_OV5640 + 227:  	LUT_DATA	= 	24'h5827_af;
	SET_OV5640 + 228:  	LUT_DATA	= 	24'h5828_df;
	SET_OV5640 + 229:  	LUT_DATA	= 	24'h5829_6f;
	SET_OV5640 + 230:  	LUT_DATA	= 	24'h582a_8e;
	SET_OV5640 + 231:  	LUT_DATA	= 	24'h582b_ab;
	SET_OV5640 + 232:  	LUT_DATA	= 	24'h582c_9e;
	SET_OV5640 + 233:  	LUT_DATA	= 	24'h582d_7f;
	SET_OV5640 + 234:  	LUT_DATA	= 	24'h582e_4f;
	SET_OV5640 + 235:  	LUT_DATA	= 	24'h582f_89;
	SET_OV5640 + 236:  	LUT_DATA	= 	24'h5830_86;
	SET_OV5640 + 237:  	LUT_DATA	= 	24'h5831_98;
	SET_OV5640 + 238:  	LUT_DATA	= 	24'h5832_6f;
	SET_OV5640 + 239:  	LUT_DATA	= 	24'h5833_4f;
	SET_OV5640 + 240:  	LUT_DATA	= 	24'h5834_6e;
	SET_OV5640 + 241:  	LUT_DATA	= 	24'h5835_7b;
	SET_OV5640 + 242:  	LUT_DATA	= 	24'h5836_7e;
	SET_OV5640 + 243:  	LUT_DATA	= 	24'h5837_6f;
	SET_OV5640 + 244:  	LUT_DATA	= 	24'h5838_de;
	SET_OV5640 + 245:  	LUT_DATA	= 	24'h5839_bf;
	SET_OV5640 + 246:  	LUT_DATA	= 	24'h583a_9f;
	SET_OV5640 + 247:  	LUT_DATA	= 	24'h583b_bf;
	SET_OV5640 + 248:  	LUT_DATA	= 	24'h583c_ec;
	SET_OV5640 + 249:  	LUT_DATA	= 	24'h583d_df;
	SET_OV5640 + 250:  	LUT_DATA	= 	24'h5025_00;
	SET_OV5640 + 251:  	LUT_DATA	= 	24'h3a0f_30;
	SET_OV5640 + 252:  	LUT_DATA	= 	24'h3a10_28;
	SET_OV5640 + 253:  	LUT_DATA	= 	24'h3a1b_30;
	SET_OV5640 + 254:  	LUT_DATA	= 	24'h3a1e_26;
	SET_OV5640 + 255:  	LUT_DATA	= 	24'h3a11_60;
	SET_OV5640 + 256:  	LUT_DATA	= 	24'h3a1f_14;
	SET_OV5640 + 257:  	LUT_DATA	= 	24'h3008_02;
	SET_OV5640 + 258:  	LUT_DATA	= 	24'h5300_08;
	SET_OV5640 + 259:  	LUT_DATA	= 	24'h5301_30;
	SET_OV5640 + 260:  	LUT_DATA	= 	24'h5302_10;
	SET_OV5640 + 261:  	LUT_DATA	= 	24'h5303_00;
	SET_OV5640 + 262:  	LUT_DATA	= 	24'h5304_08;
	SET_OV5640 + 263:  	LUT_DATA	= 	24'h5305_30;
	SET_OV5640 + 264:  	LUT_DATA	= 	24'h5306_08;
	SET_OV5640 + 265:  	LUT_DATA	= 	24'h5307_16;
	SET_OV5640 + 266:  	LUT_DATA	= 	24'h5309_08;
	SET_OV5640 + 267:  	LUT_DATA	= 	24'h530a_30;
	SET_OV5640 + 268:  	LUT_DATA	= 	24'h530b_04;
	SET_OV5640 + 269:  	LUT_DATA	= 	24'h530c_06;
	SET_OV5640 + 270:  	LUT_DATA	= 	24'h3c07_08;
	SET_OV5640 + 271:  	LUT_DATA	= 	24'h3820_40;	//上下翻转 flip 40/46
	SET_OV5640 + 272:  	LUT_DATA	= 	24'h3821_01;	//左右翻转 mirror
	SET_OV5640 + 273:  	LUT_DATA	= 	24'h3814_31;
	SET_OV5640 + 274:  	LUT_DATA	= 	24'h3815_31;
	SET_OV5640 + 275:  	LUT_DATA	= 	24'h3803_04;
	SET_OV5640 + 276:  	LUT_DATA	= 	24'h3807_9b;
	SET_OV5640 + 277:  	LUT_DATA	= 	24'h3808_02;
	SET_OV5640 + 278:  	LUT_DATA	= 	24'h3809_80;
	SET_OV5640 + 279:  	LUT_DATA	= 	24'h380a_01;
	SET_OV5640 + 280:  	LUT_DATA	= 	24'h380b_e0;
	SET_OV5640 + 281:  	LUT_DATA	= 	24'h380c_07;
	SET_OV5640 + 282:  	LUT_DATA	= 	24'h380d_68;
	SET_OV5640 + 283:  	LUT_DATA	= 	24'h380e_03;
	SET_OV5640 + 284:  	LUT_DATA	= 	24'h380f_d8;
	SET_OV5640 + 285:  	LUT_DATA	= 	24'h3813_06;
	SET_OV5640 + 286:  	LUT_DATA	= 	24'h3618_00;
	SET_OV5640 + 287:  	LUT_DATA	= 	24'h3612_29;
	SET_OV5640 + 288:  	LUT_DATA	= 	24'h3709_52;
	SET_OV5640 + 289:  	LUT_DATA	= 	24'h370c_03;
	SET_OV5640 + 290:  	LUT_DATA	= 	24'h3a02_03;
	SET_OV5640 + 291:  	LUT_DATA	= 	24'h3a03_d8;
	SET_OV5640 + 292:  	LUT_DATA	= 	24'h3a0e_03;
	SET_OV5640 + 293:  	LUT_DATA	= 	24'h3a0d_04;
	SET_OV5640 + 294:  	LUT_DATA	= 	24'h3a14_03;
	SET_OV5640 + 295:  	LUT_DATA	= 	24'h3a15_d8;
	SET_OV5640 + 296:  	LUT_DATA	= 	24'h4004_02;
	SET_OV5640 + 297:  	LUT_DATA	= 	24'h3035_11;
	SET_OV5640 + 298:  	LUT_DATA	= 	24'h3036_69;
	SET_OV5640 + 299:  	LUT_DATA	= 	24'h4837_22;
	SET_OV5640 + 300:  	LUT_DATA	= 	24'h5001_a3;
	SET_OV5640 + 301:  	LUT_DATA	= 	24'h3000_20;
	SET_OV5640 + 302:  	LUT_DATA	= 	24'h3022_00;
	SET_OV5640 + 303:  	LUT_DATA	= 	24'h3023_00;
	SET_OV5640 + 304:  	LUT_DATA	= 	24'h3024_00;
	SET_OV5640 + 305:  	LUT_DATA	= 	24'h3025_00;
	SET_OV5640 + 306:  	LUT_DATA	= 	24'h3026_00;
	SET_OV5640 + 307:  	LUT_DATA	= 	24'h3027_00;
	SET_OV5640 + 308:  	LUT_DATA	= 	24'h3028_00;
	SET_OV5640 + 309:  	LUT_DATA	= 	24'h3029_FF;
	SET_OV5640 + 310:  	LUT_DATA	= 	24'h3000_00;

	default			:	LUT_DATA	=	0;
	endcase
end
endmodule

3.I2C_Controller.v模块设计
      该模块是I2C最底层的控制逻辑,实现 1 次 I2C 数据写入的时序。i2c_clk 为 I2C 传输的时钟;i2c_en 拉高时,I2C传输数据更新,即 i2c_en 拉高则意味着一个新的 I2C 数据位传输;i2c_wdata 中存储着 I2C一次传输的所有信息(bit39-32 为读器件地址,bit31-24 为写器件地址,bit23-8 为寄存器地址,bit7-0 为写入数据);wr 信号指示当前操作为 I2C 写操作(高电平)或读操作(低电平);trans 拉高表示 I2C 操作进行中;ack 为 I2C 操作的响应信号;i2c_end 拉高表示一次 I2C 操作完成;i2c_rdata 为 I2C 读操作的读出数据。i2c_sclk 为连接 CMOS Sensor 的 I2C 时钟信号,i2c_sdat 为连接 CMOS Sensor 的 I2C 数据信号。

module I2C_Controller 
(
	//Global clk
	input			clk,		
	input			rst_n,		
	
	//I2C transfer
	input			i2c_clk,	//DATA Transfer Enable
	input			i2c_en,		//I2C DATA ENABLE
	input	[39:0]	i2c_wdata,	//DATA:[SLAVE_ADDR, SUB_ADDR, DATA]
	output			i2c_sclk,	//I2C clk
 	inout			i2c_sdat,	//I2C DATA
	input			wr,     	//Write | Read
	input			trans,      	//start transfor
	output			ack,      	//ack
	output	reg		i2c_end,     	//i2c_end transfor 
	output	reg	[7:0]	i2c_rdata	//I2C Data read
);

       写数据时:首先是主机发送一个起始位,接着是七位宽的设备地址加上一位宽的写控制位,从机响应一次;然后主机发送一字节的寄存器地址,从机响应一次;然后由主机发送一字节以上的数据,从机响应;最后发送一个停止位。
       读数据时:首先是主机发送一个起始位,接着是七位宽的设备地址加上一位宽的写控制位;然后是主机发送寄存器地址,从机应答;再重新发送一次起始位,设备地址和读控制位,用于表示接下来是要进行读操作,从机应答;从机发送数据,主机应答,在得到最后一字节数据后,由主机发送一个非应答信号;最后发送一个停止位。

读写控制逻辑代码如下:

//I2C Signal
reg			i2c_bit;
reg 		sclk;	//I2C Free Clock
reg	[6:0]	sd_counter;

//Write: ID-Address + SUB-Address + W-Data
wire 	i2c_sclk1 = 	(trans == 1 &&
						((sd_counter >= 5 && sd_counter <=12 || sd_counter == 14) ||	
						(sd_counter >= 16 && sd_counter <=23 || sd_counter == 25) ||
						(sd_counter >= 27 && sd_counter <=34 || sd_counter == 36) ||
						(sd_counter >= 38 && sd_counter <=45 || sd_counter == 47))) ? i2c_clk : sclk;

//I2C Read: {ID-Address + SUB-Address} + {ID-Address + R-Data}						
wire 	i2c_sclk2 = 	(trans == 1 &&
						((sd_counter >= 5 && sd_counter <=12 || sd_counter == 14) ||
						(sd_counter >= 16 && sd_counter <=23 || sd_counter == 25) ||
						(sd_counter >= 27 && sd_counter <=34 || sd_counter == 36) ||
						(sd_counter >= 44 && sd_counter <=52 || sd_counter == 54) ||
						(sd_counter >= 56 && sd_counter <=63 || sd_counter == 65))) ? i2c_clk : sclk;		
						
assign	i2c_sclk = wr ? i2c_sclk1 : i2c_sclk2;	

wire	sdo1	=		((sd_counter == 13 || sd_counter == 14) || 
						 (sd_counter == 24 || sd_counter == 25) || 
						 (sd_counter == 35 || sd_counter == 36) ||
						 (sd_counter == 46 || sd_counter == 47)) ? 1'b0 : 1'b1;		//input | output
						
wire	sdo2	=		((sd_counter == 13 || sd_counter == 14)|| 
						(sd_counter == 24 || sd_counter == 25) || 
						(sd_counter == 35 || sd_counter == 36) ||
						(sd_counter == 53 || sd_counter == 54) ||
						(sd_counter >= 55 && sd_counter <= 63)) ? 1'b0 : 1'b1;		//input | output
						
wire	SDO = wr ? sdo1 : sdo2;

assign	i2c_sdat = SDO ? i2c_bit : 1'bz;



//------------------------------------
//Write ack | Read ack
reg	ackw1, ackw2, ackw3,ackw4;		//0 AVTIVE
reg 	ackr1, ackr2, ackr3,ackr4;		//0 ACTIVE
assign	ack = wr ? (ackw1 | ackw2 | ackw3 | ackw4) : (ackr1 | ackr2 | ackr3 | ackr4);

IIC进行数据传输的控制逻辑如下:

always @(posedge clk or negedge rst_n) 
begin
    if(!rst_n) 
		begin 
		sclk <= 1;
		i2c_bit <= 1; 
		ackw1 <= 1; ackw2 <= 1; ackw3 <= 1;ackw4 <= 1; 
		ackr1 <= 1; ackr2 <= 1; ackr3 <= 1;ackr4 <= 1;
		i2c_end <= 0;
		i2c_rdata <= 8'h0;	
		end
	else if(i2c_en)		//data change enable
		begin
		if(trans)
			begin
			if(wr)		//I2C Write: ID-Address + SUB-Address + W-Data
				begin
				case(sd_counter)
				//IDLE
				7'd0 :begin
						sclk <= 1;
						i2c_bit <= 1;
						ackw1 <= 1; ackw2 <= 1; ackw3 <= 1; ackw4 <= 1;
						ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4 <= 1;
						i2c_end <= 0;
						end
				//Start
				7'd1 :	begin 
						sclk <= 1;
						i2c_bit <= 1;
						ackw1 <= 1; ackw2 <= 1; ackw3 <= 1;ackw4<=1;
						i2c_end <= 0;
						end
				7'd2  : i2c_bit <= 0;		//i2c_sdat = 0
				7'd3  : sclk <= 0;			//i2c_sclk = 0
				
				//SLAVE ADDR
				7'd4  : i2c_bit <= i2c_wdata[31];	//Bit8
				7'd5  : i2c_bit <= i2c_wdata[30];	//Bit7
				7'd6  : i2c_bit <= i2c_wdata[29];	//Bit6
				7'd7  : i2c_bit <= i2c_wdata[28];	//Bit5
				7'd8  : i2c_bit <= i2c_wdata[27];	//Bit4
				7'd9  : i2c_bit <= i2c_wdata[26];	//Bit3
				7'd10 : i2c_bit <= i2c_wdata[25];	//Bit2
				7'd11 : i2c_bit <= i2c_wdata[24];	//Bit1
				7'd12 : i2c_bit <= 0;					//High-Z, Input
				7'd13 : ackw1 	<= i2c_sdat;			//ACK1
				7'd14 : i2c_bit <= 0;					//Delay
				
				//SUB ADDR
				7'd15 : i2c_bit <= i2c_wdata[23];	//Bit15
				7'd16 : i2c_bit <= i2c_wdata[22];	//Bit14
				7'd17 : i2c_bit <= i2c_wdata[21];	//Bit13
				7'd18 : i2c_bit <= i2c_wdata[20];	//Bit12
				7'd19 : i2c_bit <= i2c_wdata[19];	//Bit11
				7'd20 : i2c_bit <= i2c_wdata[18];	//Bit10
				7'd21 : i2c_bit <= i2c_wdata[17];   //Bit9
				7'd22 : i2c_bit <= i2c_wdata[16];	//Bit8
				7'd23 : i2c_bit <= 0;					//High-Z, Input
				7'd24 : ackw2 	<= i2c_sdat;			//ACK2
				7'd25 : i2c_bit <= 0;					//Delay
				
				7'd26 : i2c_bit <= i2c_wdata[15];	//Bit7
				7'd27 : i2c_bit <= i2c_wdata[14];	//Bit6
				7'd28 : i2c_bit <= i2c_wdata[13];	//Bit5
				7'd29 : i2c_bit <= i2c_wdata[12];	//Bit4
				7'd30 : i2c_bit <= i2c_wdata[11];	//Bit3
				7'd31 : i2c_bit <= i2c_wdata[10];	//Bit2
				7'd32 : i2c_bit <= i2c_wdata[9];		//Bit1
				7'd33 : i2c_bit <= i2c_wdata[8];		//Bit0
				7'd34 : i2c_bit <= 0;					//High-Z, Input
				7'd35 : ackw3 	<= i2c_sdat;			//ACK3
				7'd36 : i2c_bit <= 0;					//Delay
				
				//Send data
				7'd37 : i2c_bit <= i2c_wdata[7];		//Bit8 
				7'd38 : i2c_bit <= i2c_wdata[6];		//Bit7
				7'd39 : i2c_bit <= i2c_wdata[5];		//Bit6
				7'd40 : i2c_bit <= i2c_wdata[4];		//Bit5
				7'd41 : i2c_bit <= i2c_wdata[3];		//Bit4
				7'd42 : i2c_bit <= i2c_wdata[2];		//Bit3
				7'd43 : i2c_bit <= i2c_wdata[1];		//Bit2
				7'd44 : i2c_bit <= i2c_wdata[0];		//Bit1
				7'd45 : i2c_bit <= 0;					//High-Z, Input
				7'd46 : ackw4 	<= i2c_sdat;			//ACK4
				7'd47 : i2c_bit <= 0;					//Delay

				//Stop
				7'd48 : begin	sclk <= 0; i2c_bit <= 0; end
				7'd49 : sclk <= 1;	
				7'd50 : begin i2c_bit <= 1; i2c_end <= 1; end 
				default : begin i2c_bit <= 1; sclk <= 1; end
				endcase
				end
			else		//I2C Read: {ID-Address + SUB-Address} + {ID-Address + R-Data}
				begin
				case(sd_counter)
				//IDLE
				7'd0 :begin
						sclk <= 1;
						i2c_bit <= 1;
						ackw1 <= 1; ackw2 <= 1; ackw3 <= 1; ackw4 <= 1;
						ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4 <= 1; 
						i2c_end <= 0;
						end
				//I2C Read1: {ID-Address + SUB-Address}
				//Start
				7'd1 :begin 
						sclk <= 1;
						i2c_bit <= 1;
						ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4 <= 1;
						i2c_end <= 0;
						end
				7'd2  : i2c_bit <= 0;		//i2c_sdat = 0
				7'd3  : sclk <= 0;			//i2c_sclk = 0
				
				//SLAVE ADDR   //78H
				7'd4  : i2c_bit <= i2c_wdata[31];	//Bit8
				7'd5  : i2c_bit <= i2c_wdata[30];	//Bit7
				7'd6  : i2c_bit <= i2c_wdata[29];	//Bit6
				7'd7  : i2c_bit <= i2c_wdata[28];	//Bit5
				7'd8  : i2c_bit <= i2c_wdata[27];	//Bit4
				7'd9  : i2c_bit <= i2c_wdata[26];	//Bit3
				7'd10 : i2c_bit <= i2c_wdata[25];	//Bit2
				7'd11 : i2c_bit <= i2c_wdata[24];	//Bit1
				7'd12 : i2c_bit <= 0;					//High-Z, Input
				7'd13 : ackr1 	<= i2c_sdat;			//ACK1
				7'd14 : i2c_bit <= 0;					//Delay
				
				//SUB ADDR
				7'd15 : i2c_bit <= i2c_wdata[23];	//Bit15
				7'd16 : i2c_bit <= i2c_wdata[22];	//Bit14
				7'd17 : i2c_bit <= i2c_wdata[21];	//Bit13
				7'd18 : i2c_bit <= i2c_wdata[20];	//Bit12
				7'd19 : i2c_bit <= i2c_wdata[19];	//Bit11
				7'd20 : i2c_bit <= i2c_wdata[18];	//Bit10
				7'd21 : i2c_bit <= i2c_wdata[17];   //Bit9
				7'd22 : i2c_bit <= i2c_wdata[16];	//Bit8
				7'd23 : i2c_bit <= 0;					//High-Z, Input
				7'd24 : ackr2 	<= i2c_sdat;			//ACK2
				7'd25 : i2c_bit <= 0;					//Delay

				7'd26 : i2c_bit <= i2c_wdata[15];	//Bit7
				7'd27 : i2c_bit <= i2c_wdata[14];	//Bit6
				7'd28 : i2c_bit <= i2c_wdata[13];	//Bit5
				7'd29 : i2c_bit <= i2c_wdata[12];	//Bit4
				7'd30 : i2c_bit <= i2c_wdata[11];	//Bit3
				7'd31 : i2c_bit <= i2c_wdata[10];	//Bit2
				7'd32 : i2c_bit <= i2c_wdata[9];		//Bit1
				7'd33 : i2c_bit <= i2c_wdata[8];		//Bit0
				7'd34 : i2c_bit <= 0;					//High-Z, Input
				7'd35 : ackr3 	<= i2c_sdat;			//ACK3
				7'd36 : i2c_bit <= 0;					//Delay
				
				//Stop
				7'd37 : begin	sclk <= 0; i2c_bit <= 0; end
				7'd38 : sclk <= 1;	
				7'd39 : begin i2c_bit <= 1; /*i2c_end <= 1;*/end 

				//I2C Read2: {ID-Address + R-Data}
				//Start
				7'd40 :	begin 
						sclk <= 1;
						i2c_bit <= 1;
						end
				7'd41 : i2c_bit <= 0;		//i2c_sdat = 0
				7'd42 : sclk <= 0;			//i2c_sclk = 0
				
				//SLAVE ADDR
				7'd43 : i2c_bit <= i2c_wdata[39];	//Bit8
				7'd44 : i2c_bit <= i2c_wdata[38];	//Bit7
				7'd45 : i2c_bit <= i2c_wdata[37];	//Bit6
				7'd46 : i2c_bit <= i2c_wdata[36];	//Bit5
				7'd47 : i2c_bit <= i2c_wdata[35];	//Bit4
				7'd48 : i2c_bit <= i2c_wdata[34];	//Bit3
				7'd49 : i2c_bit <= i2c_wdata[33];	//Bit2
				7'd50 : i2c_bit <= i2c_wdata[32];	//Bit1
				7'd51 : i2c_bit <= 1'b1;				//Bit1	Read Data Flag
				7'd52 : i2c_bit <= 0;					//High-Z, Input
				7'd53 : ackr4 	<= i2c_sdat;			//ACK4
				7'd54 : i2c_bit <= 0;					//Delay
				
				//Read DATA
				7'd55 : i2c_bit 	  <= 0;			//High-Z, Input
				7'd56 : i2c_rdata[7] <= i2c_sdat;	//Bit8	, Input
				7'd57 : i2c_rdata[6] <= i2c_sdat;	//Bit7	, Input 
				7'd58 : i2c_rdata[5] <= i2c_sdat;	//Bit6	, Input 
				7'd59 : i2c_rdata[4] <= i2c_sdat;	//Bit5	, Input 
				7'd60 : i2c_rdata[3] <= i2c_sdat;	//Bit4	, Input 
				7'd61 : i2c_rdata[2] <= i2c_sdat;	//Bit3	, Input 
				7'd62 : i2c_rdata[1] <= i2c_sdat;	//Bit2	, Input 
				7'd63 : i2c_rdata[0] <= i2c_sdat;	//Bit1	, Input 	
				7'd64 : i2c_bit 	  <= 1;			//Output //ACK4 NACK
				7'd65 : i2c_bit 	  <= 0;			//Delay
				
				//Stop
				7'd66 : begin	sclk <= 0; i2c_bit <= 0; end
				7'd67 : sclk <= 1;	
				7'd68 : begin i2c_bit <= 1; i2c_end <= 1; end 
				endcase
				end
			end
		else
			begin
			sclk <= 1;
			i2c_bit <= 1; 
			ackw1 <= 1; ackw2 <= 1; ackw3 <= 1; ackw4<=1;
			ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4<=1;
			i2c_end <= 0;
			i2c_rdata <= i2c_rdata;
			end
		end
end

该模块完整代码如下:

`timescale 1ns/1ns
module I2C_Controller 
(
	//Global clk
	input			clk,		
	input			rst_n,		
	
	//I2C transfer
	input			i2c_clk,	//DATA Transfer Enable
	input			i2c_en,		//I2C DATA ENABLE
	input	[39:0]	i2c_wdata,	//DATA:[SLAVE_ADDR, SUB_ADDR, DATA]
	output			i2c_sclk,	//I2C clk
 	inout			i2c_sdat,	//I2C DATA
	input			wr,     	//Write | Read
	input			trans,      	//start transfor
	output			ack,      	//ack
	output	reg		i2c_end,     	//i2c_end transfor 
	output	reg	[7:0]	i2c_rdata	//I2C Data read
);

//------------------------------------
//I2C Signal
reg			i2c_bit;
reg 		sclk;	//I2C Free Clock
reg	[6:0]	sd_counter;

//Write: ID-Address + SUB-Address + W-Data
wire 	i2c_sclk1 = 	(trans == 1 &&
						((sd_counter >= 5 && sd_counter <=12 || sd_counter == 14) ||	
						(sd_counter >= 16 && sd_counter <=23 || sd_counter == 25) ||
						(sd_counter >= 27 && sd_counter <=34 || sd_counter == 36) ||
						(sd_counter >= 38 && sd_counter <=45 || sd_counter == 47))) ? i2c_clk : sclk;

//I2C Read: {ID-Address + SUB-Address} + {ID-Address + R-Data}						
wire 	i2c_sclk2 = 	(trans == 1 &&
						((sd_counter >= 5 && sd_counter <=12 || sd_counter == 14) ||
						(sd_counter >= 16 && sd_counter <=23 || sd_counter == 25) ||
						(sd_counter >= 27 && sd_counter <=34 || sd_counter == 36) ||
						(sd_counter >= 44 && sd_counter <=52 || sd_counter == 54) ||
						(sd_counter >= 56 && sd_counter <=63 || sd_counter == 65))) ? i2c_clk : sclk;		
						
assign	i2c_sclk = wr ? i2c_sclk1 : i2c_sclk2;	

wire	sdo1	=		((sd_counter == 13 || sd_counter == 14) || 
						 (sd_counter == 24 || sd_counter == 25) || 
						 (sd_counter == 35 || sd_counter == 36) ||
						 (sd_counter == 46 || sd_counter == 47)) ? 1'b0 : 1'b1;		//input | output
						
wire	sdo2	=		((sd_counter == 13 || sd_counter == 14)|| 
						(sd_counter == 24 || sd_counter == 25) || 
						(sd_counter == 35 || sd_counter == 36) ||
						(sd_counter == 53 || sd_counter == 54) ||
						(sd_counter >= 55 && sd_counter <= 63)) ? 1'b0 : 1'b1;		//input | output
						
wire	SDO = wr ? sdo1 : sdo2;

assign	i2c_sdat = SDO ? i2c_bit : 1'bz;



//------------------------------------
//Write ack | Read ack
reg	ackw1, ackw2, ackw3,ackw4;		//0 AVTIVE
reg 	ackr1, ackr2, ackr3,ackr4;		//0 ACTIVE
assign	ack = wr ? (ackw1 | ackw2 | ackw3 | ackw4) : (ackr1 | ackr2 | ackr3 | ackr4);


//------------------------------------
//I2C COUNTER
always @(posedge clk or negedge rst_n) 
begin
	if (!rst_n) 
		sd_counter <= 7'b0;
	else if(i2c_en)
		begin
		if (trans == 0 || i2c_end == 1) 
			sd_counter <= 7'b0;
		else if (sd_counter < 7'd70) 
			sd_counter <= sd_counter + 7'd1;	
		end
	else
		sd_counter <= sd_counter;
end

//------------------------------------
//I2C Transfer
always @(posedge clk or negedge rst_n) 
begin
    if(!rst_n) 
		begin 
		sclk <= 1;
		i2c_bit <= 1; 
		ackw1 <= 1; ackw2 <= 1; ackw3 <= 1;ackw4 <= 1; 
		ackr1 <= 1; ackr2 <= 1; ackr3 <= 1;ackr4 <= 1;
		i2c_end <= 0;
		i2c_rdata <= 8'h0;	
		end
	else if(i2c_en)		//data change enable
		begin
		if(trans)
			begin
			if(wr)		//I2C Write: ID-Address + SUB-Address + W-Data
				begin
				case(sd_counter)
				//IDLE
				7'd0 :begin
						sclk <= 1;
						i2c_bit <= 1;
						ackw1 <= 1; ackw2 <= 1; ackw3 <= 1; ackw4 <= 1;
						ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4 <= 1;
						i2c_end <= 0;
						end
				//Start
				7'd1 :	begin 
						sclk <= 1;
						i2c_bit <= 1;
						ackw1 <= 1; ackw2 <= 1; ackw3 <= 1;ackw4<=1;
						i2c_end <= 0;
						end
				7'd2  : i2c_bit <= 0;		//i2c_sdat = 0
				7'd3  : sclk <= 0;			//i2c_sclk = 0
				
				//SLAVE ADDR
				7'd4  : i2c_bit <= i2c_wdata[31];	//Bit8
				7'd5  : i2c_bit <= i2c_wdata[30];	//Bit7
				7'd6  : i2c_bit <= i2c_wdata[29];	//Bit6
				7'd7  : i2c_bit <= i2c_wdata[28];	//Bit5
				7'd8  : i2c_bit <= i2c_wdata[27];	//Bit4
				7'd9  : i2c_bit <= i2c_wdata[26];	//Bit3
				7'd10 : i2c_bit <= i2c_wdata[25];	//Bit2
				7'd11 : i2c_bit <= i2c_wdata[24];	//Bit1
				7'd12 : i2c_bit <= 0;					//High-Z, Input
				7'd13 : ackw1 	<= i2c_sdat;			//ACK1
				7'd14 : i2c_bit <= 0;					//Delay
				
				//SUB ADDR
				7'd15 : i2c_bit <= i2c_wdata[23];	//Bit15
				7'd16 : i2c_bit <= i2c_wdata[22];	//Bit14
				7'd17 : i2c_bit <= i2c_wdata[21];	//Bit13
				7'd18 : i2c_bit <= i2c_wdata[20];	//Bit12
				7'd19 : i2c_bit <= i2c_wdata[19];	//Bit11
				7'd20 : i2c_bit <= i2c_wdata[18];	//Bit10
				7'd21 : i2c_bit <= i2c_wdata[17];   //Bit9
				7'd22 : i2c_bit <= i2c_wdata[16];	//Bit8
				7'd23 : i2c_bit <= 0;					//High-Z, Input
				7'd24 : ackw2 	<= i2c_sdat;			//ACK2
				7'd25 : i2c_bit <= 0;					//Delay
				
				7'd26 : i2c_bit <= i2c_wdata[15];	//Bit7
				7'd27 : i2c_bit <= i2c_wdata[14];	//Bit6
				7'd28 : i2c_bit <= i2c_wdata[13];	//Bit5
				7'd29 : i2c_bit <= i2c_wdata[12];	//Bit4
				7'd30 : i2c_bit <= i2c_wdata[11];	//Bit3
				7'd31 : i2c_bit <= i2c_wdata[10];	//Bit2
				7'd32 : i2c_bit <= i2c_wdata[9];		//Bit1
				7'd33 : i2c_bit <= i2c_wdata[8];		//Bit0
				7'd34 : i2c_bit <= 0;					//High-Z, Input
				7'd35 : ackw3 	<= i2c_sdat;			//ACK3
				7'd36 : i2c_bit <= 0;					//Delay
				
				//Send data
				7'd37 : i2c_bit <= i2c_wdata[7];		//Bit8 
				7'd38 : i2c_bit <= i2c_wdata[6];		//Bit7
				7'd39 : i2c_bit <= i2c_wdata[5];		//Bit6
				7'd40 : i2c_bit <= i2c_wdata[4];		//Bit5
				7'd41 : i2c_bit <= i2c_wdata[3];		//Bit4
				7'd42 : i2c_bit <= i2c_wdata[2];		//Bit3
				7'd43 : i2c_bit <= i2c_wdata[1];		//Bit2
				7'd44 : i2c_bit <= i2c_wdata[0];		//Bit1
				7'd45 : i2c_bit <= 0;					//High-Z, Input
				7'd46 : ackw4 	<= i2c_sdat;			//ACK4
				7'd47 : i2c_bit <= 0;					//Delay

				//Stop
				7'd48 : begin	sclk <= 0; i2c_bit <= 0; end
				7'd49 : sclk <= 1;	
				7'd50 : begin i2c_bit <= 1; i2c_end <= 1; end 
				default : begin i2c_bit <= 1; sclk <= 1; end
				endcase
				end
			else		//I2C Read: {ID-Address + SUB-Address} + {ID-Address + R-Data}
				begin
				case(sd_counter)
				//IDLE
				7'd0 :begin
						sclk <= 1;
						i2c_bit <= 1;
						ackw1 <= 1; ackw2 <= 1; ackw3 <= 1; ackw4 <= 1;
						ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4 <= 1; 
						i2c_end <= 0;
						end
				//I2C Read1: {ID-Address + SUB-Address}
				//Start
				7'd1 :begin 
						sclk <= 1;
						i2c_bit <= 1;
						ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4 <= 1;
						i2c_end <= 0;
						end
				7'd2  : i2c_bit <= 0;		//i2c_sdat = 0
				7'd3  : sclk <= 0;			//i2c_sclk = 0
				
				//SLAVE ADDR   //78H
				7'd4  : i2c_bit <= i2c_wdata[31];	//Bit8
				7'd5  : i2c_bit <= i2c_wdata[30];	//Bit7
				7'd6  : i2c_bit <= i2c_wdata[29];	//Bit6
				7'd7  : i2c_bit <= i2c_wdata[28];	//Bit5
				7'd8  : i2c_bit <= i2c_wdata[27];	//Bit4
				7'd9  : i2c_bit <= i2c_wdata[26];	//Bit3
				7'd10 : i2c_bit <= i2c_wdata[25];	//Bit2
				7'd11 : i2c_bit <= i2c_wdata[24];	//Bit1
				7'd12 : i2c_bit <= 0;					//High-Z, Input
				7'd13 : ackr1 	<= i2c_sdat;			//ACK1
				7'd14 : i2c_bit <= 0;					//Delay
				
				//SUB ADDR
				7'd15 : i2c_bit <= i2c_wdata[23];	//Bit15
				7'd16 : i2c_bit <= i2c_wdata[22];	//Bit14
				7'd17 : i2c_bit <= i2c_wdata[21];	//Bit13
				7'd18 : i2c_bit <= i2c_wdata[20];	//Bit12
				7'd19 : i2c_bit <= i2c_wdata[19];	//Bit11
				7'd20 : i2c_bit <= i2c_wdata[18];	//Bit10
				7'd21 : i2c_bit <= i2c_wdata[17];   //Bit9
				7'd22 : i2c_bit <= i2c_wdata[16];	//Bit8
				7'd23 : i2c_bit <= 0;					//High-Z, Input
				7'd24 : ackr2 	<= i2c_sdat;			//ACK2
				7'd25 : i2c_bit <= 0;					//Delay

				7'd26 : i2c_bit <= i2c_wdata[15];	//Bit7
				7'd27 : i2c_bit <= i2c_wdata[14];	//Bit6
				7'd28 : i2c_bit <= i2c_wdata[13];	//Bit5
				7'd29 : i2c_bit <= i2c_wdata[12];	//Bit4
				7'd30 : i2c_bit <= i2c_wdata[11];	//Bit3
				7'd31 : i2c_bit <= i2c_wdata[10];	//Bit2
				7'd32 : i2c_bit <= i2c_wdata[9];		//Bit1
				7'd33 : i2c_bit <= i2c_wdata[8];		//Bit0
				7'd34 : i2c_bit <= 0;					//High-Z, Input
				7'd35 : ackr3 	<= i2c_sdat;			//ACK3
				7'd36 : i2c_bit <= 0;					//Delay
				
				//Stop
				7'd37 : begin	sclk <= 0; i2c_bit <= 0; end
				7'd38 : sclk <= 1;	
				7'd39 : begin i2c_bit <= 1; /*i2c_end <= 1;*/end 

				//I2C Read2: {ID-Address + R-Data}
				//Start
				7'd40 :	begin 
						sclk <= 1;
						i2c_bit <= 1;
						end
				7'd41 : i2c_bit <= 0;		//i2c_sdat = 0
				7'd42 : sclk <= 0;			//i2c_sclk = 0
				
				//SLAVE ADDR
				7'd43 : i2c_bit <= i2c_wdata[39];	//Bit8
				7'd44 : i2c_bit <= i2c_wdata[38];	//Bit7
				7'd45 : i2c_bit <= i2c_wdata[37];	//Bit6
				7'd46 : i2c_bit <= i2c_wdata[36];	//Bit5
				7'd47 : i2c_bit <= i2c_wdata[35];	//Bit4
				7'd48 : i2c_bit <= i2c_wdata[34];	//Bit3
				7'd49 : i2c_bit <= i2c_wdata[33];	//Bit2
				7'd50 : i2c_bit <= i2c_wdata[32];	//Bit1
				7'd51 : i2c_bit <= 1'b1;				//Bit1	Read Data Flag
				7'd52 : i2c_bit <= 0;					//High-Z, Input
				7'd53 : ackr4 	<= i2c_sdat;			//ACK4
				7'd54 : i2c_bit <= 0;					//Delay
				
				//Read DATA
				7'd55 : i2c_bit 	  <= 0;			//High-Z, Input
				7'd56 : i2c_rdata[7] <= i2c_sdat;	//Bit8	, Input
				7'd57 : i2c_rdata[6] <= i2c_sdat;	//Bit7	, Input 
				7'd58 : i2c_rdata[5] <= i2c_sdat;	//Bit6	, Input 
				7'd59 : i2c_rdata[4] <= i2c_sdat;	//Bit5	, Input 
				7'd60 : i2c_rdata[3] <= i2c_sdat;	//Bit4	, Input 
				7'd61 : i2c_rdata[2] <= i2c_sdat;	//Bit3	, Input 
				7'd62 : i2c_rdata[1] <= i2c_sdat;	//Bit2	, Input 
				7'd63 : i2c_rdata[0] <= i2c_sdat;	//Bit1	, Input 	
				7'd64 : i2c_bit 	  <= 1;			//Output //ACK4 NACK
				7'd65 : i2c_bit 	  <= 0;			//Delay
				
				//Stop
				7'd66 : begin	sclk <= 0; i2c_bit <= 0; end
				7'd67 : sclk <= 1;	
				7'd68 : begin i2c_bit <= 1; i2c_end <= 1; end 
				endcase
				end
			end
		else
			begin
			sclk <= 1;
			i2c_bit <= 1; 
			ackw1 <= 1; ackw2 <= 1; ackw3 <= 1; ackw4<=1;
			ackr1 <= 1; ackr2 <= 1; ackr3 <= 1; ackr4<=1;
			i2c_end <= 0;
			i2c_rdata <= i2c_rdata;
			end
		end
end
		
endmodule

4.选择IIC的原因
   OV5640使用的是两线式SCCB接口总线,因为SCCB的写传输协议和IIC几乎相同,因此我们可以直接使用IIC的驱动程序来配置摄像头。

接下来将解析image_capture.v 模块实现图像采集和缓存功能。I2C_OV5640_Init_RGB565.v 模块和image_capture.v 模块的顶层Image_controller模块。

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值