[HDMI]FPGA上實現HDMI(1)

HDMI是一個數字視頻接口,通過FPGA可以很快的實現驅動。下面可以看到HDMI是怎麼工作的.

connector

標準的HDMI連接器稱爲"A型",有19個引腳,其中8個引腳是需要注意的,組成了四個差分對TMDS(Transition Min imized Differential Signaling)[過度調製差分信號]。

  1. TMDS data2+ and data2-
  2. TMDS data1+ and data1-
  3. TMDS data0+ and data0-
  4. TMDS clock+ and clock-

我們鏈接HDMI和FPGA很簡單,只要使用其中的4對差分信號就可以了。

video signal

現在需要插入一個640x480 RGB 24bpp(一個像素需要的bit數) @ 60Hz。所以一幀數據需要307200像素,而且每個像素需要24bit(RGB各8bit),在60Hz中HDMI鏈路中有用信號信號的速率是0.44Gbps。同時在視頻信號中存在“off-area”區域,在所有的HDMI驅動控制中是非常有用的。640x480格式的實際上需要800x525格式。

TMDS signals

FPGA的TMDS驅動有4對不同的差分對。TMDS時鐘是像素時鐘 ,所以這裏使用的是25MHz。其他3個差分對轉化輸出是紅、綠、藍信號。

但是事實上每一bit都會更復雜,HDMI要求使用“TMDS編碼”來實現對應的顯示數據,其中需要加2bit的加擾數據,所以實際上每通道是10bit而不是8bit,一幀數據傳輸需要30bit數據。

Source code

1、視頻生成

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;

 

2、加入HSYNC和VSYNC同步信號

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

 

3、生成紅、綠、藍信號(每個顏色8bit)

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

 

4、通過"TMDS編碼"將8bit數據展誠10bit

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

 

5、每個時鐘需要去發送10bit的數據,我們使用的時鐘是25MHz,所以需要乘以10倍,轉換成250MHz的時鐘。

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

 

6、三個RGB的移位寄存器是在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

 

Higher resolutions

如果使用640x480分辨率,我們需要使用250MHz時鐘的串行時鐘, 但是如果要更高的分辨率,需要更高的頻率,但是會超出FPGA本身的工作頻率。可以選擇使用一些特殊的FPGA IO引腳,譬如DDR輸出和IO串行器。在更高頻率是還有其他問題是,如何將像素時鐘的數據轉換到串行工作區中。一種可行的技術是使用一個淺(小)的FIFO。具體可以看xilinx XAPP460 和 XAPP495,可以得到相關的信息。

發佈了31 篇原創文章 · 獲贊 126 · 訪問量 20萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章