HDMI是(shì)一(yī)種(zhǒng)數字(zì)視頻接口(kǒu),易于(yú)從現(xiàn)代(dài)FPGA驅動(dòng)。
讓我(wǒ)们(men)看(kàn)看(kàn)它(tā)是(shì)如(rú)何工作的(de)。
連(lián)接器
标(biāo)準的(de)HDMI連(lián)接器稱为(wèi)“A型”,有(yǒu)19个(gè)引脚。在(zài)19个(gè)引脚中(zhōng),有(yǒu)8个(gè)是(shì)特(tè)别感(gǎn)興趣的(de),因(yīn)为(wèi)它(tā)们(men)形成(chéng)了(le)4个(gè)TMDS差分(fēn)对(duì)来(lái)傳輸实際的(de)高(gāo)速視頻信(xìn)息。
-
TMD时(shí)鐘(zhōng)+和(hé)时(shí)鐘(zhōng)-
-
TMDs data 0+和(hé)data 0-
-
TMDs data 1+和(hé)data 1-
-
TMDs data 2+和(hé)data 2-
我(wǒ)们(men)從FPGA到(dào)HDMI連(lián)接器的(de)連(lián)接非(fēi)常簡單.我(wǒ)们(men)使用(yòng)8个(gè)FPGA引脚配置为(wèi)4个(gè)差分(fēn)TMDS輸出(chū)。
視頻信(xìn)号(hào)
讓我(wǒ)们(men)創建一(yī)个(gè)640x480 RGB 24 bpp@60 Hz視頻信(xìn)号(hào)。这(zhè)是(shì)每幀307200像素,因(yīn)为(wèi)每个(gè)像素都有(yǒu)24位(紅(hóng)色(sè)、綠(lǜ)色(sè)和(hé)藍(lán)色(sè)8位),在(zài)60 Hz时(shí),HDMI鍊(liàn)路(lù)傳輸0.44Gbps的(de)“有(yǒu)用(yòng)”數據(jù)。
但是(shì)視頻信(xìn)号(hào)通(tòng)常也(yě)有(yǒu)一(yī)个(gè)“離屏”區(qū)域,HDMI接收(shōu)器(電(diàn)視或(huò)監視器)用(yòng)于(yú)一(yī)些家(jiā)务管(guǎn)理。我(wǒ)们(men)的(de)640x480幀实際上(shàng)是(shì)作为(wèi)800x525幀發(fà)送的(de)。
考慮到(dào)这(zhè)一(yī)點(diǎn),我(wǒ)们(men)需要(yào)一(yī)个(gè)24.5MHz像素时(shí)鐘(zhōng)来(lái)达(dá)到(dào)每秒(miǎo)鐘(zhōng)60幀,但是(shì)HDMI指定(dìng)了(le)一(yī)个(gè)25 MHz的(de)最(zuì)小像素时(shí)鐘(zhōng),所(suǒ)以(yǐ)我(wǒ)们(men)使用(yòng)它(tā)(这(zhè)可(kě)以(yǐ)獲得61 Hz的(de)幀速率)。
TMD信(xìn)号(hào)
FPGA有(yǒu)4个(gè)TMDS差分(fēn)对(duì)来(lái)驅動(dòng)。
首先(xiān),TMDS时(shí)鐘(zhōng)只(zhī)是(shì)像素时(shí)鐘(zhōng),所(suǒ)以(yǐ)它(tā)在(zài)25 MHz運行。另(lìng)外(wài)3对(duì)發(fà)出(chū)紅(hóng)色(sè)、綠(lǜ)色(sè)和(hé)藍(lán)色(sè)的(de)信(xìn)号(hào),所(suǒ)以(yǐ)我(wǒ)们(men)得到(dào)了(le)類(lèi)似的(de)信(xìn)号(hào)。
其实事(shì)情(qíng)有(yǒu)點(diǎn)複雜。HDMI要(yào)求我(wǒ)们(men)对(duì)數據(jù)進(jìn)行置亂,并在(zài)每条(tiáo)彩色(sè)車道(dào)上(shàng)增加2位,所(suǒ)以(yǐ)我(wǒ)们(men)有(yǒu)10位而(ér)不(bù)是(shì)8位,而(ér)鍊(liàn)路(lù)以(yǐ)每像素30位的(de)速度(dù)結束(shù)。hdmi接收(shōu)機(jī)需要(yào)加擾和(hé)額外(wài)的(de)位,以(yǐ)便正(zhèng)确地(dì)同(tóng)步和(hé)獲取(qǔ)dvi和(hé)hdmi規範中(zhōng)的(de)每个(gè)車道(dào)模式细(xì)节(jié)。
源代(dài)碼
首先(xiān)是(shì)視頻發(fà)生(shēng)器。我(wǒ)们(men)使用(yòng)了(le)幾(jǐ)个(gè)計(jì)數器,它(tā)们(men)穿过(guò)800x525像素區(qū)域.
reg [9:0] CounterX; // counts from 0 to 799 always @(posedge pixclk) CounterX <= (CounterX==799) ? 0 : CounterX+1; reg [9:0] CounterY; // counts from 0 to 524 always @(posedge pixclk) if(CounterX==799) CounterY <= (CounterY==524) ? 0 : CounterY+1;
創建hsync和(hé)vsync信(xìn)号(hào).。
wire hSync = (CounterX>=656) && (CounterX<752); wire vSync = (CounterY>=490) && (CounterY<492); wire DrawArea = (CounterX<640) && (CounterY<480);
産生(shēng)一(yī)些紅(hóng),綠(lǜ),藍(lán)的(de)信(xìn)号(hào)(每个(gè)8位).
wire [7:0] red = {CounterX[5:0] & {6{CounterY[4:3]==~CounterX[4:3]}}, 2'b00}; wire [7:0] green = CounterX[7:0] & {8{CounterY[6]}}; wire [7:0] blue = CounterY[7:0];
通(tòng)过(guò)三(sān)个(gè)“TMDS_編碼器”实例将其擴展(zhǎn)到(dào)10位。
wire [9:0] TMDS_red, TMDS_green, TMDS_blue;
TMDS_encoder encode_R(.clk(pixclk), .VD(red ), .TMDS(TMDS_red) , .CD(2'b00) , .VDE(DrawArea));
TMDS_encoder encode_G(.clk(pixclk), .VD(green), .TMDS(TMDS_green), .CD(2'b00) , .VDE(DrawArea));
TMDS_encoder encode_B(.clk(pixclk), .VD(blue ), .TMDS(TMDS_blue) , .CD({vSync,hSync}), .VDE(DrawArea));
現(xiàn)在(zài),我(wǒ)们(men)为(wèi)每个(gè)像素时(shí)鐘(zhōng)周期(qī)發(fà)送三(sān)个(gè)10位值。我(wǒ)们(men)把25 MHz的(de)时(shí)鐘(zhōng)乘以(yǐ)10来(lái)産生(shēng)一(yī)个(gè)250 MHz的(de)时(shí)鐘(zhōng).
wire clk_TMDS, DCM_TMDS_CLKFX; DCM_SP #(.CLKFX_MULTIPLY(10)) DCM_TMDS_inst(.CLKIN(pixclk), .CLKFX(DCM_TMDS_CLKFX), .RST(1'b0)); BUFG BUFG_TMDSp(.I(DCM_TMDS_CLKFX), .O(clk_TMDS)); // 250 MHz
在(zài)250 MHz頻率下(xià)使用(yòng)三(sān)个(gè)移位寄存器.
reg [3:0] TMDS_mod10; // modulus 10 counter always @(posedge clk_TMDS) TMDS_mod10 <= (TMDS_mod10==9) ? 0 : TMDS_mod10+1; reg TMDS_shift_load; always @(posedge clk_TMDS) TMDS_shift_load <= (TMDS_mod10==9); reg [9:0] TMDS_shift_red, TMDS_shift_green, TMDS_shift_blue; always @(posedge clk_TMDS) begin TMDS_shift_red <= TMDS_shift_load ? TMDS_red : TMDS_shift_red [9:1];
TMDS_shift_green <= TMDS_shift_load ? TMDS_green : TMDS_shift_green[9:1];
TMDS_shift_blue <= TMDS_shift_load ? TMDS_blue : TMDS_shift_blue [9:1]; end
将TMDS數據(jù)發(fà)送到(dào)FPGA之外(wài)。
OBUFDS OBUFDS_red (.I(TMDS_shift_red [0]), .O(TMDSp[2]), .OB(TMDSn[2])); OBUFDS OBUFDS_green(.I(TMDS_shift_green[0]), .O(TMDSp[1]), .OB(TMDSn[1])); OBUFDS OBUFDS_blue (.I(TMDS_shift_blue [0]), .O(TMDSp[0]), .OB(TMDSn[0])); OBUFDS OBUFDS_clock(.I(pixclk), .O(TMDSp_clock), .OB(TMDSn_clock));
完整的(de)源代(dài)碼是(shì)可(kě)用(yòng)的(de)。这(zhè)里(lǐ).
較高(gāo)分(fēn)辨率
对(duì)于(yú)640x480,我(wǒ)们(men)使用(yòng)250 MHz时(shí)鐘(zhōng)串行化(huà),但对(duì)于(yú)更(gèng)高(gāo)的(de)分(fēn)辨率,我(wǒ)们(men)需要(yào)更(gèng)高(gāo)的(de)頻率,这(zhè)可(kě)以(yǐ)迅速超过(guò)FPGA的(de)能(néng)力。解(jiě)決辦(bàn)法是(shì)使用(yòng)一(yī)些特(tè)殊的(de)FPGA IO特(tè)性(xìng),如(rú)DDR輸出(chū)和(hé)IO串行化(huà)。
在(zài)較高(gāo)頻率上(shàng)的(de)另(lìng)一(yī)个(gè)問(wèn)題(tí)是(shì)如(rú)何可(kě)靠地(dì)将數據(jù)從像素时(shí)鐘(zhōng)域傳輸到(dào)序列化(huà)器域。一(yī)種(zhǒng)可(kě)能(néng)的(de)技術(shù)是(shì)使用(yòng)淺层FIFO。檢查XilinxXAPP 460(斯巴达(dá)-3A)及(jí)XAPP 495(对(duì)于(yú)斯巴达(dá)-6)申請说(shuō)明(míng),以(yǐ)獲得一(yī)些想(xiǎng)法。
截图(tú)
以(yǐ)下(xià)是(shì)幾(jǐ)张(zhāng)用(yòng)數碼相機(jī)拍攝的(de)由(yóu)Pluto-IIxHDMI驅動(dòng)的(de)液晶顯示器的(de)照片(piàn)。
我(wǒ)们(men)有(yǒu)乒乓球比赛...
为(wèi)了(le)好(hǎo)玩,經(jīng)典的(de)吃豆人(rén)街(jiē)機(jī)遊戏.。以(yǐ)前(qián)可(kě)以(yǐ)從fpgaarcade.com但是(shì)这(zhè)个(gè)网(wǎng)站最(zuì)近(jìn)被(bèi)重(zhòng)新設計(jì)了(le)。仍然可(kě)以(yǐ)使用(yòng)回(huí)車機(jī).
下(xià)面(miàn)是(shì)我(wǒ)们(men)测試板的(de)一(yī)张(zhāng)图(tú)片(piàn)(PlutoIIxHDMI加载了(le)一(yī)个(gè)可(kě)選的(de)HDMI适配器,因(yīn)此(cǐ)我(wǒ)们(men)实際上(shàng)有(yǒu)两(liǎng)个(gè)HDMI輸出(chū)要(yào)处理.)。