一、什么是DVP?
DVP(Digital Video Port) 是傳統(tǒng)的sensor輸出接口,采用并行輸出方式,d數(shù)據(jù)位寬有8bit、10bit、12bit、16bit,是CMOS電平信號(重點是非差分信號),PCLK最大速率為96MHz,接口如下圖:

PCLK:pixel clock ,像素時鐘,每個時鐘對應一個像素數(shù)據(jù);
HSYNC:horizonal synchronization,行同步信號
VSYNC:vertical synchronization,幀同步信號;
DATA:像素數(shù)據(jù),視頻數(shù)據(jù),具體位寬要看ISP是否支持;
XCLK:或者MCLK,ISP芯片輸出給驅(qū)動sensor的時鐘;
SCL,SDA:IIC用來讀寫sensor的寄存器,配置sensor。
DVP協(xié)議是攝像頭中常用的協(xié)議,除了DVP協(xié)議攝像頭中還有其他常用的協(xié)議如:MIPI、LVDS等協(xié)議。其整體協(xié)議時序圖如圖:


圖中PIXCLK信號即是PCLk信號,F(xiàn)V是幀同步信號,LV是行同步信號,輸出的P0~Pn就是像素數(shù)據(jù)。
二、OV7670攝像頭的DVP協(xié)議時序
(1)水平時序

(2)和VGA對應的幀時序
DVP協(xié)議和VGA接口協(xié)議基本一樣,只是VSYNC信號高低電平相反了。還有DVP協(xié)議的HREF信號是在HERF為高電平是直接輸出像素數(shù)據(jù),而VGA接口的HSYNC信號在HSYNC為高時先后輸出顯示后沿、有效圖像數(shù)據(jù)、顯示前沿。

(3)這里對OV7670攝像頭配置輸出的是RGB565圖像數(shù)據(jù),其時序為:

(4)配置成RGB555和RGB444輸出時序如圖:

RGB555

RGB444
三、RTL設計
從上邊所看的時序圖可以將DVP協(xié)議轉(zhuǎn)換成標準的圖像的數(shù)據(jù)流,代碼如下:
// 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協(xié)議(digital video port)獲取ov7670數(shù)據(jù)并轉(zhuǎn)換成16位RGB565圖像數(shù)據(jù)
module ov7670_data_16rgb565(
inputclk,//輸入為攝像頭輸入時鐘pclk 25MHz
inputrst_n,//系統(tǒng)復位
inputvsync,//場同步信號
inputhref,//行同步信號
input[7:0]din,//ov7670攝像頭數(shù)據(jù)輸入
inputinit_done,//ov7670攝像頭初始化結(jié)束標志
outputreg[15:0]data_rgb565,//轉(zhuǎn)換成16位RGB565圖像數(shù)據(jù)
outputregdata_rgb565_vld //16位RGB565圖像數(shù)據(jù)有效標志
);
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幀圖像數(shù)據(jù)

可以看到,data_rgb565_vld數(shù)據(jù)有效信號在10幀圖像數(shù)據(jù)后才有輸出,這是為了在初始化后圖像數(shù)據(jù)可能會有不穩(wěn)定情況,因此將前十幀圖像丟棄。
(2)1幀圖像數(shù)據(jù)(注意看幀同步信號)

(3)傳輸數(shù)據(jù)部分細節(jié)

-
FPGA
+關注
關注
1660文章
22406瀏覽量
636099 -
寄存器
+關注
關注
31文章
5608瀏覽量
129943 -
接口
+關注
關注
33文章
9518瀏覽量
156996 -
圖像數(shù)據(jù)
+關注
關注
0文章
54瀏覽量
11673 -
dvp
+關注
關注
0文章
18瀏覽量
9546
原文標題:基于FPGA的DVP協(xié)議實現(xiàn)標準圖像數(shù)據(jù)流轉(zhuǎn)換
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
基于FPGA的DVP接口實現(xiàn)
用FPGA配置TVP5150,把PAL制標準視頻轉(zhuǎn)換成BT656數(shù)據(jù)格式,能否把數(shù)據(jù)流直接給SAA7121?
#硬聲創(chuàng)作季 #FPGA FPGA-54-01 RAW數(shù)據(jù)流轉(zhuǎn)換到RGB888圖像數(shù)據(jù)原理分析-1
#硬聲創(chuàng)作季 #FPGA FPGA-54-01 RAW數(shù)據(jù)流轉(zhuǎn)換到RGB888圖像數(shù)據(jù)原理分析-2
#硬聲創(chuàng)作季 #FPGA FPGA-54-01 RAW數(shù)據(jù)流轉(zhuǎn)換到RGB888圖像數(shù)據(jù)原理分析-3
基于FPGA的數(shù)字視頻轉(zhuǎn)換接口的設計與實現(xiàn)
采用FPGA的數(shù)字視頻接口轉(zhuǎn)換設備設計
采用FPGA作為主控芯片的數(shù)字視頻接口轉(zhuǎn)換設備
采用FPGA的數(shù)字視頻接口轉(zhuǎn)換設備
采用FPGA實現(xiàn)數(shù)字視頻轉(zhuǎn)換接口設計
采用FPGA的數(shù)字視頻接口轉(zhuǎn)換設備設計
【工程源碼】基于FPGA的OV5640數(shù)據(jù)流接收和應用基本邏輯設計
基于FPGA和EPP的圖像傳感器高速數(shù)據(jù)采集
yuv422p格式數(shù)據(jù)流轉(zhuǎn)換成RGB888格式數(shù)據(jù)流
如何使用FPGA實現(xiàn)Bayer到RGB圖像格式轉(zhuǎn)換的設計
基于FPGA的DVP協(xié)議實現(xiàn)標準圖像數(shù)據(jù)流轉(zhuǎn)換
評論