DE2_TV例程的几点说明

一、摘要

  对DE2_TV例程做了分析,并阐明了相关概念。

二、实验平台

  硬件平台:DIY_DE2

  软件平台:Quartus II 9.0 

三、一些概念及说明

1、PAL和NTSC的区别

  常见的电视信号制式是PAL和NTSC,另外还有SECAM等。 NTSC即正交平衡调幅制,PAL为逐行倒像正交平衡调幅制。 
(1)PAL电视标准 
  PAL电视标准,每秒25帧,电视扫描线为625线,奇场在前,偶场在后,标准的数字化PAL电视标准分辨率为720*576, 24比特的色彩位深,画面的宽高比为4:3,PAL电视标准用于中国、欧洲等国家和地区。 
(2)NTSC电视标准 
  NTSC电视标准,每秒29.97帧(简化为30帧),电视扫描线为525线,偶场在前,奇场在后,标准的数字化NTSC电视标准分辨率为720*486,24比特的色彩位深,画面的宽高比为4:3。NTSC电视标准用于美、日等国家和地区。

  下面重点说一下PAL制式。PAL一帧的数据行格式如图1所示。

DE2_TV例程的几点说明_第1张图片

图1 一帧图像数据行格式

  对于有效数据行的格式,如图2所示。

DE2_TV例程的几点说明_第2张图片

图2 有效视频行的数据格式

  如上图所示,EAV和SAV为嵌入式控制字,分别表示有效视频的终点和起点。EAV和SAV均为4个字节构成,前3个字节FF、00、00为固定头,“XY”为控制字。“XY”的8个bit含义如下:

  • Bit7(Const),常数,总为1。
  • Bit6(F),场同步信号,表示该行数据处于奇场还是偶场。
  • Bit5(V),垂直同步信号,表示处于场消隐区间还是正程区间(有效数据行)。
  • Bit4(H),水平同步信号,表示是“SAV”还是“EAV”。
  • Bit3-0(P3P2P1P0),纠错位。P3=V(XOR)H;P2=F(XOR)H;P1=F(XOR)V;P0=F(XOR)V(XOR)H。

EAV与SAV的详细定义如表1所示。

表1

Bit7

Bit6

Bit5

Bit4

Bit3-0(P3P2P1P0)

Hex

Description

1

0

0

0

0000

0x80

Even,Active,SAV

1

0

0

1

1101

0x9d

Even, Active,EAV

1

0

1

0

1011

0xab

Even,Blank, SAV

1

0

1

1

0110

0xb6

Even, Blank, EAV

1

1

0

0

0111

0xc7

Odd, Active, SAV

1

1

0

1

1010

0xda

Odd, Active, EAV

1

1

1

0

1100

0xec

Odd, Blank, SAV

1

1

1

1

0001

0xf1

Odd, Blank, EAV

  Blanking为水平消隐区,通常由80H/10H来填充。

  对于图2中的Valid data(有效数据)区,其数据排列顺序如图3所示。即Y : Cb : Cr=4 : 2 : 2。从图像的像素点上来理解,就是每个像素点有一个单独的Y值,而相邻的两个像素点的CbCr数据是一样的。

图3 数据排列顺序

2、ITU-R BT.601和ITU-R BT.656的区别

  关于这两种信号的区别: 
  ITU-R BT.601: 16位数据传输,21芯;Y、U、V信号并行传输,并有场频和行频传输线。最后更新的文档代号为:ITU-R  BT.601-5。
  ITU-R BT.656: 8位数据传输,9芯;串行视频传输,不需要同步信号;传输速率是601的2倍。最后更新的文档代号为:ITU-R  BT.656-4。

  656输出的是串行数据,行场同步信号嵌入在数据流中,601是并行数据,行场同步有单独输出。

  656只是数据传输接口而已,可以说是作为601的一个传输方式。简单的说ITU-R BT.601是"演播室数字电视编码参数"标准,而ITU-R BT.656 则是ITU-R BT.601附件A中的数字接口标准,用于主要数字视频设备(包括芯片)之间采用27Mhz/s并口或243Mb/s串行接口的数字传输接口标准。

