第1节 OV7670摄像头显示 --作者:小黑同学 本文为明德扬原创及录用**,转载请注明出处! 1.1 总体设计1.1.1 概述OV7670是一种图像传感器,图像传感器,体积小,工作电压低,提供单片VGA摄像头和影像处理器的所有功能。通过SCCB总线控制,可以输入整帧、子采样、取窗口等方式的各种分辨率8位影像数据。该产品VGA图像最高达到30帧/秒。用户可以完全控制图像质量、数据格式和传输方式。所有图像处理功能过程包括伽玛曲线、白平衡、饱和度、色度等都可以通过SCCB接口编程。OmmiVision图像传感器应用独有的传感器技术,通过减少或消除光学或电子缺陷如固定图案噪声、托尾、浮散等,提高图像质量,得到清晰的稳定的彩色图像。 1.1.2 设计目标本工程使用ov7670摄像头、SDRAM、VGA显示器、按键等,实现摄像头显示的功能,具体要求如下: 1、 通过SCCB接口对摄像头中的寄存器进行配置。 2、 通过按键/矩阵键盘控制是否对摄像头进行配置。 3、 对摄像头输出的图像数据进行采集之后,通过SDRAM进行缓存 4、 通过VGA显示器显示摄像头采集到的图像。 1.1.3 系统结构框图系统结构框图1.1.4模块功能 按键检测模块实现功能1、 将外来异步信号打两拍处理,将异步信号同步化。 2、 实现20ms按键消抖功能。 3、 实现矩阵键盘或者普通案件的检测功能,并输出有效按键信号。 锁相环PLL_11、 将摄像头输出的像素时钟转化为同频同相的25M时钟。 锁相环PLL_2
1、产生摄像头需要的25M时钟xlclk。 2、 产生SDRAM工作需要的100M时钟。 配置模块模块实现功能1、 根据按键信息,将配置表中的寄存器信息读出。 2、 根据SCCB接口模块的指示,将配置信息输出到SCCB模块。
SCCB接口模块实现功能1、 根据上游模块的读写使能命令、地址以及数据,产生对应的SCCB时序,从而将数据写入摄像头指定的寄存器中,或者从指定的摄像头寄存器中读取数据。
图像采集模块实现功能1、 根据摄像头输出格式,对像素数据进行接收。 2、 对摄像头输出数据进行串并转换。
存储控制模块实现功能1、 通过乒乓操作的方法,控制SDRAM的读写以及Bank地址,以保证图像数据连续显示到显示器上。
SDRAM接口模块实现功能1、 接收上游模块发送的读/写请求、Bank地址、行地址和写数据,产生SDRAM的控制时序。
VGA接口模块实现功能1、 产生VGA时序,在有效显示区域,将图像数据送入显示器进行显示。 1.1.5顶层信号
信号名 | | | | | | | | | | | | | | | 4位按键信号,开发板按键为矩阵键盘时,不需要该信号 | | | | 4位矩阵键盘列信号,默认高电平,开发板按键为普通按键时,不需要该信号 | | | | 4位矩阵键盘行信号,默认低电平,开发板按键为普通按键时,不需要该信号 | | | | SDRAM数据总线,既能作为数据输出,也能作为数据输入。 | | | | SDRAM时钟使能信号,决定是否启用clk输入,为高电平时,时钟有效。 | | | | SDRAM片选信号,决定设备内是否启用命令输入,当cs为低时启用,当cs为高时禁用命令输入。 | | | | | | | | | | | | | | | | 数据掩码,控制I/O的高低字节,低电平有效。例如:2’b10,表示数据高字节无效,低字节有效。 | | | | | | | | Bank地址选择信号,通过该信号决定哪个Bank正处于激活、读、写、预充电等命令期间。 | | | | SDRAM输入时钟,除cke外,SDRAM的所有输入与该引脚的上升沿同步获得。 | | | | | | | | | | | | | | | | | | | | | | | | 摄像头待机状态指示信号,该信号为1表示,摄像头处于待机状态,不工作,该信号为0,摄像头处于唤醒状态。 | | | | | | | | | | | | | | | | | | | | |
1.1.6参考代码
下面是使用工程的顶层代码: - module mdyOV7670CameraDisplay_top(
- clk ,
- rst_n ,
- key_in ,
- pclk ,
- vsync ,
- href ,
- din ,
- xclk ,
- pwdn ,
- sio_c ,
- sio_d ,
- vga_hys ,
- vga_vys ,
- vga_rgb ,
- cke ,
- cs ,
- ras ,
- cas ,
- we ,
- dqm ,
- sd_addr ,
- sd_bank ,
- sd_clk ,
- dq
- );
- input clk ;
- input rst_n ;
- input pclk ;
- input [3:0] key_in ;
- input vsync ;
- input href ;
- input [7:0] din ;
- output xclk ;
- output pwdn ;
- output vga_hys ;
- output vga_vys ;
- output [15:0] vga_rgb ;
- output sio_c ;
- output cs ;
- output ras ;
- output cas ;
- output we ;
- output [1 :0] dqm ;
- output [12:0] sd_addr ;
- output [1 :0] sd_bank ;
- output sd_clk ;
- output cke ;
- inout [15:0] dq ;
- inout sio_d ;
- wire [15:0] dq_in ;
- wire [15:0] dq_out ;
- wire dq_out_en ;
- wire en_sio_d_w ;
- wire sio_d_w ;
- wire sio_d_r ;
- wire xclk_ ;
- wire clk_100m ;
- wire locked ;
- wire [3:0] key_num ;
- wire en_coms ;
- wire [7:0] value_gray ;
- wire rdy ;
- wire wen ;
- wire ren ;
- wire [7:0] wdata ;
- wire capture_en ;
- wire [7:0] rdata ;
- wire rdata_vld ;
- wire [15:0] cmos_dout ;
- wire cmos_dout_vld ;
- wire cmos_dout_sop ;
- wire cmos_dout_eop ;
- wire [15:0] rd_addr ;
- wire rd_en ;
- wire [15:0] vga_data ;
- wire rd_end ;
- wire wr_end ;
- wire rd_addr_sel ;
- wire [3:0] key_vld ;
- wire display_area ;
- wire [7:0] sub_addr ;
- wire cke ;
- wire cs ;
- wire ras ;
- wire cas ;
- wire we ;
- wire [1 :0] dqm ;
- wire [12:0] sd_addr ;
- wire [1 :0] sd_bank ;
- wire sd_clk ;
- wire [15:0] sd_rdata ;
- wire sd_rdata_vld ;
- wire [15:0] fifo2sd_wdata ;
- wire wr_ack ;
- wire rd_ack ;
- wire wr_req ;
- wire rd_req ;
- wire [1 :0] bank ;
- wire [12:0] addr ;
- assign dq_in = dq;
- assign dq = dq_out_en?dq_out:16'hzzzz;
- assign sio_d = en_sio_d_w ? sio_d_w : 1'dz;
- assign sio_d_r = sio_d;
- pll_sd pll_sd_inst2 (
- .inclk0 (clk ),
- .c0 (xclk ),
- .c1 (clk_100m )
- );
- cmos_pll u_cmos_pll(
- .inclk0 (pclk ),
- .c0 (clk_25M )
- );
- key_module#(.KEY_W(4)) u_key_module(
- .clk (xclk ),
- .rst_n (rst_n ),
- .key_in (key_in ),
- .key_vld (key_vld )
- );
- ov7670_config u4(
- .clk (xclk ),
- .rst_n (rst_n ),
- .config_en (key_vld[1] ),
- .rdy (rdy ),
- .rdata (rdata ),
- .rdata_vld (rdata_vld ),
- .wdata (wdata ),
- .addr (sub_addr ),
- .wr_en (wen ),
- .rd_en (ren ),
- .cmos_en (en_capture ),
- .pwdn (pwdn )
- );
- sccb u5(
- .clk (xclk ),
- .rst_n (rst_n ),
- .ren (ren ),
- .wen (wen ),
- .sub_addr (sub_addr ),
- .rdata (rdata ),
- .rdata_vld (rdata_vld ),
- .wdata (wdata ),
- .rdy (rdy ),
- .sio_c (sio_c ),
- .sio_d_r (sio_d_r ),
- .en_sio_d_w (en_sio_d_w ),
- .sio_d_w (sio_d_w )
- );
- cmos_capture u6(
- .clk (clk_25M ),
- .rst_n (rst_n ),
- .en_capture (en_capture ),
- .vsync (vsync ),
- .href (href ),
- .din (din ),
- .dout (cmos_dout ),
- .dout_vld (cmos_dout_vld),
- .dout_sop (cmos_dout_sop),
- .dout_eop (cmos_dout_eop)
- );
- vga_config u11(
- .clk (clk_25M ),
- .clk_in (clk_100m ),
- .rst_n (rst_n ),
- .din (cmos_dout ),
- .din_vld (cmos_dout_vld),
- .din_sop (cmos_dout_sop),
- .din_eop (cmos_dout_eop),
- .dout (vga_data ),
- .wr_req (wr_req ),
- .rd_req (rd_req ),
- .wr_ack (wr_ack ),
- .rd_ack (rd_ack ),
- .wdata (fifo2sd_wdata),
- .sd_rdata (sd_rdata ),
- .sd_rdata_vld (sd_rdata_vld ),
- .display_area (display_area ),
- .bank (bank ),
- .addr (addr )
- );
- sdram_intf u20 (
- .clk (clk_100m ),
- .rst_n (rst_n ),
- .wr_req (wr_req ),
- .rd_req (rd_req ),
- .dq_in (dq_in ),
- .dq_out (dq_out ),
- .dq_out_en (dq_out_en ),
- .wr_ack (wr_ack ),
- .rd_ack (rd_ack ),
- .rdata (sd_rdata ),
- .rdata_vld (sd_rdata_vld ),
- .cke (cke ),
- .cs (cs ),
- .ras (ras ),
- .cas (cas ),
- .we (we ),
- .dqm (dqm ),
- .sd_addr (sd_addr ),
- .sd_bank (sd_bank ),
- .sd_clk (sd_clk ),
- .wdata (fifo2sd_wdata),
- .bank (bank ),
- .addr (addr )
- );
- vga_driver u12(
- .clk (clk_25M ),
- .rst_n (rst_n ),
- .din (vga_data ),
- .vga_hys (vga_hys ),
- .vga_vys (vga_vys ),
- .vga_rgb (vga_rgb ),
- .display_area(display_area )
- );
- endmodule
[color=rgb(51, 102, 153) !important]复制代码
1.2 按键检测模块设计1.2.1接口信号
下面为使用矩阵键盘时的接口信号:
下面是使用普通按键时的接口信号:
1.2.2 设计思路
在前面的案例中已经有按键检测的介绍,所以这里不在过多介绍,详细介绍请看下方链接: 【每周FPGA案例】至简设计系列_按键控制数字时钟
|