关于DE2_115_TV范例的说明

    我自从去年开始接触DE2_115开发板,主要研究的是视频处理算法,因此想好好研究一下TV范例,不过限于当时水平有限很多模块的代码,还没有弄的很明白。前几天又用到它了,决定再好好研究一下。经过了2天的研究,收获还是不少的,很多代码终于看明白了,于是决定分享一下我的看法。

    首先我觉得大家需要了解一下PAL、NTSC以及ITU-R BT.656。详见:http://www.cnblogs.com/sunev/archive/2012/05/21/2512149.html

    1.TD_Detect模块

 1 module TD_Detect(    
 2           oTD_Stable,
 3           oNTSC,
 4           oPAL,
 5                     iTD_VS,
 6                     iTD_HS,
 7                     iRST_N    );
 8 input        iTD_VS;
 9 input        iTD_HS;
10 input        iRST_N;
11 output    oTD_Stable;
12 output  oNTSC;
13 output  oPAL;
14 reg            NTSC;
15 reg            PAL;
16 reg            Pre_VS;
17 reg    [7:0]    Stable_Cont;
18 /*********************************************************
19 垂直同步信号:
20 1    0   1                     1  0   1   
21 ---|___|------------------------|___|---
22     消隐                         消隐
23 
24 在垂直消隐期间(!iTD_VS),对iTD_HS即行数进行计数来判断PAL或NTSC,
25 且结果在{Pre_VS,iTD_VS}==2'b01时完成判断,只要第一次判断出制式,
26 oTD_Stable就一直是1。
27 *********************************************************/
28 assign    oTD_Stable    =    NTSC || PAL;
29 assign  oNTSC  = NTSC;
30 assign  oPAL   = PAL;
31 
32 always@(posedge iTD_HS or negedge iRST_N)
33     if(!iRST_N)
34     begin
35         Pre_VS          <=    1'b0;
36         Stable_Cont    <=    4'h0;
37         NTSC    <=    1'b0;
38         PAL      <=    1'b0;
39     end
40     else
41     begin
42         Pre_VS    <=    iTD_VS;
43         if(!iTD_VS)
44           Stable_Cont    <=    Stable_Cont+1'b1;
45         else
46           Stable_Cont    <=    0;
47     //判断是PAL还是NTSC,为了后面的sdram分配存储空间做准备    
48         if({Pre_VS,iTD_VS}==2'b01)//通过垂直消隐期间的行数来判断
49         begin
50             if((Stable_Cont>=4 && Stable_Cont<=14))
51               NTSC    <=    1'b1;
52             else
53               NTSC    <=    1'b0;
54             
55             if((Stable_Cont>=8'h14 && Stable_Cont<=8'h1f))
56               PAL    <=    1'b1;
57             else
58               PAL    <=    1'b0;
59         end
60     end
61 
62 endmodule

    2.Reset_Delay模块

 1 module    Reset_Delay(iCLK,iRST,oRST_0,oRST_1,oRST_2);
 2 input        iCLK;
 3 input        iRST;
 4 output reg    oRST_0;
 5 output reg    oRST_1;
 6 output reg    oRST_2;
 7 
 8 reg    [21:0]    Cont;
 9 
10 always@(posedge iCLK or negedge iRST)
11 begin
12     if(!iRST)//TD_Detect 模块的oTD_Stable信号做为复位信号,检测不到正常的格式则复位。
13     begin
14         Cont    <=    0;
15         oRST_0    <=    0;
16         oRST_1    <=    0;
17         oRST_2    <=    0;
18     end
19     else
20     begin
21         if(Cont!=22'h3FFFFF)
22         Cont    <=    Cont+1;
23         if(Cont>=22'h1FFFFF)
24         oRST_0    <=    1; //oRST_0最先恢复正常,sdram、linebuffer等
25         if(Cont>=22'h2FFFFF)
26         oRST_1    <=    1;//oRST_1第二恢复正常,ITU_656 Decoder
27         if(Cont>=22'h3FFFFF)
28         oRST_2    <=    1;//oRST_2最后恢复正常,其他模块
29     end
30 end
31 
32 endmodule

    3.ITU_656_Decoder模块

  1 /*****************************************************
  2 本模块实现去除消隐区,并将一行720个像素减为640个
  3 详见:http://www.cnblogs.com/sunev/archive/2012/05/21/2512149.html
  4 *****************************************************/
  5 module    ITU_656_Decoder(    //    TV Decoder Input
  6                             iTD_DATA,
  7                             //    Position Output
  8                             oTV_X,
  9                             oTV_Y,
 10                             oTV_Cont,
 11                             //    YUV 4:2:2 Output
 12                             oYCbCr,
 13                             oDVAL,
 14                             //    Control Signals
 15                             iSwap_CbCr,
 16                             iSkip,
 17                             iRST_N,
 18                             iCLK_27    );
 19 input    [7:0]    iTD_DATA;
 20 input            iSwap_CbCr;
 21 input            iSkip;
 22 input            iRST_N;
 23 input            iCLK_27;
 24 output    [15:0]    oYCbCr;
 25 output    [9:0]    oTV_X;
 26 output    [9:0]    oTV_Y;
 27 output    [31:0]    oTV_Cont;
 28 output            oDVAL;
 29 
 30 //    For detection
 31 reg        [23:0]    Window;        //    Sliding window register
 32 reg        [17:0]    Cont;        //    Counter
 33 reg                Active_Video;
 34 reg                Start;
 35 reg                Data_Valid;
 36 reg                Pre_Field;
 37 reg                Field;
 38 wire            SAV;
 39 reg                FVAL;
 40 reg        [9:0]    TV_Y;
 41 reg        [31:0]    Data_Cont;
 42 
 43 //    For ITU-R 656 to ITU-R 601 串转并
 44 reg        [7:0]    Cb;
 45 reg        [7:0]    Cr;
 46 reg        [15:0]    YCbCr;
 47 
 48 assign    oTV_X    =    Cont>>1;  // Cont/2 :像素的位置
 49 assign    oTV_Y    =    TV_Y;
 50 assign    oYCbCr    =    YCbCr;
 51 assign    oDVAL    =    Data_Valid;
 52 assign    SAV        =    (Window==24'hFF0000)&(iTD_DATA[4]==1'b0);//iTD_DATA[4] 0:SAV,1:EAV
 53 assign    oTV_Cont=    Data_Cont;
 54 
 55 always@(posedge iCLK_27 or negedge iRST_N)
 56 begin
 57     if(!iRST_N)
 58     begin
 59         //    Register initial
 60         Active_Video<=    1'b0;
 61         Start        <=    1'b0;
 62         Data_Valid    <=    1'b0;
 63         Pre_Field    <=    1'b0;
 64         Field        <=    1'b0;
 65         Window        <=    24'h0;
 66         Cont        <=    18'h0;
 67         Cb            <=    8'h0;
 68         Cr            <=    8'h0;
 69         YCbCr        <=    16'h0;
 70         FVAL        <=    1'b0;
 71         TV_Y        <=    10'h0;
 72         Data_Cont    <=    32'h0;
 73     end
 74     else
 75     begin
 76         //    Sliding window
 77         Window    <=    {Window[15:0],iTD_DATA};
 78         //    Active data counter
 79         if(SAV)  //SAV区域
 80         Cont    <=    18'h0;
 81         else if(Cont<1440)
 82         Cont    <=    Cont+1'b1;//Cont为YC的个数
 83         //    Check the video data is active?
 84         if(SAV)
 85         Active_Video<=    1'b1;
 86         else if(Cont==1440)
 87         Active_Video<=    1'b0;
 88         //    Is frame start?
 89         Pre_Field    <=    Field;
 90         if({Pre_Field,Field}==2'b10) //奇场———>偶场
 91         Start        <=    1'b1;
 92         //    Field and frame valid check
 93         if(Window==24'hFF0000)  // SAV :  FF 00 00 XY
 94         /*******************************
 95         详见:http://www.cnblogs.com/sunev/archive/2012/05/21/2512149.html
 96         表1.
 97         iTD_DATA[5]是 垂直同步信号。1:消隐,0:有效数据
 98         iTD_DATA[6]是 场同步信号,表示该行数据处于奇场还是偶场。1:奇场,0:偶场
 99         *******************************/
100         begin
101             FVAL    <=    !iTD_DATA[5];
102             Field    <=    iTD_DATA[6];
103         end
104         
105         //    ITU-R 656 to ITU-R 601
106         /****************************************
107         分子:[9:0]接oTV_X,    分母:[3:0],常数9. 
108         商:[9:0] 接iSwap_CbCr。余数:[3:0],==?
109         Swap_CbCr除数除以被除数的商,Cont为当前视频行的当前字节数,下面以例子示之。
110  
111       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
112        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
113       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
114       YCbCr             Y1Cb1  Y2Cr1  Y3Cb2  Y4Cr2  Y5Cb3  Y6Cr3   Y7Cb4  Y8Cr4  Y9Cb5  Y10Cb5  Y11Cr5  Y12Cb6
115                         
116         ****************************************/
117         if(iSwap_CbCr)
118         begin
119             case(Cont[1:0])        //    Swap,Cont[1:0]=00,01,10,11.
120             0:    Cb        <=     iTD_DATA;
121             1:    YCbCr    <=    {iTD_DATA,Cr};
122             2:    Cr        <=     iTD_DATA;
123             3:    YCbCr    <=    {iTD_DATA,Cb};
124             endcase
125         end
126         else //iSwap_CbCr =0
127         begin
128             case(Cont[1:0])        //    Normal
129             0:    Cb        <=     iTD_DATA;//Cb 8bit临时寄存器,将8bit  iTD_DATA中的Cb保存
130             1:    YCbCr    <=    {iTD_DATA,Cb};//YCbCr 16bit, =iTD_DATA中的Y + Cb
131             2:    Cr        <=     iTD_DATA;
132             3:    YCbCr    <=    {iTD_DATA,Cr};
133             endcase
134         end
135         //    Check data valid
136         if(        Start                //    Frame Start?
137             &&     FVAL                //    Frame valid? FVAL==1,即iTD_DATA[5]=0,处于有效数据区!!
138             &&     Active_Video        //    Active video?
139             &&     Cont[0]                //    Complete ITU-R 601?
140             &&     !iSkip    )            //    Is non-skip pixel?
141         Data_Valid    <=    1'b1;  //有效数据
142         else
143         Data_Valid    <=    1'b0;
144         //    TV decoder line counter for one field
145         if(FVAL && SAV)
146         TV_Y<=    TV_Y+1;
147         if(!FVAL)
148         TV_Y<=    0;
149         //    Data counter for one field
150         if(!FVAL)
151         Data_Cont    <=    0;
152         if(Data_Valid)
153         Data_Cont    <=    Data_Cont+1'b1;
154     end
155 end
156 
157 endmodule

    4.YUV422_to_444模块

 1 module YUV422_to_444    (    //    YUV 4:2:2 Input
 2                             iYCbCr,
 3                             //    YUV    4:4:4 Output
 4                             oY,
 5                             oCb,
 6                             oCr,
 7                             //    Control Signals
 8                             iX,
 9                             iCLK,
10                             iRST_N    );
11 //    YUV 4:2:2 Input
12 input    [15:0]    iYCbCr;
13 //    YUV    4:4:4 Output
14 output    [7:0]    oY;
15 output    [7:0]    oCb;
16 output    [7:0]    oCr;
17 //    Control Signals
18 input    [9:0]    iX;
19 input            iCLK;
20 input            iRST_N;
21 //    Internal Registers
22 reg        [7:0]    mY;
23 reg        [7:0]    mCb;
24 reg        [7:0]    mCr;
25 
26 assign    oY    =    mY;
27 assign    oCb    =    mCb;
28 assign    oCr    =    mCr;
29 /***********************************
30 iX[0]     0   1   0   1   0  ...
31 输入:     Y   Y   Y   Y   Y  ...
32           Cb  Cr  Cb  Cr  Cb ...
33 输出:mY   Y   Y   Y   Y   Y  ...
34      mCb  Cb ---  Cb ---  Cb ...
35       mCr      Cr---   Cr --- ...
36 ************************************/
37 always@(posedge iCLK or negedge iRST_N)
38 begin
39     if(!iRST_N)
40     begin
41         mY    <=    0;
42         mCb    <=    0;
43         mCr    <=    0;
44     end
45     else
46     begin
47         if(iX[0])
48         {mY,mCr}    <=    iYCbCr;
49         else
50         {mY,mCb}    <=    iYCbCr;
51     end
52 end
53 
54 endmodule

    5.YCbCr2RGB模块

  1 /****************************************************
  2 详见:http://www.cnblogs.com/oomusou/archive/2008/12/09/verilog_ycrcb2rgb.html#commentform
  3 R = 1.164(Y-16) + 1.596(Cr-128) 
  4 G = 1.164(Y-16) - 0.391(Cb-128) - 0.813(Cr-128) 
  5 B = 1.164(Y-16) + 2.018(Cb-128)
  6 --->
  7 R = 1.164Y                + 1.596Cr - 222.912
  8 G = 1.164Y - 0.391Cb - 0.813Cr + 135.488
  9 B = 1.164Y + 2.018Cb                - 276.928
 10 先放大在缩小,例如放大512倍即2^9--->
 11 R << 9 = 596Y          + 817Cr - 114131
 12 G << 9 = 596Y - 200Cb  - 416Cr + 69370
 13 B << 9 = 596Y + 1033Cb         - 141787
 14 ****************************************************/
 15 module YCbCr2RGB (    Red,Green,Blue,oDVAL,
 16                     iY,iCb,iCr,iDVAL,
 17                     iRESET,iCLK);
 18 //    Input
 19 input [7:0] iY,iCb,iCr;
 20 input iDVAL,iRESET,iCLK;
 21 wire iCLK;
 22 //    Output
 23 output [9:0] Red,Green,Blue;
 24 output reg    oDVAL;
 25 //    Internal Registers/Wires
 26 reg [9:0] oRed,oGreen,oBlue;
 27 reg    [3:0] oDVAL_d;
 28 reg [19:0] X_OUT,Y_OUT,Z_OUT;
 29 wire [26:0] X,Y,Z;
 30 
 31 assign    Red  =    oRed;
 32 assign    Green=    oGreen;
 33 assign    Blue =    oBlue;
 34 
 35 always@(posedge iCLK)
 36 begin
 37     if(iRESET)
 38     begin
 39         oDVAL<=0;
 40         oDVAL_d<=0;
 41         oRed<=0;
 42         oGreen<=0;
 43         oBlue<=0;
 44     end
 45     else
 46     begin
 47         // Red
 48         if(X_OUT[19])//溢出
 49         oRed<=0;
 50         else if(X_OUT[18:0]>1023)
 51         oRed<=1023; //上界,output [9:0] 是10 bit,最大1023
 52         else
 53         oRed<=X_OUT[9:0];
 54         // Green
 55         if(Y_OUT[19])
 56         oGreen<=0;
 57         else if(Y_OUT[18:0]>1023)
 58         oGreen<=1023;
 59         else
 60         oGreen<=Y_OUT[9:0];
 61         // Blue
 62         if(Z_OUT[19])
 63         oBlue<=0;
 64         else if(Z_OUT[18:0]>1023)
 65         oBlue<=1023;
 66         else
 67         oBlue<=Z_OUT[9:0];
 68         // Control
 69     /************************************************
 70     oDVAL_d <= iDVAL;
 71     oDVAL   <= oDVAL_d;精简写法。
 72     因为运算较多,所以希望oDVAL多一个时钟delay
 73     ************************************************/
 74         {oDVAL,oDVAL_d}<={oDVAL_d,iDVAL};
 75     end
 76 end
 77 
 78 always@(posedge iCLK)
 79 begin
 80     if(iRESET)
 81     begin
 82         X_OUT<=0;
 83         Y_OUT<=0;
 84         Z_OUT<=0;
 85     end
 86     else
 87     /************************************************
 88     X_OUT <= (( X - 114131 ) >> 9) << 2;
 89     Y_OUT <= (( Y + 69370  ) >> 9) << 2;
 90     Z_OUT <= (( Z - 141787 ) >> 9) << 2;
 91     output [9:0] 是10 bit,而input [7:0] 是8 bit,所以<<2
 92     ************************************************/
 93     begin
 94         X_OUT<=( X - 114131 ) >>7;
 95         Y_OUT<=( Y + 69370  ) >>7;
 96         Z_OUT<=( Z - 141787 ) >>7;            
 97     end
 98 end
 99 
100 //    Y        596,        0,            817
101 MAC_3 u0(
102             .aclr0(iRESET),
103             .clock0(iCLK),
104             .dataa_0(iY),
105             .dataa_1(iCb),
106             .dataa_2(iCr),
107             .datab_0(17'h00254),
108             .datab_1(17'h00000),
109             .datab_2(17'h00331),
110             .result(X)            
111             );
112 //MAC_3 u0(    iRESET,        iCLK,iY,            iCb,        iCr,
113 //            17'h00254,    17'h00000,    17'h00331,
114 //                     X);
115 //    Cb        596,        -200,        -416
116 MAC_3 u1(
117             .aclr0(iRESET),
118             .clock0(iCLK),
119             .dataa_0(iY),
120             .dataa_1(iCb),
121             .dataa_2(iCr),
122             .datab_0(17'h00254),
123             .datab_1(17'h3FF38),
124             .datab_2(17'h3FE60),
125             .result(Y)            
126             );
127 //MAC_3 u1(    iRESET,        iCLK,iY,            iCb,        iCr,
128 //            17'h00254,    17'h3FF38,    17'h3FE60,
129 //            Y        );
130 //    Cr        596,        1033,        0
131 MAC_3 u2(
132             .aclr0(iRESET),
133             .clock0(iCLK),
134             .dataa_0(iY),
135             .dataa_1(iCb),
136             .dataa_2(iCr),
137             .datab_0(17'h00254),
138             .datab_1(17'h00409),
139             .datab_2(17'h00000),
140             .result(Z)            
141             );
142 //MAC_3 u2(    iRESET,        iCLK,iY,            iCb,        iCr,
143 //            17'h00254,    17'h00409,    17'h00000,
144 //            Z        );
145 
146 endmodule

     我觉得以上5个模块可能是难度比较大的模块了,当然除了Sdram_Control_4Port模块以外。具体的解释我都在代码中注释了,另外还加上了一些大神的链接,应该不难理解了。至于Sdram_Control_4Port模块,我也曾研究过一段时间,但是由于时间关系,有很多地方还是不能完全理解,有时间的话我会再仔细研究一下,和大家一块分享。

    另外附上我的DE2_115_TV的工程,里面把不需要的模块都精简掉了,看起来比较清爽。加上了Sobel滤波模块和灰度显示,具体可以参考代码中的说明。

    DE2_115_TV_Sobel.rar

 

 

 

posted on 2012-08-31 16:56  万里-先生  阅读(2147)  评论(4编辑  收藏  举报

导航