本帖最后由 UT发布 于 2025-4-19 09:55 编辑
软件版本: TD_ 5.6.4 _Release_ 97693
操作系统: WIN11 64bit
硬件平台:适用安路 (Anlogic)FPGA
1概述 Vi deo Timing Con trol ler 缩写 V TC是我们在所有涉及 F PGA图像、 F PGA视频类方案中经常用到的一种用于产生视频时序的控制器。 本课以 VGA 为切入点 ,学习视频传输的基本知识和相关概念,以及视频时序的控制器的相关内容。
1.1 显示器发展 1.1.1 屏幕显示技术的变化 显示器如今已经成为我们日常生活中不可或缺的一部分,随着显示器技术的不断发展和创新,从最早的黑白 CRT 到今天的 MicroLED ,显示器行业已经发生了翻天覆地的改变,为我们提供更好的视觉体验,本章先和大家聊一聊显示器的发展历史。
CRT 显示器 :
CRT 的全称是 Cathode Ray Tube ,即阴极射线管, CRT 显示器的成像原理是将输入的模拟信号经过放大,变换后直接驱动电子枪扫描屏幕,电子枪发射出来的电子光束撞击到在涂有荧光粉的屏幕上,产生 RGB 三基色(红、绿、蓝),合成一个彩色像素,电子光束由上到下、由左到右依次扫描屏幕,从而形成图像。由于起初阴极射线需保证发射点到屏幕任何一点半径需等长,所以屏幕就必须得是一个弧形,而为了屏幕做大,显示器的厚度也就越厚。
CRT显示器
液晶显示器:
在 CRT 显示器飞速发展的几年期间,也诞生了 LCD ( Liquid Crystal Display )液晶显示技术,由众多细小的液晶颗粒按照矩阵的形式排布而组成的显示屏,因此 LCD 显示屏的物理像素数量是确定的,每个像素点的颜色都可以对应一个图像数据。图像数据是数字信号,采用“电信号”显示方式,通过在液晶层中加电,改变对液晶像素点单元施加电压的电压大小,使用色彩滤光片,将白色光分解成红、绿、蓝三种基色的光,然后通过液晶面板控制光的透过与阻挡,从而显示出图像。 LCD 显示器的发展让显示设备彻底摆脱了厚重的机身,也为便携式计算机的出现创造了可能。
LCD显示器
1.1.2 视频接口的变化 显示器显示画面质量的好坏,不仅与显示器有关,还与视频接口有直接关系。 显示器接口是计算机与外部显示设备之间进行数据传输和连接的通道 ,随着视频技术的发展,人们对于视频画面质量的显示也提出了更高的要求,这也推动了显示器视频接口的发展,本文介绍几种常见的显示接口及其特点。
CVBS 接口:
CVBS 将音频、视频分离的视频接口,一般由三个颜色组成,黄色的“ V ”代表连接混合视频信号,白色的“ L ”代表左声道音频信号,红色的“ R ”代表右声道的音频信号,常用于电视、 DVD 等产品。
S-VIDEO 接口:
S-Video 全称是 Separate Video ,也称为 Super Video ,将色度,亮度分离的视频信号,提高了稳定性。 S-Video 接口它实际上是一种五芯接口,由两路视频亮度信号、两路视频色度信号和一路公共屏蔽地线共五条芯线组成,避免了视频设备内信号串扰而产生的图像失真,极大地提高了图像的清晰度。
VGA 接口:
1987 年,第一台带有 VGA 模拟信号接口的显示器由 IBM 发布, VGA 接口是一种 D 型接口,上面共有 15 针空,分成三排,每排五个,它传输红、绿、蓝模拟信号以及同步信号 ( 水平和垂直信号 ) ,可以提供 640 x 480 分辨率的彩色显示屏,一次可以显示 16 种颜色,当把分辨率降低到 320 x 200 ,则显示 256 种颜色。 VGA 接口是显卡上应用最为广泛的接口类型,从 CRT 显示器时代开始, VGA 接口就被使用,并且一直沿用至今。由于液晶显示器发展比 CRT 显示技术晚,模拟信号驱动的 VGA 接口已经在显示器上得到广泛的使用,为了能够兼容传统的显示接口 VGA ,液晶显示器通过内部电路实现了对 VGA 接口的完全兼容。
当使用 VGA 接口传输图像时,生成的图像数字信息要先经过显示驱动芯片(如显卡) D/A (数字 / 模拟) 转换器 转换为 R 、 G 、 B 三原色信号和行、场同步信号,由 VGA 线缆送到显示器的 VGA 接口,对于 CRT 显示器,这些模拟信号会直接被放大后用于驱动电子枪发射电子,对于液晶显示器,则需要使用 A/D (模拟 / 数字) 转换器 将模拟信号再转换为数字信号后,去驱动 RGB 接口的液晶显示屏显示图像。
DVI 接口:
由于 VGA 接口采用的是模拟信号传输,在 CRT 显示器上使用时可以直接生成图像,在 LCD 显示器使用时,需要再配置 A/D (模拟 / 数字) 转换器 ,而在 D/A 和 A/D 两次转换的过程中,不可避免缺失一些图像细节。 1999 年, Intel 发明了高速传输数字信号的 DVI 接口,设计的初衷是用来传输未经 压缩 的数字化视频,相比 VGA 接口来说,视频传输的清晰度更高。
HDMI 接口:
HDMI 接口是高清多媒体接口,也是现在的主流显示器接口,可以同时传输未经 压缩 的视频、音频的数字信号。 HDMI1 可以传输 1080@60Hz 全高清的影像输出,带宽达到 4.85Gbps 。到了 2013 年, HDMI2.0 版本推出,带宽达到 18Gbps ,可以支持 4K@60FPS 画面输出。目前的 HDMI2.1 接口,可提供 48Gbps 的带宽,并且支持 8K@60Hz 以及 4K@120Hz 视频传输,现阶段主要还是以 HDMI2.0 为主。
DP 接口:
DP ( DisplayPort )接口,可以同时传输视频、音频的数字信号,相比 HDMI 接口, DP 接口拥有更大的带宽, 2009 年的 DP1.2 接口的带宽达到 21.6bps , 2016 年推出的 DP1.4 接口带宽已经达到了 32.4Gbps ,接近 HDMI2.0 接口带宽的 2 倍,可以支持 8K@60Hz 以及 4K@120Hz 输出,现在 DP1.4 接口已成为大部分显示器的标配接口。到了 2019 年, DP2.0 推出,带宽达到 80Gbps ,速度是 HDMI2.1 的 1.6 倍左右。
1.2 分辨率 当提及电子设备的显示器时,就会提及一个词 “ 分辨率”,例如1080P 分辨率、 2K 分辨率、 4K 分辨率, 分辨率是决定屏幕的清晰程度的重要参数。分辨率只是数学上的一个概念,仅仅是用来表示横向和纵向有多少个像素点,以 1080 P 分辨率为例做说明:它的意思是,这块屏幕横向分布了 1920 列像素,在纵向分为 1080 行像素 ,那么一张分辨率为 1920 x 1080 的 图像分辨率就达到了 2073600 像素 ,分辨率越高,所包含的像素就越多,图像就越清晰,它也会增加文件占用的存储空间。
上图为 1080P 显示器的像素点排布示意图, X 轴是显示器的横轴, Y 轴是显示器的竖轴, 图中的一个小方块就是一个像素点。2K 就是 2560*1440 个像素点 ,4K就是 3840*2160 个像素点。 显示屏大小尺寸固定时,显示分辨率越高图像越清晰,比如看视频时我们可以选择视频的清晰度,分辨率越高视频越清晰;反之,显示分辨率一定的情况下,显示屏越小图像越清晰,比如 1080P 的 5 寸的手机要比 1080P 的 24 寸显示器显示的图像细腻。
常见的显示屏分辨率标准:
1.3 刷新率 刷新率( FPS , Frames Per Second ),单位为 Hz ,即每秒传输图像的帧数(帧数 /s )。每秒钟帧数 (FPS) 愈多,一帧是静止的图象;快速连续地显示不同帧便形成了运动的假象,每秒钟帧数愈多,所显示的动作就会愈流畅。例如: 60Hz 的刷新率刷也就是指屏幕一秒内只扫描 60 次,即 60 帧 / 秒。
2 VGA 成像原理及时序标准 由上面显示器的发展介绍中,我们了解到VGA 标准兴起的时候, 模拟信号驱动的 VGA 接口已经在显示器上得到广泛的使用,当时 常见的彩色显示器一般由 CRT (阴极射线管)构成, 我们以白底的”米联客 logo ”为例,将图片完全显示在 CRT 显示器有效区域上,并对比现在大规模使用的液晶显示器,来介绍显示器完整展现这幅图的各个阶段 。
1 、 CRT 显示器
一幅图像,可以理解成由多个像素点从左向右依次平铺构成的, CRT 显示器基于电子枪,每次只能点亮一个像素点上的荧光粉,类似我们看书的方式,从页面的左上方开始逐字按行从左到右阅读,显示一帧图像电子枪是按照‘ Z ’形在运动,如上图红色箭头的运动方向,当扫描速度很快的时候看起来就是一幅完成的画面了。
行扫描过程:
CRT 显示器扫描是按照一行一行的方式进行的,如上图红色实心箭头运动轨迹,扫描完一行有效数据段之后不会立马返回,而是会继续向右扫描一段区域,这个区域称为右边界区域( horizontal right border ),该区域不在有效的显示范围内,对应的荧光屏玻璃上没有荧光粉也不能被点亮,可以理解为显示器右边的黑边。同样,显示器左边也有这样一段黑边,在开始显示有效数据之前,电子枪扫描到的这段区域也没有荧光粉,不会显示图像 , 这个区域称为左边界区域( horizontal left border ),如上图所示的蓝色区域范围为边界区域,
当电子枪扫描过了右侧没有荧光粉的边界区域后,并不会自动回到最左边准备下一行,而是需要有一个通知信号,即行同步信号脉冲( horizontal sync pulse , HSYC )。再没有收到行同步信号脉冲之前,需要关闭电子枪以实现消隐,这段时间就称为 horizontal front porch ,消隐是为了不影响已经点亮的像从最右侧回到显示屏的最左侧,如图所示红素点。当收到 HSYC 信号,电子枪会在一定时间内色虚线箭头运动轨迹,这个回去的过程需要耗费一定的时间,这个时间就称为 horizontal back porch 。当 HSYC 信号结束以后,电子枪就会重新打开,就可以显示新的一行图像数据了。
场扫描过程:
对于 CRT 显示器,电子枪扫描完所有有效行的图像后会继续向下扫描一段区域,这个区域称为下边界区域( vertical bottom border ),该区域不在有效的显示范围内,对应的荧光屏玻璃上没有荧光粉也不能被点亮,可以理解为显示器下边的黑边。同样的,显示器上边也有这样一段黑边,在扫描有效数据之前,电子枪扫描到的这段区域不会显示图像 , 这个区域称为上边界区域( vertical top border )。
当电子枪扫描一场图像到达荧光屏的最下方后,其并不会自动回到最上边,而是需要有一个通知信号,即场同步信号脉冲( vertical sync pulse , VSYC )。再没有收到场同步信号脉冲之前,需要关闭电子枪以实现消隐,这段时间就称为 vertical front porch ,消隐是为了不影响已经点亮的像素点。当收到 VSYC 信号,电子枪会在一定时间内从最下方回到最上方,如图所示红色虚线箭头运动轨迹,这个回去的过程需要耗费一定的时间,这个时间就称为 vertical back porch 。当 VSYC 信号结束以后,电子枪就会重新打开,就可以显示新的一行图像数据了。
2 、 LCD 显示器
由于 CRT 显示器采用电子枪显示图像,不可避免而存在黑边的原因,然而现在使用的液晶显示器不需要电子枪了,还有存在黑边是因为 LCD 屏幕内部是有一个 IC , IC 是一套集成电路 芯片 装置,用来对透明电极上电位信号 的相位、峰值、频率等进行调整与控制,从而建立起驱动电场,从而实现液晶显示图像。然而发送一行或者一帧数据给 IC , IC 需要反应时间去识别一行数据扫描完需要要换行,或者一帧图像扫描完了需要扫描下一帧图像。因此,在 LCD 屏幕中需要存在 boder 这些参数来锁定有效的像素数据。
3 像素时钟 像素时钟( Pixel clock , pclk ),也叫 RGB clock 或 Dot clock ,即 RGB 的时钟信号,一个基准时钟 clk 对应一个像素点,根据上面我们分析的行时序和场时序,显示一帧图像需要的基准时钟 数 N(CLK) = H_FrameEnd * V_FrameEnd ,结合刷新率,可以计算像素时钟 = H_FrameEnd * V_FrameEnd * 帧率。 如果是标准分辨率,建议大家以标准分辨率参数直接填入,如果不是标准分辨率则根据实际情况可以用接近标准分辨率的参数去修改相关参数。视频数据在 H _AcitiveSize 和 V_AcitiveSize 同时有效时候有效,显示屏上的显示效果如下图所示 :
H_ActiveSize: 有效显示区域( Visible area )
H_Syncstart: 有效显示区域 + 前沿 (Front Porch+Right Border)
H_SyncEnd: 有效显示区域 + 前沿 +HSYC(Sync Pulse)
H_FrameEnd: 有效显示区域 + 前沿 +HSYC+ 后沿 (Back Porch+Left Border)
V_ActiveSize: 有效显示区域( Visible area )
V_Syncstart: 有效显示区域 + 前沿 (Front Porch+Bottom Border)
V_SyncEnd: 有效显示区域 + 前沿 +VSYC(Sync Pulse)
V_FrameEnd: 有效显示区域 + 前沿 +VSYC+ 后沿 (Back Porch+Top Border)
常用 标准 系统 分辨率时序参数:
比如对于分辨率1920*1 080*60的分辨率通常采用 1 48.5MHZ的像素时钟。H_FrameSize* V_FrameSize*帧率 = 2,200* 1,125*60= 148,500,000,在时钟晶振足够精确的情况下,可以确保帧率以恒定 6 0fps输出。我们可以给出以下参数设置:
H_ActiveSize =1920
H_SyncStart =1920+88
H_SyncEnd =1920+88+44
H_FrameSize =1920+88+44+148
V_ActiveSize =1080
V_SyncStart =1080+4
V_SyncEnd =1080+4+5
V_FrameSize =1080+4+5+36 复制代码
但是很多时候如果某个参数不能满足要求,那么我们也可以重新调整参数,尽量来接近标准分辨率。
对于非标准分辨率,比如当以 1 40MHZ输出 1 080*1920*60的视频时,H_FrameSize* V_FrameSize *帧率 = 2,123*1099*60=139,990,620 这样每一帧的精确度误差为0.000067,用户可以以上面介绍的方法计算相近参数。
对于 1 40MHZ的时钟输出帧率会稍微快点。我们给出以下参数:
H_ActiveSize =1920
H_SyncStart =1920+88
H_SyncEnd =1920+88+44
H_FrameSize =1920+88+44+71
V_ActiveSize =1080
V_SyncStart =1080+4
V_SyncEnd =1080+4+5
V_FrameSize =1080+4+5+16 复制代码
对于非标准75MHZ像素时钟,输出1280*720*60
H_ActiveSize =1280
H_SyncStart =1280+88
H_SyncEnd =1280+88+44
H_FrameSize =1280+88+44+239
V_ActiveSize =720
V_SyncStart =720+4
V_SyncEnd =720+4+5
V_FrameSize =720+4+5+28 复制代码
4 VTC控制器设计 通过学习VGA 时序,我们知道设计一个VGA 控制器需要包括行计数器、场计数器、行、场同步信号,有效图像数据输出的使能信号。本实验以 1920 *108 0的分辨率为例,使用 2 个计数器分别产生 h s行时序 v s场时序中各个时间参数信号,以及有效图像数据输出的d e使能信号。
hcnt 列计数器 :
每 1 个像素时钟列计数器 hcnt 加 1 ,一行像素扫描完成后,计数器清零并重新计数。
//视频水平方向,列计数器
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 复制代码
vcnt 行计数器 :
行计数器 vcnt 的 前提条件是 列计数器 hcnt 计数到设定值, 行计数器 vcnt 加 1 ,所有行的像素扫描完成后,计数器清零并重新计数。
//视频垂直方向,行计数器,用于计数已经完成的行视频信号
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
end
end 复制代码
行场同步信号 :
根据 VGA时序,我们知道在消隐段期间, 产生行同步信号和场同步信号, 我们设置行同步信号 和场同步信号为 高电平 时有效。根据行、 列计数器的值 ,当相应的计数器计数到消隐时间段时,拉高同步信号。 SyncStart
表示边界区域扫描完成即将进入消隐区域,此时产生行 / 场同步信号, SyncEnd 表示行 / 场同步信号产生完成,边界区域扫描完成 即将进入边界区域。同时扫描到场有效显示区域和行有效显示区域时, vtc_de 信号拉高,表示数据有效。
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;//只有当视频水平方向,列有效和视频垂直方向,行同时有效,视频数据部分才是有效 复制代码
RGB时序转为 stream 时序 :
stream 是一种标准协议接口,可用于芯片内部的数据流传输,不同于内存数据传输相关协议,基础篇没有用到这个接口,这里只给出相关代码,详细介绍请参考“总线篇”。
//********************** 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; 复制代码
5 VTC源码
module uivtc#
(
parameter H_ActiveSize = 1920, //视频时间参数,行视频信号,一行有效(需要显示的部分)像素所占的时钟数,一个时钟对应一个有效像素
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_ActiveSize
parameter 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 [11:0] hcnt = 12'd0; //视频水平方向,列计数器,寄存器
reg [11:0] vcnt = 12'd0; //视频垂直方向,行计数器,寄存器
reg [2 :0] rst_cnt = 3'd0; //复位计数器,寄存器
wire rst_sync = rst_cnt[2]; //同步复位
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[2] == 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
end
end
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 复制代码
6 RTL仿真 6 . 1仿真激励文件 为简化仿真,这里模拟的视频格式为 320*5 即一行的有效数据为 350 个像素,一帧数据有 5 行像素数据。
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 复制代码
6 . 2仿真结果
7 常用系统分辨率 对于148.5MHZ像素时钟,输出1080*1920*60
H_ActiveSize =1920
H_SyncStart =1920+88
H_SyncEnd =1920+88+44
H_FrameSize =1920+88+44+148
V_ActiveSize =1080
V_SyncStart =1080+4
V_SyncEnd =1080+4+5
V_FrameSize =1080+4+5+36 复制代码
对于 74.25MHZ像素时钟,输出 1280*720*60
H_ActiveSize =1280
H_SyncStart =1280+110
H_SyncEnd =1280+110+ 40
H_FrameSize =1280+110+ 40+220
V_ActiveSize =720
V_SyncStart =720+4
V_SyncEnd =720+4+5
V_FrameSize =720+4+5+21 复制代码
H_ActiveSize =640
H_SyncStart =640+16
H_SyncEnd =640+16+96
H_FrameSize =640+16+96+48
V_ActiveSize =480
V_SyncStart =480+9
V_SyncEnd =480+9+2
V_FrameSize =480+9+2+34 复制代码
对于非标准分辨率,用户可以以上面介绍的方法计算相近参数。
比如对于非标准 140MHZ像素时钟,输出 1080*1920*60
H_ActiveSize =1920
H_SyncStart =1920+88
H_SyncEnd =1920+88+44
H_FrameSize =1920+88+44+71
V_ActiveSize =1080
V_SyncStart =1080+4
V_SyncEnd =1080+4+5
V_FrameSize =1080+4+5+16 复制代码
比如对于非标准 75MHZ像素时钟,输出 1280*720*60
H_ActiveSize =1280
H_SyncStart =1280+88
H_SyncEnd =1280+88+44
H_FrameSize =1280+88+44+239
V_ActiveSize =720
V_SyncStart =720+4
V_SyncEnd =720+4+5
V_FrameSize =720+4+5+28 复制代码