接口:基于FPGA的HDMI接口设计

您所在的位置:网站首页 hdmi接口引脚定义音频脚中文 接口:基于FPGA的HDMI接口设计

接口:基于FPGA的HDMI接口设计

2023-09-14 16:32| 来源: 网络整理| 查看: 265

        这篇文章只是一周的学习记录,由于本人只学习了如何利用HDMI传输视频图像并没有传输音频,所以这篇文章只有一个彩条实验。本人想写这篇博客只是对自己学习过程过程中产生的问题的一个记录,其中有些代码是自己借鉴后添加到自己工程中,有问题的代码我没有贴出,后续调通后会贴出代码。本人是一个FPGA的新学者,因为网上很多例程说的都不清楚,所以想通过这种方式有一个记录,如有侵权,指出后,会进行删除。如有不正确的地方也欢迎指出。

一、HDMI概述

        HDMI(High_Definition Multiface Interface)是一种音视频传输协议,主要用于解决VGA接口传输速度过慢以及体积过大的问题。HDMI传输主要是采用的TMDS(Transition Minimized Differential Signaling)协议。此外,使用TMDS也是DVI标准的主要特点 。

二、HDMI物理结构

        上图就是HDMI block结构图,可以看出HDMI在传输数据时,是经过三对差分信号传输数据和一对差分信号传输clock。其他协议暂时没有使用也就不展开说明。 引脚定义在其他博客中也有很多说明,包括在各个厂家购买的开发板上也有详细说明,如果需要的话可以自己在网站中寻找一下。

三、TMDS编码过程

       (1)TMDS编码示意图

        TMDS编码一般是将8位数据经过编码和直流平衡达到10位的最小数据。这仿佛是增加了冗余位,对传输要求更高了。但是实际上这种算法使得到的数据在同轴电缆中可靠性更强了,下图就是编码过程,8位并行的RED数据编码后进行并转串。(这些数据在各家提供的开发手册中都有,这些只是为了让自己更明白才写的)

(1)将 8 位并行 RED 数据发送到 TMDS 収送端。 (2)并/串转换。 (3)进行最小化传输处理,加上第 9 位,即编码过程。第 9 位数据称为编码位。

