本文设计思想采用明德扬至简设计法。在做摄像头数据采集处理之前,需要配置OV5640传感器内部寄存器使其按要求正常工作,详细内容请参见《OV5640自动对焦照相模组应用指南》。首先要关注OV5640的上电时序:
主控制器控制RESET PWDN两个信号按上电时序要求变化,之后允许ov_config模块配置内部寄存器。这里始终将PWDN拉低。实验中将摄像头分辨率设置为720p,即1280*720 ,帧率为30fps,图像输出格式是RGB565。此时摄像头输入时钟XCLK频率24MHz,输出像素时钟PCLK为84MHz。由于实验使用的是OV5640双目摄像头模组,且XCLK由外部24MHz晶振给出,故ov_config模块整体结构及端口定义如下:
setup模块构造上电时序,两个reg_config分别配置一个OV5640摄像头。SCCB_interface子模块负责SCCB协议读写寄存器数据。由于OV5640摄像头内部寄存器地址为16位,因此写寄存器地址阶段分高低字节两次写入。datasheet中给出了OV5640的SCCB 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
sccb_interface
寄存器配置模块:
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
reg_config
上电时序模块:
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
setup
以下是生成原理图结构及仿真波形:
下面完成最重要的板级调试,先测试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像素数据即可。
转载于:https://www.cnblogs.com/moluoqishi/p/9506706.html