【文章】OV5640摄像头及RGB图像数据采集
主页-old > 教程中心 > 案例中心 > 征集文章 >
2021-06-26 人气:  作者:admin

原创博客,转载请注明出处:FPGA配置OV5640摄像头及RGB图像数据采集 - 没落骑士 - 博客园
https://www.cnblogs.com/moluoqishi/p/9506706.html

本文设计思想采用明德扬至简设计法。在做摄像头数据采集处理之前,需要配置OV5640传感器内部寄存器使其按要求正常工作,详细内容请参见《OV5640自动对焦照相模组应用指南》。首先要关注OV5640的上电时序:


主控制器控制RESET PWDN两个信号按上电时序要求变化,之后允许ov_config模块配置内部寄存器。这里始终将PWDN拉低。实验中将摄像头分辨率设置为720p,即1280*720 ,帧率为30fps,图像输出格式是RGB565。此时摄像头输入时钟XCLK频率24MHz,输出像素时钟PCLK84MHz。由于实验使用的是OV5640双目摄像头模组,且XCLK由外部24MHz晶振给出,故ov_config模块整体结构及端口定义如下:

setup模块构造上电时序,两个reg_config分别配置一个OV5640摄像头。SCCB_interface子模块负责SCCB协议读写寄存器数据。由于OV5640摄像头内部寄存器地址为16位,因此写寄存器地址阶段分高低字节两次写入。datasheet中给出了OV5640SCCB ID地址(写),故读ID地址为0X79


SCCB时序图及AC characteristics如下:

SCCB时钟SIOC支持最大频率为400KHz,一般选100KHz即可。以下是本人设计的SCCB接口读写时序状态机,写操作:IDLE START WRI_ID WRI_REG WRI_DATA STOP 对应三相写,读操作:IDLE START WRI_ID WRI_REG STOP      START WRI_ID RD_DATA STOP对应两相写和两相读。


上代码:

SCCB读写模块:

  1 `timescale 1ns / 1ps
  2
  3
  4 module sccb_interface(
  5     input clk,
  6     input rst_n,
  7
  8     input wr_en,
  9     input rd_en,
 10     input [8-1:0] id_addr,
 11     input [16-1:0] reg_addr,
 12     input [8-1:0] wr_data,
 13     output reg [8-1:0] rd_data,
 14     output reg rd_vld,
 15     output rdy,
 16
 17     output reg sio_c,
 18     output reg sio_out_en,
 19     output reg sio_out,
 20     input sio_in
 21     );
 22
 23     parameter CYC = 500;
 24     
 25
 26 localparam  IDLE = 0 ;
 27 localparam  START = 1 ;
 28 localparam  WRI_ID = 2 ;
 29 localparam  WRI_REG = 3 ;
 30 localparam  WRI_DATA = 4;
 31 localparam  RD_DATA = 5;
 32 localparam  STOP = 6 ;
 33
 34 //计数器
 35 reg [ (9-1):0]  div_cnt     ;
 36 wire        add_div_cnt ;
 37 wire        end_div_cnt ;
 38 reg [ (5-1):0]  bit_cnt     ;
 39 wire        add_bit_cnt ;
 40 wire        end_bit_cnt ;
 41 reg [5-1:0] N;
 42 (*DONT_TOUCH = "TRUE"*)reg [7-1:0] state_c,state_n;
 43 wire idle2start,start2wri_id,wri_id2wri_reg,wri_id2rd_data, wri_reg2wri_data,wri_reg2stop,wri_data2stop,rd_data2stop,stop2start,stop2idle;
 44 wire [18-1:0] regaddr;
 45 reg [16-1:0] reg_addr_tmp;
 46 reg [8-1:0] wr_data_tmp;
 47 wire [9-1:0] idaddr_nc;
 48 reg [8-1:0] id_addr_tmp;
 49 reg rd_oper,rd_flag;
 50 wire [9-1:0] wdata_nc;
 51 wire [8-1:0] id_rwCtrl;
 52
 53
 54 assign rdy = state_c == IDLE && !wr_en && !rd_en;
 55
 56 always @(posedge clk or negedge rst_n) begin 
 57     if (rst_n==0) begin
 58         div_cnt <= 0; 
 59     end
 60     else if(add_div_cnt) begin
 61         if(end_div_cnt)
 62             div_cnt <= 0; 
 63         else
 64             div_cnt <= div_cnt+1 ;
 65    end
 66 end
 67 assign add_div_cnt = (state_c != IDLE);
 68 assign end_div_cnt = add_div_cnt  && div_cnt == (CYC)-1 ;//5000ns,200KHZ
 69
 70 always @(posedge clk or negedge rst_n) begin 
 71     if (rst_n==0) begin
 72         bit_cnt <= 0; 
 73     end
 74     else if(add_bit_cnt) begin
 75         if(end_bit_cnt)
 76             bit_cnt <= 0; 
 77         else
 78             bit_cnt <= bit_cnt+1 ;
 79    end
 80 end
 81 assign add_bit_cnt = (end_div_cnt);
 82 assign end_bit_cnt = add_bit_cnt  && bit_cnt == (N)-1 ;
 83
 84 always@(*)begin
 85     case(state_c)
 86         START:                  N = 1;
 87         WRI_REG:                N = 18; //(8+1)*2 = 18
 88         WRI_ID,WRI_DATA,RD_DATA:N = 9;//8+1
 89         STOP:                   N = 2;
 90         default:;
 91     endcase
 92 end
 93
 94 //FSM:IDLE START WRI_ID WRI_REG STOP
 95 always @(posedge clk or negedge rst_n) begin 
 96     if (rst_n==0) begin
 97         state_c <= IDLE ;
 98     end
 99     else begin
100         state_c <= state_n;
101    end
102 end
103 //write:IDLE START WRI_ID WRI_REG WRI_DATA STOP IDLE...
104 //read: IDLE START WRI_ID WRI_REG STOP      START WRI_ID RD_DATA STOP IDLE...
105
106 always @(*) begin 
107     case(state_c)  
108         IDLE :begin                             //0
109             if(idle2start) 
110                 state_n = START ;
111             else 
112                 state_n = state_c ;
113         end
114         START :begin                            //1
115             if(start2wri_id) 
116                 state_n = WRI_ID ;
117             else 
118                 state_n = state_c ;
119         end
120         WRI_ID :begin                           //2
121             if(wri_id2wri_reg) 
122                 state_n = WRI_REG ;
123             else if(wri_id2rd_data)
124                 state_n = RD_DATA;
125             else 
126                 state_n = state_c ;
127         end
128         WRI_REG :begin                          //3
129             if(wri_reg2wri_data)
130                 state_n = WRI_DATA;
131             else if(wri_reg2stop) 
132                 state_n = STOP ;
133             else 
134                 state_n = state_c ;
135         end
136         WRI_DATA:begin                          //4
137             if(wri_data2stop)
138                 state_n = STOP;
139             else 
140                 state_n = state_c;
141         end 
142         RD_DATA:begin                           //5
143             if(rd_data2stop)
144                 state_n = STOP;
145             else
146                 state_n = state_c;
147         end
148         STOP :begin                             //6
149             if(stop2start)
150                 state_n = START;
151             else if(stop2idle) 
152                 state_n = IDLE ;
153             else 
154                 state_n = state_c ;
155         end
156         default : state_n = IDLE ;
157     endcase
158 end
159
160 assign idle2start           = state_c==IDLE         && (wr_en || rd_en);
161 assign start2wri_id         = state_c==START        && (end_bit_cnt);
162 assign wri_id2wri_reg       = state_c==WRI_ID       && (end_bit_cnt && !rd_oper);
163 assign wri_id2rd_data       = state_c==WRI_ID       && (end_bit_cnt && rd_oper);
164 assign wri_reg2wri_data     = state_c==WRI_REG      && (end_bit_cnt && !rd_flag);
165 assign wri_reg2stop         = state_c==WRI_REG      && (end_bit_cnt && rd_flag);
166 assign wri_data2stop        = state_c==WRI_DATA     && (end_bit_cnt);
167 assign rd_data2stop         = state_c==RD_DATA      && (end_bit_cnt);
168 assign stop2start           = state_c==STOP         && (end_bit_cnt && rd_flag && !rd_oper);
169 assign stop2idle            = state_c==STOP         && (end_bit_cnt && (!rd_flag || rd_oper));
170
171 always  @(posedge clk or negedge rst_n)begin
172     if(rst_n==1'b0)begin
173         rd_oper <= 0;
174     end
175     else if(stop2start)begin
176         rd_oper <= 1;
177     end
178     else if(rd_oper && stop2idle)
179         rd_oper <= 0;
180 end
181
182 always  @(posedge clk or negedge rst_n)begin
183     if(rst_n==1'b0)begin
184         rd_flag <= 0;
185     end
186     else if(idle2start && rd_en)begin
187         rd_flag <= 1;
188     end
189     else if(stop2idle)
190         rd_flag <= 0;
191 end
192
193 //SCCB时钟
194 always  @(posedge clk or negedge rst_n)begin
195     if(rst_n==1'b0)
196         sio_c <= 1'b1;
197     else if(add_div_cnt && div_cnt == CYC/4-1)
198         sio_c <= 1;
199     else if(add_div_cnt && div_cnt == CYC/4+CYC/2-1)
200         sio_c <= 0;
201     else if(state_c == IDLE)
202         sio_c <= 1;//空闲状态sioc为1
203 end
204
205 always  @(posedge clk or negedge rst_n)begin
206     if(rst_n==1'b0)begin
207         sio_out <= 1;
208     end
209     else if(state_c == START && div_cnt == CYC/2-1)
210         sio_out <= 0;//开始条件
211     else if(state_c == WRI_ID)
212         sio_out <= idaddr_nc[9-1-bit_cnt];
213     else if(wri_reg2stop || wri_data2stop || rd_data2stop)
214         sio_out <= 0;
215     else if(state_c == WRI_REG)
216         sio_out <= regaddr[18-1-bit_cnt];
217     else if(state_c == WRI_DATA)
218         sio_out <= wdata_nc[9-1-bit_cnt];
219     else if(state_c == RD_DATA && bit_cnt == 9-1)
220         sio_out <= 1;//NACK
221     else if(state_c == STOP && div_cnt == CYC/2-1 && bit_cnt == 0)
222         sio_out <= 1;//结束条件
223 end
224
225 assign idaddr_nc = {id_rwCtrl,1'b1};
226 assign regaddr = {reg_addr_tmp[15:8],1'b1,reg_addr_tmp[7:0],1'b1};
227 assign wdata_nc = {wr_data_tmp,1'b1};
228
229 assign id_rwCtrl = rd_oper ? {id_addr[7:1],1'b1} : id_addr;
230
231 always  @(posedge clk or negedge rst_n)begin
232     if(rst_n==1'b0)begin
233         reg_addr_tmp <= 0;
234         wr_data_tmp <= 0;
235     end
236     else if(wr_en || rd_en)begin
237         reg_addr_tmp <= reg_addr;
238         wr_data_tmp <= wr_data;
239     end
240 end
241
242
243 always  @(posedge clk or negedge rst_n)begin
244     if(rst_n==1'b0)begin
245         sio_out_en <= 0;
246     end
247     else begin
248         case(state_c)
249             START,STOP:begin
250                 sio_out_en <= 1;
251             end
252             WRI_ID,WRI_DATA:begin
253                 if(bit_cnt != 9-1)
254                     sio_out_en <= 1;
255                 else
256                     sio_out_en <= 0;
257             end
258             WRI_REG:begin
259                 if(bit_cnt != 9-1 && bit_cnt != 18-1)
260                     sio_out_en <= 1;
261                 else
262                     sio_out_en <= 0;
263             end
264             RD_DATA:begin
265                 if(bit_cnt == 9-1)
266                     sio_out_en <= 1;
267                 else
268                     sio_out_en <= 0;
269             end 
270             default:sio_out_en <= 0;
271         endcase
272     end
273 end
274
275 //read data
276 always  @(posedge clk or negedge rst_n)begin
277     if(rst_n==1'b0)begin
278         rd_data <= 0;
279     end
280     else if(state_c == RD_DATA && bit_cnt != 9-1 && div_cnt == CYC/2-1)begin
281         rd_data[8-1-bit_cnt] <= sio_in;
282     end
283 end
284
285 always  @(posedge clk or negedge rst_n)begin
286     if(rst_n==1'b0)begin
287         rd_vld <= 0;
288     end
289     else if(rd_data2stop)begin
290         rd_vld <= 1;
291     end
292     else 
293         rd_vld <= 0;
294 end
295
296
297 endmodule
298
299
300

寄存器配置模块:

>   1 `timescale 1ns / 1ps
  2
  3
  4 module reg_config(
  5     input           clk,
  6     input           rst_n,
  7
  8     input           en,
  9     output          finish,
 10
 11     inout           sio_d,
 12     output          sio_c
 13     );
 14
 15 localparam WR_ID = 8'h78;
 16 localparam RW_CTRL = 2'b11;//读
 17 wire sio_out_en;
 18 wire sio_out;
 19 wire sio_in;
 20 reg [9-1:0] reg_cnt;
 21 wire add_reg_cnt,end_reg_cnt;
 22 reg config_flag;
 23 reg [26-1:0] op_reg_data;
 24 wire rdy;
 25 reg wr_en;
 26 reg [16-1:0] reg_addr;
 27 reg [8-1:0] wr_data;
 28 reg config_done;
 29 reg [ (2-1):0]  rw_cnt     ;
 30 wire        add_rw_cnt ;
 31 wire        end_rw_cnt ;
 32 reg rd_en;
 33 (*DONT_TOUCH = "TRUE"*)wire [8-1:0] rd_data;
 34 (*DONT_TOUCH = "TRUE"*)wire rd_vld;
 35
 36 sccb_interface sccb_interface(
 37     .clk    (clk) ,
 38     .rst_n     (rst_n) ,
 39     .wr_en     (wr_en) ,
 40     .rd_en     (rd_en),
 41     .id_addr   (WR_ID) ,
 42     .reg_addr  (reg_addr) ,
 43     .wr_data   (wr_data) ,
 44     .rd_data   (rd_data),
 45     .rd_vld    (rd_vld),
 46     .rdy       (rdy) ,
 47     .sio_c     (sio_c) ,
 48     .sio_out_en(sio_out_en) ,
 49     .sio_out   (sio_out) ,
 50     .sio_in    (sio_in) 
 51     );
 52
 53     assign sio_d = sio_out_en ? sio_out : 1'bz;
 54     assign sio_in = sio_d;
 55
 56     always @(posedge clk or negedge rst_n) begin 
 57         if (rst_n==0) begin
 58             rw_cnt <= 0; 
 59         end
 60         else if(add_rw_cnt) begin
 61             if(end_rw_cnt)
 62                 rw_cnt <= 0; 
 63             else
 64                 rw_cnt <= rw_cnt+1 ;
 65         end
 66     end
 67     assign add_rw_cnt = (config_flag && rdy);
 68     assign end_rw_cnt = add_rw_cnt  && rw_cnt == (2)-1 ;//0 write 1 read
 69
 70     always @(posedge clk or negedge rst_n)begin
 71         if(!rst_n)begin
 72             reg_cnt <= 0;
 73         end
 74         else if(add_reg_cnt)begin
 75             if(end_reg_cnt)
 76                 reg_cnt <= 0;
 77             else
 78                 reg_cnt <= reg_cnt + 1;
 79         end
 80     end
 81
 82     assign add_reg_cnt = end_rw_cnt;      
 83     assign end_reg_cnt = add_reg_cnt && reg_cnt == 261-1;  
 84
 85     //配置指令
 86     always  @(posedge clk or negedge rst_n)begin
 87         if(rst_n==1'b0)begin
 88             wr_en <= 0;
 89             reg_addr <= 0;
 90             wr_data <= 0;
 91         end
 92         else if(add_rw_cnt && rw_cnt == 0)begin
 93             wr_en    <= op_reg_data[25];
 94             reg_addr <= op_reg_data[23:8];
 95             wr_data  <= op_reg_data[7:0];
 96         end
 97         else if(end_rw_cnt)begin
 98             rd_en     <= op_reg_data[24];
 99             reg_addr  <= op_reg_data[23:8];
100         end
101         else begin
102             wr_en <= 0;
103             rd_en <= 0;
104         end
105     end
106
107
108     always  @(posedge clk or negedge rst_n)begin
109         if(rst_n==1'b0)begin
110             config_flag <= 0;
111         end
112         else if(en && !config_flag && !config_done)begin
113             config_flag <= 1;
114         end
115         else if(end_reg_cnt)
116             config_flag <= 0;
117     end
118
119     always  @(posedge clk or negedge rst_n)begin
120         if(rst_n==1'b0)begin
121             config_done <= 0;
122         end
123         else if(end_reg_cnt)begin
124             config_done <= 1;
125         end
126     end
127
128     assign finish = config_done && rdy;
129
130 always@(*)  
131  begin//op_reg_data [25] wr     [24] rd     [23:8] reg_addr     [7:0] wr_data    
132     case(reg_cnt)
133      //15fps VGA YUV output  // 24MHz input clock, 24MHz PCLK
134      0:op_reg_data=   {RW_CTRL, 24'h310311};// system clock from pad, bit[1]
135      1:op_reg_data=   {RW_CTRL, 24'h300882};// software reset, bit[7]// delay 5ms
136      2:op_reg_data=   {RW_CTRL, 24'h300842};// software power down, bit[6]
137      3:op_reg_data=   {RW_CTRL, 24'h310303};// system clock from PLL, bit[1]
138      4:op_reg_data=   {RW_CTRL, 24'h3017ff};// FREX, Vsync, HREF, PCLK, D[9:6] output enable
139      5:op_reg_data=   {RW_CTRL, 24'h3018ff};// D[5:0], GPIO[1:0] output enable
140      6:op_reg_data=   {RW_CTRL, 24'h30341A};// MIPI 10-bit
141      7:op_reg_data=   {RW_CTRL, 24'h303713};// PLL root divider, bit[4], PLL pre-divider, bit[3:0]
142      8:op_reg_data=   {RW_CTRL, 24'h310801};// PCLK root divider, bit[5:4], SCLK2x root divider, bit[3:2] // SCLK root divider, bit[1:0]
143      9:op_reg_data=   {RW_CTRL, 24'h363036};
144      10:op_reg_data=  {RW_CTRL, 24'h36310e};
145      11:op_reg_data=  {RW_CTRL, 24'h3632e2};
146      12:op_reg_data=  {RW_CTRL, 24'h363312};
147      13:op_reg_data=  {RW_CTRL, 24'h3621e0};
148      14:op_reg_data=  {RW_CTRL, 24'h3704a0};
149      15:op_reg_data=  {RW_CTRL, 24'h37035a};
150      16:op_reg_data=  {RW_CTRL, 24'h371578};
151      17:op_reg_data=  {RW_CTRL, 24'h371701};
152      18:op_reg_data=  {RW_CTRL, 24'h370b60};
153      19:op_reg_data=  {RW_CTRL, 24'h37051a};
154      20:op_reg_data=  {RW_CTRL, 24'h390502};
155      21:op_reg_data=  {RW_CTRL, 24'h390610};
156      22:op_reg_data=  {RW_CTRL, 24'h39010a};
157      23:op_reg_data=  {RW_CTRL, 24'h373112};
158      24:op_reg_data=  {RW_CTRL, 24'h360008};// VCM control
159      25:op_reg_data=  {RW_CTRL, 24'h360133};// VCM control
160      26:op_reg_data=  {RW_CTRL, 24'h302d60};// system control
161      27:op_reg_data=  {RW_CTRL, 24'h362052};
162      28:op_reg_data=  {RW_CTRL, 24'h371b20};
163      29:op_reg_data=  {RW_CTRL, 24'h471c50};
164      30:op_reg_data=  {RW_CTRL, 24'h3a1343};// pre-gain = 1.047x
165      31:op_reg_data=  {RW_CTRL, 24'h3a1800};// gain ceiling
166      32:op_reg_data=  {RW_CTRL, 24'h3a19f8};// gain ceiling = 15.5x
167      33:op_reg_data=  {RW_CTRL, 24'h363513};
168      34:op_reg_data=  {RW_CTRL, 24'h363603};
169      35:op_reg_data=  {RW_CTRL, 24'h363440};
170      36:op_reg_data=  {RW_CTRL, 24'h362201}; // 50/60Hz detection     50/60Hz 灯光条纹过滤
171      37:op_reg_data=  {RW_CTRL, 24'h3c0134};// Band auto, bit[7]
172      38:op_reg_data=  {RW_CTRL, 24'h3c0428};// threshold low sum    
173      39:op_reg_data=  {RW_CTRL, 24'h3c0598};// threshold high sum
174      40:op_reg_data=  {RW_CTRL, 24'h3c0600};// light meter 1 threshold[15:8]
175      41:op_reg_data=  {RW_CTRL, 24'h3c0708};// light meter 1 threshold[7:0]
176      42:op_reg_data=  {RW_CTRL, 24'h3c0800};// light meter 2 threshold[15:8]
177      43:op_reg_data=  {RW_CTRL, 24'h3c091c};// light meter 2 threshold[7:0]
178      44:op_reg_data=  {RW_CTRL, 24'h3c0a9c};// sample number[15:8]
179      45:op_reg_data=  {RW_CTRL, 24'h3c0b40};// sample number[7:0]
180      46:op_reg_data=  {RW_CTRL, 24'h381000};// Timing Hoffset[11:8]
181      47:op_reg_data=  {RW_CTRL, 24'h381110};// Timing Hoffset[7:0]
182      48:op_reg_data=  {RW_CTRL, 24'h381200};// Timing Voffset[10:8]
183      49:op_reg_data=  {RW_CTRL, 24'h370864};
184      50:op_reg_data=  {RW_CTRL, 24'h400102};// BLC start from line 2
185      51:op_reg_data=  {RW_CTRL, 24'h40051a};// BLC always update
186      52:op_reg_data=  {RW_CTRL, 24'h300000};// enable blocks
187      53:op_reg_data=  {RW_CTRL, 24'h3004ff};// enable clocks
188      54:op_reg_data=  {RW_CTRL, 24'h300e58};// MIPI power down, DVP enable
189      55:op_reg_data=  {RW_CTRL, 24'h302e00};
190      56:op_reg_data=  {RW_CTRL, 24'h430060};// RGB565
191      57:op_reg_data=  {RW_CTRL, 24'h501f01};// ISP RGB
192      58:op_reg_data=  {RW_CTRL, 24'h440e00};
193      59:op_reg_data=  {RW_CTRL, 24'h5000a7}; // Lenc on, raw gamma on, BPC on, WPC on, CIP on // AEC target    自动曝光控制
194      60:op_reg_data=  {RW_CTRL, 24'h3a0f30};// stable range in high
195      61:op_reg_data=  {RW_CTRL, 24'h3a1028};// stable range in low
196      62:op_reg_data=  {RW_CTRL, 24'h3a1b30};// stable range out high
197      63:op_reg_data=  {RW_CTRL, 24'h3a1e26};// stable range out low
198      64:op_reg_data=  {RW_CTRL, 24'h3a1160};// fast zone high
199      65:op_reg_data=  {RW_CTRL, 24'h3a1f14};// fast zone low// Lens correction for ?   镜头补偿
200      66:op_reg_data=  {RW_CTRL, 24'h580023};
201      67:op_reg_data=  {RW_CTRL, 24'h580114};
202      68:op_reg_data=  {RW_CTRL, 24'h58020f};
203      69:op_reg_data=  {RW_CTRL, 24'h58030f};
204      70:op_reg_data=  {RW_CTRL, 24'h580412};
205      71:op_reg_data=  {RW_CTRL, 24'h580526};
206      72:op_reg_data=  {RW_CTRL, 24'h58060c};
207      73:op_reg_data=  {RW_CTRL, 24'h580708};
208      74:op_reg_data=  {RW_CTRL, 24'h580805};
209      75:op_reg_data=  {RW_CTRL, 24'h580905};
210      76:op_reg_data=  {RW_CTRL, 24'h580a08};
211      77:op_reg_data=  {RW_CTRL, 24'h580b0d};
212      78:op_reg_data=  {RW_CTRL, 24'h580c08};
213      79:op_reg_data=  {RW_CTRL, 24'h580d03};
214      80:op_reg_data=  {RW_CTRL, 24'h580e00};
215      81:op_reg_data=  {RW_CTRL, 24'h580f00};
216      82:op_reg_data=  {RW_CTRL, 24'h581003};
217      83:op_reg_data=  {RW_CTRL, 24'h581109};
218      84:op_reg_data=  {RW_CTRL, 24'h581207};
219      85:op_reg_data=  {RW_CTRL, 24'h581303};
220      86:op_reg_data=  {RW_CTRL, 24'h581400};
221      87:op_reg_data=  {RW_CTRL, 24'h581501};
222      88:op_reg_data=  {RW_CTRL, 24'h581603};
223      89:op_reg_data=  {RW_CTRL, 24'h581708};
224      90:op_reg_data=  {RW_CTRL, 24'h58180d};
225      91:op_reg_data=  {RW_CTRL, 24'h581908};
226      92:op_reg_data=  {RW_CTRL, 24'h581a05};
227      93:op_reg_data=  {RW_CTRL, 24'h581b06};
228      94:op_reg_data=  {RW_CTRL, 24'h581c08};
229      95:op_reg_data=  {RW_CTRL, 24'h581d0e};
230      96:op_reg_data=  {RW_CTRL, 24'h581e29};
231      97:op_reg_data=  {RW_CTRL, 24'h581f17};
232      98:op_reg_data=  {RW_CTRL, 24'h582011};
233      99:op_reg_data=  {RW_CTRL, 24'h582111};
234      100:op_reg_data= {RW_CTRL, 24'h582215};
235      101:op_reg_data= {RW_CTRL, 24'h582328};
236      102:op_reg_data= {RW_CTRL, 24'h582446};
237      103:op_reg_data= {RW_CTRL, 24'h582526};
238      104:op_reg_data= {RW_CTRL, 24'h582608};
239      105:op_reg_data= {RW_CTRL, 24'h582726};
240      106:op_reg_data= {RW_CTRL, 24'h582864};
241      107:op_reg_data= {RW_CTRL, 24'h582926};
242      108:op_reg_data= {RW_CTRL, 24'h582a24};
243      109:op_reg_data= {RW_CTRL, 24'h582b22};
244      110:op_reg_data= {RW_CTRL, 24'h582c24};
245      111:op_reg_data= {RW_CTRL, 24'h582d24};
246      112:op_reg_data= {RW_CTRL, 24'h582e06};
247      113:op_reg_data= {RW_CTRL, 24'h582f22};
248      114:op_reg_data= {RW_CTRL, 24'h583040};
249      115:op_reg_data= {RW_CTRL, 24'h583142};
250      116:op_reg_data= {RW_CTRL, 24'h583224};
251      117:op_reg_data= {RW_CTRL, 24'h583326};
252      118:op_reg_data= {RW_CTRL, 24'h583424};
253      119:op_reg_data= {RW_CTRL, 24'h583522};
254      120:op_reg_data= {RW_CTRL, 24'h583622};
255      121:op_reg_data= {RW_CTRL, 24'h583726};
256      122:op_reg_data= {RW_CTRL, 24'h583844};
257      123:op_reg_data= {RW_CTRL, 24'h583924};
258      124:op_reg_data= {RW_CTRL, 24'h583a26};
259      125:op_reg_data= {RW_CTRL, 24'h583b28};
260      126:op_reg_data= {RW_CTRL, 24'h583c42};
261      127:op_reg_data= {RW_CTRL, 24'h583dce};// lenc BR offset // AWB   自动白平衡
262      128:op_reg_data= {RW_CTRL, 24'h5180ff};// AWB B block
263      129:op_reg_data= {RW_CTRL, 24'h5181f2};// AWB control
264      130:op_reg_data= {RW_CTRL, 24'h518200};// [7:4] max local counter, [3:0] max fast counter
265      131:op_reg_data= {RW_CTRL, 24'h518314};// AWB advanced
266      132:op_reg_data= {RW_CTRL, 24'h518425};
267      133:op_reg_data= {RW_CTRL, 24'h518524};
268      134:op_reg_data= {RW_CTRL, 24'h518609};
269      135:op_reg_data= {RW_CTRL, 24'h518709};
270      136:op_reg_data= {RW_CTRL, 24'h518809};
271      137:op_reg_data= {RW_CTRL, 24'h518975};
272      138:op_reg_data= {RW_CTRL, 24'h518a54};
273      139:op_reg_data= {RW_CTRL, 24'h518be0};
274      140:op_reg_data= {RW_CTRL, 24'h518cb2};
275      141:op_reg_data= {RW_CTRL, 24'h518d42};
276      142:op_reg_data= {RW_CTRL, 24'h518e3d};
277      143:op_reg_data= {RW_CTRL, 24'h518f56};
278      144:op_reg_data= {RW_CTRL, 24'h519046};
279      145:op_reg_data= {RW_CTRL, 24'h5191f8};// AWB top limit
280      146:op_reg_data= {RW_CTRL, 24'h519204};// AWB bottom limit
281      147:op_reg_data= {RW_CTRL, 24'h519370};// red limit
282      148:op_reg_data= {RW_CTRL, 24'h5194f0};// green limit
283      149:op_reg_data= {RW_CTRL, 24'h5195f0};// blue limit
284      150:op_reg_data= {RW_CTRL, 24'h519603};// AWB control
285      151:op_reg_data= {RW_CTRL, 24'h519701};// local limit
286      152:op_reg_data= {RW_CTRL, 24'h519804};
287      153:op_reg_data= {RW_CTRL, 24'h519912};
288      154:op_reg_data= {RW_CTRL, 24'h519a04};
289      155:op_reg_data= {RW_CTRL, 24'h519b00};
290      156:op_reg_data= {RW_CTRL, 24'h519c06};
291      157:op_reg_data= {RW_CTRL, 24'h519d82};
292      158:op_reg_data= {RW_CTRL, 24'h519e38};// AWB control // Gamma    伽玛曲线
293      159:op_reg_data= {RW_CTRL, 24'h548001};// Gamma bias plus on, bit[0]
294      160:op_reg_data= {RW_CTRL, 24'h548108};
295      161:op_reg_data= {RW_CTRL, 24'h548214};
296      162:op_reg_data= {RW_CTRL, 24'h548328};
297      163:op_reg_data= {RW_CTRL, 24'h548451};
298      164:op_reg_data= {RW_CTRL, 24'h548565};
299      165:op_reg_data= {RW_CTRL, 24'h548671};
300      166:op_reg_data= {RW_CTRL, 24'h54877d};
301      167:op_reg_data= {RW_CTRL, 24'h548887};
302      168:op_reg_data= {RW_CTRL, 24'h548991};
303      169:op_reg_data= {RW_CTRL, 24'h548a9a};
304      170:op_reg_data= {RW_CTRL, 24'h548baa};
305      171:op_reg_data= {RW_CTRL, 24'h548cb8};
306      172:op_reg_data= {RW_CTRL, 24'h548dcd};
307      173:op_reg_data= {RW_CTRL, 24'h548edd};
308      174:op_reg_data= {RW_CTRL, 24'h548fea};
309      175:op_reg_data= {RW_CTRL, 24'h54901d};// color matrix   色彩矩阵
310      176:op_reg_data= {RW_CTRL, 24'h53811e};// CMX1 for Y
311      177:op_reg_data= {RW_CTRL, 24'h53825b};// CMX2 for Y
312      178:op_reg_data= {RW_CTRL, 24'h538308};// CMX3 for Y
313      179:op_reg_data= {RW_CTRL, 24'h53840a};// CMX4 for U
314      180:op_reg_data= {RW_CTRL, 24'h53857e};// CMX5 for U
315      181:op_reg_data= {RW_CTRL, 24'h538688};// CMX6 for U
316      182:op_reg_data= {RW_CTRL, 24'h53877c};// CMX7 for V
317      183:op_reg_data= {RW_CTRL, 24'h53886c};// CMX8 for V
318      184:op_reg_data= {RW_CTRL, 24'h538910};// CMX9 for V
319      185:op_reg_data= {RW_CTRL, 24'h538a01};// sign[9]
320      186:op_reg_data= {RW_CTRL, 24'h538b98}; // sign[8:1] // UV adjust   UV色彩饱和度调整
321      187:op_reg_data= {RW_CTRL, 24'h558006};// saturation on, bit[1]
322      188:op_reg_data= {RW_CTRL, 24'h558340};
323      189:op_reg_data= {RW_CTRL, 24'h558410};
324      190:op_reg_data= {RW_CTRL, 24'h558910};
325      191:op_reg_data= {RW_CTRL, 24'h558a00};
326      192:op_reg_data= {RW_CTRL, 24'h558bf8};
327      193:op_reg_data= {RW_CTRL, 24'h501d40};// enable manual offset of contrast// CIP  锐化和降噪
328      194:op_reg_data= {RW_CTRL, 24'h530008};// CIP sharpen MT threshold 1
329      195:op_reg_data= {RW_CTRL, 24'h530130};// CIP sharpen MT threshold 2
330      196:op_reg_data= {RW_CTRL, 24'h530210};// CIP sharpen MT offset 1
331      197:op_reg_data= {RW_CTRL, 24'h530300};// CIP sharpen MT offset 2
332      198:op_reg_data= {RW_CTRL, 24'h530408};// CIP DNS threshold 1
333      199:op_reg_data= {RW_CTRL, 24'h530530};// CIP DNS threshold 2
334      200:op_reg_data= {RW_CTRL, 24'h530608};// CIP DNS offset 1
335      201:op_reg_data= {RW_CTRL, 24'h530716};// CIP DNS offset 2
336      202:op_reg_data= {RW_CTRL, 24'h530908};// CIP sharpen TH threshold 1
337      203:op_reg_data= {RW_CTRL, 24'h530a30};// CIP sharpen TH threshold 2
338      204:op_reg_data= {RW_CTRL, 24'h530b04};// CIP sharpen TH offset 1
339      205:op_reg_data= {RW_CTRL, 24'h530c06};// CIP sharpen TH offset 2
340      206:op_reg_data= {RW_CTRL, 24'h502500};
341      207:op_reg_data= {RW_CTRL, 24'h300802}; // wake up from standby, bit[6]
342     
343      //set OV5640 to video mode 720p
344      208:op_reg_data=  {RW_CTRL, 24'h303521};// PLL     input clock =24Mhz, PCLK =84Mhz
345      209:op_reg_data=  {RW_CTRL, 24'h303669};// PLL
346      210:op_reg_data=  {RW_CTRL, 24'h3c0707}; // lightmeter 1 threshold[7:0]
347      211:op_reg_data=  {RW_CTRL, 24'h382047}; // flip
348      212:op_reg_data=  {RW_CTRL, 24'h382100}; // mirror
349      213:op_reg_data=  {RW_CTRL, 24'h381431}; // timing X inc
350      214:op_reg_data=  {RW_CTRL, 24'h381531}; // timing Y inc
351      215:op_reg_data=  {RW_CTRL, 24'h380000}; // HS
352      216:op_reg_data=  {RW_CTRL, 24'h380100}; // HS
353      217:op_reg_data=  {RW_CTRL, 24'h380200}; // VS
354      218:op_reg_data=  {RW_CTRL, 24'h3803fa}; // VS
355      219:op_reg_data=  {RW_CTRL, 24'h38040a}; // HW (HE)
356      220:op_reg_data=  {RW_CTRL, 24'h38053f}; // HW (HE)
357      221:op_reg_data=  {RW_CTRL, 24'h380606}; // VH (VE)
358      222:op_reg_data=  {RW_CTRL, 24'h3807a9}; // VH (VE)
359      223:op_reg_data=  {RW_CTRL, 24'h380805}; // DVPHO     (1280)
360      224:op_reg_data=  {RW_CTRL, 24'h380900}; // DVPHO     (1280)
361      225:op_reg_data=  {RW_CTRL, 24'h380a02}; // DVPVO     (720)->
362      226:op_reg_data=  {RW_CTRL, 24'h380bd0}; // DVPVO     (720)->
363      227:op_reg_data=  {RW_CTRL, 24'h380c07}; // HTS
364      228:op_reg_data=  {RW_CTRL, 24'h380d64}; // HTS
365      229:op_reg_data=  {RW_CTRL, 24'h380e02}; // VTS
366      230:op_reg_data=  {RW_CTRL, 24'h380fe4}; // VTS
367      231:op_reg_data=  {RW_CTRL, 24'h381304}; // timing V offset
368      232:op_reg_data=  {RW_CTRL, 24'h361800};
369      233:op_reg_data=  {RW_CTRL, 24'h361229};
370      234:op_reg_data=  {RW_CTRL, 24'h370952};
371      235:op_reg_data=  {RW_CTRL, 24'h370c03};
372      236:op_reg_data=  {RW_CTRL, 24'h3a0202}; // 60Hz max exposure
373      237:op_reg_data=  {RW_CTRL, 24'h3a03e0}; // 60Hz max exposure
374      238:op_reg_data=  {RW_CTRL, 24'h3a0800}; // B50 step
375      239:op_reg_data=  {RW_CTRL, 24'h3a096f}; // B50 step
376      240:op_reg_data=  {RW_CTRL, 24'h3a0a00}; // B60 step
377      241:op_reg_data=  {RW_CTRL, 24'h3a0b5c}; // B60 step
378      242:op_reg_data=  {RW_CTRL, 24'h3a0e06}; // 50Hz max band
379      243:op_reg_data=  {RW_CTRL, 24'h3a0d08}; // 60Hz max band
380      244:op_reg_data=  {RW_CTRL, 24'h3a1402}; // 50Hz max exposure
381      245:op_reg_data=  {RW_CTRL, 24'h3a15e0}; // 50Hz max exposure
382      246:op_reg_data=  {RW_CTRL, 24'h400402}; // BLC line number
383      247:op_reg_data=  {RW_CTRL, 24'h30021c}; // reset JFIFO, SFIFO, JPG
384      248:op_reg_data=  {RW_CTRL, 24'h3006c3}; // disable clock of JPEG2x, JPEG
385      249:op_reg_data=  {RW_CTRL, 24'h471303}; // JPEG mode 3
386      250:op_reg_data=  {RW_CTRL, 24'h440704}; // Quantization sacle
387      251:op_reg_data=  {RW_CTRL, 24'h460b37};
388      252:op_reg_data=  {RW_CTRL, 24'h460c20};
389      253:op_reg_data=  {RW_CTRL, 24'h483716}; // MIPI global timing
390      254:op_reg_data=  {RW_CTRL, 24'h382404}; // PCLK manual divider
391      255:op_reg_data=  {RW_CTRL, 24'h5001a3}; // SDE on, CMX on, AWB on, scale on
392      256:op_reg_data=  {RW_CTRL, 24'h350300}; // AEC/AGC on
393      257:op_reg_data=  {RW_CTRL, 24'h301602}; //Strobe output enable
394      258:op_reg_data=  {RW_CTRL, 24'h3b070a}; //FREX strobe mode1    
395      //strobe flash and frame exposure      
396      259:op_reg_data={RW_CTRL, 24'h3b0083};              //STROBE CTRL: strobe request ON, Strobe mode: LED3
397      260:op_reg_data={RW_CTRL, 24'h3b0000};              //STROBE CTRL: strobe request OFF
398     
399      default:op_reg_data={RW_CTRL, 24'h000000};
400     endcase      
401 end    
402
403
404 endmodule
405

上电时序模块:

>   1 `timescale 1ns / 1ps
  2
  3
  4 module setup(
  5     input clk,//50MHZ
  6     input rst_n,
  7     output reg init_en,
  8
  9     output reg ov_pwdn1,
 10     output reg ov_rst_n1,
 11     output reg ov_pwdn2,
 12     output reg ov_rst_n2
 13     );
 14
 15 parameter MS_CYC = 50_000;
 16
 17 reg [16-1:0] ms_cnt;
 18 wire add_ms_cnt;
 19 wire end_ms_cnt;
 20 reg [ (5-1):0]  wait_cnt     ;
 21 wire        add_wait_cnt ;
 22 wire        end_wait_cnt ;
 23 reg [5-1:0] N;
 24 reg [ (2-1):0]  phase_cnt     ;
 25 wire        add_phase_cnt ;
 26 wire        end_phase_cnt ;
 27 reg setup_done;
 28
 29
 30     //ms计数
 31 always @(posedge clk or negedge rst_n)begin
 32     if(!rst_n)begin
 33         ms_cnt <= 0;
 34     end
 35     else if(add_ms_cnt)begin
 36         if(end_ms_cnt)
 37             ms_cnt <= 0;
 38         else
 39             ms_cnt <= ms_cnt + 1;
 40     end
 41 end
 42
 43 assign add_ms_cnt = !setup_done;      
 44 assign end_ms_cnt = add_ms_cnt && ms_cnt== MS_CYC-1; //1_000_000/20 = 50_000  
 45
 46 always @(posedge clk or negedge rst_n) begin 
 47     if (rst_n==0) begin
 48         wait_cnt <= 0; 
 49     end
 50     else if(add_wait_cnt) begin
 51         if(end_wait_cnt)
 52             wait_cnt <= 0; 
 53         else
 54             wait_cnt <= wait_cnt+1 ;
 55    end
 56 end
 57 assign add_wait_cnt = (end_ms_cnt);
 58 assign end_wait_cnt = add_wait_cnt  && wait_cnt == (N)-1 ;
 59
 60 always @(posedge clk or negedge rst_n) begin 
 61     if (rst_n==0) begin
 62         phase_cnt <= 0; 
 63     end
 64     else if(add_phase_cnt) begin
 65         if(end_phase_cnt)
 66             phase_cnt <= 0; 
 67         else
 68             phase_cnt <= phase_cnt+1 ;
 69    end
 70 end
 71 assign add_phase_cnt = (end_wait_cnt);
 72 assign end_phase_cnt = add_phase_cnt  && phase_cnt == (3)-1 ;
 73
 74 always  @(posedge clk or negedge rst_n)begin
 75     if(rst_n==1'b0)begin
 76         setup_done <= 0;
 77     end
 78     else if(end_phase_cnt)begin
 79         setup_done <= 1;
 80     end
 81 end
 82
 83
 84 always@(*)begin
 85     case(phase_cnt)
 86         0:N = 5;
 87         1:N = 2;
 88         2:N = 21;
 89         default:;
 90     endcase
 91 end
 92
 93 //信号逻辑
 94 always  @(posedge clk or negedge rst_n)begin
 95     if(rst_n==1'b0)begin
 96         ov_pwdn1 <= 1;
 97         ov_pwdn2 <= 1;
 98     end
 99     else if(add_phase_cnt && phase_cnt == 0)begin
100         ov_pwdn1 <= 0;
101         ov_pwdn2 <= 0;
102     end
103 end
104
105 always  @(posedge clk or negedge rst_n)begin
106     if(rst_n==1'b0)begin
107         ov_rst_n1 <= 0;
108         ov_rst_n2 <= 0;
109     end
110     else if(add_phase_cnt && phase_cnt == 1)begin
111         ov_rst_n1 <= 1;
112         ov_rst_n2 <= 1;
113     end
114 end
115
116 always  @(posedge clk or negedge rst_n)begin
117     if(rst_n==1'b0)begin
118         init_en <= 0;
119     end
120     else if(end_phase_cnt)begin
121         init_en <= 1;
122     end
123 end
124
125
126 endmodule


以下是生成原理图结构及仿真波形:



下面完成最重要的板级调试,先测试SCCB读,再测试SCCB写。



读状态下SIOD信号有响应,并非所有寄存器数据均为0,说明SCCB_interface模块将摄像头内部寄存器初始值读出。接下来把寄存器配置模块WR_CTRL设置为2'b11,检测读取数据是否与写入一致,从而进一步验证SCCB读写时序。



写入数据状态下,第9bit SIO_D信号被从机拉低,从机收到完整字节数据。这再次说明了SCCB的本质就是IIC。读取数据与写入数据基本一致,说明SCCB读写时序无误。现在在是PCLK时钟域下抓取VSYNC HREF DATA波形,ILA可以稳定启动并捕获到信号与DVP接口时序一致,此时摄像头正常工作。




配置完成后开始采集RGB数据。根据RGB565时序,每两个字节数据组成一个像素数据,因此采集输出过程中只需将PCLK时钟上升沿得到的两个数据拼接为16bit像素数据即可。


- 没落骑士 - 博客园

上一篇:【文章】FPGA驱动VGA显示静态图片
下一篇:【文章】DDS函数发生器环路Demo