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

ARM與FPGA的接口實現的解析

C#-Interface接口實現

評論