直流平衡:

        直流平衡(DC-balanced)就是指在编码过程中保证信道中直流偏移为零。方法是在原来的 9 位数据癿后面加上第 10 位数据,返样,传输的数据趋于直流平衡,使信号对传输线的电磁干扰减少,提高信号传输的可靠性。

        (2)TMDS发送和接收的链接示意图

        上图是 TMDS 发送端和接收端的连接示意图。DVI 或 HDMI 视频传输所使用的 TMDS 连接通过四个串行通道实现。对于DVI来说,其中三个通道分别用于传输视频中每个像素点的红、绿、蓝三个颜色分量(RGB4:4:4格式)。HDMI 默认也是使用三个 RGB 通道,但是它同样可以选择传输像素点的亮度和色度信息(YCrCb4:4:4或YCrCb 4:2:2格式)。第四个通道是时钟通道,用于传输像素时钟。独立的 TMDS 时钟通道为接收端提供接收的参考频率,保证数据在接收端能够正确恢复。

        在传输视频图像的过程中,数据通道上传输的是编码后的有效像素字符。而在每一帧图像的行与行之间,以及视频中不同帧之间的时间间隔(消隐期)内,数据通道上传输的则是控制字符。每个通道上有两位控制信号的输入接口,共对应四种不同的控制字符。这些控制字符提供了视频的行同步(HZYNC)以及帧同步(VSYNC)信息,也可以用来指定所传输数据的边界(用于同步)。对于 DVI 传输,整个视频的消隐期都用来传输控制字符。而 HDMI 传输的消隐期除了控制字符之外,还可以用于传输音频或者其他附加数据(例如字母信息),4-bit 音频和附加数据将通过 TERC4 编码机制转换成 10-bit TERC4 字符,然后再绿色和红色通道上传输。从上图也可以看出这一差别,即“Auxiliary Data”接口标有“HDMI Olny”,即它是 HDMI 所独有的接口。如果我们不需要附加数据,只传输视频数据的话,完全可以把 HDMI 接口当做 DVI 接口进行驱动。下图是DVI编码器示意图:

        每个通道输入的视频像素数据都要使用 DVI 规范中的 TMDS 编码算法进行编码。每个 8-bit 的数据都将被转换成 460 个特定 10-bit 字符中的一个。这个编码机制大致上实现了传输过程中的直流平衡,即一段时间内传输的高电平(数字“1”)的个数大致等于低电平(数字“0”)的个数。同时,每个编码后的 10-bit 字符中状态跳转(“由 1 到 0”或者“由 0 到 1”)的次数将被限制在五次以内。除了视频数据之外,每个通道 2-bit 控制信号的状态也要进行编码,编码后分别对应四个不同的 10-bit 控制字符,分别是 10'b1101010100,10'b0010101011,10'b0101010100,和 10'b1010101011。可以看出,每个控制字符都有七次以上的状态跳转。视频字符和控制字符状态跳转次数的不同将会被用于发送和接收设备的同步。 

  再重复一遍,HDMI 在输入附加数据的同时,还需要输入 ADE(Aux/Audio Data Enable)信号,其作用和 VDE 是类似的:当 ADE 为高电平时,表明输入端的附加数据或者音频数据有效,DIV 是不能传音频的。想了解更多有关 HDMI的细节,可以参考HDMI 接口规范——《High-Definition Multimedia Interface Specification Version 1.3a》,英语不好的也可以查看文档《HDMI1.4规范中文版》。

四、HDMI电路原理

        这边直接引用的是黑金AX7050底板的HDMI原理图接口:

 

         AZ1045_04F是TVS二极管,防止外面静电对FPGA产生损坏。本次实验只使用到TMDS数据,时钟,相关的管脚约束如下所示:

############## NET - IOSTANDARD ################## set_property CFGBVS VCCO [current_design] set_property CONFIG_VOLTAGE 3.3 [current_design] #############SPI Configurate Setting################## set_property BITSTREAM.CONFIG.SPI_BUSWIDTH 4 [current_design] set_property CONFIG_MODE SPIx4 [current_design] set_property BITSTREAM.CONFIG.CONFIGRATE 50 [current_design] create_clock -period 20.000 [get_ports sys_clk] set_property IOSTANDARD LVCMOS33 [get_ports sys_clk] set_property PACKAGE_PIN P15 [get_ports sys_clk] set_property IOSTANDARD LVCMOS33 [get_ports rst_n] set_property PACKAGE_PIN M15 [get_ports rst_n] #############HDMI_O################## set_property IOSTANDARD LVTTL [get_ports tmds_clk_n] set_property PACKAGE_PIN A20 [get_ports tmds_clk_n] set_property PACKAGE_PIN B20 [get_ports tmds_clk_p] set_property IOSTANDARD LVTTL [get_ports tmds_clk_p] set_property IOSTANDARD LVTTL [get_ports {tmds_data_n[0]}] set_property PACKAGE_PIN A17 [get_ports {tmds_data_n[0]}] set_property PACKAGE_PIN A16 [get_ports {tmds_data_p[0]}] set_property IOSTANDARD LVTTL [get_ports {tmds_data_p[0]}] set_property IOSTANDARD LVTTL [get_ports {tmds_data_n[1]}] set_property PACKAGE_PIN A13 [get_ports {tmds_data_n[1]}] set_property PACKAGE_PIN B13 [get_ports {tmds_data_p[1]}] set_property IOSTANDARD LVTTL [get_ports {tmds_data_p[1]}] set_property IOSTANDARD LVTTL [get_ports {tmds_data_n[2]}] set_property PACKAGE_PIN A12 [get_ports {tmds_data_n[2]}] set_property PACKAGE_PIN A11 [get_ports {tmds_data_p[2]}] set_property IOSTANDARD LVTTL [get_ports {tmds_data_p[2]}]

         需要注意的是,TMDS 数据和时钟信号需要在约束文件中指定电平标准为 LVTTL,此时钟约束是黑金AX7050提供的时钟约束。虽然差分信号vivado会在我们引导正极引脚位置后自动对负极进行分配,但是本人在测试后发现没有实现效果所以采用黑金提供的时序约束进行代码编写。

