一、什么是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文章
21850瀏覽量
608902 -
寄存器
+關注
關注
31文章
5394瀏覽量
122010 -
接口
+關注
關注
33文章
8788瀏覽量
152490 -
圖像數據
+關注
關注
0文章
54瀏覽量
11367 -
dvp
+關注
關注
0文章
14瀏覽量
9158
原文標題:基于FPGA的DVP協議實現標準圖像數據流轉換
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
相關推薦
用FPGA配置TVP5150,把PAL制標準視頻轉換成BT656數據格式,能否把數據流直接給SAA7121?


基于FPGA的數字視頻轉換接口的設計與實現
采用FPGA的數字視頻接口轉換設備設計
采用FPGA作為主控芯片的數字視頻接口轉換設備
采用FPGA的數字視頻接口轉換設備
采用FPGA實現數字視頻轉換接口設計
采用FPGA的數字視頻接口轉換設備設計
【工程源碼】基于FPGA的OV5640數據流接收和應用基本邏輯設計
基于FPGA芯片的數據流結構分析
如何使用FPGA實現Bayer到RGB圖像格式轉換的設計

評論