一、摘要
對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所示。

圖1 一幀圖像數據行格式
對於有效數據行的格式,如圖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值,而相鄰的兩個像素點的Cb和Cr數據是一樣的。

圖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是並行數據,行場同步有單獨輸出。
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顯示在顯示器上。
