新聞中心

        FPGA:HDMI接口

        作者: 時(shí)間:2024-01-11 來源:EEPW編譯 收藏

        HDMI 是一種數(shù)字視頻接口,因此很容易從現(xiàn)代 驅(qū)動(dòng)。讓我們看看它是如何工作的。

        本文引用地址:http://www.104case.com/article/202401/454692.htm

        連接器

        標(biāo)準(zhǔn) HDMI 連接器有 19 個(gè)引腳。 在 19 個(gè)引腳中,有 8 個(gè)特別值得關(guān)注,因?yàn)樗鼈冃纬?4 個(gè) TMDS 差分對(duì)來傳輸實(shí)際的高速視頻信息。

        • TMDS 時(shí)鐘+ 和時(shí)鐘-

        • TMDS data0+ 和 data0-

        • TMDS data1+ 和 data1-

        • TMDS data2+ 和 data2-

        我們從到HDMI連接器的連接再簡(jiǎn)單不過了......我們使用 8 個(gè) 引腳,配置為 4 個(gè)差分 TMDS 輸出。

        視頻信號(hào)

        讓我們創(chuàng)建一個(gè) 640x480 RGB 24bpp @ 60Hz 的視頻信號(hào)。 這是每幀 307200 像素,由于每個(gè)像素有 24 位(紅色、綠色和藍(lán)色為 8 位),在 60Hz 時(shí),HDMI 鏈路傳輸 0.44Gbps 的“有用”數(shù)據(jù)。

        但視頻信號(hào)通常也有一個(gè)“屏幕外”區(qū)域,HDMI接收器(電視或顯示器)使用它進(jìn)行一些內(nèi)務(wù)處理。 我們的 640x480 幀實(shí)際上是作為 800x525 幀發(fā)送的。

        考慮到這一點(diǎn),我們需要一個(gè) 24.5MHz 的像素時(shí)鐘來實(shí)現(xiàn)每秒 60 幀,但 HDMI 指定了 25MHz 的最小像素時(shí)鐘,所以我們就這樣使用(這讓我們獲得了 61Hz 的幀速率)。

        TMDS信號(hào)

        FPGA 有 4 個(gè) TMDS 差分對(duì)可供驅(qū)動(dòng)。
        首先,TMDS時(shí)鐘只是像素時(shí)鐘,因此它以25MHz運(yùn)行。 其他 3 對(duì)傳輸紅色、綠色和藍(lán)色 8 位信號(hào),因此我們得到類似的東西。

        事實(shí)上,事情只是稍微復(fù)雜一些。 HDMI 要求我們對(duì)數(shù)據(jù)進(jìn)行加擾,并在每個(gè)顏色通道上添加 2 位,因此我們有 10 位而不是 8 位,鏈路最終每像素傳輸 30 位。 HDMI 接收器需要加擾和額外位才能正確同步和采集每個(gè)通道(請(qǐng)務(wù)必查看 DVI 和 HDMI 規(guī)格以獲取更多詳細(xì)信息)。

        源代碼

        首先是視頻生成器。 我們使用幾個(gè)穿過 800x525 像素區(qū)域的計(jì)數(shù)器......

        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;

        并創(chuàng)建 H-Sync 和 V-Sync 信號(hào)...

        wire hSync = (CounterX>=656) && (CounterX<752);
        wire vSync = (CounterY>=490) && (CounterY<492);
        wire DrawArea = (CounterX<640) && (CounterY<480);

        并生成一些紅色、綠色和藍(lá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];

        通過三個(gè)“TMDS_encoder”實(shí)例分別擴(kuò)展到 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)在,我們?yōu)槊總€(gè)像素時(shí)鐘周期發(fā)送三個(gè) 10 位值。 我們將 25MHz 時(shí)鐘乘以 10 以生成 250MHz 時(shí)鐘......

        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

        并使用三個(gè)時(shí)鐘頻率為250MHz的移位寄存器...

        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數(shù)據(jù)發(fā)送到FPGA外部。

        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));

        更高的分辨率

        對(duì)于 640x480,我們使用了 250MHz 時(shí)鐘串行器,但為了獲得更高的分辨率,我們需要更高的頻率,這很快就會(huì)超過 FPGA 的能力。 解決方法是使用一些特殊的FPGA IO功能,如DDR輸出和IO串行器。

        在較高頻率下,另一個(gè)問題是如何可靠地將數(shù)據(jù)從像素時(shí)鐘域傳輸?shù)酱衅饔颉?一種可能的技術(shù)是使用淺層FIFO。 查看 Xilinx XAPP460(用于 Spartan-3A)和 XAPP495(用于 Spartan-6)應(yīng)用筆記,了解一些想法。

        截圖

        以下是使用數(shù)碼相機(jī)拍攝的幾張照片,該相機(jī)拍攝了由Pluto-IIx HDMI驅(qū)動(dòng)的LCD顯示器。
        我們有乒乓球比賽......

        為了好玩,經(jīng)典的 PacMan 街機(jī)游戲......曾經(jīng)可以從 fpgaarcade.com 獲得,但該網(wǎng)站最近進(jìn)行了重新設(shè)計(jì)。 您仍然可以使用回溯機(jī)獲取原始源代碼。

        這是我們測(cè)試板的圖片(Pluto-IIx HDMI加載了一個(gè)可選的HDMI適配器 - 所以我們實(shí)際上有兩個(gè)HDMI輸出可以玩......



        關(guān)鍵詞: FPGA HDMI接口

        評(píng)論


        相關(guān)推薦

        技術(shù)專區(qū)

        關(guān)閉
        主站蜘蛛池模板: 察哈| 宣城市| 镇安县| 江山市| 恩平市| 黑龙江省| 云和县| 洪雅县| 吕梁市| 什邡市| 保亭| 石城县| 潍坊市| 东阿县| 罗定市| 恩施市| 双流县| 隆安县| 丹寨县| 江北区| 桂平市| 肥东县| 长海县| 邢台县| 噶尔县| 增城市| 翁源县| 大石桥市| 沙湾县| 醴陵市| 张北县| 屯昌县| 博野县| 清丰县| 屯门区| 安徽省| 博白县| 中超| 宜阳县| 吴川市| 四会市|