## 视频接口实验
### 1. 实验内容
通过本实验了解视频技术的基本概念,熟悉简单的视频信号处理方法。
本实验要求使用FPGA将从AV接口输入的CVBS复合视频广播信号转换为符合ITU-R 656标准的数字视频信号,同时提取场行同步信号,同时将该数字视频信号从隔行扫描转变为逐行扫描转换,最后将视频信号从YCbCr颜色空间转换为RGB颜色空间,由VGA接口输出显示在显示器上。
\\
\\
### 2. 实验原理
CVBS是模拟彩色电视是在未叠加声音信号和未调制到射频发射出去前的信号,其全称为Composite Video Blanking and Sync。CVBS主要由图像信号、复合同步信号和复合消隐信号三部分组成。图像信号是电视系统所传送的图像信息,它是在场扫描正程期间和行扫描正程期间内传送的。其它信号则是为了确保图像清晰和稳定而设置的辅助信号,其中复合消隐(含行、场消隐)信号,是为了消除行、场回扫期间的痕迹以使图像清晰;而复合同步(含行、场同步、槽脉冲和均衡脉冲)信号,则是为了确保电视机重现图像清晰与电视台发送图像严格同步,正确重现图像并使之稳定。这些辅助信号都是在行、场逆程期间传送的。其中图像信号具体表达如图 19 1所示,其中Y表示亮度信号,Cb表示饱和度,而Cr表示色度。
{{ :图19-1.jpg |图19-1 NTSC标准中CVBS具体表达形式}}
**图19-1 NTSC标准中CVBS具体表达形式**
目前主流的模拟彩色电视标准分为PAL、NTSC和SECAM三种。 每一种标准对应的CVBS信号的格式又各不相同,所以在模拟领域各种标准之间电视节目互相转换比较困难,为了方便各个标准的节目的交换,国际无线电咨询委员会就制定了相应的数字标准,具体将在章节2.2内介绍。
#### 2.1 ITU-R 601和ITU-R 656数字电视标准
##### 2.1.1 ITU-R 601介绍
1982年CCIR(International Radio Consultative Committee国际无线电咨询委员会)制定了彩色视频数字化标准,称为CCIR601标准,现改为ITU-R 601标准。该标准规定了彩色视频转换成数字图像时使用的采样频率,RGB和YCbCr两个彩色空间之间的转换关系等。
为了便于国际间的节目交换,为消除数字设备之间的制式差别,以及为了 625行电视系统(PAL)与 525行电视系统(NTSC)之间兼容,向着数字电视广播系统参数统一化、标准化迈出,在 1982年2月国际无线电咨询委员会(CCIR)第15次全会上,通过了601号建议,确定以分量编码为基础,即以亮度分量Y和两个色差分量R-Y、B-Y为基础进行编码,作为电视演播室数字编码的国际标准,601号建议单独规定了电视演播室的编码标准。该标准规定:
➢ 不论是PAL制,还是 NTSC制电视,Y、R-Y、B-Y三分量的抽样频率分别为13.5MHz、6.75MHz、6.75MHz。
➢ 抽样后采用线性量化,同时规定了每个样点的量化比特数,用于演播室的量化位数为10bit,用于传输为8bit。
➢ Y、R-Y、B-Y三分量样点之间比例为4:2:2。亮度信号的抽样频率为13.5MHz,每个色差信号的抽样频率为6.75MHz,其抽样频率之比为4:2:2,或者说,每数字有效行亮度信号的取样点数是720个,而每个色差信号的取样点数是360个,其取样点数之比也为4:2:2,这就是数字分量编码的4:2:2标准,也称为4:2:2格式,用作演播室数字设备及其联接或国际节目交换时的数字化标准。如图 19-2所示。
{{ :图19-2.png |图19-2 4:2:2图像格式含义}}
**图19-2 4:2:2图像格式含义**
➢ 进一步明确了模拟与数字行的对应关系,并规定从数字有效行末尾至基准时间样点的间隔,对 525行、60场/秒制式(NTSC)来说为16个样点,对625行、50场/秒制式(PAL)则为12 个样点。不论625行/50场或525行/60场,其数字有效行的亮度样点数都是720,色差信号的样点数均是360,这是为了便于制式转换。若亮度样点数被2除,就得到色差信号的数据。
##### 2.2.2 采样频率
为了保证信号的同步,采样频率必须是电视信号行频的倍数。CCIR为NTSC、PAL和SECAM制式制定的共同的电视图像采样标准:
**fs=13.5MHz**
这个采样频率正好是PAL、SECAM制行频的864倍,NTSC制行频的858倍,可以保证采样时采样时钟与行同步信号同步。对于4:2:2的采样格式,亮度信号用13.5MHz频率采样,两个色差信号分别用fs/2=6.75MHz的频率采样。除了标准的4:2:2格式之外,还有将色差信号的抽样频率取为3.375MHz的较低标准的4:1:1和4:2:0格式。另外还有为适合更高图像质量要求而将色差信号抽样频率取为13.5MHz的更高标准的4:4:4格式。
##### 2.2.3 分辨率
根据采样频率,可算出对于PAL和SECAM制式,每一扫描行采样864个样本点;对于NTSC制则是858个样本点。由于电视信号中每一行都包括一定的同步信号和回扫信号,故有效的图像信号样本点并没有那么多,CCIR 601规定对所有的制式,其每一行的有效样本点数为720点。不同的制式其每帧的有效行数不同,PAL和SECAM制为576行,NTSC制为484行。
##### 2.2.4 数据比特率
CCIR 601规定,每个样本点都按8位数字化,也即有256个等级。但实际上亮度信号占220级,色度信号占225级,其它位作同步、编码等控制用。如果按fs的采样率4:2:2的格式采样,则数字视频的数据比特率为:
**13.5(MHz)×8(bit)+2×6.75(MHz)×8(bit) = 27Mbyte/s**
##### 2.2.5 ITU-R BT.601与ITU-R BT.656的区别
ITU-R BT.601是16位数据传输,Y、U、V信号同时传输。ITU-R BT.656是YUV串行传输,不需要同步信号,8位数据传输,传输速率是601的2倍,先传Y,后传UV。656输出的是串行数据,行场同步信号嵌入在数据流中,也即是嵌入到图3所示的AV信号内,通过分析AV8bit数据可以得到行场同步信号;而601是并行数据,行场同步有单独输出。具体如图 19-3所示。其中行起始、结束的标准位为:FF 00 00 XX,根据该标准可以检出行同步。
{{ :图19-3.jpg |图19-3 ITU-R 601和ITU-R 656之间的区别}}
**图19-3 ITU-R 601和ITU-R 656之间的区别**
##### 2.2.6 将视频信号从隔行扫描转为逐行扫描
隔行扫描就是每一帧被分割为两场,每一场包含了一帧中所有的奇数扫描行或者偶数扫描行,通常是先扫描奇数行得到第一场,然后扫描偶数行得到第二场。由于视觉暂留效应,人眼将会看到平滑的运动而不是闪动的半帧半帧的图像。模拟数字电视信号均是隔行扫描信号,而目前大部分VGA显示器均使用的是逐行扫描,而在本实验中需要在VGA显示数字化后的模拟电视信号,所以需要将电视信号从隔行转换为逐行扫描。具体转换算法有很多种,在不同场合适应不同算法,在此采用了一种最简单的隔行转为逐行的算法:就是通过简单的重复每一行,每一场扩大为完整的一帧。
##### 2.2.7 ADV7181简介
ADV7181是美国ADI公司生产的一款低功耗的多功能数字视频解码芯片。它可以自动检测 NTSC、 PAL和 SECAM等标准的复合电视信号并将其转换为 16位或 8位的 IT U-R BT.656 YUV 4:2:2的视频数据输出格式。
ADV7181内部共有 240个控制寄存器用来对该芯片的功能和状态进行设置和查询。这些寄存器的取值对ADV7181的功能和状态的影响的详细内容可以参考 ADV7181的数据手册。 ADV7181的寄存器的取值分为默认值和设置值。它对应芯片设计的初始化功能状态;默认值是芯片复位后的寄存器缺省取值,设置值是通过I2C总线配置方式对这些控制寄存器的默认值进行修改,以达到重新设定 ADV7181的各种功能的目的。具体的向ADV7181的读写时序如图 19-4所示,其中A(s)是传输8bit数据后的ACK信号,此时该信号应该被拉低。
{{ :图19-4.png |图19-4 ADV7181的读写时序}}
**图19-4 ADV7181的读写时序**
\\
\\
### 3. 程序设计
#### 3.1 总体架构
整个程序由6个模块组成(图 19-5):\\
1. TE3_DVD2VGA是顶层模块,将各子模块实例化并连接各模块。\\
2. I2C_AV_Config模块负责配置ADV7181。\\
3. TV_to_VGA模块生成VGA所需的场合同步信号。\\
4. itu_r656_decoder模块根据ITU-R 656标准解码ADV7181给出的数据流,并将隔行扫描的信号转为逐行扫描的信号。\\
5. dul_port_c1024利用FPGA内部的双口RAM将一行信号重复转为两行信号。\\
6. YCbCr2RGB模块将YCbCr色度空间的数据转为RGB色度空间的数据。
{{ :图19-5.png |图19-5 程序总体架构}}
**图19-5 程序总体架构**
#### 3.2 TE3_DVD2VGA模块(TE3_DVD2VGA.v)
TE3_DVD2VGA是顶层模块,主要是起连接作用,将各个模块连接起来,其接口如下所示:
input OSC_27; //27 MHz时钟接口
input OSC_50; //50 MHz时钟接口
input RESET; //全局复位信号
inout I2C_SDAT; //I2C接口数据线
output I2C_SCLK; //I2C接口时钟线
output VGA_CLK; //VGA接口时钟信号
output VGA_HS; //VGA接口行同步信号
output VGA_VS; //VGA接口场同步信号
output VGA_BLANK; //VGA接口场消隐信号
output VGA_SYNC; //VGA接口同步信号
output [9:0] VGA_R; //VGA Red[9:0]
output [9:0] VGA_G; //VGA Green[9:0]
output [9:0] VGA_B; //VGA Blue[9:0]
input [7:0] TD_DATA; //TV Decoder的8bit数据信号
input TD_HS; //TV Decoder行同步信号
input TD_VS; //TV Decoder场同步信号
output TD_RESET; //TV Decoder复位信号
#### 3.3 I2C_AV_Config模块(I2C_AV_Config.v)
I2C接口模块,负责配置ADV7181,具体I2C的工作原理已在I2C接口实验介绍,在此仅给出其接口:
input iCLK; //时钟信号,50MHZ
input iRST_N; //异步复位信号
output iRST_N; // I2C串行时钟线
inout I2C_SDAT; // I2C串行数据线
#### 3.4 TV_to_VGA模块(TV_to_VGA.v)
实例化并连接itu_r656_decoder和YCbCr2RGB模块,根据itu_r656_decoder模块给出的两倍于ADV7181给出的TD_HS的信号mTD_HSx2,生成VGA接口所需的场行同步信号,其接口定义如下:
input OSC_27; //时钟:27MHz
input RESET; //系统复位
output VGA_BLANK; //VGA接口空白指示信号
output VGA_SYNC; //VGA接口同步信号
output VGA_CLOCK; //VGA接口时钟信号
output VGA_HS; //VGA接口行同步信号
output VGA_VS; //VGA接口场同步信号
output [9:0]VGA_R; //VGA红颜色信号
output [9:0]VGA_G; //VGA绿颜色信号
output [9:0]VGA_B; //VGA蓝颜色信号
input [7:0]TD_D; //TV Decoder的8bit数据信号
input TD_HS; //TV Decoder行同步信号
input TD_VS; //TV Decoder场同步信号
要注意的一点是,VGA的行同步信号VGA_HS的频率是ADV7181给出的行同步信号TD_HS频率的两倍。具体程序如下:
assign VGA_HS = oVGA_H_SYNC;
assign VGA_VS = oVGA_V_SYNC;
always@(posedge OSC_27 or negedge sync_en) begin
if(!sync_en) begin
Pre_HS <= 0; //存储TV_Decoder输出的行同步信号
mACT_HS <= 0; //行像素信号有效指示位
H_Cont <= 0; //行内像素点计数器
oVGA_H_SYNC <= 0; //向VGA输出的行同步信号
end
else begin
Pre_HS<=mTD_HSx2;// itu_r656_decoder模块输出的两倍于TD_HS的行同步信号
if( {Pre_HS,mTD_HSx2}==2'b10 )
mACT_HS <= 1;
if(mACT_HS) begin
if( H_Cont < 852 ) //像素点计数器自动加一。
H_Cont <= H_Cont+1;
else begin
H_Cont <= 0;
mACT_HS <= 0;
end
if( H_Cont < H_SYNC_CYC ) //根据像素点计数器产生行同步信号。
oVGA_H_SYNC <= 0;
else
oVGA_H_SYNC <= 1;
end
else begin
oVGA_H_SYNC <= 0;
H_Cont <= 0;
end
end
end
/*根据两倍于ADV7181给出的行同步TD_HS的信号mTD_HSx2生成VGA所需的场同步信号oVGA_V_SYNC*/
always@(posedge OSC_27 or negedge sync_en) begin
if(!sync_en) begin
Pre_VS <= 1; //存储TV_Decoder输出的场同步信号
mACT_VS <= 0; //视频场内行有效指示位
V_Cont <= 0; //视频场内行计数器
oVGA_V_SYNC <= 0; //向VGA输出的帧同步信号
end
else begin
Pre_VS <= TD_VS;//ADV7181给出的场同步信号
if({Pre_VS,TD_VS}==2'b01)
mACT_VS <= 1;
if( (H_Cont==1) && mACT_VS) begin
if( V_Cont < 524 ) //行计数器
V_Cont <= V_Cont+1;
else
V_Cont <= 0;
if( V_Cont < V_SYNC_CYC ) //根据行计数器生成场同步信号
oVGA_V_SYNC <= 0;
else
oVGA_V_SYNC <= 1;
end
end
end
#### 3.5 itu_r656_decoder模块(itu_r656_decoder.v)
根据ITU-R BT.656标准解码ADV7181给出的数据流,并将隔行扫描的信号转为符合VGA接口标准的逐行扫描的信号。其接口如下所示:
input CLOCK //27 MHz时钟接口
input [7:0]TD_D //TV Decoder的8bit位宽的数据信号
input TD_HS //TV Decoder行同步信号
input TD_VS //TV Decoder场同步信号
output [7:0]Y //解出来的YCbCr色度空间内的亮度Y信号
output [7:0]Cb //解出来的YCbCr色度空间内的色度Cb信号
output [7:0]Cr //解出来的YCbCr色度空间内的饱和度Cr信号
output reg HSx2 //两倍于TD_HS的行同步信号
output blank //VGA接口空白指示信号
该模块首先需要解码出场行同步信号。具体程序如下所示:
// 检测行场同步信号
reg[7:0]R1,R2,R3;
reg[7:0]RR1,RR2,RR3;
wire Y_check=( (R3==8'hff) && (R2==8'h00) && (R1==8'h00) )?1:0; //根据标准检测
//行同步信号
always @(posedge CLOCK) begin
RR1=TD_D;//通过8位宽的移位寄存器暂存3个ADV7181输出的8bit数据,
//以用来行同步检测
RR2=R1;
RR3=R2;
end
always @(negedge CLOCK) begin
R1=RR1;
R2=RR2;
R3=RR3;
end
/////解出场行指示信号
reg START,Field;
always @(posedge CLOCK) begin
if (Y_check==1) begin
START=~TD_D[4]; //检测行开始信号
Field= TD_D[6]; //检测出奇偶场
end
end
因为需要将隔行扫描转为逐行扫描,而逐行扫描的行同步信号需要为隔行扫描行同步信号的二倍。具体程序如下所示:
//用27Mhz系统时钟,记录每一行内图像数据的个数,也就是行周期内像素点的个数。
reg [10:0]H_COUNTER;//行周期内像素计数器
reg [10:0]RH_COUNTER;//行周期内像素的总数
always @(posedge CLOCK) begin
if (TD_HS) H_COUNTER=0;
else H_COUNTER=H_COUNTER+1;
end
always @(posedge TD_HS) begin
RH_COUNTER=H_COUNTER;
end
//根据像素点计数器生成ITU-R 656规定的视频场内行周期两倍的信号。
always @(posedge CLOCK) begin
if (
((H_COUNTER >= 0) && (H_COUNTER < `sync)) ||
((H_COUNTER >= RH_COUNTER[10:1]) && (H_COUNTER < (RH_COUNTER[10:1]+`sync+1)))
)
HSx2=0;
else
HSx2=1;
end
上面程序中生成了一个两倍于隔行扫描行同步的信号,根据该信号生成逐行扫描信号所需的场合同步信号。
#### 3.6 dul_port_c1024模块(dul_port_c1024.v)
利用FPGA内部的双口RAM将一行场信号重复转为两行场信号。其实现主要原理为:双口RAM写入时钟为13.5MHz,而读取时钟为27MHz,通过这样就可以将一行信号转为两行信号,实现隔行向逐行转换。其接口为:
input [7:0]iDATA, //输入信号
input iHSYNC, //行同步信号,和TD_HS相同频率
input iHSYNCx2, //行同步信号,频率两倍于TD_HS,同时其中场消影期间为0
input Y_CLOCK, //时钟:13.5MHz
input Y_CLOCKx2, //时钟:27MHz
input field, //电视信号奇场偶场指示信号
input VS, //TV Decoder场同步信号
output [7:0]oDATA //输出信号
具体程序如下所示:
/*counter:写入RAM的地址信号,其在输入的行同步信号TD_HS有效时归0,同时其自动增加的频率为13.5Mhz*/
reg [9:0]counter;
always@(posedge iHSYNC or posedge Y_CLOCK)begin
if (iHSYNC)counter=0;else counter=counter+1;
end
/*counterx2:读取RAM的地址信号,其在输入的行同步信号iHSYNCx2有效时归0,而iHSYNCx2为TD_HS的两倍,同时其自动增加的频率为27Mhz;通过在一个TD_HS行周期内counterx2归0两次,同时将读取地址信号counterx2增加频率两倍于写入地址信号counter,从而实现:将每一场的行信号重复两次以实现从隔行扫描向逐行扫描的转换.*/ reg [9:0] counterx2;
always@(negedge iHSYNCx2 or posedge Y_CLOCKx2) begin
if (!iHSYNCx2) counterx2=0; else counterx2=counterx2+1;
end
/*不论I为0为1,其写入接口时钟始终为:13.5MHz,而读出接口时钟始终为:27MHz*/
wire [7:0]DATA_a,DATA_b;
wire I_a= I;
wire I_b=~I;
wire [9:0]COUNTER_a= (I)?counter:counterx2;
wire [9:0]COUNTER_b=(!I)?counter:counterx2;
wire CLOCK_a= (I)?~Y_CLOCK:~Y_CLOCKx2;
wire CLOCK_b=(!I)?~Y_CLOCK:~Y_CLOCKx2;
////datax2 output/////
assign oDATA=(!I)?DATA_a:DATA_b;
/////双口RAM//////
RAM2 u2(
.data_a (iDATA), //a port
.wren_a (I_a),
.address_a (COUNTER_a),
.clock_a (CLOCK_a),
.q_a (DATA_a),
.data_b (iDATA), //b port
.wren_b (I_b),
.address_b (COUNTER_b),
.clock_b (CLOCK_b),
.q_b (DATA_b)
);
#### 3.7 YCbCr2RGB模块(YCbCr2RGB.v)
YCbCr2RGB利用FPGA内部的乘法器实现视频信号从YCbCr色度空间向RGB色度空间的转换。
\\
\\
### 4. 演示程序文件说明
|文件名|功能|
|TE3_DVD2VGA.v|顶层模块|
|I2C_AV_Config.v|I2C接口顶层模块|
|I2C_Controller.v|I2C接口控制模块|
|TV_to_VGA.v|解码ITU-R 656标准模块|
|itu_r656_decoder.v|解码ITU-R 656标准模块|
|dul_port_c1024.v|隔行转逐行模块|
|YCbCr2RGB.v|YCbCr色度空间向RGB色度空间转换模块|
\\
\\
### 5. 演示程序使用
演示设备:核心板、扩展板、VGA接口显示器、支持NTSC输出的DVD播放器。
演示方法:将DVD的输出信号线连接到开发板的J22上,同时将显示器连接到开发板的VGA接口上,开发板上电后,将本程序下载到开发板上即可通过显示器观看DVD输出的视频信号。