2-3-23 VTC视频时序控制器设计
软件版本:VIVADO2021.1操作系统:WIN10 64bit硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA登录米联客(MiLianKe)FPGA社区-www.uisrc.com观看免费视频课程、在线答疑解惑!1 概述Video Timing Controller 缩写VTC是我们在所有涉及FPGA图像、FPGA视频类方案中经常用到的一种用于产生视频时序的控制器。2 VTC控制器设计2.1 系统框图VTC控制器通过hcnt和vcnt计数器实现hs时序vs时序以及de时序。2.2 时序设计视频数据在H_AcitiveSize和V_AcitiveSize同时有效时候有效,显示屏上的显示效果如下图所示。3 VTC源码`timescale 1ns / 1ns //仿真时间刻度/精度
module uivtc#(parameter H_ActiveSize= 1980, //视频时间参数,行视频信号,一行有效(需要显示的部分)像素所占的时钟数,一个时钟对应一个有效像素parameter H_FrameSize = 1920+88+44+148, //视频时间参数,行视频信号,一行视频信号总计占用的时钟数parameter H_SyncStart = 1920+88, //视频时间参数,行同步开始,即多少时钟数后开始产生行同步信号parameter H_SyncEnd = 1920+88+44, //视频时间参数,行同步结束,即多少时钟数后停止产生行同步信号,之后就是行有效数据部分
parameter V_ActiveSize= 1080, //视频时间参数,场视频信号,一帧图像所占用的有效(需要显示的部分)行数量,通常说的视频分辨率即H_ActiveSize*V_ActiveSizeparameter V_FrameSize = 1080+4+5+36, //视频时间参数,场视频信号,一帧视频信号总计占用的行数量parameter V_SyncStart = 1080+4, //视频时间参数,场同步开始,即多少行数后开始产生场同步信号parameter V_SyncEnd = 1080+4+5 //视频时间参数,场同步结束,即多少场数后停止产生场同步信号,之后就是场有效数据部分)(input I_vtc_rstn, //系统复位input I_vtc_clk, //系统时钟output O_vtc_vs, //场同步输出output O_vtc_hs, //行同步输出output O_vtc_de_valid, //视频数据有效 output O_vtc_user, //满足stream时序产生 user 信号,用于帧同步output O_vtc_last //满足stream时序产生 later 信号,用于每行结束);
reg hcnt = 12'd0; //视频水平方向,列计数器,寄存器reg vcnt = 12'd0; //视频垂直方向,行计数器,寄存器reg rst_cnt = 3'd0;//复位计数器,寄存器wire rst_sync = rst_cnt; //同步复位
always @(posedge I_vtc_clk or negedge I_vtc_rstn)begin //通过计数器产生同步复位 if(I_vtc_rstn == 1'b0) rst_cnt <= 3'd0; else if(rst_cnt == 1'b0) rst_cnt <= rst_cnt + 1'b1;end
//视频水平方向,列计数器always @(posedge I_vtc_clk)begin if(rst_sync == 1'b0) //复位 hcnt <= 12'd0; else if(hcnt < (H_FrameSize - 1'b1))//计数范围从0 ~ H_FrameSize-1 hcnt <= hcnt + 1'b1; else hcnt <= 12'd0;end
//视频垂直方向,行计数器,用于计数已经完成的行视频信号always @(posedge I_vtc_clk)begin if(rst_sync == 1'b0) vcnt <= 12'd0; else if(hcnt == (H_ActiveSize- 1'b1)) begin//视频水平方向,是否一行结束 vcnt <= (vcnt == (V_FrameSize - 1'b1)) ? 12'd0 : vcnt + 1'b1;//视频垂直方向,行计数器加1,计数范围0~V_FrameSize - 1 endend
wire hs_valid=hcnt < H_ActiveSize; //行信号有效像素部分wire vs_valid=vcnt < V_ActiveSize; //场信号有效像素部分wire vtc_hs =(hcnt >= H_SyncStart && hcnt < H_SyncEnd);//产生hs,行同步信号wire vtc_vs =(vcnt > V_SyncStart && vcnt <= V_SyncEnd);//产生vs,场同步信号 wire vtc_de =hs_valid && vs_valid;//只有当视频水平方向,列有效和视频垂直方向,行同时有效,视频数据部分才是有效
//**********************video stream video rgb***************************//如果是输入RGB时序,那么转为stream时序reg vtc_vs_r1;reg vtc_hs_r1;reg vtc_de_r1;reg vtc_user_r1 ,vtc_user_r2;reg vtc_valid_r1,vtc_valid_r2;reg vtc_last_r2;reg vs_start;
always @(posedge I_vtc_clk )begin if(rst_sync == 1'b0) //复位 vs_start <= 1'b0; else if(vtc_user_r1)//清除VS帧同步 vs_start <= 1'b0; else if(vtc_vs && vtc_vs_r1==1'b0)//当vtc_vs发生上升沿跳变代表一帧开始 vs_start <= 1'b1;end
always @(posedge I_vtc_clk)begin vtc_vs_r1 <= vtc_vs; vtc_hs_r1 <= vtc_hs; vtc_user_r1<= ~vtc_user_r1 & vs_start & vtc_de;//vtc_user延迟1拍 vtc_last_r2<= ~vtc_de & vtc_valid_r1; //产生stream video last 延迟于数据输入2拍 vtc_valid_r1 <= vtc_de;//vtc_valid延迟1拍 vtc_valid_r2 <= vtc_valid_r1;//vtc_valid对输入信号延迟2拍,以和vtc_last_r2信号配套同步 vtc_user_r2<= vtc_user_r1; //vtc_user 对输入信号延迟2拍,以和vtc_last_r2信号配套同步 end
assign O_vtc_vs =vtc_vs_r1;assign O_vtc_hs =vtc_hs_r1;assign O_vtc_de_valid =vtc_valid_r2;assign O_vtc_user =vtc_user_r2;assign O_vtc_last =vtc_last_r2;
endmodule
4 RTL仿真4.1 仿真激励文件为简化仿真,这里模拟的视频格式为320*5 即一行的有效数据为350个像素,一帧数据有5行像素数据。
/*************视频时序测试仿真文件*************************************************************************************************************/
`timescale 1ns / 1ns //仿真时间刻度/精度
module vtc_tb;
localparam SYS_TIME = 20;//系统时钟周期20ns
reg I_vtc_rstn,I_vtc_clk;wire O_vid_vs,O_vid_hs,O_vtc_de_valid,O_vtc_user,O_vtc_last;
//例化视频时序产生模块uivtc#(.H_ActiveSize(320), //视频时间参数,行视频信号,一行有效(需要显示的部分)像素所占的时钟数,一个时钟对应一个有效像素,设置320个像素.H_FrameSize(320+88+44+239),//视频时间参数,行视频信号,一行视频信号总计占用的时钟数.H_SyncStart(320+88), //视频时间参数,行同步开始,即多少时钟数后开始产生行同步信号.H_SyncEnd(320+88+44), //视频时间参数,行同步结束,即多少时钟数后停止产生行同步信号,之后就是行数据有效数据部分.V_ActiveSize(5), //视频时间参数,场视频信号,一帧图像所占用的有效(需要显示的部分)行数量,通常说的视频分辨率即H_ActiveSize*V_ActiveSize.V_FrameSize(5+4+5+28), //视频时间参数,场视频信号,一帧视频信号总计占用的行数量.V_SyncStart(5+4), //视频时间参数,场同步开始,即多少行数后开始产生场同步信号.V_SyncEnd (5+4+5) //视频时间参数,场同步结束,即多少行数后停止产生场同步信号,之后就是场有效数据部分)uivtc_inst(.I_vtc_clk(I_vtc_clk),//系统时钟.I_vtc_rstn(I_vtc_rstn),//系统复位.O_vtc_vs(O_vid_vs), //图形的vs信号.O_vtc_hs(O_vid_hs), //图形的hs信号.O_vtc_de_valid(O_vtc_de_valid), //de数据有效信号.O_vtc_user(O_vtc_user), //满足stream时序产生 user 信号,用于帧同步.O_vtc_last(O_vtc_last) //满足stream时序产生 later 信号,用于每行结束);
initial begin I_vtc_clk= 1'b0; I_vtc_rstn = 1'b0; #100; I_vtc_rstn = 1'b1;end
always #(SYS_TIME/2) I_vtc_clk= ~I_vtc_clk;
endmodule
4.2 仿真结果5 分辨率以及时钟计算方法如果是标准分辨率,建议大家以标准分辨率参数直接填入,如果不是标准分辨率则根据实际情况可以用接近标准分辨率的参数去修改相关参数。比如对于标准分辨率1080*1920*60的分辨率通常采用148.5MHZ的像素时钟。此时我们可以给出以下参数设置:
H_ActiveSize =1920H_SyncStart =1920+88H_SyncEnd =1920+88+44H_FrameSize =1920+88+44+148V_ActiveSize =1080V_SyncStart =1080+4V_SyncEnd =1080+4+5V_FrameSize =1080+4+5+36
计算分辨率和时钟的推断可以用一个关键公式 像素时钟= H_FrameSize* V_FrameSize*帧率,但是通常我们只会知道,H_ActiveSize、V_ActiveSize以及帧率,而像素时钟和其他参数都需要我们自己设置。 可以先以以上标准1080*1920*60的分辨率计算下:H_FrameSize* V_FrameSize*帧率 = 2,200* 1,125*60= 148,500,000,在时钟晶振足够精确的情况下,可以确保帧率以恒定60fps输出。但是很多时候如果某个参数不能满足要求,比如系统时钟只能提供140MHZ的情况,那么我们也可以重新调整参数,尽量来接近标准分辨率。比如当以140MHZ输出1080*1920*60fps的视频时,我们给出以下参数:
H_ActiveSize =1920H_SyncStart =1920+88H_SyncEnd =1920+88+44H_FrameSize =1920+88+44+71
V_ActiveSize =1080V_SyncStart =1080+4V_SyncEnd =1080+4+5V_FrameSize =1080+4+5+16
H_FrameSize* V_FrameSize *帧率=2,123*1099*60=139,990,620 这样每一帧的精确度误差为0.000067。对于140MHZ的时钟输出帧率会稍微快点。6 常用系统分辨率对于148.5MHZ像素时钟,输出1080*1920*60
H_ActiveSize =1920H_SyncStart =1920+88H_SyncEnd =1920+88+44H_FrameSize =1920+88+44+148V_ActiveSize =1080V_SyncStart =1080+4V_SyncEnd =1080+4+5V_FrameSize =1080+4+5+36
对于74.25MHZ像素时钟,输出1280*720*60
H_ActiveSize =1280H_SyncStart =1280+110H_SyncEnd =1280+110+ 40H_FrameSize =1280+110+ 40+220V_ActiveSize =720V_SyncStart =720+4V_SyncEnd =720+4+5V_FrameSize =720+4+5+21
对于42MHZ像素时钟,输出640*480*60
H_ActiveSize =640H_SyncStart =640+16H_SyncEnd =640+16+96H_FrameSize =640+16+96+48V_ActiveSize =480V_SyncStart =480+9V_SyncEnd =480+9+2V_FrameSize =480+9+2+34
对于非标准分辨率,用户可以以上面介绍的方法计算相近参数。比如对于非标准140MHZ像素时钟,输出1080*1920*60
H_ActiveSize =1920H_SyncStart =1920+88H_SyncEnd =1920+88+44H_FrameSize =1920+88+44+71
V_ActiveSize =1080V_SyncStart =1080+4V_SyncEnd =1080+4+5V_FrameSize =1080+4+5+16
比如对于非标准75MHZ像素时钟,输出1280*720*60
H_ActiveSize =1280H_SyncStart =1280+88H_SyncEnd =1280+88+44H_FrameSize =1280+88+44+239
V_ActiveSize =720V_SyncStart =720+4V_SyncEnd =720+4+5V_FrameSize =720+4+5+28
页:
[1]