一、什么是DVP?
DVP(Digital Video Port) 是传统的sensor输出接口,采用并行输出方式,d数据位宽有8bit、10bit、12bit、16bit,是CMOS电平信号(重点是非差分信号),PCLK最大速率为96MHz,接口如下图:
PCLK:pixel clock ,像素时钟,每个时钟对应一个像素数据;
HSYNC:horizonal synchronization,行同步信号
VSYNC:vertical synchronization,帧同步信号;
DATA:像素数据,视频数据,具体位宽要看ISP是否支持;
XCLK:或者MCLK,ISP芯片输出给驱动sensor的时钟;
SCL,SDA:IIC用来读写sensor的寄存器,配置sensor。
DVP协议是摄像头中常用的协议,除了DVP协议摄像头中还有其他常用的协议如:MIPI、LVDS等协议。其整体协议时序图如图:
图中PIXCLK信号即是PCLk信号,FV是帧同步信号,LV是行同步信号,输出的P0~Pn就是像素数据。
二、OV7670摄像头的DVP协议时序
(1)水平时序
(2)和VGA对应的帧时序
DVP协议和VGA接口协议基本一样,只是VSYNC信号高低电平相反了。还有DVP协议的HREF信号是在HERF为高电平是直接输出像素数据,而VGA接口的HSYNC信号在HSYNC为高时先后输出显示后沿、有效图像数据、显示前沿。
(3)这里对OV7670摄像头配置输出的是RGB565图像数据,其时序为:
(4)配置成RGB555和RGB444输出时序如图:
RGB555
RGB444
三、RTL设计
从上边所看的时序图可以将DVP协议转换成标准的图像的数据流,代码如下:
// Company :
// Engineer :
// -----------------------------------------------------------------------------
// https://blog.csdn.net/qq_33231534 PHF's CSDN blog
// -----------------------------------------------------------------------------
// Create Date : 2020-09-24 2257
// Revise Data : 2020-09-24 2257
// File Name : ov7670_data_16rgb565.v
// Target Devices : XC7Z015-CLG485-2
// Tool Versions : Vivado 2019.2
// Revision : V1.1
// Editor : sublime text3, tab size (4)
// Description : DVP协议(digital video port)获取ov7670数据并转换成16位RGB565图像数据
module ov7670_data_16rgb565(
inputclk,//输入为摄像头输入时钟pclk 25MHz
inputrst_n,//系统复位
inputvsync,//场同步信号
inputhref,//行同步信号
input[7:0]din,//ov7670摄像头数据输入
inputinit_done,//ov7670摄像头初始化结束标志
outputreg[15:0]data_rgb565,//转换成16位RGB565图像数据
outputregdata_rgb565_vld //16位RGB565图像数据有效标志
);
regvsync_r;
reghref_r;
reg[7:0]din_r;
regvsync_r_ff0;
regvsync_r_ff1;
regdata_start;
reg[3:0]frame_cnt;
regframe_vaild;
wirevsync_r_pos;
regdata_en;
//外部信号打一拍
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
vsync_r <= 0;
href_r <= 0;
din_r <= 8'd0;
end
else begin
vsync_r <= vsync;
href_r <= href;
din_r <= din;
end
end
//场同步信号上升沿检测
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
vsync_r_ff0 <= 0;
vsync_r_ff1 <= 0;
end
else begin
vsync_r_ff0 <= vsync_r;
vsync_r_ff1 <= vsync_r_ff0;
end
end
assign vsync_r_pos = (vsync_r_ff0 && ~vsync_r_ff1);
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_start <= 0;
end
else if (init_done) begin
data_start <= 1;
end
else begin
data_start <= data_start;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
frame_cnt <= 0;
end
else if (data_start && frame_vaild==0 && vsync_r_pos) begin
frame_cnt <= frame_cnt + 1'b1;
end
else begin
frame_cnt <= frame_cnt;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
frame_vaild <= 0;
end
else if (frame_cnt >= 10) begin
frame_vaild <= 1;
end
else begin
frame_vaild <= frame_vaild;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_en <= 0;
end
else if (href_r && frame_vaild) begin
data_en <= ~data_en;
end
else begin
data_en <= 0;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_rgb565_vld <= 0;
end
else if (data_en) begin
data_rgb565_vld <= 1;
end
else begin
data_rgb565_vld <= 0;
end
end
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
data_rgb565 <= 16'd0;
end
else if (data_en) begin
data_rgb565 <= {data_rgb565[15:8],din_r};
end
else begin
data_rgb565 <= {din_r,data_rgb565[7:0]};
end
end
endmodule
测试代码:
`timescale 1ns/1ns
module ov7670_data_16rgb565_tb (); /* this is automatically generated */
reg rst_n;
reg clk;
localparam clk_period = 20;
reg vsync;
reg href;
reg [7:0] din;
reg init_done;
wire [15:0] data_rgb565;
wire data_rgb565_vld;
ov7670_data_16rgb565 inst_ov7670_data_16rgb565
(
.clk (clk),
.rst_n (rst_n),
.vsync (vsync),
.href (href),
.din (din),
.init_done (init_done),
.data_rgb565 (data_rgb565),
.data_rgb565_vld (data_rgb565_vld)
);
initial clk = 1;
always #(clk_period/2) clk = ~clk;
initial begin
#2;
rst_n = 0;
vsync = 0;
href = 0;
din = 0;
init_done = 0;
#(clk_period*20);
rst_n = 1;
#(clk_period*20);
init_done = 1;
#clk_period;
init_done = 0;
#(clk_period*20);
repeat(12)begin
#(clk_period*500);
dvp_data();
end
#(clk_period*20);
$stop;
end
task dvp_data;
integer i,j;
begin
vsync = 0;
#(clk_period*10);
vsync = 1;
#(clk_period*10);
vsync = 0;
#(clk_period*100);
for(i=0;i<480;i=i+1)begin
for(j=0;j<640*2;j=j+1)begin
href = 1;
#(clk_period);
din = din + 1'b1;
end
href = 0;
#(clk_period*100);
end
din = 0;
end
endtask
endmodule
仿真图如图所示:
(1)传输12帧图像数据
可以看到,data_rgb565_vld数据有效信号在10帧图像数据后才有输出,这是为了在初始化后图像数据可能会有不稳定情况,因此将前十帧图像丢弃。
(2)1帧图像数据(注意看帧同步信号)
(3)传输数据部分细节
-
FPGA
+关注
关注
1637文章
21849浏览量
608801 -
寄存器
+关注
关注
31文章
5393浏览量
121999 -
接口
+关注
关注
33文章
8785浏览量
152476 -
图像数据
+关注
关注
0文章
54浏览量
11367 -
dvp
+关注
关注
0文章
14浏览量
9155
原文标题:基于FPGA的DVP协议实现标准图像数据流转换
文章出处:【微信号:gh_9d70b445f494,微信公众号:FPGA设计论坛】欢迎添加关注!文章转载请注明出处。
发布评论请先 登录
相关推荐
用FPGA配置TVP5150,把PAL制标准视频转换成BT656数据格式,能否把数据流直接给SAA7121?


基于FPGA的数字视频转换接口的设计与实现
采用FPGA的数字视频接口转换设备设计
采用FPGA作为主控芯片的数字视频接口转换设备
采用FPGA的数字视频接口转换设备
采用FPGA实现数字视频转换接口设计
采用FPGA的数字视频接口转换设备设计
【工程源码】基于FPGA的OV5640数据流接收和应用基本逻辑设计
基于FPGA芯片的数据流结构分析
如何使用FPGA实现Bayer到RGB图像格式转换的设计

评论