FPGA利用SCCB协议配置OV5640摄像头

FPGA利用SCCB协议配置OV5640摄像头

为什么要配置摄像头

OV5640摄像头有许多工作模式,如可以工作在1080P,720P,480P分辨率的情况下,输出的数据格式也可以是RGB,RAW格式,也可以又DVP,MIPI数据接口,那么实际中我们应该如何指定摄像头的具体工作模式,以便于我们之后的处理。所使用的方法就是SCCB协议进行配置摄像头,前面的文章中我们已经介绍了SCCB协议与IIC协议的不同点,其中写协议是完全相同的,所以这里我们将利用SCCB协议进行OV5640的配置。

配置代码

这里我们前面已经讲过了IIC协议,这里将不再详细讲解SCCB协议的时序,因为他们两个几乎完全一样,不同点参考前面的文章,这里我们说明我们进行的摄像头配置是720P的分辨率,具体配置上面的哪种情况,可以查看数据手册,只需要更改特定的寄存器即可。
这里我们直接给出逻辑代码供同学们学习,大家可以学些外设寄存器配置的方法,主要分为两个.v文件,其中控制文件代码如下:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : 
// Module Name  : ov5640_cfg.v
// Create Time  : 2020-02-08 15:29:43
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module ov5640_cfg(
    //system signals
    input                   sclk            ,
    input                   rst_n           ,
    //iic interfaces
    output  wire            iic_sck         ,
    inout                   iic_sda         ,
    //others
    input                   power_done      ,
    output  reg             cfg_done    
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
localparam      ANUM        =   304             ;
//ov5640_sccb_inst
reg                         wr_flag             ;
wire                        wr_done             ;

//others
wire                [23:0]  cfg_array[ANUM-1:0] ;
reg                         power_done_r        ;
wire                        power_pos           ;
reg                 [ 8:0]  cnt_num             ;  
 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
assign  cfg_array[000]  =       {16'h3103, 8'h11};
assign  cfg_array[001]  =       {16'h3008, 8'h82};
assign  cfg_array[002]  =       {16'h3008, 8'h42};
assign  cfg_array[003]  =       {16'h3103, 8'h03};
assign  cfg_array[004]  =       {16'h3017, 8'hff};
assign  cfg_array[005]  =       {16'h3018, 8'hff};
assign  cfg_array[006]  =       {16'h3034, 8'h1A};
assign  cfg_array[007]  =       {16'h3037, 8'h13};       // PLL root divider, bit[4], PLL pre-divider, bit[3:0]
assign  cfg_array[008]  =       {16'h3108, 8'h01};       // PCLK root divider, bit[5:4], SCLK2x root divider, bit[3:2] // SCLK root divider, bit[1:0] 
assign  cfg_array[009]  =       {16'h3630, 8'h36};
                                      
assign  cfg_array[010]  =       {16'h3631, 8'h0e};
assign  cfg_array[011]  =       {16'h3632, 8'he2};
assign  cfg_array[012]  =       {16'h3633, 8'h12};
assign  cfg_array[013]  =       {16'h3621, 8'he0};
assign  cfg_array[014]  =       {16'h3704, 8'ha0};
assign  cfg_array[015]  =       {16'h3703, 8'h5a};
assign  cfg_array[016]  =       {16'h3715, 8'h78};
assign  cfg_array[017]  =       {16'h3717, 8'h01};
assign  cfg_array[018]  =       {16'h370b, 8'h60};
assign  cfg_array[019]  =       {16'h3705, 8'h1a};
                                    
assign  cfg_array[020]  =       {16'h3905, 8'h02};
assign  cfg_array[021]  =       {16'h3906, 8'h10};
assign  cfg_array[022]  =       {16'h3901, 8'h0a};
assign  cfg_array[023]  =       {16'h3731, 8'h12};
assign  cfg_array[024]  =       {16'h3600, 8'h08};
assign  cfg_array[025]  =       {16'h3601, 8'h33};
assign  cfg_array[026]  =       {16'h302d, 8'h60};
assign  cfg_array[027]  =       {16'h3620, 8'h52};
assign  cfg_array[028]  =       {16'h371b, 8'h20};
assign  cfg_array[029]  =       {16'h471c, 8'h50};
                                     
assign  cfg_array[030]  =       {16'h3a13, 8'h43};
assign  cfg_array[031]  =       {16'h3a18, 8'h00};
assign  cfg_array[032]  =       {16'h3a19, 8'hf8};
assign  cfg_array[033]  =       {16'h3635, 8'h13};
assign  cfg_array[034]  =       {16'h3636, 8'h03};
assign  cfg_array[035]  =       {16'h3634, 8'h40};
assign  cfg_array[036]  =       {16'h3622, 8'h01};
assign  cfg_array[037]  =       {16'h3c01, 8'h34};
assign  cfg_array[038]  =       {16'h3c04, 8'h28};
assign  cfg_array[039]  =       {16'h3c05, 8'h98};     
                                     
assign  cfg_array[040]  =       {16'h3c06, 8'h00};
assign  cfg_array[041]  =       {16'h3c07, 8'h08};
assign  cfg_array[042]  =       {16'h3c08, 8'h00};
assign  cfg_array[043]  =       {16'h3c09, 8'h1c};
assign  cfg_array[044]  =       {16'h3c0a, 8'h9c};
assign  cfg_array[045]  =       {16'h3c0b, 8'h40};
assign  cfg_array[046]  =       {16'h3810, 8'h00};
assign  cfg_array[047]  =       {16'h3811, 8'h10};
assign  cfg_array[048]  =       {16'h3812, 8'h00};
assign  cfg_array[049]  =       {16'h3708, 8'h64};
                                     
assign  cfg_array[050]  =       {16'h4001, 8'h02};
assign  cfg_array[051]  =       {16'h4005, 8'h1a};
assign  cfg_array[052]  =       {16'h3000, 8'h00};
assign  cfg_array[053]  =       {16'h3004, 8'hff};
assign  cfg_array[054]  =       {16'h300e, 8'h58};
assign  cfg_array[055]  =       {16'h302e, 8'h00};
assign  cfg_array[056]  =       {16'h4300, 8'h60};
assign  cfg_array[057]  =       {16'h501f, 8'h01};
assign  cfg_array[058]  =       {16'h440e, 8'h00};
assign  cfg_array[059]  =       {16'h5000, 8'ha7};    
                                      
assign  cfg_array[060]  =       {16'h3a0f, 8'h30};
assign  cfg_array[061]  =       {16'h3a10, 8'h28};
assign  cfg_array[062]  =       {16'h3a1b, 8'h30};
assign  cfg_array[063]  =       {16'h3a1e, 8'h26};
assign  cfg_array[064]  =       {16'h3a11, 8'h60};
assign  cfg_array[065]  =       {16'h3a1f, 8'h14};
assign  cfg_array[066]  =       {16'h5800, 8'h23};
assign  cfg_array[067]  =       {16'h5801, 8'h14};
assign  cfg_array[068]  =       {16'h5802, 8'h0f};
assign  cfg_array[069]  =       {16'h5803, 8'h0f};  
                                     
assign  cfg_array[070]  =       {16'h5804, 8'h12};
assign  cfg_array[071]  =       {16'h5805, 8'h26};
assign  cfg_array[072]  =       {16'h5806, 8'h0c};
assign  cfg_array[073]  =       {16'h5807, 8'h08};
assign  cfg_array[074]  =       {16'h5808, 8'h05};
assign  cfg_array[075]  =       {16'h5809, 8'h05};
assign  cfg_array[076]  =       {16'h580a, 8'h08};
assign  cfg_array[077]  =       {16'h580b, 8'h0d};
assign  cfg_array[078]  =       {16'h580c, 8'h08};
assign  cfg_array[079]  =       {16'h580d, 8'h03};    
                                   
assign  cfg_array[080]  =       {16'h580e, 8'h00};
assign  cfg_array[081]  =       {16'h580f, 8'h00};
assign  cfg_array[082]  =       {16'h5810, 8'h03};
assign  cfg_array[083]  =       {16'h5811, 8'h09};
assign  cfg_array[084]  =       {16'h5812, 8'h07};
assign  cfg_array[085]  =       {16'h5813, 8'h03};
assign  cfg_array[086]  =       {16'h5814, 8'h00};
assign  cfg_array[087]  =       {16'h5815, 8'h01};
assign  cfg_array[088]  =       {16'h5816, 8'h03};
assign  cfg_array[089]  =       {16'h5817, 8'h08};  
                                    
assign  cfg_array[090]  =       {16'h5818, 8'h0d};
assign  cfg_array[091]  =       {16'h5819, 8'h08};
assign  cfg_array[092]  =       {16'h581a, 8'h05};
assign  cfg_array[093]  =       {16'h581b, 8'h06};
assign  cfg_array[094]  =       {16'h581c, 8'h08};
assign  cfg_array[095]  =       {16'h581d, 8'h0e};
assign  cfg_array[096]  =       {16'h581e, 8'h29};
assign  cfg_array[097]  =       {16'h581f, 8'h17};
assign  cfg_array[098]  =       {16'h5820, 8'h11};
assign  cfg_array[099]  =       {16'h5821, 8'h11};     
                                       
assign  cfg_array[100]  =       {16'h5822, 8'h15};
assign  cfg_array[101]  =       {16'h5823, 8'h28};
assign  cfg_array[102]  =       {16'h5824, 8'h46};
assign  cfg_array[103]  =       {16'h5825, 8'h26};
assign  cfg_array[104]  =       {16'h5826, 8'h08};
assign  cfg_array[105]  =       {16'h5827, 8'h26};
assign  cfg_array[106]  =       {16'h5828, 8'h64};
assign  cfg_array[107]  =       {16'h5829, 8'h26};
assign  cfg_array[108]  =       {16'h582a, 8'h24};
assign  cfg_array[109]  =       {16'h582b, 8'h22};       
                                     
assign  cfg_array[110]  =       {16'h582c, 8'h24};
assign  cfg_array[111]  =       {16'h582d, 8'h24};
assign  cfg_array[112]  =       {16'h582e, 8'h06};
assign  cfg_array[113]  =       {16'h582f, 8'h22};
assign  cfg_array[114]  =       {16'h5830, 8'h40};
assign  cfg_array[115]  =       {16'h5831, 8'h42};
assign  cfg_array[116]  =       {16'h5832, 8'h24};
assign  cfg_array[117]  =       {16'h5833, 8'h26};
assign  cfg_array[118]  =       {16'h5834, 8'h24};
assign  cfg_array[119]  =       {16'h5835, 8'h22};        
                                     
assign  cfg_array[120]  =       {16'h5836, 8'h22};
assign  cfg_array[121]  =       {16'h5837, 8'h26};
assign  cfg_array[122]  =       {16'h5838, 8'h44};
assign  cfg_array[123]  =       {16'h5839, 8'h24};
assign  cfg_array[124]  =       {16'h583a, 8'h26};
assign  cfg_array[125]  =       {16'h583b, 8'h28};
assign  cfg_array[126]  =       {16'h583c, 8'h42};
assign  cfg_array[127]  =       {16'h583d, 8'hce};
assign  cfg_array[128]  =       {16'h5180, 8'hff};
assign  cfg_array[129]  =       {16'h5181, 8'hf2};   
                                     
assign  cfg_array[130]  =       {16'h5182, 8'h00};
assign  cfg_array[131]  =       {16'h5183, 8'h14};
assign  cfg_array[132]  =       {16'h5184, 8'h25};
assign  cfg_array[133]  =       {16'h5185, 8'h24};
assign  cfg_array[134]  =       {16'h5186, 8'h09};
assign  cfg_array[135]  =       {16'h5187, 8'h09};
assign  cfg_array[136]  =       {16'h5188, 8'h09};
assign  cfg_array[137]  =       {16'h5189, 8'h75};
assign  cfg_array[138]  =       {16'h518a, 8'h54};
assign  cfg_array[139]  =       {16'h518b, 8'he0};   
                                     
assign  cfg_array[140]  =       {16'h518c, 8'hb2};
assign  cfg_array[141]  =       {16'h518d, 8'h42};
assign  cfg_array[142]  =       {16'h518e, 8'h3d};
assign  cfg_array[143]  =       {16'h518f, 8'h56};
assign  cfg_array[144]  =       {16'h5190, 8'h46};
assign  cfg_array[145]  =       {16'h5191, 8'hf8};
assign  cfg_array[146]  =       {16'h5192, 8'h04};
assign  cfg_array[147]  =       {16'h5193, 8'h70};
assign  cfg_array[148]  =       {16'h5194, 8'hf0};
assign  cfg_array[149]  =       {16'h5195, 8'hf0};   
                                      
assign  cfg_array[150]  =       {16'h5196, 8'h03};
assign  cfg_array[151]  =       {16'h5197, 8'h01};
assign  cfg_array[152]  =       {16'h5198, 8'h04};
assign  cfg_array[153]  =       {16'h5199, 8'h12};
assign  cfg_array[154]  =       {16'h519a, 8'h04};
assign  cfg_array[155]  =       {16'h519b, 8'h00};
assign  cfg_array[156]  =       {16'h519c, 8'h06};
assign  cfg_array[157]  =       {16'h519d, 8'h82};
assign  cfg_array[158]  =       {16'h519e, 8'h38};
assign  cfg_array[159]  =       {16'h5480, 8'h01};   
                                      
assign  cfg_array[160]  =       {16'h5481, 8'h08};
assign  cfg_array[161]  =       {16'h5482, 8'h14};
assign  cfg_array[162]  =       {16'h5483, 8'h28};
assign  cfg_array[163]  =       {16'h5484, 8'h51};
assign  cfg_array[164]  =       {16'h5485, 8'h65};
assign  cfg_array[165]  =       {16'h5486, 8'h71};
assign  cfg_array[166]  =       {16'h5487, 8'h7d};
assign  cfg_array[167]  =       {16'h5488, 8'h87};
assign  cfg_array[168]  =       {16'h5489, 8'h91};
assign  cfg_array[169]  =       {16'h548a, 8'h9a};   
                                     
assign  cfg_array[170]  =       {16'h548b, 8'haa};
assign  cfg_array[171]  =       {16'h548c, 8'hb8};
assign  cfg_array[172]  =       {16'h548d, 8'hcd};
assign  cfg_array[173]  =       {16'h548e, 8'hdd};
assign  cfg_array[174]  =       {16'h548f, 8'hea};
assign  cfg_array[175]  =       {16'h5490, 8'h1d};
assign  cfg_array[176]  =       {16'h5381, 8'h1e};
assign  cfg_array[177]  =       {16'h5382, 8'h5b};
assign  cfg_array[178]  =       {16'h5383, 8'h08};
assign  cfg_array[179]  =       {16'h5384, 8'h0a};  
                                       
assign  cfg_array[180]  =       {16'h5385, 8'h7e};
assign  cfg_array[181]  =       {16'h5386, 8'h88};
assign  cfg_array[182]  =       {16'h5387, 8'h7c};
assign  cfg_array[183]  =       {16'h5388, 8'h6c};
assign  cfg_array[184]  =       {16'h5389, 8'h10};
assign  cfg_array[185]  =       {16'h538a, 8'h01};
assign  cfg_array[186]  =       {16'h538b, 8'h98};
assign  cfg_array[187]  =       {16'h5580, 8'h06};
assign  cfg_array[188]  =       {16'h5583, 8'h40};
assign  cfg_array[189]  =       {16'h5584, 8'h10};  
                                      
assign  cfg_array[190]  =       {16'h5589, 8'h10};
assign  cfg_array[191]  =       {16'h558a, 8'h00};
assign  cfg_array[192]  =       {16'h558b, 8'hf8};
assign  cfg_array[193]  =       {16'h501d, 8'h40};
assign  cfg_array[194]  =       {16'h5300, 8'h08};
assign  cfg_array[195]  =       {16'h5301, 8'h30};
assign  cfg_array[196]  =       {16'h5302, 8'h10};
assign  cfg_array[197]  =       {16'h5303, 8'h00};
assign  cfg_array[198]  =       {16'h5304, 8'h08};
assign  cfg_array[199]  =       {16'h5305, 8'h30};  
                                      
assign  cfg_array[200]  =       {16'h5306, 8'h08};
assign  cfg_array[201]  =       {16'h5307, 8'h16};
assign  cfg_array[202]  =       {16'h5309, 8'h08};
assign  cfg_array[203]  =       {16'h530a, 8'h30};
assign  cfg_array[204]  =       {16'h530b, 8'h04};
assign  cfg_array[205]  =       {16'h530c, 8'h06};
assign  cfg_array[206]  =       {16'h5025, 8'h00};
assign  cfg_array[207]  =       {16'h3008, 8'h02};
assign  cfg_array[208]  =       {16'h3035, 8'h11};
assign  cfg_array[209]  =       {16'h3036, 8'h46}; 
                                     
assign  cfg_array[210]  =       {16'h3c07, 8'h08};
assign  cfg_array[211]  =       {16'h3820, 8'h41};
assign  cfg_array[212]  =       {16'h3821, 8'h07};
assign  cfg_array[213]  =       {16'h3814, 8'h31};
assign  cfg_array[214]  =       {16'h3815, 8'h31};
assign  cfg_array[215]  =       {16'h3800, 8'h00};
assign  cfg_array[216]  =       {16'h3801, 8'h00};
assign  cfg_array[217]  =       {16'h3802, 8'h00};
assign  cfg_array[218]  =       {16'h3803, 8'h04};
assign  cfg_array[219]  =       {16'h3804, 8'h0a};  
                                    
assign  cfg_array[220]  =       {16'h3805, 8'h3f};
assign  cfg_array[221]  =       {16'h3806, 8'h07};
assign  cfg_array[222]  =       {16'h3807, 8'h9b};
assign  cfg_array[223]  =       {16'h3808, 8'h03};
assign  cfg_array[224]  =       {16'h3809, 8'h20};
assign  cfg_array[225]  =       {16'h380a, 8'h02};
assign  cfg_array[226]  =       {16'h380b, 8'h58};
assign  cfg_array[227]  =       {16'h380c, 8'h07};
assign  cfg_array[228]  =       {16'h380d, 8'h68};
assign  cfg_array[229]  =       {16'h380e, 8'h03}; 
                                     
assign  cfg_array[230]  =       {16'h380f, 8'hd8};
assign  cfg_array[231]  =       {16'h3813, 8'h06};
assign  cfg_array[232]  =       {16'h3618, 8'h00};
assign  cfg_array[233]  =       {16'h3612, 8'h29};
assign  cfg_array[234]  =       {16'h3709, 8'h52};
assign  cfg_array[235]  =       {16'h370c, 8'h03};
assign  cfg_array[236]  =       {16'h3a02, 8'h17};
assign  cfg_array[237]  =       {16'h3a03, 8'h10};
assign  cfg_array[238]  =       {16'h3a14, 8'h17};
assign  cfg_array[239]  =       {16'h3a15, 8'h10}; 
                                    
assign  cfg_array[240]  =       {16'h4004, 8'h02};
assign  cfg_array[241]  =       {16'h3002, 8'h1c};
assign  cfg_array[242]  =       {16'h3006, 8'hc3};
assign  cfg_array[243]  =       {16'h4713, 8'h03};
assign  cfg_array[244]  =       {16'h4407, 8'h04};
assign  cfg_array[245]  =       {16'h460b, 8'h35};
assign  cfg_array[246]  =       {16'h460c, 8'h22};
assign  cfg_array[247]  =       {16'h4837, 8'h22};
assign  cfg_array[248]  =       {16'h3824, 8'h02};
assign  cfg_array[249]  =       {16'h5001, 8'ha3}; 
                                     
assign  cfg_array[250]  =       {16'h3503, 8'h00};
assign  cfg_array[251]  =       {16'h3035, 8'h21};       // PLL     input clock =24Mhz, PCLK =84Mhz
assign  cfg_array[252]  =       {16'h3036, 8'h69};
assign  cfg_array[253]  =       {16'h3c07, 8'h07};
assign  cfg_array[254]  =       {16'h3820, 8'h47};
assign  cfg_array[255]  =       {16'h3821, 8'h07};
assign  cfg_array[256]  =       {16'h3814, 8'h31};
assign  cfg_array[257]  =       {16'h3815, 8'h31};
assign  cfg_array[258]  =       {16'h3800, 8'h00};       // HS
assign  cfg_array[259]  =       {16'h3801, 8'h00};       // HS
                                      
assign  cfg_array[260]  =       {16'h3802, 8'h00};       // VS
assign  cfg_array[261]  =       {16'h3803, 8'hfa};       // VS
assign  cfg_array[262]  =       {16'h3804, 8'h0a};       // HW (HE)
assign  cfg_array[263]  =       {16'h3805, 8'h3f};       // HW (HE)
assign  cfg_array[264]  =       {16'h3806, 8'h06};       // VH (VE)
assign  cfg_array[265]  =       {16'h3807, 8'ha9};       // VH (VE)
assign  cfg_array[266]  =       {16'h3808, 8'h04};       // DVPHO     (1024)
assign  cfg_array[267]  =       {16'h3809, 8'h00};       // DVPHO     (1024)
assign  cfg_array[268]  =       {16'h380a, 8'h02};       // DVPVO     (720)
assign  cfg_array[269]  =       {16'h380b, 8'hd0};       // DVPVO     (720)
                                     
assign  cfg_array[270]  =       {16'h380c, 8'h07};       // HTS       (1892)  1892*740*65 = 95334200  /  90994176
assign  cfg_array[271]  =       {16'h380d, 8'h64};       // HTS
assign  cfg_array[272]  =       {16'h380e, 8'h02};       // VTS       (740)
assign  cfg_array[273]  =       {16'h380f, 8'he4};       // VTS
assign  cfg_array[274]  =       {16'h3813, 8'h04};       // timing V offset
assign  cfg_array[275]  =       {16'h3618, 8'h00};
assign  cfg_array[276]  =       {16'h3612, 8'h29};
assign  cfg_array[277]  =       {16'h3709, 8'h52};
assign  cfg_array[278]  =       {16'h370c, 8'h03};
assign  cfg_array[279]  =       {16'h3a02, 8'h02}; 
                                       
assign  cfg_array[280]  =       {16'h3a03, 8'he0};
assign  cfg_array[281]  =       {16'h3a08, 8'h00};
assign  cfg_array[282]  =       {16'h3a09, 8'h6f};
assign  cfg_array[283]  =       {16'h3a0a, 8'h00};
assign  cfg_array[284]  =       {16'h3a0b, 8'h5c};
assign  cfg_array[285]  =       {16'h3a0e, 8'h06};
assign  cfg_array[286]  =       {16'h3a0d, 8'h08};
assign  cfg_array[287]  =       {16'h3a14, 8'h02};
assign  cfg_array[288]  =       {16'h3a15, 8'he0};
assign  cfg_array[289]  =       {16'h4004, 8'h02}; 
                                      
assign  cfg_array[290]  =       {16'h3002, 8'h1c};
assign  cfg_array[291]  =       {16'h3006, 8'hc3};
assign  cfg_array[292]  =       {16'h4713, 8'h03};
assign  cfg_array[293]  =       {16'h4407, 8'h04};
assign  cfg_array[294]  =       {16'h460b, 8'h37};
assign  cfg_array[295]  =       {16'h460c, 8'h20};
assign  cfg_array[296]  =       {16'h4837, 8'h16};
assign  cfg_array[297]  =       {16'h3824, 8'h04};       // PCLK manual divider
assign  cfg_array[298]  =       {16'h5001, 8'h83};
assign  cfg_array[299]  =       {16'h3503, 8'h00}; 
                                    
assign  cfg_array[300]  =       {16'h3016, 8'h02};
assign  cfg_array[301]  =       {16'h3b07, 8'h0a};
assign  cfg_array[302]  =       {16'h3b00, 8'h83};
assign  cfg_array[303]  =       {16'h3b00, 8'h00};

assign  power_pos       =       power_done && ~power_done_r;

always @(posedge sclk)
    power_done_r        <=      power_done;


always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        wr_flag         <=      1'b0;
    else if(power_pos == 1'b1 || (wr_done == 1'b1 && cnt_num < ANUM - 1'b1)) 
        wr_flag         <=      1'b1;
    else
        wr_flag         <=      1'b0;

always @(posedge sclk)
    if(rst_n == 1'b0)
        cnt_num         <=      9'd0;
    else if(cnt_num == ANUM - 1'b1 && wr_done == 1'b1)
        cnt_num         <=      9'd0;
    else if(wr_done == 1'b1)
        cnt_num         <=      cnt_num + 1'b1; 
    else
        cnt_num         <=      cnt_num;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cfg_done        <=      1'b0; 
    else if(cnt_num == ANUM - 1'b1 && wr_done == 1'b1) 
        cfg_done        <=      1'b1;
    else
        cfg_done        <=      cfg_done;

ov5640_sccb ov5640_sccb_inst(
    .sclk                   (sclk                       ),
    .rst_n                  (rst_n                      ),
    .wr_flag                (wr_flag                    ),
    .wr_data                (cfg_array[cnt_num][7:0]    ),
    .addr                   (cfg_array[cnt_num][23:8]   ),
    .wr_done                (wr_done                    ),
    .iic_sck                (iic_sck                    ),
    .iic_sda                (iic_sda                    )
);
endmodule

底层驱动代码如下:

`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : 
// Module Name  : ov5640_sccb.v
// Create Time  : 2020-02-08 15:24:58
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module ov5640_sccb(
    input                   sclk            ,
    input                   rst_n           ,
    input                   wr_flag         ,
    input           [ 7:0]  wr_data         ,
    input           [15:0]  addr            ,
    output  reg             wr_done         ,
    output  reg             iic_sck         ,
    inout                   iic_sda     
);
 
//========================================================================================\
//**************Define Parameter and  Internal Signals**********************************
//========================================================================================/
parameter  DIV_CNT      =   499             ;
parameter  DEVICE_ADDR  =   8'h78           ;

reg                         wr_busy         ;
reg                 [ 8:0]  cnt_500         ;
reg                 [ 5:0]  cnt_bit         ;
reg                         sda_oe          ;
reg                         iic_sda_r       ;


 
//========================================================================================\
//**************     Main      Code        **********************************
//========================================================================================/
assign  iic_sda         =       (sda_oe && !iic_sda_r) ? 1'b0:1'bz;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        wr_busy         <=      1'b0;
    else if(wr_flag == 1'b1)
        wr_busy         <=      1'b1;
    else if(wr_done == 1'b1)
        wr_busy         <=      1'b0;

always @(posedge sclk)
    if(rst_n == 1'b0)
        cnt_500         <=      8'd0;     
    else if(cnt_500 == DIV_CNT || wr_done == 1'b1)
        cnt_500         <=      8'd0;
    else if(wr_busy == 1'b1)
        cnt_500         <=      cnt_500 + 1'b1;
    else
        cnt_500         <=      cnt_500;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        cnt_bit         <=      5'd0;
    else if(wr_done == 1'b1)
        cnt_bit         <=      5'd0;
    else if(cnt_500 == DIV_CNT)
        cnt_bit         <=      cnt_bit + 1'b1;
    else 
        cnt_bit         <=      cnt_bit;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        iic_sck         <=      1'b1;
    else if(cnt_bit != 'd37 && cnt_500 == DIV_CNT/2)
        iic_sck         <=      1'b0;
    else if(cnt_500 == 'd0)
        iic_sck         <=      1'b1;
    else
        iic_sck         <=      iic_sck;

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        sda_oe          <=      1'b1;
    else if((cnt_bit == 8 || cnt_bit == 17 || cnt_bit == 26 || cnt_bit == 35) && cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
        sda_oe          <=      1'b0;
    else if((cnt_bit == 9 || cnt_bit == 18 || cnt_bit == 27|| cnt_bit == 36) && cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
        sda_oe          <=      1'b1;
    else
        sda_oe          <=      sda_oe;
          
always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        iic_sda_r       <=      1'b1;
    else case(cnt_bit)
        0   :               if(cnt_500 == (DIV_CNT/4))
                                iic_sda_r       <=      1'b0;
                            else if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      DEVICE_ADDR[7-cnt_bit];
                            else
                                iic_sda_r       <=      iic_sda_r;                                  
        1,2,3,4,5,6     :   if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      DEVICE_ADDR[7-cnt_bit];
                            else
                                iic_sda_r       <=      iic_sda_r;
        7               :   if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      1'b0;
                             else
                                iic_sda_r       <=      iic_sda_r;
        8               :   if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      1'b0;
                            else 
                                iic_sda_r       <=      iic_sda_r;
        9,10,11,12,13,14,15,16   :   
                            if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      addr[24-cnt_bit];
                            else
                                iic_sda_r       <=      iic_sda_r;
        17              :   if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      1'b0;
                            else 
                                iic_sda_r       <=      iic_sda_r;
        18,19,20,21,22,23,24,25 :
                            if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      addr[25-cnt_bit];
                            else
                                iic_sda_r       <=      iic_sda_r;
        26              :   if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      1'b0;
                            else 
                                iic_sda_r       <=      iic_sda_r;
        27,28,29,30,31,32,33,34 :
                            if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      wr_data[34-cnt_bit];
                            else
                                iic_sda_r       <=      iic_sda_r;
        35              :   if(cnt_500 == (DIV_CNT/2 + DIV_CNT/4))
                                iic_sda_r       <=      1'b0;
                            else 
                                iic_sda_r       <=      iic_sda_r;
        36              :   iic_sda_r       <=      iic_sda_r;
        37              :   if(cnt_500 == (DIV_CNT/4))
                                iic_sda_r       <=      1'b1;
        default         :   iic_sda_r       <=      1'b1;
    endcase 

always @(posedge sclk or negedge rst_n)
    if(rst_n == 1'b0)
        wr_done         <=      1'b0;
    else if(cnt_bit == 'd37 && cnt_500 == (DIV_CNT/2)) 
        wr_done         <=      1'b1;
    else
        wr_done         <=      1'b0;
        

endmodule

大家经过上面的代码学习,相信可以学会FPGA配置OV5640摄像头。

测试代码

经常看我文章的童鞋应该知道我的套路了,一般情况下一定会给出测试代码方便大家学习,这里我们也给出测试代码如下:

`timescale 1ns / 1ps
`define     CLOCK   20
// *********************************************************************************
// Project Name : OSXXXX
// Author       : zhangningning
// Email        : [email protected]
// Website      : 
// Module Name  : ov5640_cfg_tb.v
// Create Time  : 2020-02-08 16:08:57
// Editor       : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date             By              Version                 Change Description
// -----------------------------------------------------------------------
// XXXX       zhangningning          1.0                        Original
//  
// *********************************************************************************

module ov5640_cfg_tb;
reg                     sclk            ;
reg                     rst_n           ;
wire                    iic_sck         ;
wire                    iic_sda         ;
reg                     power_done      ;
wire                    cfg_done        ;

initial begin 
        sclk        =       1'b0;
        rst_n       <=      1'b0;
        power_done  <=      1'b0;
        #(100*`CLOCK);
        rst_n       <=      1'b1;
        #(10*`CLOCK);
        power_done  <=      1'b1;

end
always  #(`CLOCK/2)     sclk        =       ~sclk;


ov5640_cfg ov5640_cfg_inst(
    //system signals
    .sclk                   (sclk                   ),
    .rst_n                  (rst_n                  ),
    //iic interfaces
    .iic_sck                (iic_sck                ),
    .iic_sda                (iic_sda                ),
    //others
    .power_done             (power_done             ),
    .cfg_done               (cfg_done               )
);

endmodule

总结

创作不易,认为文章有帮助的同学们可以关注点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

发布了23 篇原创文章 · 获赞 9 · 访问量 5399

猜你喜欢

转载自blog.csdn.net/zhangningning1996/article/details/104227154