3、关于DIY_DE2的视频部分的说明

  DE2视频解码芯片是SAA7181,DIY_DE2采用的视频解码芯片是SAA7113,两种芯片都支持ITU-R BT.656和ITU-R BT.601两种信号接口。SAA7113采用的外部晶振为24.576MHz,经过内部锁相环之后,像素时钟为27MHz,亮度信号时钟为13.5MHz,色差信号时钟为6.75MHz。

  DE2_TV例程是针对NTSC制式的摄像头,而我这里是用的PAL制式的摄像头,视频信号为隔行扫描,奇场在前,偶场在后。使用的视频接口为ITU-R BT.656因此对例程做了些修改。

四、DE2_TV例程分析

1、IIC配置视频解码芯片

  具体配置方法上篇博文中已经说明,这里给出配置参数。

     SET_VIDEO+0:    LUT_DATA    <=    16'h0108;
        SET_VIDEO+1:    LUT_DATA    <=    16'h02C3;//default C0
        SET_VIDEO+2:    LUT_DATA    <=    16'h0333;//default 33
        SET_VIDEO+3:    LUT_DATA    <=    16'h0400;//default 00
        SET_VIDEO+4:    LUT_DATA    <=    16'h0500;//default 00
        SET_VIDEO+5:    LUT_DATA    <=    16'h06e9;
        SET_VIDEO+6:    LUT_DATA    <=    16'h070d;
        SET_VIDEO+7:    LUT_DATA    <=    16'h0898;
        SET_VIDEO+8:    LUT_DATA    <=    16'h0901;
        SET_VIDEO+9:    LUT_DATA    <=    16'h0a80;
      
        SET_VIDEO+10:    LUT_DATA    <=    16'h0b47;
        SET_VIDEO+11:    LUT_DATA    <=    16'h0c40;
        SET_VIDEO+12:    LUT_DATA    <=    16'h0d00;
        SET_VIDEO+13:    LUT_DATA    <=    16'h0e01;
        SET_VIDEO+14:    LUT_DATA    <=    16'h0f2a;
        SET_VIDEO+15:    LUT_DATA    <=    16'h1000;
        SET_VIDEO+16:    LUT_DATA    <=    16'h110c;
        SET_VIDEO+17:    LUT_DATA    <=    16'h12b7;
        SET_VIDEO+18:    LUT_DATA    <=    16'h1300;
        SET_VIDEO+19:    LUT_DATA    <=    16'h1500;
      
        SET_VIDEO+20:    LUT_DATA    <=    16'h1600;
        SET_VIDEO+21:    LUT_DATA    <=    16'h1700;
        SET_VIDEO+22:    LUT_DATA    <=    16'h4002;
        SET_VIDEO+23:    LUT_DATA    <=    16'h41ff;
        SET_VIDEO+24:    LUT_DATA    <=    16'h42ff;
        SET_VIDEO+25:    LUT_DATA    <=    16'h43ff;
        SET_VIDEO+26:    LUT_DATA    <=    16'h44ff;
        SET_VIDEO+27:    LUT_DATA    <=    16'h45ff;
        SET_VIDEO+28:    LUT_DATA    <=    16'h46ff;
        SET_VIDEO+29:    LUT_DATA    <=    16'h47ff;
      
        SET_VIDEO+30:    LUT_DATA    <=    16'h48ff;
        SET_VIDEO+31:    LUT_DATA    <=    16'h49ff;
        SET_VIDEO+32:    LUT_DATA    <=    16'h4aff;
        SET_VIDEO+33:    LUT_DATA    <=    16'h4bff;
        SET_VIDEO+34:    LUT_DATA    <=    16'h4cff;
        SET_VIDEO+35:    LUT_DATA    <=    16'h4dff;
        SET_VIDEO+36:    LUT_DATA    <=    16'h4eff;
        SET_VIDEO+37:    LUT_DATA    <=    16'h4fff;
        SET_VIDEO+38:    LUT_DATA    <=    16'h50ff;
        SET_VIDEO+39:    LUT_DATA    <=    16'h51ff;
        SET_VIDEO+40:    LUT_DATA    <=    16'h52ff;
      
        SET_VIDEO+41:    LUT_DATA    <=    16'h53ff;
        SET_VIDEO+42:    LUT_DATA    <=    16'h54ff;
        SET_VIDEO+43:    LUT_DATA    <=    16'h55ff;
        SET_VIDEO+44:    LUT_DATA    <=    16'h56ff;
        SET_VIDEO+45:    LUT_DATA    <=    16'h57ff;
        SET_VIDEO+46:    LUT_DATA    <=    16'h5800;
        SET_VIDEO+47:    LUT_DATA    <=    16'h5954;
        SET_VIDEO+48:    LUT_DATA    <=    16'h5a07;
        SET_VIDEO+49:    LUT_DATA    <=    16'h5b83;
        SET_VIDEO+50:    LUT_DATA    <=    16'h5e00;

