一、ov5640的端口
ov5640的視頻輸出接口共有10位,D[9:0]。當輸出10bit RGB RAW格式時,使用D[9:0]。當輸出8 bit的YCrCb或RGB565時,使用高八位D[9:2]。同步信號href和hsync使用同一個引腳href,通過SCCB設置此引腳為href或hsync信號。ov5640的端口列表如表所示
端口名稱 | 位數 | 方向 | 備注 |
data[9:0] | 10bit | output | 傳感器數據 |
vsync | 1bit | output | 垂直同步 |
hsync | 1bit | output | 水平同步 |
sio_c | 1bit | output | SCCB的時鍾 |
sio_d | 1bit | inout | SCCB的數據 |
reset# | 1bit | input | 傳感器上電穩定后,保持高電平 |
pwdn | 1bit | input | 傳感器上電穩定后,保持低電平 |
pclk | 1bit | output | 傳感器數據時鍾 |
二、寄存器配置
在ov5640正常工作前,必須對傳感器進行初始化,即通過配置寄存器使其工作在預期的工作模式中。在上電20ms以后,通過SCCB寫傳輸協議來對傳感器進行配置,很多寄存器都是采用默認值。ov5640的ISP輸入窗口設置、預縮放窗口設置和輸出大小窗口設置,這幾個設置與我們的正常使用密切相關。圖像窗口設置如圖所示
ISP輸入窗口設置允許用戶設置整個傳感器顯示區域(2632*1951),其中2592*1944是有效的,開窗范圍從0*0-2632*1951都可以任意設置,即對寄存器0x3800-0x3807進行設置。該窗口設置范圍中的像素數據將進入ISP進行圖像處理。
預縮放窗口設置允許用戶在ISP輸入窗口的基礎上進行裁剪,用於設置將進行縮放的窗口大小,該設置僅在ISP輸入窗口內進行X/Y方向的偏移,通過寄存器0x3810-0x3813進行配置,分別設置為8'h00, 8'h10, 8'h00和8'h06。
輸入大小窗口設置是在預縮放窗口的基礎上,經過DSP進行縮放處理,並將處理后的數據輸出給外部的圖像窗口,圖像窗口控制着最終的圖像輸出尺寸。通過寄存器0x3808-0x380B進行配置,配置的值為輸出水平像素的高4位、低8位以及輸出垂直像素的高3位、低8位,不足8位高位補0。當輸出大小窗口與預縮放窗口比例不一致時,圖像將進行縮放處理(圖像變形),僅當比例一致時,輸出比例才是1:1的正常圖像。
配置寄存器見代碼。
三、SCCB協議
SCCB協議與IIC協議幾乎一致。ov5640中所使用的SCCB協議只用到了寫傳輸,寫傳輸協議格式為:
START + ID Address + X + Sub-Address(H) + X + Sub-Address(L) + X + Write-Data + X + STOP
ov5640的器件地址為8'h78,Sub-Address為配置寄存器的地址,Write-Data為配置寄存器的值。
四、FPGA框圖
五、代碼

