13. ov5640摄像头tft_lcd图像显示¶
在上面章节,我们实现了OV5640摄像头VGA、HDMI显示,在本章节我们实现OV5640摄像头TFT显示。
13.1. 理论学习¶
参照“OV5640摄像头VGA显示”的“理论学习”小节。
13.2. 实战演练¶
13.2.1. 实验目标¶
使用SDRAM做图像数据缓存,将OV5640摄像头采集到的图像数据在TFT显示屏上实时显示。分辨率480*272。
13.2.2. 硬件资源¶
参见“OV7725摄像头VGA图像显示”的“硬件资源”小节。
13.3. 程序设计¶
13.3.1. 整体说明¶
在本小节我们分两部分讲解一下实验工程的整体框架,第一部分是OV5640的相关模块,OV5640部分的整体框图和介绍,具体见图 63‑1、表格 63‑1。
图 63‑1 ov5640整体框图
表格 63‑1 OV5640各模块功能介绍
模块名称 |
功能描述 |
---|---|
ov5640_top |
OV5640顶层模块 |
i2c_ctrl |
i2c驱动模块 |
ov5640_cfg |
OV5640寄存器配置模块 |
ov5640_data |
OV5640图像采集模块 |
由上述图表可知,第一部分的OV5640相关模块包含4个子模块,首先是ov5640_top模块,这一模块作为ov5640部分的顶层模块,内部实例化3个子功能模块,连接各子模块对应信号,外部对摄像头进行相关配置并接收摄像头采集的数据信息;ov5640_cfg模块,是寄存器配置模块,内部包含对ov5640 摄像头的配置信息;i2c_ctrl模块,i2c协议与SCCB协议几乎无差别,使用i2c协议代替SCCB接口协议向ov7725摄像头写入ov7725_cfg模块内部包含的寄存器配置信息;ov5640_data模块,是ov5640摄像头的图像采集模块,将摄像头传入的图像数据处理后写入SDRAM。
第一部分介绍完毕后,我们来说一下实验工程的第二部分。在第二部分中将第一部分的ov5640摄像头部分视为一个子模块,与其他子功能模块构成整个实验工程。整体框图和子功能模块介绍,具体见图 63‑2、表格 63‑2。
图 63‑2 OV5640-tft图像显示整体框图
表格 63‑2 OV5640-VGA图像显示各子模块功能描述
模块名称 |
功能描述 |
---|---|
ov5640_tft_480x272 |
实验工程顶层模块 |
clk_gen |
时钟生成模块 |
ov5640_top |
OV5640相关部分 |
sdram_top |
SDRAM读写控制器 |
tft_ctrl |
tft驱动模块 |
由图表可知,OV5640-TFT图像显示工程包含表格模块,ov5640_tft_640x480作为实验工程的顶层模块,内部实例化各子功能模块,连接对应信号,对外接收摄像头采集的图像数据,将处理后的数据存入SDRAM,在TFT显示屏上显示出来;clk_gen模块,调用IP核生成,产生整个实验工程的工作 时钟;ov5640_top模块,是ov5640部分各子功能模块的集合,实现ov5640摄像头的配置、图像采集与处理;sdram_top模块为SDRAM读写控制器,存储处理后的图像数据;tft_ctrl模块实现TFT显示屏的驱动控制,读取SDRAM存储的图像数据并在TFT显示屏上显示出来。
到了这里,实验工程的整体框架我们介绍完毕,整体框架与“OV5640摄像头VGA显示”章节的实验工程框架类似,只是寄存器配置参数需要更改,以及使用tft驱动模块代替了VGA驱动模块。在此我们只简要说明一下改动较大的寄存器配置模块ov5640_cfg其他改动较小或未改动模块不再说明,读者可自行回顾前面相 关章节。
13.3.1.1. 寄存器配置模块¶
模块框图
寄存器配置模块框图,具体见图 63‑3;模块输入输出信号简介,具体见表格 63‑3。
图 63‑3 寄存器配置模块框图
表格 63‑3 寄存器配置模块输入输出信号简介
信号 |
位宽 |
类型 |
功能描述 |
---|---|---|---|
sys_rst_n |
1bit |
input |
复位信号,低有效 |
cfg_end |
1bit |
input |
一个寄存器配置完成 |
sys_clk |
1bit |
input |
模块工作时钟 |
cfg_start |
1bit |
output |
单个寄存器配置触发信号 |
cfg_data |
23bit |
output |
寄存器地址+数据 |
cfg_done |
1bit |
output |
寄存器配置完成信号 |
代码编写
要想OV5640摄像头正常工作,需要先对摄像头进行寄存器配置,即向摄像头寄存器写入对应指令。由于寄存器数量较多,在此我们只列出参考代码,各寄存器的相关内容,读者可翻阅数据手册进行学习。模块参考代码,具体见代码清单 63‑1。
代码清单 63‑1 寄存器配置模块参考代码(ov5640_cfg.v)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 | module ov5640_cfg
(
input wire sys_clk , //系统时钟,由iic模块传入
input wire sys_rst_n , //系统复位,低有效
input wire cfg_end , //单个寄存器配置完成
output reg cfg_start , //单个寄存器配置触发信号
output wire [23:0] cfg_data , //ID,REG_ADDR,REG_VAL
output reg cfg_done //寄存器配置完成
);
////
//\* Parameter and Internal Signal \//
////
//parameter define
parameter REG_NUM = 8'd251 ; //总共需要配置的寄存器个数
parameter CNT_WAIT_MAX = 10'd1023 ; //寄存器配置等待计数最大值
//wire define
wire [23:0] cfg_data_reg[REG_NUM-1:0] ; //寄存器配置数据暂存
//reg define
reg [9:0] cnt_wait ; //寄存器配置等待计数器
reg [7:0] reg_num ; //配置寄存器个数
////
//\* Main Code \//
////
//cnt_wait:寄存器配置等待计数器
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cnt_wait <= 15'd0;
else if(cnt_wait < CNT_WAIT_MAX)
cnt_wait <= cnt_wait + 1'b1;
//reg_num:配置寄存器个数
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
reg_num <= 8'd0;
else if(cfg_end == 1'b1)
reg_num <= reg_num + 1'b1;
//cfg_start:单个寄存器配置触发信号
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cfg_start <= 1'b0;
else if(cnt_wait == (CNT_WAIT_MAX - 1'b1))
cfg_start <= 1'b1;
else if((cfg_end == 1'b1) && (reg_num < REG_NUM))
cfg_start <= 1'b1;
else
cfg_start <= 1'b0;
//cfg_done:寄存器配置完成
always@(posedge sys_clk or negedge sys_rst_n)
if(sys_rst_n == 1'b0)
cfg_done <= 1'b0;
else if((reg_num == REG_NUM) && (cfg_end == 1'b1))
cfg_done <= 1'b1;
//cfg_data:ID,REG_ADDR,REG_VAL
assign cfg_data = (cfg_done == 1'b1) ? 24'b0 : cfg_data_reg[reg_num];
//----------------------------------------------------
//cfg_data_reg:寄存器配置数据暂存 ID REG_ADDR REG_VAL
assign cfg_data_reg[000] = {16'h3103, 8'h11};
assign cfg_data_reg[001] = {16'h3008, 8'h82};
assign cfg_data_reg[002] = {16'h3008, 8'h42};
assign cfg_data_reg[003] = {16'h3103, 8'h03};
assign cfg_data_reg[004] = {16'h3017, 8'hff};
assign cfg_data_reg[005] = {16'h3018, 8'hff};
assign cfg_data_reg[006] = {16'h3034, 8'h1A};
assign cfg_data_reg[007] = {16'h3037, 8'h13};
assign cfg_data_reg[008] = {16'h3108, 8'h01};
assign cfg_data_reg[009] = {16'h3630, 8'h36};
assign cfg_data_reg[010] = {16'h3631, 8'h0e};
assign cfg_data_reg[011] = {16'h3632, 8'he2};
assign cfg_data_reg[012] = {16'h3633, 8'h12};
assign cfg_data_reg[013] = {16'h3621, 8'he0};
assign cfg_data_reg[014] = {16'h3704, 8'ha0};
assign cfg_data_reg[015] = {16'h3703, 8'h5a};
assign cfg_data_reg[016] = {16'h3715, 8'h78};
assign cfg_data_reg[017] = {16'h3717, 8'h01};
assign cfg_data_reg[018] = {16'h370b, 8'h60};
assign cfg_data_reg[019] = {16'h3705, 8'h1a};
assign cfg_data_reg[020] = {16'h3905, 8'h02};
assign cfg_data_reg[021] = {16'h3906, 8'h10};
assign cfg_data_reg[022] = {16'h3901, 8'h0a};
assign cfg_data_reg[023] = {16'h3731, 8'h12};
assign cfg_data_reg[024] = {16'h3600, 8'h08};
assign cfg_data_reg[025] = {16'h3601, 8'h33};
assign cfg_data_reg[026] = {16'h302d, 8'h60};
assign cfg_data_reg[027] = {16'h3620, 8'h52};
assign cfg_data_reg[028] = {16'h371b, 8'h20};
assign cfg_data_reg[029] = {16'h471c, 8'h50};
assign cfg_data_reg[030] = {16'h3a13, 8'h43};
assign cfg_data_reg[031] = {16'h3a18, 8'h00};
assign cfg_data_reg[032] = {16'h3a19, 8'hf8};
assign cfg_data_reg[033] = {16'h3635, 8'h13};
assign cfg_data_reg[034] = {16'h3636, 8'h03};
assign cfg_data_reg[035] = {16'h3634, 8'h40};
assign cfg_data_reg[036] = {16'h3622, 8'h01};
assign cfg_data_reg[037] = {16'h3c01, 8'h34};
assign cfg_data_reg[038] = {16'h3c04, 8'h28};
assign cfg_data_reg[039] = {16'h3c05, 8'h98};
assign cfg_data_reg[040] = {16'h3c06, 8'h00};
assign cfg_data_reg[041] = {16'h3c07, 8'h08};
assign cfg_data_reg[042] = {16'h3c08, 8'h00};
assign cfg_data_reg[043] = {16'h3c09, 8'h1c};
assign cfg_data_reg[044] = {16'h3c0a, 8'h9c};
assign cfg_data_reg[045] = {16'h3c0b, 8'h40};
assign cfg_data_reg[046] = {16'h3810, 8'h00};
assign cfg_data_reg[047] = {16'h3811, 8'h10};
assign cfg_data_reg[048] = {16'h3812, 8'h00};
assign cfg_data_reg[049] = {16'h3708, 8'h64};
assign cfg_data_reg[050] = {16'h4001, 8'h02};
assign cfg_data_reg[051] = {16'h4005, 8'h1a};
assign cfg_data_reg[052] = {16'h3000, 8'h00};
assign cfg_data_reg[053] = {16'h3004, 8'hff};
assign cfg_data_reg[054] = {16'h300e, 8'h58};
assign cfg_data_reg[055] = {16'h302e, 8'h00};
assign cfg_data_reg[056] = {16'h4300, 8'h61};
assign cfg_data_reg[057] = {16'h501f, 8'h01};
assign cfg_data_reg[058] = {16'h440e, 8'h00};
assign cfg_data_reg[059] = {16'h5000, 8'ha7};
assign cfg_data_reg[060] = {16'h3a0f, 8'h30};
assign cfg_data_reg[061] = {16'h3a10, 8'h28};
assign cfg_data_reg[062] = {16'h3a1b, 8'h30};
assign cfg_data_reg[063] = {16'h3a1e, 8'h26};
assign cfg_data_reg[064] = {16'h3a11, 8'h60};
assign cfg_data_reg[065] = {16'h3a1f, 8'h14};
assign cfg_data_reg[066] = {16'h5800, 8'h23};
assign cfg_data_reg[067] = {16'h5801, 8'h14};
assign cfg_data_reg[068] = {16'h5802, 8'h0f};
assign cfg_data_reg[069] = {16'h5803, 8'h0f};
assign cfg_data_reg[070] = {16'h5804, 8'h12};
assign cfg_data_reg[071] = {16'h5805, 8'h26};
assign cfg_data_reg[072] = {16'h5806, 8'h0c};
assign cfg_data_reg[073] = {16'h5807, 8'h08};
assign cfg_data_reg[074] = {16'h5808, 8'h05};
assign cfg_data_reg[075] = {16'h5809, 8'h05};
assign cfg_data_reg[076] = {16'h580a, 8'h08};
assign cfg_data_reg[077] = {16'h580b, 8'h0d};
assign cfg_data_reg[078] = {16'h580c, 8'h08};
assign cfg_data_reg[079] = {16'h580d, 8'h03};
assign cfg_data_reg[080] = {16'h580e, 8'h00};
assign cfg_data_reg[081] = {16'h580f, 8'h00};
assign cfg_data_reg[082] = {16'h5810, 8'h03};
assign cfg_data_reg[083] = {16'h5811, 8'h09};
assign cfg_data_reg[084] = {16'h5812, 8'h07};
assign cfg_data_reg[085] = {16'h5813, 8'h03};
assign cfg_data_reg[086] = {16'h5814, 8'h00};
assign cfg_data_reg[087] = {16'h5815, 8'h01};
assign cfg_data_reg[088] = {16'h5816, 8'h03};
assign cfg_data_reg[089] = {16'h5817, 8'h08};
assign cfg_data_reg[090] = {16'h5818, 8'h0d};
assign cfg_data_reg[091] = {16'h5819, 8'h08};
assign cfg_data_reg[092] = {16'h581a, 8'h05};
assign cfg_data_reg[093] = {16'h581b, 8'h06};
assign cfg_data_reg[094] = {16'h581c, 8'h08};
assign cfg_data_reg[095] = {16'h581d, 8'h0e};
assign cfg_data_reg[096] = {16'h581e, 8'h29};
assign cfg_data_reg[097] = {16'h581f, 8'h17};
assign cfg_data_reg[098] = {16'h5820, 8'h11};
assign cfg_data_reg[099] = {16'h5821, 8'h11};
assign cfg_data_reg[100] = {16'h5822, 8'h15};
assign cfg_data_reg[101] = {16'h5823, 8'h28};
assign cfg_data_reg[102] = {16'h5824, 8'h46};
assign cfg_data_reg[103] = {16'h5825, 8'h26};
assign cfg_data_reg[104] = {16'h5826, 8'h08};
assign cfg_data_reg[105] = {16'h5827, 8'h26};
assign cfg_data_reg[106] = {16'h5828, 8'h64};
assign cfg_data_reg[107] = {16'h5829, 8'h26};
assign cfg_data_reg[108] = {16'h582a, 8'h24};
assign cfg_data_reg[109] = {16'h582b, 8'h22};
assign cfg_data_reg[110] = {16'h582c, 8'h24};
assign cfg_data_reg[111] = {16'h582d, 8'h24};
assign cfg_data_reg[112] = {16'h582e, 8'h06};
assign cfg_data_reg[113] = {16'h582f, 8'h22};
assign cfg_data_reg[114] = {16'h5830, 8'h40};
assign cfg_data_reg[115] = {16'h5831, 8'h42};
assign cfg_data_reg[116] = {16'h5832, 8'h24};
assign cfg_data_reg[117] = {16'h5833, 8'h26};
assign cfg_data_reg[118] = {16'h5834, 8'h24};
assign cfg_data_reg[119] = {16'h5835, 8'h22};
assign cfg_data_reg[120] = {16'h5836, 8'h22};
assign cfg_data_reg[121] = {16'h5837, 8'h26};
assign cfg_data_reg[122] = {16'h5838, 8'h44};
assign cfg_data_reg[123] = {16'h5839, 8'h24};
assign cfg_data_reg[124] = {16'h583a, 8'h26};
assign cfg_data_reg[125] = {16'h583b, 8'h28};
assign cfg_data_reg[126] = {16'h583c, 8'h42};
assign cfg_data_reg[127] = {16'h583d, 8'hce};
assign cfg_data_reg[128] = {16'h5180, 8'hff};
assign cfg_data_reg[129] = {16'h5181, 8'hf2};
assign cfg_data_reg[130] = {16'h5182, 8'h00};
assign cfg_data_reg[131] = {16'h5183, 8'h14};
assign cfg_data_reg[132] = {16'h5184, 8'h25};
assign cfg_data_reg[133] = {16'h5185, 8'h24};
assign cfg_data_reg[134] = {16'h5186, 8'h09};
assign cfg_data_reg[135] = {16'h5187, 8'h09};
assign cfg_data_reg[136] = {16'h5188, 8'h09};
assign cfg_data_reg[137] = {16'h5189, 8'h75};
assign cfg_data_reg[138] = {16'h518a, 8'h54};
assign cfg_data_reg[139] = {16'h518b, 8'he0};
assign cfg_data_reg[140] = {16'h518c, 8'hb2};
assign cfg_data_reg[141] = {16'h518d, 8'h42};
assign cfg_data_reg[142] = {16'h518e, 8'h3d};
assign cfg_data_reg[143] = {16'h518f, 8'h56};
assign cfg_data_reg[144] = {16'h5190, 8'h46};
assign cfg_data_reg[145] = {16'h5191, 8'hf8};
assign cfg_data_reg[146] = {16'h5192, 8'h04};
assign cfg_data_reg[147] = {16'h5193, 8'h70};
assign cfg_data_reg[148] = {16'h5194, 8'hf0};
assign cfg_data_reg[149] = {16'h5195, 8'hf0};
assign cfg_data_reg[150] = {16'h5196, 8'h03};
assign cfg_data_reg[151] = {16'h5197, 8'h01};
assign cfg_data_reg[152] = {16'h5198, 8'h04};
assign cfg_data_reg[153] = {16'h5199, 8'h12};
assign cfg_data_reg[154] = {16'h519a, 8'h04};
assign cfg_data_reg[155] = {16'h519b, 8'h00};
assign cfg_data_reg[156] = {16'h519c, 8'h06};
assign cfg_data_reg[157] = {16'h519d, 8'h82};
assign cfg_data_reg[158] = {16'h519e, 8'h38};
assign cfg_data_reg[159] = {16'h5480, 8'h01};
assign cfg_data_reg[160] = {16'h5481, 8'h08};
assign cfg_data_reg[161] = {16'h5482, 8'h14};
assign cfg_data_reg[162] = {16'h5483, 8'h28};
assign cfg_data_reg[163] = {16'h5484, 8'h51};
assign cfg_data_reg[164] = {16'h5485, 8'h65};
assign cfg_data_reg[165] = {16'h5486, 8'h71};
assign cfg_data_reg[166] = {16'h5487, 8'h7d};
assign cfg_data_reg[167] = {16'h5488, 8'h87};
assign cfg_data_reg[168] = {16'h5489, 8'h91};
assign cfg_data_reg[169] = {16'h548a, 8'h9a};
assign cfg_data_reg[170] = {16'h548b, 8'haa};
assign cfg_data_reg[171] = {16'h548c, 8'hb8};
assign cfg_data_reg[172] = {16'h548d, 8'hcd};
assign cfg_data_reg[173] = {16'h548e, 8'hdd};
assign cfg_data_reg[174] = {16'h548f, 8'hea};
assign cfg_data_reg[175] = {16'h5490, 8'h1d};
assign cfg_data_reg[176] = {16'h5381, 8'h1e};
assign cfg_data_reg[177] = {16'h5382, 8'h5b};
assign cfg_data_reg[178] = {16'h5383, 8'h08};
assign cfg_data_reg[179] = {16'h5384, 8'h0a};
assign cfg_data_reg[180] = {16'h5385, 8'h7e};
assign cfg_data_reg[181] = {16'h5386, 8'h88};
assign cfg_data_reg[182] = {16'h5387, 8'h7c};
assign cfg_data_reg[183] = {16'h5388, 8'h6c};
assign cfg_data_reg[184] = {16'h5389, 8'h10};
assign cfg_data_reg[185] = {16'h538a, 8'h01};
assign cfg_data_reg[186] = {16'h538b, 8'h98};
assign cfg_data_reg[187] = {16'h5580, 8'h06};
assign cfg_data_reg[188] = {16'h5583, 8'h40};
assign cfg_data_reg[189] = {16'h5584, 8'h10};
assign cfg_data_reg[190] = {16'h5589, 8'h10};
assign cfg_data_reg[191] = {16'h558a, 8'h00};
assign cfg_data_reg[192] = {16'h558b, 8'hf8};
assign cfg_data_reg[193] = {16'h501d, 8'h40};
assign cfg_data_reg[194] = {16'h5300, 8'h08};
assign cfg_data_reg[195] = {16'h5301, 8'h30};
assign cfg_data_reg[196] = {16'h5302, 8'h10};
assign cfg_data_reg[197] = {16'h5303, 8'h00};
assign cfg_data_reg[198] = {16'h5304, 8'h08};
assign cfg_data_reg[199] = {16'h5305, 8'h30};
assign cfg_data_reg[200] = {16'h5306, 8'h08};
assign cfg_data_reg[201] = {16'h5307, 8'h16};
assign cfg_data_reg[202] = {16'h5309, 8'h08};
assign cfg_data_reg[203] = {16'h530a, 8'h30};
assign cfg_data_reg[204] = {16'h530b, 8'h04};
assign cfg_data_reg[205] = {16'h530c, 8'h06};
assign cfg_data_reg[206] = {16'h5025, 8'h00};
assign cfg_data_reg[207] = {16'h3008, 8'h02};
assign cfg_data_reg[208] = {16'h3035, 8'h11};
assign cfg_data_reg[209] = {16'h3036, 8'h46};
assign cfg_data_reg[210] = {16'h3c07, 8'h08};
assign cfg_data_reg[211] = {16'h3820, 8'h47};
assign cfg_data_reg[212] = {16'h3821, 8'h00};
assign cfg_data_reg[213] = {16'h3814, 8'h31};
assign cfg_data_reg[214] = {16'h3815, 8'h31};
assign cfg_data_reg[215] = {16'h3800, 8'h00};
assign cfg_data_reg[216] = {16'h3801, 8'h00};
assign cfg_data_reg[217] = {16'h3802, 8'h00};
assign cfg_data_reg[218] = {16'h3803, 8'h04};
assign cfg_data_reg[219] = {16'h3804, 8'h0a};
assign cfg_data_reg[220] = {16'h3805, 8'h3f};
assign cfg_data_reg[221] = {16'h3806, 8'h07};
assign cfg_data_reg[222] = {16'h3807, 8'h9b};
assign cfg_data_reg[223] = {16'h3808, 8'h01};
assign cfg_data_reg[224] = {16'h3809, 8'he0};
assign cfg_data_reg[225] = {16'h380a, 8'h01};
assign cfg_data_reg[226] = {16'h380b, 8'h10};
assign cfg_data_reg[227] = {16'h380c, 8'h07};
assign cfg_data_reg[228] = {16'h380d, 8'h68};
assign cfg_data_reg[229] = {16'h380e, 8'h03};
assign cfg_data_reg[230] = {16'h380f, 8'hd8};
assign cfg_data_reg[231] = {16'h3813, 8'h06};
assign cfg_data_reg[232] = {16'h3618, 8'h00};
assign cfg_data_reg[233] = {16'h3612, 8'h29};
assign cfg_data_reg[234] = {16'h3709, 8'h52};
assign cfg_data_reg[235] = {16'h370c, 8'h03};
assign cfg_data_reg[236] = {16'h3a02, 8'h17};
assign cfg_data_reg[237] = {16'h3a03, 8'h10};
assign cfg_data_reg[238] = {16'h3a14, 8'h17};
assign cfg_data_reg[239] = {16'h3a15, 8'h10};
assign cfg_data_reg[240] = {16'h4004, 8'h02};
assign cfg_data_reg[241] = {16'h3002, 8'h1c};
assign cfg_data_reg[242] = {16'h3006, 8'hc3};
assign cfg_data_reg[243] = {16'h4713, 8'h03};
assign cfg_data_reg[244] = {16'h4407, 8'h04};
assign cfg_data_reg[245] = {16'h460b, 8'h35};
assign cfg_data_reg[246] = {16'h460c, 8'h22};
assign cfg_data_reg[247] = {16'h4837, 8'h22};
assign cfg_data_reg[248] = {16'h3824, 8'h02};
assign cfg_data_reg[249] = {16'h5001, 8'ha3};
assign cfg_data_reg[250] = {16'h3503, 8'h00};
//-------------------------------------------------------
endmodule
|
13.3.1.2. 顶层模块¶
顶层模块部分只列出参考代码,不再进行模块框图讲解和波形图的绘制,参考代码具体见代码清单 63‑2。
代码清单 63‑2 顶层模块参考代码(ov5640_vga_480x272.v)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 | module ov5640_tft_480x272
(
input wire sys_clk , //系统时钟
input wire sys_rst_n , //系统复位,低电平有效
//摄像头接口
input wire ov5640_pclk , //摄像头数据像素时钟
input wire ov5640_vsync, //摄像头场同步信号
input wire ov5640_href , //摄像头行同步信号
input wire [7:0] ov5640_data , //摄像头数据
output wire ov5640_rst_n, //摄像头复位信号,低电平有效
output wire ov5640_pwdn , //摄像头时钟选择信号, 1:使用摄像头自带的晶振
output wire sccb_scl , //摄像头SCCB_SCL线
inout wire sccb_sda , //摄像头SCCB_SDA线
//SDRAM接口
output wire sdram_clk , //SDRAM 时钟
output wire sdram_cke , //SDRAM 时钟使能
output wire sdram_cs_n , //SDRAM 片选
output wire sdram_ras_n , //SDRAM 行有效
output wire sdram_cas_n , //SDRAM 列有效
output wire sdram_we_n , //SDRAM 写有效
output wire [1:0] sdram_ba , //SDRAM Bank地址
output wire [1:0] sdram_dqm , //SDRAM 数据掩码
output wire [12:0] sdram_addr , //SDRAM 地址
inout wire [15:0] sdram_dq , //SDRAM 数据
//VGA接口
output wire tft_clk ,
output wire tft_de ,
output wire tft_bl ,
output wire tft_hs , //行同步信号
output wire tft_vs , //场同步信号
output wire [15:0] tft_rgb //红绿蓝三原色输出
);
////
//\* Parameter and Internal Signal \//
////
//parameter define
parameter H_PIXEL = 24'd480 ; //水平方向像素个数,用于设置SDRAM缓存大小
parameter V_PIXEL = 24'd272 ; //垂直方向像素个数,用于设置SDRAM缓存大小
//wire define
wire clk_100m ; //100MHz时钟,SDRAM操作时钟
wire clk_100m_shift ; //100MHz时钟,SDRAM相位偏移时钟
wire clk_9m ; //9MHz时钟,提供给tft驱动时钟
wire locked ; //PLL锁定信号
wire rst_n ; //复位信号(sys_rst_n & locked)
wire cfg_done ; //摄像头初始化完成
wire wr_en ; //sdram写使能
wire [15:0] wr_data ; //sdram写数据
wire rd_en ; //sdram读使能
wire [15:0] rd_data ; //sdram读数据
wire sdram_init_done ; //SDRAM初始化完成
wire sys_init_done ; //系统初始化完成(SDRAM初始化+摄像头初始化)
////
//\* Main Code \//
////
//rst_n:复位信号(sys_rst_n & locked)
assign rst_n = sys_rst_n & locked;
//sys_init_done:系统初始化完成(SDRAM初始化+摄像头初始化)
assign sys_init_done = sdram_init_done & cfg_done;
//ov5640_rst_n:摄像头复位,固定高电平
assign ov5640_rst_n = 1'b1;
//ov5640_pwdn
assign ov5640_pwdn = 1'b0;
//------------- clk_gen_inst -------------
clk_gen clk_gen_inst(
.areset (~sys_rst_n ),
.inclk0 (sys_clk ),
.c0 (clk_100m ),
.c1 (clk_100m_shift ),
.c2 (clk_9m ),
.locked (locked )
);
//------------- ov5640_top_inst -------------
ov5640_top ov5640_top_inst(
.sys_clk (clk_9m ), //系统时钟
.sys_rst_n (rst_n ), //复位信号
.sys_init_done (sys_init_done ), //系统初始化完成(SDRAM + 摄像头)
.ov5640_pclk (ov5640_pclk ), //摄像头像素时钟
.ov5640_href (ov5640_href ), //摄像头行同步信号
.ov5640_vsync (ov5640_vsync ), //摄像头场同步信号
.ov5640_data (ov5640_data ), //摄像头图像数据
.cfg_done (cfg_done ), //寄存器配置完成
.sccb_scl (sccb_scl ), //SCL
.sccb_sda (sccb_sda ), //SDA
.ov5640_wr_en (wr_en ), //图像数据有效使能信号
.ov5640_data_out (wr_data ) //图像数据
);
//------------- sdram_top_inst -------------
sdram_top sdram_top_inst(
.sys_clk (clk_100m ), //sdram 控制器参考时钟
.clk_out (clk_100m_shift ), //用于输出的相位偏移时钟
.sys_rst_n (rst_n ), //系统复位
//用户写端口
.wr_fifo_wr_clk (ov5640_pclk ), //写端口FIFO: 写时钟
.wr_fifo_wr_req (wr_en ), //写端口FIFO: 写使能
.wr_fifo_wr_data (wr_data ), //写端口FIFO: 写数据
.sdram_wr_b_addr (24'd0 ), //写SDRAM的起始地址
.sdram_wr_e_addr (H_PIXEL*V_PIXEL), //写SDRAM的结束地址
.wr_burst_len (10'd512 ), //写SDRAM时的数据突发长度
.wr_rst (~rst_n ), //写端口复位: 复位写地址,清空写FIFO
//用户读端口
.rd_fifo_rd_clk (clk_9m ), //读端口FIFO: 读时钟
.rd_fifo_rd_req (rd_en ), //读端口FIFO: 读使能
.rd_fifo_rd_data (rd_data ), //读端口FIFO: 读数据
.sdram_rd_b_addr (24'd0 ), //读SDRAM的起始地址
.sdram_rd_e_addr (H_PIXEL*V_PIXEL), //读SDRAM的结束地址
.rd_burst_len (10'd512 ), //从SDRAM中读数据时的突发长度
.rd_rst (~rst_n ), //读端口复位: 复位读地址,清空读FIFO
//用户控制端口
.read_valid (1'b1 ), //SDRAM 读使能
.pingpang_en (1'b1 ), //SDRAM 乒乓操作使能
.init_end (sdram_init_done), //SDRAM 初始化完成标志
//SDRAM 芯片接口
.sdram_clk (sdram_clk ), //SDRAM 芯片时钟
.sdram_cke (sdram_cke ), //SDRAM 时钟有效
.sdram_cs_n (sdram_cs_n ), //SDRAM 片选
.sdram_ras_n (sdram_ras_n ), //SDRAM 行有效
.sdram_cas_n (sdram_cas_n ), //SDRAM 列有效
.sdram_we_n (sdram_we_n ), //SDRAM 写有效
.sdram_ba (sdram_ba ), //SDRAM Bank地址
.sdram_addr (sdram_addr ), //SDRAM 行/列地址
.sdram_dq (sdram_dq ), //SDRAM 数据
.sdram_dqm (sdram_dqm ) //SDRAM 数据掩码
);
//------------- tft_ctrl_inst -------------
tft_ctrl tft_ctrl_inst(
.clk_9m (clk_9m ), //输入时钟,频率9MHz
.sys_rst_n (rst_n ), //系统复位,低电平有效
.data_in (rd_data ), //待显示数据
.data_req (rd_en ),
.rgb_tft (tft_rgb ), //TFT显示数据
.hsync (tft_hs ), //TFT行同步信号
.vsync (tft_vs ), //TFT场同步信号
.tft_clk (tft_clk ), //TFT像素时钟
.tft_de (tft_de ), //TFT数据使能
.tft_bl (tft_bl ) //TFT背光信号
);
endmodule
|
13.3.1.3. RTL视图¶
至此实验工程基本完成,在Quartus中对代码进行编译,编译若有错误,请读者根据错误提示信息作出更改,直至编译通过,编译通过后查看RTL视图,与顶层模块框图对比,两者一致,各信号连接正确。RTL视图,具体见图 63‑4。
图 63‑4 RTL视图
13.4. 上板调试¶
13.4.1. 引脚约束¶
仿真验证通过后,准备上板验证,上板验证之前先要进行引脚约束。工程中各输入输出信号与开发板引脚对应关系如表格 63‑4所示。
表格 63‑4 引脚分配表
信号名 |
信号类型 |
对应引脚 |
备注 |
---|---|---|---|
sys_clk |
Input |
E1 |
时钟 |
sys_rst_n |
Input |
M15 |
复位 |
ov5640_data[7] |
Input |
L13 |
OV5640摄像头采集图像数据 |
ov5640_ data[6] |
Input |
F13 |
OV5640摄像头采集图像数据 |
ov5640_ data[5] |
Input |
B16 |
OV5640摄像头采集图像数据 |
ov5640_ data[4] |
Input |
C15 |
OV5640摄像头采集图像数据 |
ov5640_ data[3] |
Input |
D16 |
OV5640摄像头采集图像数据 |
ov5640_ data[2] |
Input |
F14 |
OV5640摄像头采集图像数据 |
ov5640_ data[1] |
Input |
F15 |
OV5640摄像头采集图像数据 |
ov5640_ data[0] |
Input |
G15 |
OV5640摄像头采集图像数据 |
ov5640_href |
Input |
J13 |
摄像头行同步信号 |
ov5640_vsync |
Input |
C16 |
摄像头场同步信号 |
ov5640_pclk |
Input |
M16 |
摄像头数据像素时钟 |
ov5640_pwdn |
Output |
G11 |
摄像头时钟选择信号 |
ov5640_rst_n |
Output |
F16 |
摄像头复位信号 |
sccb_scl |
Output |
P15 |
摄像头SCCB_SCL线 |
sccb_sda |
Inout |
N14 |
摄像头SCCB_SDA线 |
sdram_clk |
Output |
R4 |
SDRAM芯片时钟 |
sdram_cke |
Output |
R9 |
SDRAM时钟有效信号 |
sdram_cs_n |
Output |
R12 |
SDRAM片选信号 |
sdram_cas_n |
Output |
R10 |
SDRAM列地址选通脉冲 |
sdram_ras_n |
Output |
R11 |
SDRAM行地址选通脉冲 |
sdram_we_n |
Output |
L9 |
SDRAM写允许位 |
sdram_ba[0] |
Output |
R13 |
SDRAM的L-Bank地址线 |
sdram_ba[1] |
Output |
R14 |
SDRAM的L-Bank地址线 |
sdram_addr[0] |
Output |
P11 |
SDRAM地址总线 |
sdram_addr[1] |
Output |
P14 |
SDRAM地址总线 |
sdram_addr[2] |
Output |
N9 |
SDRAM地址总线 |
sdram_addr[3] |
Output |
N11 |
SDRAM地址总线 |
sdram_addr[4] |
Output |
T14 |
SDRAM地址总线 |
sdram_addr[5] |
Output |
T13 |
SDRAM地址总线 |
sdram_addr[6] |
Output |
T12 |
SDRAM地址总线 |
sdram_addr[7] |
Output |
T11 |
SDRAM地址总线 |
sdram_addr[8] |
Output |
T10 |
SDRAM地址总线 |
sdram_addr[9] |
Output |
P9 |
SDRAM地址总线 |
sdram_addr[10] |
Output |
T15 |
SDRAM地址总线 |
sdram_addr[11] |
Output |
N12 |
SDRAM地址总线 |
sdram_addr[12] |
Output |
M11 |
SDRAM地址总线 |
sdram_dqm[0] |
Output |
M10 |
SDRAM数据掩码 |
sdram_dqm[1] |
Output |
M9 |
SDRAM数据掩码 |
sdram_dq[0] |
Output |
R3 |
SDRAM数据总线 |
sdram_dq[1] |
Output |
T9 |
SDRAM数据总线 |
sdram_dq[2] |
Output |
R5 |
SDRAM数据总线 |
sdram_dq[3] |
Output |
R6 |
SDRAM数据总线 |
sdram_dq[4] |
Output |
R7 |
SDRAM数据总线 |
sdram_dq[5] |
Output |
M8 |
SDRAM数据总线 |
sdram_dq[6] |
Output |
R8 |
SDRAM数据总线 |
sdram_dq[7] |
Output |
N8 |
SDRAM数据总线 |
sdram_dq[8] |
Output |
P8 |
SDRAM数据总线 |
sdram_dq[9] |
Output |
T8 |
SDRAM数据总线 |
sdram_dq[10] |
Output |
T7 |
SDRAM数据总线 |
sdram_dq[11] |
Output |
T6 |
SDRAM数据总线 |
sdram_dq[12] |
Output |
T5 |
SDRAM数据总线 |
sdram_dq[13] |
Output |
T4 |
SDRAM数据总线 |
sdram_dq[14] |
Output |
T3 |
SDRAM数据总线 |
sdram_dq[15] |
Output |
T2 |
SDRAM数据总线 |
tft_clk |
Output |
L2 |
时钟信号 |
tft_de |
Output |
K1 |
使能信号 |
tft_bl |
Output |
L3 |
背光信号 |
tft_hs |
Output |
L1 |
行同步信号 |
tft_vs |
Output |
K2 |
场同步信号 |
tft_rgb [15] |
Output |
G1 |
RGB色彩信息(红) |
tft_rgb [14] |
Output |
F5 |
RGB色彩信息(红) |
tft_rgb [13] |
Output |
F3 |
RGB色彩信息(红) |
tft_rgb [12] |
Output |
F2 |
RGB色彩信息(红) |
tft_rgb [11] |
Output |
F1 |
RGB色彩信息(红) |
tft_rgb [10] |
Output |
E5 |
RGB色彩信息(绿) |
tft_rgb [9] |
Output |
D4 |
RGB色彩信息(绿) |
tft_rgb [8] |
Output |
J6 |
RGB色彩信息(绿) |
tft_rgb [7] |
Output |
K6 |
RGB色彩信息(绿) |
tft_rgb [6] |
Output |
L6 |
RGB色彩信息(绿) |
tft_rgb [5] |
Output |
J2 |
RGB色彩信息(绿) |
tft_rgb [4] |
Output |
J1 |
RGB色彩信息(蓝) |
tft_rgb [3] |
Output |
L4 |
RGB色彩信息(蓝) |
tft_rgb [2] |
Output |
K5 |
RGB色彩信息(蓝) |
tft_rgb [1] |
Output |
G5 |
RGB色彩信息(蓝) |
tft_rgb [0] |
Output |
G2 |
RGB色彩信息(蓝) |
下面进行管脚分配,管脚的分配方法在前面章节已有所讲解,在此就不再过多叙述,管脚的分配如下图 63‑5、图 63‑6所示。
图 63‑5 管脚分配
图 63‑6 管脚分配
13.4.1.1. 结果验证¶
如图 63‑7所示,开发板连接12V直流电源、USB-Blaster下载器JTAG端口、TFT_LCD液晶屏和OV5640摄像头。线路正确连接后,打开开关为板卡上电。
图 63‑7 程序下载连线图
如图 63‑8所示,使用“Programmer”为开发板下载程序。
图 63‑8 程序下载图
程序下载完成后,VGA显示屏上会显示出OV5640摄像头采集到的图像,分辨率为480*272,如图 63‑9所示。
图 63‑9 OV5640+TFT图像显示
13.5. 章末总结¶
本章节详细介绍了OV5640摄像头的相关知识,并将OV5640摄像头与TFT_LCD相结合,实现了OV5640采集图像的实时显示,OV5640相比OV7725功能更加强大,读者可查阅数据手册深入学习。