2、视频采集、解码及视频裁剪部分

  由于采用PAL制式的摄像机,其视频画面的有效分辨率为720*576,即总共576行(分奇偶两场,各占288行),每行720个像素点,由于是8位串行输出,因此每行总共有1440个字节。

  视频解码文件完成的任务就是:通过判断SAV信号,来判断接下来的数据是否为有效视频数据,如果是,则进一步分离出有效数据的同步信号oDVAL和有效数据Y、Cb、Cr。

  视频的裁剪是通过一个除法器辅助完成的,主要是对每行视频数据进行裁剪,从720个像素裁剪到640像素。除数为当前视频行的当前字节数右移1位,被除数为9。也就是说,每9个像素中,有一个像素点被裁剪掉,即720-720/9=640。具体代码如下。

 

        if(iSwap_CbCr)
        begin
            case(Cont[1:0])        //    Swap
            0:    Cb        <=     iTD_DATA;
            1:    YCbCr    <=    {iTD_DATA,Cr};
            2:    Cr        <=     iTD_DATA;
            3:    YCbCr    <=    {iTD_DATA,Cb};
            endcase
        end
        else
        begin
            case(Cont[1:0])        //    Normal
            0:    Cb        <=     iTD_DATA;
            1:    YCbCr    <=    {iTD_DATA,Cb};
            2:    Cr        <=     iTD_DATA;
            3:    YCbCr    <=    {iTD_DATA,Cr};
            endcase
        end

 

  上述代码中,iSwap_CbCr除数除以被除数的商,Cont为当前视频行的当前字节数,下面以例子示之。

 

Cont[1:0]         00  01  10  11  00  01  10  11  00  01  10  11  00  01  10  11  00  01  10  11  00  01  10  11

iSwap_CbCr       0    0   0    0    0    0    0    0    0    0    0    0    0   0    0    0    0    0    1    1    1    1    1    1

iTD_DATA         Cb1 Y1 Cr1 Y2 Cb2 Y3 Cr2 Y4 Cb3 Y5 Cr3 Y6  Cb4 Y7 Cr4 Y8 Cb5 Y9 Cr5 Y10 Cb6 Y11 Cr6 Y12

YCbCr                Y1Cb1  Y2Cr1  Y3Cb2  Y4Cr2  Y5Cb3  Y6Cr3   Y7Cb4  Y8Cr4  Y9Cb5  Y10Cb5  Y11Cr5  Y12Cb6

 

  从上述例子可以看出,每4个时钟周期输出2个像素值,即输出像素值的频率减小了一半,这与分离出来的同步信号oDVAL的时钟频率一样,同为13.5MHz

  另外,裁剪部分,由于Y9Cb5与Y10Cb5有很大的相似性,这里应该是将Y9Cb5剔除,但是具体在什么位置剔除,却不得而知。莫非是分析错误?求解。

3、视频数据存取

   存储在SDRAM采用的是1入2出的模式,即一个端口写入,2个端口读出。存取数据的代码如下:

 