五、HDMI程序设计

        TMDS在逻辑功能上有两个阶段:编码和并转串。编码阶段就是将8bit的像素数据,行场数据分别编码成10bit的数据,在进行并转串设计,分别将RGB以及时钟信号发送出去。整个过程示意图如下:

 其中详解可以得到如下框图:

         Encoder模块负责对数据进行编码,即8bit编码成为10bit数据。

设计流程     

(1)上述框图中,图片数据来源模块与VGA模块的设计,可以在CSDN上寻找现成的代码。

(2)Encoder模块设计

        这部分编码可以在Xilinx官网下载例程(关于Xilinx官网下载代码,这个操作比较麻烦,以后找到方法会在列出)在此直接贴出代码,此代码的开发笔记可以在Xilinx提供的DocNav软件中找到(如何操作有时间会贴出)。

        Encoder模块把 8 比特的数据进行从新映射为 10bit 数据,防止连续的 0 和 1 出现导致直流不平衡造成误码率升高。

`timescale 1 ps / 1ps module encode ( input clkin, // pixel clock input input rstin, // async. reset input (active high) input [7:0] din, // data inputs: expect registered input c0, // c0 input input c1, // c1 input input de, // de input output reg [9:0] dout // data outputs ); // Counting number of 1s and 0s for each incoming pixel // component. Pipe line the result. // Register Data Input so it matches the pipe lined adder // output reg [3:0] n1d; //number of 1s in din reg [7:0] din_q; always @ (posedge clkin) begin n1d 4'h4) | ((n1d == 4'h4) & (din_q[0] == 1'b0)); wire [8:0] q_m; assign q_m[0] = din_q[0]; assign q_m[1] = (decision1) ? (q_m[0] ^~ din_q[1]) : (q_m[0] ^ din_q[1]); assign q_m[2] = (decision1) ? (q_m[1] ^~ din_q[2]) : (q_m[1] ^ din_q[2]); assign q_m[3] = (decision1) ? (q_m[2] ^~ din_q[3]) : (q_m[2] ^ din_q[3]); assign q_m[4] = (decision1) ? (q_m[3] ^~ din_q[4]) : (q_m[3] ^ din_q[4]); assign q_m[5] = (decision1) ? (q_m[4] ^~ din_q[5]) : (q_m[4] ^ din_q[5]); assign q_m[6] = (decision1) ? (q_m[5] ^~ din_q[6]) : (q_m[5] ^ din_q[6]); assign q_m[7] = (decision1) ? (q_m[6] ^~ din_q[7]) : (q_m[6] ^ din_q[7]); assign q_m[8] = (decision1) ? 1'b0 : 1'b1; / // Stage 2: 9 bit -> 10 bit // Refer to DVI 1.0 Specification, page 29, Figure 3-5 / reg [3:0] n1q_m, n0q_m; // number of 1s and 0s for q_m always @ (posedge clkin) begin n1q_m N0q_m)] or [(cnt < 0) and (N0q_m > N1q_m)] / assign decision3 = (~cnt[4] & (n1q_m > n0q_m)) | (cnt[4] & (n0q_m > n1q_m)); // pipe line alignment reg de_q, de_reg; reg c0_q, c1_q; reg c0_reg, c1_reg; reg [8:0] q_m_reg; always @ (posedge clkin) begin de_q


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3