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模块。