//    SDRAM frame buffer
Sdram_Control_4Port    u6    (    //    HOST Side
                            .REF_CLK(CLOCK_50),
                            //.CLK_18(AUD_CTRL_CLK),
                            .RESET_N(1'b1),
                            //    FIFO Write Side 1
                            .WR1_DATA(YCbCr),
                            .WR1(TV_DVAL),
                            .WR1_FULL(WR1_FULL),
                            .WR1_ADDR(0),
                            .WR1_MAX_ADDR(640*576),        //    525-18
                            .WR1_LENGTH(9'h80),
                            .WR1_LOAD(!DLY0),
                            .WR1_CLK(PPI_CLK),
                            //    FIFO Read Side 1
                            .RD1_DATA(m1YCbCr),
                            .RD1(m1VGA_Read),
                            .RD1_ADDR(640*12),            //    Read odd field and bypess blanking
                            .RD1_MAX_ADDR(640*252),
                            .RD1_LENGTH(9'h80),
                            .RD1_LOAD(!DLY0),
                            .RD1_CLK(PPI_CLK),
                            //    FIFO Read Side 2
                            .RD2_DATA(m2YCbCr),
                            .RD2(m2VGA_Read),
                            .RD2_ADDR(640*300),            //    Read even field and bypess blanking
                            .RD2_MAX_ADDR(640*540),
                            .RD2_LENGTH(9'h80),
                            .RD2_LOAD(!DLY0),
                            .RD2_CLK(PPI_CLK),
                            //    SDRAM Side
                            .SA(DRAM0_A),
                            .BA(DRAM0_BA),
                            .CS_N(DRAM0_CS),
                            .CKE(DRAM0_CKE),
                            .RAS_N(DRAM0_RAS),
                            .CAS_N(DRAM0_CAS),
                            .WE_N(DRAM0_WE),
                            .DQ(DRAM0_D),
                            .DQM(DRAM0_DQM),
                            .SDR_CLK(DRAM0_CLK)    );

  

  经过裁剪后的视频分辨率为640*576。

  写入SDRAM中时,是将640*576个像素全部写入进去,由于是奇场数据在前,偶场数据在后,因此前640*288行数据为奇场数据,后 640*288行数据为偶场数据。

  读取视频数据时,采用乒乓操作,先后读取奇偶场的数据,各240行,组成一幅完整的画面,读取方法如下:

1

……

11

读取12到251行,共240行

252

……

288

以上为奇数场数据,以下为偶数场数据

289

……

299

读取300到539行,共240行

540

……

576

  其中,1~288行为奇数场数据,289~576为偶数场数据。上述数据是从11~251,300~539读取的,当然也可以从1~240,289~529读取,只要满足奇偶场的起始行为相邻行,且保证奇数场的数据行在前即可。

  因此,最后得到的视频分辨率为640*480.

4、色彩空间转换

   进行色彩空间转换之前,对视频行数据进行了简单的算法处理,代码如下:

 

//    Line buffer, delay one line
Line_Buffer u10    (    .clken(VGA_Read),
                    .clock(PPI_CLK),
                    .shiftin(mYCbCr_d),
                    .shiftout(m3YCbCr));

Line_Buffer u11    (    .clken(VGA_Read),
                    .clock(PPI_CLK),
                    .shiftin(m3YCbCr),
                    .shiftout(m4YCbCr));

wire    [15:0]    m4YCbCr;
wire    [15:0]    m5YCbCr;
wire    [8:0]    Tmp1,Tmp2;
wire    [7:0]    Tmp3,Tmp4;

assign    Tmp1    =    m4YCbCr[7:0]+mYCbCr_d[7:0];
assign    Tmp2    =    m4YCbCr[15:8]+mYCbCr_d[15:8];
assign    Tmp3    =    Tmp1[8:2]+m3YCbCr[7:1];
assign    Tmp4    =    Tmp2[8:2]+m3YCbCr[15:9];
assign    m5YCbCr    =    {Tmp4,Tmp3};

 

  对视频行进行了加和及数乘运算。

  最后将YUV 4:2:2先转换为YUV4:4:4的形式,之后再通过公式转换成RGB色彩空间,最后通过VGA显示在显示器上。

 

 

 

 

你可能感兴趣的:(DE2_TV例程的几点说明)