一、DVP簡介
DVP接口(Digital Video Port)是一種用于數(shù)字視頻傳輸?shù)牟⑿薪涌冢R娪?a target="_blank">嵌入式系統(tǒng)和圖像傳感器中。DVP直接傳輸數(shù)字視頻信號,減少模數(shù)轉換需求,適合中低速視頻傳輸。數(shù)據(jù)線:通常為8、10、12或16根數(shù)據(jù)線,用于傳輸像素數(shù)據(jù)。控制信號包括像素時鐘(PCLK)、行同步(HSYNC 或 HREF)信號、場同步(VSYNC)等,用于同步數(shù)據(jù)傳輸。
DVP和VGA時序有相似之處,都使用行同步(HSYNC)和場同步(VSYNC)信號來同步圖像數(shù)據(jù)。區(qū)別在于DVP是數(shù)字接口,直接傳輸數(shù)字像素數(shù)據(jù),包含像素時鐘(PCLK)和數(shù)據(jù)線;VGA是模擬接口,傳輸模擬RGB信號,需數(shù)模轉換 。
本例介紹的DVP行同步信號采用 HREF,用于 ov5640 DVP數(shù)據(jù)接收采集。
(1)行時序
1.高電平有效:HREF為高電平時,表示正在傳輸有效像素數(shù)據(jù)。
2.像素傳輸:在HREF高電平期間,每個PCLK周期傳輸一個像素數(shù)據(jù)。
3.行結束:HREF從高電平變?yōu)榈碗娖剑瑯酥疽恍袛?shù)據(jù)傳輸完成。
4.像素數(shù)據(jù)周期:ov5640 DVP每個有效數(shù)據(jù)為8位,數(shù)據(jù)采集時需要根據(jù)輸出格式進行調整,輸出RGB565格式需要兩個像素時鐘才能完成傳輸,先傳輸高8位,后第8位。
(2)場時序
1.同步脈沖:VSYNC產生高電平脈沖(取決于極性,ov5640為高)表示新一幀開始。
2.有效數(shù)據(jù)期:新一幀開始一段時間后,每行數(shù)據(jù)通過HSYNC或HREF信號同步。
3.幀結束:一幀數(shù)據(jù)傳輸完成后,VSYNC再次產生脈沖,標志下一幀的開始。
二、Verilog 實現(xiàn)
(1)設計要求
1. 對 ov5640 輸出RGB565格式的圖像數(shù)據(jù)進行接收
2. 接收數(shù)據(jù)輸出給存儲器(如rom、fifo、ddr)進行存儲,包含必要輸出端口
(2)設計要點
1. 場同步:每當 vsync 產生一次上升沿即代表新一幀的開始(上升沿通過打拍判斷)
2. 行同步:href 的每段高電平代表一行有效數(shù)據(jù)
3. 數(shù)據(jù)格式:一個pclk像素時鐘傳8位,而RGB565一個像素16位,需要兩個pclk像素時鐘才傳輸完一個像素數(shù)據(jù),因此需要進行先緩存高8位數(shù)據(jù),并在接收第8位時拼接數(shù)據(jù)并輸出
4. 數(shù)據(jù)有效信號:高電平時代表當前RGB565數(shù)據(jù)有效,可供后續(xù)存儲器作寫使能使用
(3)模塊代碼
`timescale 1ns / 1ps
module DVP_ctrl#(
parameter PIC_CNT_MAX = 4'd10 //舍棄前10幀不穩(wěn)定圖像數(shù)據(jù)
)(
input wire rst_n,
input wire ov5640_pclk, //攝像頭像素時鐘
input wire ov5640_href, //攝像頭行同步信號
input wire ov5640_vsync, //攝像頭場同步信號
input wire [7:0] ov5640_data, //攝像頭場數(shù)據(jù)輸入
output reg [15:0] RGB565_data, //圖像數(shù)據(jù)輸出(RGB565格式)
output wire data_valid //數(shù)據(jù)有效信號(給存儲器的寫使能信號)
);
reg pix_flag; //一像素數(shù)據(jù)結束標志位
wire pic_flag; //一幀圖像結束標志位
reg pic_valid; //幀有效標志位
reg [3:0] pic_cnt; //幀計數(shù)器
reg [7:0] r_ov5640_data; //輸入數(shù)據(jù)緩存
reg ov5640_vsync_delay; //場同步信號打拍
reg pix_flag_delay; //一像素數(shù)據(jù)結束標志位打拍
//***************************** 場同步 ****************************//
//場同步信號打拍(用于檢測vsync上升沿)
always@(posedge ov5640_pclk or negedge rst_n)
if(rst_n == 1'b0)
ov5640_vsync_delay <= 1'b0;
else
ov5640_vsync_delay <= ov5640_vsync;
//一幀圖像結束標志位(vsync上升沿產生一次)
assign pic_flag = ((ov5640_vsync_delay == 1'b0) &&
(ov5640_vsync == 1'b1)) ? 1'b1 : 1'b0;
//前幾幀計數(shù),計滿產生幀有效信號
always @(posedge ov5640_pclk or negedge rst_n) begin
if (!rst_n) begin
pic_cnt <= 4'd0;
pic_valid <= 1'b0;
end else if (pic_flag) begin
if (pic_cnt == PIC_CNT_MAX) begin
pic_cnt <= 4'd0;
pic_valid <= 1'b1;
end else
pic_cnt <= pic_cnt + 4'd1;
end
end
//***************************** 行同步 ****************************//
//行同步
always @(posedge ov5640_pclk or negedge rst_n) begin
if (!rst_n) begin
pix_flag <= 1'b0;
r_ov5640_data <= 8'b0;
RGB565_data <= 8'b0;
end else if (ov5640_href) begin
if (!pix_flag) begin
r_ov5640_data <= ov5640_data; //先緩存高8位
pix_flag <= 1'b1;
end else begin
RGB565_data <= {r_ov5640_data , ov5640_data};//后拼接低8位輸出
pix_flag <= 1'b0;
end
end
end
//一像素數(shù)據(jù)結束標志位打拍(用于產生像素數(shù)據(jù)有效信號)
always@(posedge ov5640_pclk or negedge rst_n)
if(rst_n == 1'b0)
pix_flag_delay <= 1'b0;
else
pix_flag_delay <= pix_flag;
//像素數(shù)據(jù)有效信號
assign data_valid = pic_valid & pix_flag_delay;
endmodule
(4)仿真代碼
仿真就是給DVP模塊模擬ov5640產生的圖像數(shù)據(jù),我用的deepseek寫了一版,但經(jīng)過測試發(fā)現(xiàn)不能直接使用,于是根據(jù)它的框架自己進行了一些修改,可以通過參數(shù)設置模擬圖像數(shù)據(jù)的參數(shù)(仿真多少幀、一幀多少行、一行多少像素)。以下模擬輸出了10幀、一幀8行數(shù)據(jù)、一行16個像素點,同時DVP舍去前3幀圖像數(shù)據(jù)。
`timescale 1ns / 1ps
module DVP_data_gen_tb();
reg pclk; //像素時鐘 (10ns周期)
reg rst_n; //復位信號 (低電平有效)
reg vsync; //場同步信號
reg href; //行同步信號
reg [7:0] data; //像素數(shù)據(jù) (8bit)
wire data_valid; //數(shù)據(jù)有效信號
wire [15:0] RGB565_data; //輸出RGB565格式數(shù)據(jù) (16bit)
//模擬OV5640視頻數(shù)據(jù)生成
parameter WIDTH = 16, //寬(一行多少個像素)
HIGTH = 8, //高(一幀多少行數(shù)據(jù))
FRAME = 10; //幀(模擬發(fā)送多少幀數(shù)據(jù))
integer pixel_cnt = 0, //像素計數(shù)器
row_cnt = 0, //行計數(shù)器
frame_cnt = 0; //幀計數(shù)器
//時鐘(10ns周期)
always #5 pclk = ~pclk;
initial begin //初始化復位
pclk = 0;
rst_n = 0; #20;
rst_n = 1;
end
always @(posedge pclk or negedge rst_n) begin
if (!rst_n) begin
vsync <= 0;
href <= 0;
data <= 0;
pixel_cnt <= 0;
row_cnt <= 0;
frame_cnt <= 0;
end else begin
//******************************************模擬場同步信號 (VSYNC)
if (pixel_cnt == 0 && row_cnt == 0) begin
vsync <= 1; // 一幀開始,VSYNC拉高一個時鐘周期
end else begin
vsync <= 0; // VSYNC拉低
end
//******************************************模擬行同步信號 (HREF)
if (row_cnt < HIGTH*10 + 10) begin//一幀模擬HIGTH行,多余行模擬行與行之間的輸出間隔
if (row_cnt <10 || (row_cnt % 10)!=0)
row_cnt <= row_cnt + 1;
else begin
if (pixel_cnt < WIDTH) begin
href <= 1; //HREF高電平表示行數(shù)據(jù)傳輸
data <= data + 1; //像素數(shù)據(jù)每次自增1
pixel_cnt <= pixel_cnt + 1;
end else begin
//一行結束
href <= 0; //HREF低電平表示行結束
pixel_cnt <= 0;
row_cnt <= row_cnt + 1; //行計數(shù)器加1
end
end
end else begin//一幀結束
href <= 0;
data <= 0;
row_cnt <= 0; //重置行計數(shù)器
frame_cnt <= frame_cnt + 1; //幀計數(shù)器加1
end
//******************************************模擬FRAME幀后結束測試
if (frame_cnt == FRAME) begin
$finish; // 結束仿真
end
end
end
DVP_ctrl #(
.PIC_CNT_MAX (4'd3) //舍去前三幀圖像
) DVP_ctrl (
.ov5640_pclk (pclk),
.rst_n (rst_n),
.ov5640_vsync (vsync),
.ov5640_href (href),
.ov5640_data (data),
.data_valid (data_valid),
.RGB565_data (RGB565_data)
);
endmodule
三、仿真波形
完整波形:可以看到一共發(fā)送了10幀數(shù)據(jù),同時data_valid在前三幀保持為0,后面才開始變化,說明前三幀數(shù)據(jù)被成功舍去。
一幀波形:1幀包含8行,1行有16個8位數(shù)據(jù)。
一行波形:一個RGB565像素數(shù)據(jù)對應兩個8位數(shù)據(jù),可以看到每接收2個數(shù)據(jù)就相應拼接輸出1個RGB565數(shù)據(jù),同時data_valid數(shù)據(jù)有效信號與數(shù)據(jù)同步產生。
-
FPGA
+關注
關注
1643文章
21963瀏覽量
614091 -
接口
+關注
關注
33文章
8943瀏覽量
153202 -
圖像傳感器
+關注
關注
68文章
1963瀏覽量
130414 -
Verilog
+關注
關注
28文章
1366瀏覽量
111817 -
VGA
+關注
關注
5文章
572瀏覽量
64194
原文標題:基于FPGA的DVP接口實現(xiàn)
文章出處:【微信號:gh_9d70b445f494,微信公眾號:FPGA設計論壇】歡迎添加關注!文章轉載請注明出處。
發(fā)布評論請先 登錄
【FPGA設計實例】FPGA接口實現(xiàn)文本液晶顯示模塊
基于FPGA的腦機接口實時系統(tǒng)設計
如果不使用FPGA自帶的SERDES,可否適用LVDS接口實現(xiàn)其功能?
通過USB接口實現(xiàn)FPGA 的SelectMap配置
基于JTAG接口實現(xiàn)ARM的FPGA在線配置設計

ARM與FPGA的接口實現(xiàn)的解析

基于FPGA的SDRAM串口實驗

C#-Interface接口實現(xiàn)

基于XML語言描述的接口實現(xiàn)方法

評論