1 module sccb( 2 input clk , 3 input rst_n , 4 5 //sccb interface 6 input sccb_exec , //sccb觸發執行信號 7 input bit_ctrl , //字地址位控制(16b/8b) 8 input sccb_rh_wl , //sccb讀寫控制信號 9 input [15:0] sub_addr , //sccb器件內地址 10 input [ 7:0] wr_data , //sccb要寫的數據 11 output reg [ 7:0] rd_data , //sccb讀出的數據 12 output reg sccb_done , //sccb一次操作完成 13 output reg sccb_ack , //sccb應答標志 0:應答 1:未應答 14 output reg scl , //sccb的SCL時鍾信號 15 inout sda , //sccb的SDA信號 16 17 //user interface 18 output reg dri_clk //驅動sccb操作的驅動時鍾 19 ); 20 21 parameter SLAVE_ADDR = 7'h3c ; //EEPROM從機地址 22 parameter CLK_FREQ = 26'd50_000_000; //模塊輸入的時鍾頻率 23 parameter sccb_FREQ = 18'd250_000 ; //IIC_SCL的時鍾頻率 24 25 //localparam define 26 localparam st_idle = 8'b0000_0001; //空閑狀態 27 localparam st_sladdr = 8'b0000_0010; //發送器件地址(slave address) 28 localparam st_addr16 = 8'b0000_0100; //發送16位字地址 29 localparam st_addr8 = 8'b0000_1000; //發送8位字地址 30 localparam st_data_wr = 8'b0001_0000; //寫數據(8 bit) 31 localparam st_addr_rd = 8'b0010_0000; //發送器件地址讀 32 localparam st_data_rd = 8'b0100_0000; //讀數據(8 bit) 33 localparam st_stop = 8'b1000_0000; //結束sccb操作 34 35 //reg define 36 reg sda_dir ; //sccb數據(SDA)方向控制 37 reg sda_out ; //SDA輸出信號 38 reg st_done ; //狀態結束 39 reg wr_flag ; //寫標志 40 reg [ 6:0] cnt ; //計數 41 reg [ 7:0] cur_state ; //狀態機當前狀態 42 reg [ 7:0] next_state; //狀態機下一狀態 43 reg [15:0] addr_t ; //地址 44 reg [ 7:0] data_r ; //讀取的數據 45 reg [ 7:0] data_wr_t ; //sccb需寫的數據的臨時寄存 46 reg [ 9:0] clk_cnt ; //分頻時鍾計數 47 48 //wire define 49 wire sda_in ; //SDA輸入信號 50 wire [8:0] clk_divide ; //模塊驅動時鍾的分頻系數 51 52 //***************************************************** 53 //** main code 54 //***************************************************** 55 56 //SDA控制 57 assign sda = sda_dir ? sda_out : 1'bz; //SDA數據輸出或高阻 58 assign sda_in = sda ; //SDA數據輸入 59 assign clk_divide = (CLK_FREQ/sccb_FREQ) >> 2'd2;//模塊驅動時鍾的分頻系數 60 61 //生成sccb的SCL的四倍頻率的驅動時鍾用於驅動sccb的操作 62 always @(posedge clk or negedge rst_n) begin 63 if(!rst_n) begin 64 dri_clk <= 1'b0; 65 clk_cnt <= 10'd0; 66 end 67 else if(clk_cnt == clk_divide[8:1] - 1'd1) begin 68 clk_cnt <= 10'd0; 69 dri_clk <= ~dri_clk; 70 end 71 else 72 clk_cnt <= clk_cnt + 1'b1; 73 end 74 75 //(三段式狀態機)同步時序描述狀態轉移 76 always @(posedge dri_clk or negedge rst_n) begin 77 if(!rst_n) 78 cur_state <= st_idle; 79 else 80 cur_state <= next_state; 81 end 82 83 //組合邏輯判斷狀態轉移條件 84 always @(*) begin 85 next_state = st_idle; 86 case(cur_state) 87 st_idle: begin //空閑狀態 88 if(sccb_exec) begin 89 next_state = st_sladdr; 90 end 91 else 92 next_state = st_idle; 93 end 94 st_sladdr: begin 95 if(st_done) begin 96 if(bit_ctrl) //判斷是16位還是8位字地址 97 next_state = st_addr16; 98 else 99 next_state = st_addr8 ; 100 end 101 else 102 next_state = st_sladdr; 103 end 104 st_addr16: begin //寫16位字地址 105 if(st_done) begin 106 next_state = st_addr8; 107 end 108 else begin 109 next_state = st_addr16; 110 end 111 end 112 st_addr8: begin //8位字地址 113 if(st_done) begin 114 if(wr_flag==1'b0) //讀寫判斷 115 next_state = st_data_wr; 116 else 117 next_state = st_addr_rd; 118 end 119 else begin 120 next_state = st_addr8; 121 end 122 end 123 st_data_wr: begin //寫數據(8 bit) 124 if(st_done) 125 next_state = st_stop; 126 else 127 next_state = st_data_wr; 128 end 129 st_addr_rd: begin //寫地址以進行讀數據 130 if(st_done) begin 131 next_state = st_data_rd; 132 end 133 else begin 134 next_state = st_addr_rd; 135 end 136 end 137 st_data_rd: begin //讀取數據(8 bit) 138 if(st_done) 139 next_state = st_stop; 140 else 141 next_state = st_data_rd; 142 end 143 st_stop: begin //結束sccb操作 144 if(st_done) 145 next_state = st_idle; 146 else 147 next_state = st_stop ; 148 end 149 default: next_state= st_idle; 150 endcase 151 end 152 153 //時序電路描述狀態輸出 154 always @(posedge dri_clk or negedge rst_n) begin 155 //復位初始化 156 if(!rst_n) begin 157 scl <= 1'b1; 158 sda_out <= 1'b1; 159 sda_dir <= 1'b1; 160 sccb_done <= 1'b0; 161 sccb_ack <= 1'b0; 162 cnt <= 1'b0; 163 st_done <= 1'b0; 164 data_r <= 1'b0; 165 rd_data<= 1'b0; 166 wr_flag <= 1'b0; 167 addr_t <= 1'b0; 168 data_wr_t <= 1'b0; 169 end 170 else begin 171 st_done <= 1'b0 ; 172 cnt <= cnt +1'b1 ; 173 case(cur_state) 174 st_idle: begin //空閑狀態 175 scl <= 1'b1; 176 sda_out <= 1'b1; 177 sda_dir <= 1'b1; 178 sccb_done<= 1'b0; 179 cnt <= 7'b0; 180 if(sccb_exec) begin 181 wr_flag <= sccb_rh_wl ; 182 addr_t <= sub_addr ; 183 data_wr_t <= wr_data; 184 sccb_ack <= 1'b0; 185 end 186 end 187 st_sladdr: begin //寫地址(器件地址和字地址) 188 case(cnt) 189 7'd1 : sda_out <= 1'b0; //開始sccb 190 7'd3 : scl <= 1'b0; 191 7'd4 : sda_out <= SLAVE_ADDR[6]; //傳送器件地址 192 7'd5 : scl <= 1'b1; 193 7'd7 : scl <= 1'b0; 194 7'd8 : sda_out <= SLAVE_ADDR[5]; 195 7'd9 : scl <= 1'b1; 196 7'd11: scl <= 1'b0; 197 7'd12: sda_out <= SLAVE_ADDR[4]; 198 7'd13: scl <= 1'b1; 199 7'd15: scl <= 1'b0; 200 7'd16: sda_out <= SLAVE_ADDR[3]; 201 7'd17: scl <= 1'b1; 202 7'd19: scl <= 1'b0; 203 7'd20: sda_out <= SLAVE_ADDR[2]; 204 7'd21: scl <= 1'b1; 205 7'd23: scl <= 1'b0; 206 7'd24: sda_out <= SLAVE_ADDR[1]; 207 7'd25: scl <= 1'b1; 208 7'd27: scl <= 1'b0; 209 7'd28: sda_out <= SLAVE_ADDR[0]; 210 7'd29: scl <= 1'b1; 211 7'd31: scl <= 1'b0; 212 7'd32: sda_out <= 1'b0; //0:寫 213 7'd33: scl <= 1'b1; 214 7'd35: scl <= 1'b0; 215 7'd36: begin 216 sda_dir <= 1'b0; 217 sda_out <= 1'b1; 218 end 219 7'd37: scl <= 1'b1; 220 7'd38: begin //從機應答 221 st_done <= 1'b1; 222 if(sda_in == 1'b1) //高電平表示未應答 223 sccb_ack <= 1'b1; //拉高應答標志位 224 end 225 7'd39: begin 226 scl <= 1'b0; 227 cnt <= 1'b0; 228 end 229 default : ; 230 endcase 231 end 232 st_addr16: begin 233 case(cnt) 234 7'd0 : begin 235 sda_dir <= 1'b1 ; 236 sda_out <= addr_t[15]; //傳送字地址 237 end 238 7'd1 : scl <= 1'b1; 239 7'd3 : scl <= 1'b0; 240 7'd4 : sda_out <= addr_t[14]; 241 7'd5 : scl <= 1'b1; 242 7'd7 : scl <= 1'b0; 243 7'd8 : sda_out <= addr_t[13]; 244 7'd9 : scl <= 1'b1; 245 7'd11: scl <= 1'b0; 246 7'd12: sda_out <= addr_t[12]; 247 7'd13: scl <= 1'b1; 248 7'd15: scl <= 1'b0; 249 7'd16: sda_out <= addr_t[11]; 250 7'd17: scl <= 1'b1; 251 7'd19: scl <= 1'b0; 252 7'd20: sda_out <= addr_t[10]; 253 7'd21: scl <= 1'b1; 254 7'd23: scl <= 1'b0; 255 7'd24: sda_out <= addr_t[9]; 256 7'd25: scl <= 1'b1; 257 7'd27: scl <= 1'b0; 258 7'd28: sda_out <= addr_t[8]; 259 7'd29: scl <= 1'b1; 260 7'd31: scl <= 1'b0; 261 7'd32: begin 262 sda_dir <= 1'b0; 263 sda_out <= 1'b1; 264 end 265 7'd33: scl <= 1'b1; 266 7'd34: begin //從機應答 267 st_done <= 1'b1; 268 if(sda_in == 1'b1) //高電平表示未應答 269 sccb_ack <= 1'b1; //拉高應答標志位 270 end 271 7'd35: begin 272 scl <= 1'b0; 273 cnt <= 1'b0; 274 end 275 default : ; 276 endcase 277 end 278 st_addr8: begin 279 case(cnt) 280 7'd0: begin 281 sda_dir <= 1'b1 ; 282 sda_out <= addr_t[7]; //字地址 283 end 284 7'd1 : scl <= 1'b1; 285 7'd3 : scl <= 1'b0; 286 7'd4 : sda_out <= addr_t[6]; 287 7'd5 : scl <= 1'b1; 288 7'd7 : scl <= 1'b0; 289 7'd8 : sda_out <= addr_t[5]; 290 7'd9 : scl <= 1'b1; 291 7'd11: scl <= 1'b0; 292 7'd12: sda_out <= addr_t[4]; 293 7'd13: scl <= 1'b1; 294 7'd15: scl <= 1'b0; 295 7'd16: sda_out <= addr_t[3]; 296 7'd17: scl <= 1'b1; 297 7'd19: scl <= 1'b0; 298 7'd20: sda_out <= addr_t[2]; 299 7'd21: scl <= 1'b1; 300 7'd23: scl <= 1'b0; 301 7'd24: sda_out <= addr_t[1]; 302 7'd25: scl <= 1'b1; 303 7'd27: scl <= 1'b0; 304 7'd28: sda_out <= addr_t[0]; 305 7'd29: scl <= 1'b1; 306 7'd31: scl <= 1'b0; 307 7'd32: begin 308 sda_dir <= 1'b0; 309 sda_out <= 1'b1; 310 end 311 7'd33: scl <= 1'b1; 312 7'd34: begin //從機應答 313 st_done <= 1'b1; 314 if(sda_in == 1'b1) //高電平表示未應答 315 sccb_ack <= 1'b1; //拉高應答標志位 316 end 317 7'd35: begin 318 scl <= 1'b0; 319 cnt <= 1'b0; 320 end 321 default : ; 322 endcase 323 end 324 st_data_wr: begin //寫數據(8 bit) 325 case(cnt) 326 7'd0: begin 327 sda_out <= data_wr_t[7]; //sccb寫8位數據 328 sda_dir <= 1'b1; 329 end 330 7'd1 : scl <= 1'b1; 331 7'd3 : scl <= 1'b0; 332 7'd4 : sda_out <= data_wr_t[6]; 333 7'd5 : scl <= 1'b1; 334 7'd7 : scl <= 1'b0; 335 7'd8 : sda_out <= data_wr_t[5]; 336 7'd9 : scl <= 1'b1; 337 7'd11: scl <= 1'b0; 338 7'd12: sda_out <= data_wr_t[4]; 339 7'd13: scl <= 1'b1; 340 7'd15: scl <= 1'b0; 341 7'd16: sda_out <= data_wr_t[3]; 342 7'd17: scl <= 1'b1; 343 7'd19: scl <= 1'b0; 344 7'd20: sda_out <= data_wr_t[2]; 345 7'd21: scl <= 1'b1; 346 7'd23: scl <= 1'b0; 347 7'd24: sda_out <= data_wr_t[1]; 348 7'd25: scl <= 1'b1; 349 7'd27: scl <= 1'b0; 350 7'd28: sda_out <= data_wr_t[0]; 351 7'd29: scl <= 1'b1; 352 7'd31: scl <= 1'b0; 353 7'd32: begin 354 sda_dir <= 1'b0; 355 sda_out <= 1'b1; 356 end 357 7'd33: scl <= 1'b1; 358 7'd34: begin //從機應答 359 st_done <= 1'b1; 360 if(sda_in == 1'b1) //高電平表示未應答 361 sccb_ack <= 1'b1; //拉高應答標志位 362 end 363 7'd35: begin 364 scl <= 1'b0; 365 cnt <= 1'b0; 366 end 367 default : ; 368 endcase 369 end 370 st_addr_rd: begin //寫地址以進行讀數據 371 case(cnt) 372 7'd0 : begin 373 sda_dir <= 1'b1; 374 sda_out <= 1'b1; 375 end 376 7'd1 : scl <= 1'b1; 377 7'd2 : sda_out <= 1'b0; //重新開始 378 7'd3 : scl <= 1'b0; 379 7'd4 : sda_out <= SLAVE_ADDR[6]; //傳送器件地址 380 7'd5 : scl <= 1'b1; 381 7'd7 : scl <= 1'b0; 382 7'd8 : sda_out <= SLAVE_ADDR[5]; 383 7'd9 : scl <= 1'b1; 384 7'd11: scl <= 1'b0; 385 7'd12: sda_out <= SLAVE_ADDR[4]; 386 7'd13: scl <= 1'b1; 387 7'd15: scl <= 1'b0; 388 7'd16: sda_out <= SLAVE_ADDR[3]; 389 7'd17: scl <= 1'b1; 390 7'd19: scl <= 1'b0; 391 7'd20: sda_out <= SLAVE_ADDR[2]; 392 7'd21: scl <= 1'b1; 393 7'd23: scl <= 1'b0; 394 7'd24: sda_out <= SLAVE_ADDR[1]; 395 7'd25: scl <= 1'b1; 396 7'd27: scl <= 1'b0; 397 7'd28: sda_out <= SLAVE_ADDR[0]; 398 7'd29: scl <= 1'b1; 399 7'd31: scl <= 1'b0; 400 7'd32: sda_out <= 1'b1; //1:讀 401 7'd33: scl <= 1'b1; 402 7'd35: scl <= 1'b0; 403 7'd36: begin 404 sda_dir <= 1'b0; 405 sda_out <= 1'b1; 406 end 407 7'd37: scl <= 1'b1; 408 7'd38: begin //從機應答 409 st_done <= 1'b1; 410 if(sda_in == 1'b1) //高電平表示未應答 411 sccb_ack <= 1'b1; //拉高應答標志位 412 end 413 7'd39: begin 414 scl <= 1'b0; 415 cnt <= 1'b0; 416 end 417 default : ; 418 endcase 419 end 420 st_data_rd: begin //讀取數據(8 bit) 421 case(cnt) 422 7'd0: sda_dir <= 1'b0; 423 7'd1: begin 424 data_r[7] <= sda_in; 425 scl <= 1'b1; 426 end 427 7'd3: scl <= 1'b0; 428 7'd5: begin 429 data_r[6] <= sda_in ; 430 scl <= 1'b1 ; 431 end 432 7'd7: scl <= 1'b0; 433 7'd9: begin 434 data_r[5] <= sda_in; 435 scl <= 1'b1 ; 436 end 437 7'd11: scl <= 1'b0; 438 7'd13: begin 439 data_r[4] <= sda_in; 440 scl <= 1'b1 ; 441 end 442 7'd15: scl <= 1'b0; 443 7'd17: begin 444 data_r[3] <= sda_in; 445 scl <= 1'b1 ; 446 end 447 7'd19: scl <= 1'b0; 448 7'd21: begin 449 data_r[2] <= sda_in; 450 scl <= 1'b1 ; 451 end 452 7'd23: scl <= 1'b0; 453 7'd25: begin 454 data_r[1] <= sda_in; 455 scl <= 1'b1 ; 456 end 457 7'd27: scl <= 1'b0; 458 7'd29: begin 459 data_r[0] <= sda_in; 460 scl <= 1'b1 ; 461 end 462 7'd31: scl <= 1'b0; 463 7'd32: begin 464 sda_dir <= 1'b1; 465 sda_out <= 1'b1; 466 end 467 7'd33: scl <= 1'b1; 468 7'd34: st_done <= 1'b1; //非應答 469 7'd35: begin 470 scl <= 1'b0; 471 cnt <= 1'b0; 472 rd_data <= data_r; 473 end 474 default : ; 475 endcase 476 end 477 st_stop: begin //結束sccb操作 478 case(cnt) 479 7'd0: begin 480 sda_dir <= 1'b1; //結束sccb 481 sda_out <= 1'b0; 482 end 483 7'd1 : scl <= 1'b1; 484 7'd3 : sda_out <= 1'b1; 485 7'd15: st_done <= 1'b1; 486 7'd16: begin 487 cnt <= 1'b0; 488 sccb_done <= 1'b1; //向上層模塊傳遞sccb結束信號 489 end 490 default : ; 491 endcase 492 end 493 endcase 494 end 495 end 496 endmodule

1 module configure( 2 input clk , //時鍾信號 3 input rst_n , //復位信號,低電平有效 4 5 input [7:0] sccb_data_r, //sccb讀出的數據 6 input sccb_done , //sccb寄存器配置完成信號 7 input [12:0] cmos_h_pixel , 8 input [12:0] cmos_v_pixel , 9 input [12:0] total_h_pixel, //水平總像素大小 10 input [12:0] total_v_pixel, //垂直總像素大小 11 output reg sccb_exec , //sccb觸發執行信號 12 output reg [23:0] sccb_data , //sccb要配置的地址與數據(高16位地址,低8位數據) 13 output reg sccb_rh_wl, //sccb讀寫控制信號 14 output reg init_done //初始化完成信號 15 ); 16 17 //parameter define 18 localparam REG_NUM = 8'd250 ; //總共需要配置的寄存器個數 19 20 //reg define 21 reg [12:0] start_init_cnt; //等待延時計數器 22 reg [7:0] init_reg_cnt ; //寄存器配置個數計數器 23 24 //***************************************************** 25 //** main code 26 //***************************************************** 27 28 //clk時鍾配置成250khz,周期為4us 5000*4us = 20ms 29 //OV5640上電到開始配置IIC至少等待20ms 30 always @(posedge clk or negedge rst_n) begin 31 if(!rst_n) 32 start_init_cnt <= 13'b0; 33 else if(start_init_cnt < 13'd5000) begin 34 start_init_cnt <= start_init_cnt + 1'b1; 35 end 36 end 37 38 //寄存器配置個數計數 39 always @(posedge clk or negedge rst_n) begin 40 if(!rst_n) 41 init_reg_cnt <= 8'd0; 42 else if(sccb_exec) 43 init_reg_cnt <= init_reg_cnt + 8'b1; 44 end 45 46 //sccb觸發執行信號 47 always @(posedge clk or negedge rst_n) begin 48 if(!rst_n) 49 sccb_exec <= 1'b0; 50 else if(start_init_cnt == 13'd4999) 51 sccb_exec <= 1'b1; 52 else if(sccb_done && (init_reg_cnt < REG_NUM)) 53 sccb_exec <= 1'b1; 54 else 55 sccb_exec <= 1'b0; 56 end 57 58 //配置sccb讀寫控制信號 59 always @(posedge clk or negedge rst_n) begin 60 if(!rst_n) 61 sccb_rh_wl <= 1'b1; 62 else if(init_reg_cnt == 8'd2) 63 sccb_rh_wl <= 1'b0; 64 end 65 66 //初始化完成信號 67 always @(posedge clk or negedge rst_n) begin 68 if(!rst_n) 69 init_done <= 1'b0; 70 else if((init_reg_cnt == REG_NUM) && sccb_done) 71 init_done <= 1'b1; 72 end 73 74 //配置寄存器地址與數據 75 always @(posedge clk or negedge rst_n) begin 76 if(!rst_n) 77 sccb_data <= 24'b0; 78 else begin 79 case(init_reg_cnt) 80 //先對寄存器進行軟件復位,使寄存器恢復初始值 81 //寄存器軟件復位后,需要延時1ms才能配置其它寄存器 82 8'd0 : sccb_data <= {16'h300a,8'h0}; // 83 8'd1 : sccb_data <= {16'h300b,8'h0}; // 84 8'd2 : sccb_data <= {16'h3008,8'h82}; //Bit[7]:復位 Bit[6]:電源休眠 85 8'd3 : sccb_data <= {16'h3008,8'h02}; //正常工作模式 86 8'd4 : sccb_data <= {16'h3103,8'h02}; //Bit[1]:1 PLL Clock 87 //引腳輸入/輸出控制 FREX/VSYNC/HREF/PCLK/D[9:6] 88 8'd5 : sccb_data <= {8'h30,8'h17,8'hff}; 89 //引腳輸入/輸出控制 D[5:0]/GPIO1/GPIO0 90 8'd6 : sccb_data <= {16'h3018,8'hff}; 91 8'd7 : sccb_data <= {16'h3037,8'h13}; //PLL分頻控制 92 8'd8 : sccb_data <= {16'h3108,8'h01}; //系統根分頻器 93 8'd9 : sccb_data <= {16'h3630,8'h36}; 94 8'd10 : sccb_data <= {16'h3631,8'h0e}; 95 8'd11 : sccb_data <= {16'h3632,8'he2}; 96 8'd12 : sccb_data <= {16'h3633,8'h12}; 97 8'd13 : sccb_data <= {16'h3621,8'he0}; 98 8'd14 : sccb_data <= {16'h3704,8'ha0}; 99 8'd15 : sccb_data <= {16'h3703,8'h5a}; 100 8'd16 : sccb_data <= {16'h3715,8'h78}; 101 8'd17 : sccb_data <= {16'h3717,8'h01}; 102 8'd18 : sccb_data <= {16'h370b,8'h60}; 103 8'd19 : sccb_data <= {16'h3705,8'h1a}; 104 8'd20 : sccb_data <= {16'h3905,8'h02}; 105 8'd21 : sccb_data <= {16'h3906,8'h10}; 106 8'd22 : sccb_data <= {16'h3901,8'h0a}; 107 8'd23 : sccb_data <= {16'h3731,8'h12}; 108 8'd24 : sccb_data <= {16'h3600,8'h08}; //VCM控制,用於自動聚焦 109 8'd25 : sccb_data <= {16'h3601,8'h33}; //VCM控制,用於自動聚焦 110 8'd26 : sccb_data <= {16'h302d,8'h60}; //系統控制 111 8'd27 : sccb_data <= {16'h3620,8'h52}; 112 8'd28 : sccb_data <= {16'h371b,8'h20}; 113 8'd29 : sccb_data <= {16'h471c,8'h50}; 114 8'd30 : sccb_data <= {16'h3a13,8'h43}; //AEC(自動曝光控制) 115 8'd31 : sccb_data <= {16'h3a18,8'h00}; //AEC 增益上限 116 8'd32 : sccb_data <= {16'h3a19,8'hf8}; //AEC 增益上限 117 8'd33 : sccb_data <= {16'h3635,8'h13}; 118 8'd34 : sccb_data <= {16'h3636,8'h03}; 119 8'd35 : sccb_data <= {16'h3634,8'h40}; 120 8'd36 : sccb_data <= {16'h3622,8'h01}; 121 8'd37 : sccb_data <= {16'h3c01,8'h34}; 122 8'd38 : sccb_data <= {16'h3c04,8'h28}; 123 8'd39 : sccb_data <= {16'h3c05,8'h98}; 124 8'd40 : sccb_data <= {16'h3c06,8'h00}; //light meter 1 閾值[15:8] 125 8'd41 : sccb_data <= {16'h3c07,8'h08}; //light meter 1 閾值[7:0] 126 8'd42 : sccb_data <= {16'h3c08,8'h00}; //light meter 2 閾值[15:8] 127 8'd43 : sccb_data <= {16'h3c09,8'h1c}; //light meter 2 閾值[7:0] 128 8'd44 : sccb_data <= {16'h3c0a,8'h9c}; //sample number[15:8] 129 8'd45 : sccb_data <= {16'h3c0b,8'h40}; //sample number[7:0] 130 8'd46 : sccb_data <= {16'h3810,8'h00}; //Timing Hoffset[11:8] 131 8'd47 : sccb_data <= {16'h3811,8'h10}; //Timing Hoffset[7:0] 132 8'd48 : sccb_data <= {16'h3812,8'h00}; //Timing Voffset[10:8] 133 8'd49 : sccb_data <= {16'h3708,8'h64}; 134 8'd50 : sccb_data <= {16'h4001,8'h02}; //BLC(黑電平校准)補償起始行號 135 8'd51 : sccb_data <= {16'h4005,8'h1a}; //BLC(黑電平校准)補償始終更新 136 8'd52 : sccb_data <= {16'h3000,8'h00}; //系統塊復位控制 137 8'd53 : sccb_data <= {16'h3004,8'hff}; //時鍾使能控制 138 8'd54 : sccb_data <= {16'h4300,8'h61}; //格式控制 RGB565 139 8'd55 : sccb_data <= {16'h501f,8'h01}; //ISP RGB 140 8'd56 : sccb_data <= {16'h440e,8'h00}; 141 8'd57 : sccb_data <= {16'h5000,8'ha7}; //ISP控制 142 8'd58 : sccb_data <= {16'h3a0f,8'h30}; //AEC控制;stable range in high 143 8'd59 : sccb_data <= {16'h3a10,8'h28}; //AEC控制;stable range in low 144 8'd60 : sccb_data <= {16'h3a1b,8'h30}; //AEC控制;stable range out high 145 8'd61 : sccb_data <= {16'h3a1e,8'h26}; //AEC控制;stable range out low 146 8'd62 : sccb_data <= {16'h3a11,8'h60}; //AEC控制; fast zone high 147 8'd63 : sccb_data <= {16'h3a1f,8'h14}; //AEC控制; fast zone low 148 //LENC(鏡頭校正)控制 16'h5800~16'h583d 149 8'd64 : sccb_data <= {16'h5800,8'h23}; 150 8'd65 : sccb_data <= {16'h5801,8'h14}; 151 8'd66 : sccb_data <= {16'h5802,8'h0f}; 152 8'd67 : sccb_data <= {16'h5803,8'h0f}; 153 8'd68 : sccb_data <= {16'h5804,8'h12}; 154 8'd69 : sccb_data <= {16'h5805,8'h26}; 155 8'd70 : sccb_data <= {16'h5806,8'h0c}; 156 8'd71 : sccb_data <= {16'h5807,8'h08}; 157 8'd72 : sccb_data <= {16'h5808,8'h05}; 158 8'd73 : sccb_data <= {16'h5809,8'h05}; 159 8'd74 : sccb_data <= {16'h580a,8'h08}; 160 8'd75 : sccb_data <= {16'h580b,8'h0d}; 161 8'd76 : sccb_data <= {16'h580c,8'h08}; 162 8'd77 : sccb_data <= {16'h580d,8'h03}; 163 8'd78 : sccb_data <= {16'h580e,8'h00}; 164 8'd79 : sccb_data <= {16'h580f,8'h00}; 165 8'd80 : sccb_data <= {16'h5810,8'h03}; 166 8'd81 : sccb_data <= {16'h5811,8'h09}; 167 8'd82 : sccb_data <= {16'h5812,8'h07}; 168 8'd83 : sccb_data <= {16'h5813,8'h03}; 169 8'd84 : sccb_data <= {16'h5814,8'h00}; 170 8'd85 : sccb_data <= {16'h5815,8'h01}; 171 8'd86 : sccb_data <= {16'h5816,8'h03}; 172 8'd87 : sccb_data <= {16'h5817,8'h08}; 173 8'd88 : sccb_data <= {16'h5818,8'h0d}; 174 8'd89 : sccb_data <= {16'h5819,8'h08}; 175 8'd90 : sccb_data <= {16'h581a,8'h05}; 176 8'd91 : sccb_data <= {16'h581b,8'h06}; 177 8'd92 : sccb_data <= {16'h581c,8'h08}; 178 8'd93 : sccb_data <= {16'h581d,8'h0e}; 179 8'd94 : sccb_data <= {16'h581e,8'h29}; 180 8'd95 : sccb_data <= {16'h581f,8'h17}; 181 8'd96 : sccb_data <= {16'h5820,8'h11}; 182 8'd97 : sccb_data <= {16'h5821,8'h11}; 183 8'd98 : sccb_data <= {16'h5822,8'h15}; 184 8'd99 : sccb_data <= {16'h5823,8'h28}; 185 8'd100: sccb_data <= {16'h5824,8'h46}; 186 8'd101: sccb_data <= {16'h5825,8'h26}; 187 8'd102: sccb_data <= {16'h5826,8'h08}; 188 8'd103: sccb_data <= {16'h5827,8'h26}; 189 8'd104: sccb_data <= {16'h5828,8'h64}; 190 8'd105: sccb_data <= {16'h5829,8'h26}; 191 8'd106: sccb_data <= {16'h582a,8'h24}; 192 8'd107: sccb_data <= {16'h582b,8'h22}; 193 8'd108: sccb_data <= {16'h582c,8'h24}; 194 8'd109: sccb_data <= {16'h582d,8'h24}; 195 8'd110: sccb_data <= {16'h582e,8'h06}; 196 8'd111: sccb_data <= {16'h582f,8'h22}; 197 8'd112: sccb_data <= {16'h5830,8'h40}; 198 8'd113: sccb_data <= {16'h5831,8'h42}; 199 8'd114: sccb_data <= {16'h5832,8'h24}; 200 8'd115: sccb_data <= {16'h5833,8'h26}; 201 8'd116: sccb_data <= {16'h5834,8'h24}; 202 8'd117: sccb_data <= {16'h5835,8'h22}; 203 8'd118: sccb_data <= {16'h5836,8'h22}; 204 8'd119: sccb_data <= {16'h5837,8'h26}; 205 8'd120: sccb_data <= {16'h5838,8'h44}; 206 8'd121: sccb_data <= {16'h5839,8'h24}; 207 8'd122: sccb_data <= {16'h583a,8'h26}; 208 8'd123: sccb_data <= {16'h583b,8'h28}; 209 8'd124: sccb_data <= {16'h583c,8'h42}; 210 8'd125: sccb_data <= {16'h583d,8'hce}; 211 //AWB(自動白平衡控制) 16'h5180~16'h519e 212 8'd126: sccb_data <= {16'h5180,8'hff}; 213 8'd127: sccb_data <= {16'h5181,8'hf2}; 214 8'd128: sccb_data <= {16'h5182,8'h00}; 215 8'd129: sccb_data <= {16'h5183,8'h14}; 216 8'd130: sccb_data <= {16'h5184,8'h25}; 217 8'd131: sccb_data <= {16'h5185,8'h24}; 218 8'd132: sccb_data <= {16'h5186,8'h09}; 219 8'd133: sccb_data <= {16'h5187,8'h09}; 220 8'd134: sccb_data <= {16'h5188,8'h09}; 221 8'd135: sccb_data <= {16'h5189,8'h75}; 222 8'd136: sccb_data <= {16'h518a,8'h54}; 223 8'd137: sccb_data <= {16'h518b,8'he0}; 224 8'd138: sccb_data <= {16'h518c,8'hb2}; 225 8'd139: sccb_data <= {16'h518d,8'h42}; 226 8'd140: sccb_data <= {16'h518e,8'h3d}; 227 8'd141: sccb_data <= {16'h518f,8'h56}; 228 8'd142: sccb_data <= {16'h5190,8'h46}; 229 8'd143: sccb_data <= {16'h5191,8'hf8}; 230 8'd144: sccb_data <= {16'h5192,8'h04}; 231 8'd145: sccb_data <= {16'h5193,8'h70}; 232 8'd146: sccb_data <= {16'h5194,8'hf0}; 233 8'd147: sccb_data <= {16'h5195,8'hf0}; 234 8'd148: sccb_data <= {16'h5196,8'h03}; 235 8'd149: sccb_data <= {16'h5197,8'h01}; 236 8'd150: sccb_data <= {16'h5198,8'h04}; 237 8'd151: sccb_data <= {16'h5199,8'h12}; 238 8'd152: sccb_data <= {16'h519a,8'h04}; 239 8'd153: sccb_data <= {16'h519b,8'h00}; 240 8'd154: sccb_data <= {16'h519c,8'h06}; 241 8'd155: sccb_data <= {16'h519d,8'h82}; 242 8'd156: sccb_data <= {16'h519e,8'h38}; 243 //Gamma(伽馬)控制 16'h5480~16'h5490 244 8'd157: sccb_data <= {16'h5480,8'h01}; 245 8'd158: sccb_data <= {16'h5481,8'h08}; 246 8'd159: sccb_data <= {16'h5482,8'h14}; 247 8'd160: sccb_data <= {16'h5483,8'h28}; 248 8'd161: sccb_data <= {16'h5484,8'h51}; 249 8'd162: sccb_data <= {16'h5485,8'h65}; 250 8'd163: sccb_data <= {16'h5486,8'h71}; 251 8'd164: sccb_data <= {16'h5487,8'h7d}; 252 8'd165: sccb_data <= {16'h5488,8'h87}; 253 8'd166: sccb_data <= {16'h5489,8'h91}; 254 8'd167: sccb_data <= {16'h548a,8'h9a}; 255 8'd168: sccb_data <= {16'h548b,8'haa}; 256 8'd169: sccb_data <= {16'h548c,8'hb8}; 257 8'd170: sccb_data <= {16'h548d,8'hcd}; 258 8'd171: sccb_data <= {16'h548e,8'hdd}; 259 8'd172: sccb_data <= {16'h548f,8'hea}; 260 8'd173: sccb_data <= {16'h5490,8'h1d}; 261 //CMX(彩色矩陣控制) 16'h5381~16'h538b 262 8'd174: sccb_data <= {16'h5381,8'h1e}; 263 8'd175: sccb_data <= {16'h5382,8'h5b}; 264 8'd176: sccb_data <= {16'h5383,8'h08}; 265 8'd177: sccb_data <= {16'h5384,8'h0a}; 266 8'd178: sccb_data <= {16'h5385,8'h7e}; 267 8'd179: sccb_data <= {16'h5386,8'h88}; 268 8'd180: sccb_data <= {16'h5387,8'h7c}; 269 8'd181: sccb_data <= {16'h5388,8'h6c}; 270 8'd182: sccb_data <= {16'h5389,8'h10}; 271 8'd183: sccb_data <= {16'h538a,8'h01}; 272 8'd184: sccb_data <= {16'h538b,8'h98}; 273 //SDE(特殊數碼效果)控制 16'h5580~16'h558b 274 8'd185: sccb_data <= {16'h5580,8'h06}; 275 8'd186: sccb_data <= {16'h5583,8'h40}; 276 8'd187: sccb_data <= {16'h5584,8'h10}; 277 8'd188: sccb_data <= {16'h5589,8'h10}; 278 8'd189: sccb_data <= {16'h558a,8'h00}; 279 8'd190: sccb_data <= {16'h558b,8'hf8}; 280 8'd191: sccb_data <= {16'h501d,8'h40}; //ISP MISC 281 //CIP(顏色插值)控制 (16'h5300~16'h530c) 282 8'd192: sccb_data <= {16'h5300,8'h08}; 283 8'd193: sccb_data <= {16'h5301,8'h30}; 284 8'd194: sccb_data <= {16'h5302,8'h10}; 285 8'd195: sccb_data <= {16'h5303,8'h00}; 286 8'd196: sccb_data <= {16'h5304,8'h08}; 287 8'd197: sccb_data <= {16'h5305,8'h30}; 288 8'd198: sccb_data <= {16'h5306,8'h08}; 289 8'd199: sccb_data <= {16'h5307,8'h16}; 290 8'd200: sccb_data <= {16'h5309,8'h08}; 291 8'd201: sccb_data <= {16'h530a,8'h30}; 292 8'd202: sccb_data <= {16'h530b,8'h04}; 293 8'd203: sccb_data <= {16'h530c,8'h06}; 294 8'd204: sccb_data <= {16'h5025,8'h00}; 295 //系統時鍾分頻 Bit[7:4]:系統時鍾分頻 input clock =24Mhz, PCLK = 48Mhz 296 8'd205: sccb_data <= {16'h3035,8'h11}; 297 8'd206: sccb_data <= {16'h3036,8'h3c}; //PLL倍頻 298 8'd207: sccb_data <= {16'h3c07,8'h08}; 299 //時序控制 16'h3800~16'h3821 300 8'd208: sccb_data <= {16'h3820,8'h46}; 301 8'd209: sccb_data <= {16'h3821,8'h01}; 302 8'd210: sccb_data <= {16'h3814,8'h31}; 303 8'd211: sccb_data <= {16'h3815,8'h31}; 304 8'd212: sccb_data <= {16'h3800,8'h00}; 305 8'd213: sccb_data <= {16'h3801,8'h00}; 306 8'd214: sccb_data <= {16'h3802,8'h00}; 307 8'd215: sccb_data <= {16'h3803,8'h04}; 308 8'd216: sccb_data <= {16'h3804,8'h0a}; 309 8'd217: sccb_data <= {16'h3805,8'h3f}; 310 8'd218: sccb_data <= {16'h3806,8'h07}; 311 8'd219: sccb_data <= {16'h3807,8'h9b}; 312 //設置輸出像素個數 313 //DVP 輸出水平像素點數高4位 314 8'd220: sccb_data <= {16'h3808,{4'd0,cmos_h_pixel[11:8]}}; 315 //DVP 輸出水平像素點數低8位 316 8'd221: sccb_data <= {16'h3809,cmos_h_pixel[7:0]}; 317 //DVP 輸出垂直像素點數高3位 318 8'd222: sccb_data <= {16'h380a,{5'd0,cmos_v_pixel[10:8]}}; 319 //DVP 輸出垂直像素點數低8位 320 8'd223: sccb_data <= {16'h380b,cmos_v_pixel[7:0]}; 321 //水平總像素大小高5位 322 8'd224: sccb_data <= {16'h380c,{3'd0,total_h_pixel[12:8]}}; 323 //水平總像素大小低8位 324 8'd225: sccb_data <= {16'h380d,total_h_pixel[7:0]}; 325 //垂直總像素大小高5位 326 8'd226: sccb_data <= {16'h380e,{3'd0,total_v_pixel[12:8]}}; 327 //垂直總像素大小低8位 328 8'd227: sccb_data <= {16'h380f,total_v_pixel[7:0]}; 329 8'd228: sccb_data <= {16'h3813,8'h06}; 330 8'd229: sccb_data <= {16'h3618,8'h00}; 331 8'd230: sccb_data <= {16'h3612,8'h29}; 332 8'd231: sccb_data <= {16'h3709,8'h52}; 333 8'd232: sccb_data <= {16'h370c,8'h03}; 334 8'd233: sccb_data <= {16'h3a02,8'h17}; //60Hz max exposure 335 8'd234: sccb_data <= {16'h3a03,8'h10}; //60Hz max exposure 336 8'd235: sccb_data <= {16'h3a14,8'h17}; //50Hz max exposure 337 8'd236: sccb_data <= {16'h3a15,8'h10}; //50Hz max exposure 338 8'd237: sccb_data <= {16'h4004,8'h02}; //BLC(背光) 2 lines 339 8'd238: sccb_data <= {16'h4713,8'h03}; //JPEG mode 3 340 8'd239: sccb_data <= {16'h4407,8'h04}; //量化標度 341 8'd240: sccb_data <= {16'h460c,8'h22}; 342 8'd241: sccb_data <= {16'h4837,8'h22}; //DVP CLK divider 343 8'd242: sccb_data <= {16'h3824,8'h02}; //DVP CLK divider 344 8'd243: sccb_data <= {16'h5001,8'ha3}; //ISP 控制 345 8'd244: sccb_data <= {16'h3b07,8'h0a}; //幀曝光模式 346 //彩條測試使能 347 8'd245: sccb_data <= {16'h503d,8'h00}; //8'h00:正常模式 8'h80:彩條顯示 348 //測試閃光燈功能 349 8'd246: sccb_data <= {16'h3016,8'h02}; 350 8'd247: sccb_data <= {16'h301c,8'h02}; 351 8'd248: sccb_data <= {16'h3019,8'h02}; //打開閃光燈 352 8'd249: sccb_data <= {16'h3019,8'h00}; //關閉閃光燈 353 //只讀存儲器,防止在case中沒有列舉的情況,之前的寄存器被重復改寫 354 default : sccb_data <= {16'h300a,8'h00}; //器件ID高8位 355 endcase 356 end 357 end 358 359 endmodule

1 module ov5640_drive( 2 input clk , 3 input rst_n , 4 //攝像頭接口 5 input cam_pclk , 6 input cam_vsync , 7 input cam_href , 8 input [7:0] cam_pdata , 9 output reset_n , 10 output pwdn , 11 output sio_c , 12 inout sio_d 13 ); 14 localparam cmos_h_pixel = 1024; 15 localparam cmos_v_pixel = 720; 16 localparam total_h_pixel = cmos_h_pixel + 1216; 17 localparam total_v_pixel = cmos_v_pixel + 504; 18 19 //wire difine 20 wire sccb_exec ; 21 wire [23:0] sccb_data ; 22 wire sccb_done ; 23 wire sccb_dri_clk ; 24 wire [ 7:0] sccb_data_r ; 25 wire sccb_rh_wl ; 26 wire cam_init_done ; 27 28 //電源休眠模式選擇 0:正常模式 1:電源休眠模式 29 assign pwdn = 1'b0; 30 assign reset_n = 1'b1; 31 32 //sccb配置模塊 33 configure u_configure( 34 .clk (sccb_dri_clk ), 35 .rst_n (rst_n ), 36 .sccb_exec (sccb_exec ), 37 .sccb_data (sccb_data ), 38 .sccb_rh_wl (sccb_rh_wl ), //sccb讀寫控制信號 39 .sccb_done (sccb_done ), 40 .sccb_data_r (sccb_data_r ), 41 .cmos_h_pixel (cmos_h_pixel ), //CMOS水平方向像素個數 42 .cmos_v_pixel (cmos_v_pixel ), //CMOS垂直方向像素個數 43 .total_h_pixel (total_h_pixel), //水平總像素大小 44 .total_v_pixel (total_v_pixel), //垂直總像素大小 45 .init_done (cam_init_done) 46 ); 47 48 sccb u_sccb( 49 .clk (clk ), 50 .rst_n (rst_n ), 51 .sccb_exec (sccb_exec ), 52 .bit_ctrl (1'b1 ), 53 .sccb_rh_wl (sccb_rh_wl ), 54 .sub_addr (sccb_data[23:8]), 55 .wr_data (sccb_data[7:0] ), 56 .rd_data (sccb_data_r ), 57 .sccb_done (sccb_done ), 58 .sccb_ack ( ), 59 .scl (sio_c ), 60 .sda (sio_d ), 61 .dri_clk (sccb_dri_clk ) //sccb操作時鍾 62 ); 63 endmodule
六、信號抓取