精华内容
下载资源
问答
  • HDMI 显示RGB彩条实验

    2016-11-01 19:16:43
    verilog语言实现HDMI 显示RGB彩条实验
  • 使用VDMA驱动HDMI显示

    2019-01-23 16:54:39
    在ZYNQ的PS中生成显示数据,然后通过VDMA输出到HDMI接口
  • BeagleBone Green HDMI Cape是一块 HDMI 显示扩展板,可以方便的接到 BBG 上,从而极大的拓宽 BBG 的应用场景,例如 DIY 小型电脑,投影仪,数字电视或者数字音频设备。此款扩展板可以连接到任何标准 HDMI 接口的...
  • zynq 7000 的HDMI 显示实验

    千次阅读 2021-01-29 12:45:58
    用了很多年的zynq 7000,一直就没做hdmi 显示实验。前几天终于做了这个实验,也就做一个总结。 我的实验是在微相的z7r-lite下根据他们的教程完成的。平台是windows 10 , Vivado 2018.3。如果硬件设计不一样,主要是...

    用了很多年的zynq 7000,一直就没做hdmi 显示实验。前几天终于做了这个实验,也就做一个总结。

    我的实验是在微相的z7-lite下根据他们的教程完成的。平台是windows 10 , Vivado 2018.3。如果硬件设计不一样,主要是替换rgb2dvi 模块和gpio 中断部分。

    工程资料下载,

    链接:https://pan.baidu.com/s/11-RLOYtl1AyxcQ_XGbw2YQ 
    提取码:zvnc 

    这个下载里里三个文件,一个hdmi_out 全工程67M,下了这个就包含其他2个了,如果只是ip ,可以下hmdiip(375k),如果只是源代码 hdmisrc( 15M),主要是图形数据占空间。
    如果你有微相的资料,那就是 z7_Lite\03_SDK_Demo\17_hdmi_out

    IP准备

    这个实验用了2个IP,可以从 https://github.com/Digilent/vivado-library 下载。但我实验中用的是微相提供的是rgb2dvi_v1_2,这个ip 在工程的ip_repo目录里。

    该链接内有 Digilent 提供的很多个自定义 IP,但这个实验只用2个。其中 axi_dynclk  是时钟发生模块,会根据不同的屏幕分辨率,自动生成相应的像素时钟和串行时钟,而rgb2dvi  模块会将图像的红绿蓝信号转换成MDS 信号, 送往 HDMI 端口发出。网上版本比较新,我本想用新版本做测试的,结果sdk的时候报错,只好用微相提供的版本。IP文件目录如下图所示:


    在这里特别注意: if 文件目录也要复制,就是if 目录,其中包含了tmds 目录。ip目录下的 axi_dynclk, rgb2dvi 。图中内容复制到你的你的ip_repo,就是集中放IP的目录,我这目录下就放了其他IP。

    开始的时候,我习惯只把ip 下的目录复制过来,结果通过不了。

    硬件设计

    在 Vivado 下新建一个工程,名字为 hdmi_out。整个硬件设计是比较复杂的,我把它分为几个部分:

    添加ip目录,添加并配置zynq,添加 VDMA IP,AXI-Stream Subset Converter 模块,AXI4-Stream to Video Out 模块,Video Timing Controller 模块,rgb2dvi 模块,中断合并。

    图像数据的流向是:zynq的DDR中, VDMA 读取,AXI-Stream Subset Converter转换,AXI4-Stream to Video Out 模块,rgb2dvi 模块输出。

    Run Automation Connect的时候,一般只勾选当时介绍的IP, 如果多勾了,与后面指定操作冲突时,可以选择脚,右键,Disconnect Pin,使它脱离连接。

    添加ip 目录 

    在主窗口左侧边栏 Project Manager 下点击 Project Settings 选项, 向工程中添加这两个自定义 IP,其实是把 IP 存放目录加上去如下图所示:


    可以Project Manager -> IP Catalog 看到我们添加的IP。 

    原理图添加并配置zynq

    新建一个原理图, 加入zynq ,原理图是这样的:

     双击zynq进行设置:

    点击 PS-PL Configuration 选项, 在 HP Slave AXI interface 下勾选 S AXI HP0  interface, 本节实验要用这个端口获取 DDR 中存储的图像数据。


    使能 UART0,这与开发板有关,z7_lite对应的是14,15。

    点击 Clock Configuration 选项,在 PL Fabric Clocks 窗口,勾选 FCLK_CLK0和 FCLK_CLK1,并将其分别设为 100, 140MHz。 其中 FCLK_CLK0 将作为 Zynq配置各个模块的时钟, 而 FCLK_CLK1 将作为图像数据流的时钟,


    再点击 DDR Configuration, 选择跟开发板一致的 DDR 型号.z7_lite 是 MT41K256M16 RE-125,16 Bit

    再点击 Interrupt 选项,激活 IRQ_F2P[15:0]选项,点击 OK,配置完成。


    手动连接 FCLK_CLK0 到 MAXI_GPO_ACLK, 连接 FCLK_CLK1 到 S_AXI_HP0_ACLK,

    检查并对比,原理图是否一致。

    添加 VDMA IP 

    如下图所示:

    VDMA 添加完成如下图所示:
     


     

    双击上图 axi_vdma_0, 进行参数配置。 首先 Basic 选项, Address Width设为 32 bits, 寻址空间可以达到 4GB。 Frame Buffers 设为 1,取消 Enable WriteChannel 选项,因为本实验 VDMA 只从 DDR 中读取图像数据。 在 Enable Read Channel 下, 将 Line Buffer Depth 改为 4096, 其它默认, 如下图所示:

    再点击 Advanced 选项卡, 将 GenLock Mode 改为 Master,点击 OK 完成配置。

    现在原理图是如下样子,点击 Run Connection Automation,自动生成 AXI 互联总线及系统复位电路,在弹出的对话框中勾选 All Automation, 点击 OK。

    然后手动将 m_axis_mm2s_aclk 和 m_axi_mm2s_aclk 两个时钟连在一起。

    AXI-Stream Subset Converter 模块

    添加 AXI-Stream Subset Converter 模块
     

    添加完成后如下图所示:

    双击上图的 axis_subset_converter_0,如下配置。

    TDATA 输入为 32-bit,即 4-Byte,输出为 24-Bit, 即 3-Byte。

    将 TKEEP、 TLAST 修改为 yes,并将 USERWidth 置为 1,

    这里要重点说一下 TDATA Remap String 项,因为要显示的图像在 DDR 中的存储方式为 24-bit 默认方式 B, G, R,分别以[7:0], [15:8], [23:16]组成 24-bit,而本例中使用的产生 TMDS 信号模块 rgb2dvi 的像素排序为 R, B, G,所以需要在 TDATA Remap String 这一项做顺序调整。调整字符串为:tdata[23:16],tdata[7:0],tdata[15:8]

    配置如下图所示:

    配置好了,点OK。

    手 动 连 接 axis_subset_converter_0 的 S_AXIS 端 口 到 axi_vdma_0 的M_AXIS_MM2S 端口。

    并将其 aclk 连接到 FCLK_CLK1 时钟网络。 如下图所示:

    增加一个常量输出模块 Constant, 将 axis_subset_convert_0 的复位端口 aresetn 拉高,使其始终处于工作状态,

    双击刚刚添加的 xlconstant_0,保持默认的 1bit 位宽输出高电平 1 的配置,点击 OK,

    将 xlconstant_0 的 dout 端口连到 axis_subset_converter_0 的 aresetn端口,
     

    AXI4-Stream to Video Out 模块

    添加 AXI4-Stream to Video Out 模块。本例用这个模块将 VDMA 从 DDR 读出的 AXI4-Stream 转换成 RGB 图像数据。

    双击 v_axi4s_vid_out_0 进行配置。

    将 FIFO Depth 改为 4096,

    Clock Mode 设为 Independent,

    Timing Mode 设为 Master,点击 OK。

    手动将 v_axi4s_vid_out_0 的 video_in 端口连接到 axis_subset_converter_0的 M_AXIS 端口,

    再将其 aclk 连接到 FCLK_CLK1 时钟网络,如下图,
     

    Video Timing Controller 模块

    添加 Video Timing Controller 模块。本例使用这个模块,来产生不同的分辨率下时序控制信号。

    双击 v_tc_0 进行配置。取消掉 Enable Detection 选项的勾选,其它保持默认,点击 OK,

    点击 Diagram 窗口的 Run Connection Automation,自动生成 v_tc_0 模块的相关连接。

    勾选 All Automation, 点击“ OK”。
     

    连接 v_tc_0 的 vtiming_out 端口到 v_axi4s_vid_out_0 的 vtiming_in 端口,

    连接 v_tc_0 的 gen_clken 端口到 v_axi4s_vid_out_0 的 vtg_ce 端口,

    rgb2dvi 模块

    添加 rgb2dvi 模块。此模块将 RGB 信号转换为 DVI 信号,即 TMDS 格式。

    双击 rgb2dvi_0 进行配置。 这里取消勾选 Reset active high

    和 Generate SerialClk internally from pixel clock,

    信号频率设置选择<120MHz(720p)这一项。

    连接 v_axi4s_vid_out_0 的 vid_io_out 端口到 rgb2dvi_0 端口,

    右键单击 rgb2dvi_0 的 TMDS 端口, 选择 Make External 生成外部引脚,
     

    添加时钟生成模块,点击上方工具栏“ +”,在搜索框输入 dynclk, 回车添加模块。


    此模块使用默认参数, 点击 Run Connection Automation

    将 axi_dynclk_0的像素时钟 PXL_CLK_O 端口连接到 rgb2dvi_0 的 PixelClk 端口,

    并将其串行时钟PXL_CLK_5X_O 端口连接到 rgb2dvi_0 的SerialCLk 端口,

    再将 axi_dynclk_0 的 LOCKED_O 端口连接到 rgb2dvi_0 的 aRst_n 端口,

    这样当锁相环锁定,即时钟信号稳定输出时,rgb2dvi 模块开始工作,

    做到这我没截图,所以下面图中还包含了一些下一步的连线。

    将 v_tc_0 的 clk 端口连接到 axi_dynclk_0 的 PXL_CLK_O 端口上。同样,
    将 v_axi4s_vid_out_0 的 vid_io_out_clk 也连接到 PXL_CLK_O 这一网络上,

    中断合并

    添加 GPIO 模块,用作 HDMI 的热拔插检测信号 HPD

    双击 axi_gpio_0 进行配置,将其设为 1 位输入, 使能 Interrupt,点击 OK,
     

    将端口名称修改为“ HDMI_HPD”,
     

    添加一个 concat 模块,将所有中断信号集中起来,然后再连接到 Zynq 处理器的中断输入端口。
     

    双击 xlconcat_0 进行配置。本例中有 3 个中断信号, 设置端口数为 3, 点击 OK, 如下图所示:
     

    将 axi_gpio_0 的 中 断 端 口 ip2intc_irpt , axi_vdma_0 的 中 断 端 口mm2s_introut, v_tc_0 的中断端口 irq,分别连接到 xlconcat_0 的 In0, In1, In2上,并将 xlconcat_0 的输出端口 dout 连接到 Zynq 的 IRQ_F2P 上,

    由于图比较大,可能脚比较远,也可以选择要连接的端口之一,比如axi_vdma_0 的 中 断 端 口mm2s_introut,然后右键选择 Make Connetion,出现可能的连线,然后做一个选择,下图中选择xlconc_0 的In1。看下图所示:

    连接后是这样的,

    硬件设计完成了,如果有 Run Block Automation 提示,那就点击 Run Block Automation,在弹出的对话框中全选所有信号端口,点击“ OK”。
     

    点击 Regenerate Layout 生成标准布局如下图, 再点击 Validate Design 验证设计:
     

    验证成功后, 弹窗点击 OK, Ctrl+S 保存设计。

    我的在验证时出现如下错误:

    [BD 41-1343] Reset pin /v_tc_0/resetn (associated clock /v_tc_0/clk) is connected to reset source /rst_ps7_0_100M/peripheral_aresetn (synchronous to clock source /processing_system7_0/FCLK_CLK0).
    This may prevent design from meeting timing. Please add Processor System Reset module to create a reset that is synchronous to the associated clock source /axi_dynclk_0/PXL_CLK_O.

    我对照一下,点击pin /v_tc_0/resetn, 然后右键 Disconnect Pin,再验证就好了。

    来到 Source 窗口, 生成设计代码和顶层文件, 右键点击 hdmi_out 选择Generate Output Producs, 在弹出的窗口点击 Generate,点击 OK。 右键点击hdmi_out 选择 Create HDL Wrapper,在弹出的窗口点击 OK。

    添加管脚约束,这里可以直接添加一个约束文件,然后把下面内容复制过去就可。

    set_property IOSTANDARD LVCMOS33 [get_ports {HDMI_HPD_tri_i[0]}]
    set_property PACKAGE_PIN P19 [get_ports {HDMI_HPD_tri_i[0]}]
    set_property PACKAGE_PIN U18 [get_ports TMDS_0_clk_p]
    set_property PACKAGE_PIN V20 [get_ports {TMDS_0_data_p[0]}]
    set_property PACKAGE_PIN T20 [get_ports {TMDS_0_data_p[1]}]
    set_property PACKAGE_PIN N20 [get_ports {TMDS_0_data_p[2]}]

    这个约束文件很简单,看电路图,都用了脚对,虽然4个脚,实际是8个脚。

    原文中有设置约束文件的方法,不错,值得学习。但复制约束文件比较简单。

    产生比特流,输出硬件(要包含比特流),然后打开SDK,就开始软件设计部分了。

    软件设计

    在打开的 SDK 软件内点击 File > New > Application Project, 工程名填入“ hdmi_out”, 工程模板选择 Empty Application 工程, 点击 Finish。

    创 建 完 成 后 , 打 开 资 料 目 录hdmi_out/hdmi_out.sdk/hdmi_out/src 文件夹,复制文件夹内的所有文件,粘贴到当前工程同样的目录下(注意,不要覆盖本工程下的 lscript.ld), 右键单击工程 hdmi_out
    选择 Refresh,则开始自动编译。双击打开 src 目录底下的 display_demo.c, 这就是 SDK 主程序。
    接下来讲解代码,展开工程下的 src 可以看到文件结构如下图所示, 其中display_ctrl 文件夹包含不同视频分辨率情况下的时序控制, dynclk 包含不同分辨率情况下的像素时钟和串行时钟生成。
     

    打开 display_demo.c 文件,这就是本实验的主程序,我们分段讲解各部分的作用。

    #include <stdio.h>
    #include <math.h>
    #include <ctype.h>
    #include <stdlib.h>
    #include "xil_types.h"
    #include "xil_cache.h"
    #include "xparameters.h"
    #include "display_demo.h"
    #include "display_ctrl/display_ctrl.h"
    #include "display_ctrl/vga_modes.h"
    
    // Image data for each resolution
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    //#include "pic_800_600.h"
    //#include "pic_1280_720.h"
    //#include "pic_1280_1024.h"
    #include "pic_1920_1080.h"
    //@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    /*
     * XPAR redefines
     */
    #define DYNCLK_BASEADDR     XPAR_AXI_DYNCLK_0_BASEADDR
    #define VGA_VDMA_ID         XPAR_AXIVDMA_0_DEVICE_ID
    #define DISP_VTC_ID         XPAR_VTC_0_DEVICE_ID
    
    /* ------------------------------------------------------------ */
    /*				Global Variables								*/
    /* ------------------------------------------------------------ */
    
    /*
     * Display Driver struct
     */
    DisplayCtrl dispCtrl;
    XAxiVdma vdma;
    
    /*
     * Frame buffers for video data
     */
    u8 frameBuf[DISPLAY_NUM_FRAMES][DEMO_MAX_FRAME];
    u8 *pFrames[DISPLAY_NUM_FRAMES];  // array of pointers to the frame buffers
    
    /* ------------------------------------------------------------ */
    /*				Procedure Definitions							*/
    /* ------------------------------------------------------------ */
    
    int main(void)
    {
    	int i;
    	int Status;
    	XAxiVdma_Config *vdmaConfig;
    
    	/*
    	 * Initialize an array of pointers to the 3 frame buffers
    	 */
    	for (i = 0; i < DISPLAY_NUM_FRAMES; i++)
    	{
    		pFrames[i] = frameBuf[i];
    	}
    
    	/*
    	 * Initialize VDMA driver, get the hardware VDMA configurations
    	 */
    	vdmaConfig = XAxiVdma_LookupConfig(VGA_VDMA_ID);
    	if (vdmaConfig == NULL)
    	{
    		xil_printf("No video DMA found for ID %d\r\n", VGA_VDMA_ID);
    	}
    
    	/*
    	 * Use hardware VDMA configurations to initialize the driver
    	 */
    	Status = XAxiVdma_CfgInitialize(&vdma, vdmaConfig, vdmaConfig->BaseAddress);
    	if (Status != XST_SUCCESS)
    	{
    		xil_printf("VDMA Configuration Initialization failed %d\r\n", Status);
    	}
    
    	/*
    	 * Initialize the Display controller and start it
    	 */
    
    	// Video Mode for each resolution
    	//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    	//VideoMode VMODE = VMODE_800x600;
    	//VideoMode VMODE = VMODE_1280x720;
    	//VideoMode VMODE = VMODE_1280x1024;
    	VideoMode VMODE = VMODE_1920x1080;
    	//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    	Status = DisplayInitialize(&dispCtrl, &vdma, DISP_VTC_ID, DYNCLK_BASEADDR, pFrames, DEMO_STRIDE, VMODE);
    	if (Status != XST_SUCCESS)
    	{
    		xil_printf("Display Ctrl initialization failed during demo initialization%d\r\n", Status);
    	}
    
    	Status = DisplayStart(&dispCtrl);
    	if (Status != XST_SUCCESS)
    	{
    		xil_printf("Couldn't start display during demo initialization%d\r\n", Status);
    	}
    
    	DemoPrintTest(dispCtrl.framePtr[dispCtrl.curFrame], dispCtrl.vMode.width, dispCtrl.vMode.height, dispCtrl.stride);
    
    	return 0;
    }
    
    void DemoPrintTest(u8 *frame, u32 width, u32 height, u32 stride)
    {
    	u32 xcoi, ycoi;
    	u32 linesStart = 0;
    	u32 pixelIdx = 0;
    
    	for(ycoi = 0; ycoi < height; ycoi++)
    	{
    		for(xcoi = 0; xcoi < (width * 4); xcoi+=4)
    		{
    
    			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    
    			/*
    			// 800 x 600
    			frame[linesStart + xcoi    ] = Pixel_800_600[pixelIdx++];  // Blue
    			frame[linesStart + xcoi + 1] = Pixel_800_600[pixelIdx++];  // Green
    			frame[linesStart + xcoi + 2] = Pixel_800_600[pixelIdx++];  // Red
    			*/
    
    			/*
    			// 1280 x 720
    			frame[linesStart + xcoi    ] = Pixel_1280_720[pixelIdx++];
    			frame[linesStart + xcoi + 1] = Pixel_1280_720[pixelIdx++];
    			frame[linesStart + xcoi + 2] = Pixel_1280_720[pixelIdx++];
    			*/
    
    			/*
    			// 1280 x 1024
    			frame[linesStart + xcoi    ] = Pixel_1280_1024[pixelIdx++];
    			frame[linesStart + xcoi + 1] = Pixel_1280_1024[pixelIdx++];
    			frame[linesStart + xcoi + 2] = Pixel_1280_1024[pixelIdx++];
    			*/
    
    			// 1920 x 1080
    			frame[linesStart + xcoi    ] = Pixel_1920_1080[pixelIdx++];
    			frame[linesStart + xcoi + 1] = Pixel_1920_1080[pixelIdx++];
    			frame[linesStart + xcoi + 2] = Pixel_1920_1080[pixelIdx++];
    
    			//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
    		}
    
    		linesStart += stride;
    	}
    
    	/*
    	 * Flush the frame buffer memory range to ensure changes are written to the
    	 * actual memory, and therefore accessible by the VDMA.
    	 */
    	Xil_DCacheFlushRange((unsigned int) frame, DEMO_MAX_FRAME);
    }
    

    这部分提供了 4 个不同分辨率图像的像素数据, 这些数据以头文件的形式包含在工程目录中,比如 pic_800_600.h。 以 800x600 图像像素为例,如下图,每个像素以三基色表示,一共 800x600x3 = 1440000 个数据点。屏幕左上角坐标(0,0)处第一个像素的蓝色,绿色,红色数值依次是 0xF1, 0xDC, 0xDB, 其它点的像素值依次类推。

    pic_800_600.h 文件内容,其实就是定义图形常量:

    const unsigned char Pixel_800_600[1440000] = {
    0XF1,0XDC,0XDB,0XF1,0XDC,0XDB,0XF3,0XDE,0XDD,0XF4,0XDF,0XDE,0XF5,0XE0,0XDF,0XF6,0XE1,0XE0,
    0XF7,0XE2,0XE1,0XF7,0XE2,0XE1,0XFC,0XE7,0XE6,0XFB,0XE7,0XE6,0XFB,0XE7,0XE6,0XFC,0XE8,0XE7,
    
    ...
    
    };

    主程序的开始部分是4个全局变量的定义

    /*
     * Display Driver struct
     */
    DisplayCtrl dispCtrl;
    XAxiVdma vdma;
    
    /*
     * Frame buffers for video data
     */
    u8 frameBuf[DISPLAY_NUM_FRAMES][DEMO_MAX_FRAME];
    u8 *pFrames[DISPLAY_NUM_FRAMES];  // array of pointers to the frame buffers

    显示控制结构体 DisplayCtrl 和 VDMA 例化(读者可以按住 Ctrl 键的同时鼠标左键点进去看看这两个结构体包含的内容)。

    然后是显示数据定义。

    main 函数:

    先初始化pFrames(frame buffers 的指针)

     get the hardware VDMA configurations  :vdmaConfig

    初始化驱动

    显示启动。

    最后通过函数DemoPrintTest把显示数据复制到显示缓存,图像就显示了

    程序结束

    程序代码是针对1600x1200的,如果要更改方式,有3个地方需要修改:

    1,#include "pic_1920_1080.h"

    2:VideoMode VMODE = VMODE_1920x1080;

    3:DemoPrintTest函数中

                // 1920 x 1080
                frame[linesStart + xcoi    ] = Pixel_1920_1080[pixelIdx++];
                frame[linesStart + xcoi + 1] = Pixel_1920_1080[pixelIdx++];
                frame[linesStart + xcoi + 2] = Pixel_1920_1080[pixelIdx++];

    这3个地方都有//@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@

    包括了,应该容易找到。

    验证

    编译好了,就可以验证显示了。

    连接电脑 USB 到开发板 JTAG 口,连接电脑另一个 USB 到开发板 UART口,确保开发板启动模式设置为 JTAG,连接开发板 HDMI 口到 HDMI 显示器,给开发板上电。按照之前实验的操作方式连接串口(在本实验中,如果未发送错误则串口不打印信息)。其实每阶段运行完了,给个阶段显示更好,可以加点print。
    Xilinx->program FPGA下载比特流,然后Run-> Run Configuration,做如下选择,然后Run

    第一次的时候,我直接 Run As ->Launch on Hardware,结果没显示,按上面方法才显示,可能要等的时间长一点。我新做这个实验, Run As -> Launch on Hardware也能显示。

    做这个实验还是花很多时间才完成,有点难。成功显示后还有点成就感,再做一遍,并写上此文。

    展开全文
  • 基于FPGA的HDMI显示(二)

    千次阅读 2019-12-15 21:56:05
    1.4 基于FPGA的720P HDMI显示 1.4.1 HDMI 硬件电路分析   本次设计采用了 IO 模拟的方式实现 HDMI 的功能。与采用专用 HDMI 芯片相比,此方案具有成本更低、效果不输于采用专用芯片的效果、经过测试,兼容性方面也...

    基于FPGA的720P HDMI显示

    1.4.1 HDMI 硬件电路分析

      本次设计采用了 IO 模拟的方式实现 HDMI 的功能。与采用专用 HDMI 芯片相比,此方案具有成本更低、效果不输于采用专用芯片的效果、经过测试,兼容性方面也要比专用芯片要好、最大输出图像分辨率 1080P、图像传输稳定等显著的优势。
      具体硬件电路上面已经提到过了,这里简单分析一下。
    在这里插入图片描述
                图1 32 HDMI 硬件电路
      从图中可以看到, HDMI 接口设计全由 IO 模拟方式实现, HDMI 的信号线 D0~D2 其实是一个差分信号,在我们程序当中体现为 TMDS 类型,因此其输入信号为串行的数字信号,内部实际上是将输入的 RGB 信号进行编码,转换为 HDMI 数据(实际我们称其为 DVI)进行输出,因此在设计中通常可以将 RGB 信号单独引出,作为 RGB 输出,用来作为双显输出使用。下表是 HDMI 接口信号的功能定义。
            表1 5 HDMI 接口信号的功能定义
    在这里插入图片描述
    在这里插入图片描述
              图1 33 HDMI 视频输出时序

    1.4.2 工程文件设计

      HDMI 采用和 DVI 相同癿传输原理——TMDS(Transition Minimized Differential signal),最小化传输差分信号。
      TMDS 传输系统分为两个部分:发送端和接收端。 TMDS 发送端收到HDMI 接口传来的表示 RGB 信号的24 位并行数据(TMDS 对每个像素的 RGB 三原色分别按 8bit 编码,即 R信号有 8 位,G 信号有 8 位,B 信号有 8 位),然后对这些数据进行编码和并/串转换,再将表示 3 个 RGB 信号的数据分别分配到独立的传输通道发送出去。接收端接收来自发送端的串行信号,对其进行解码和串/并转换,然后发送到显示器的控制端。与此同时也接收时钟信号,以实现同步。
      TMDS的原理
      每一个 TMDS 链路都包括 3 个传输 RGB 信号的数据通道和 1 个传输时钟信号的通道。每一个数据通道都通过编码算法,将 8 位的视、音频数据转换成最小化传输、直流平衡的 10 位数据。这使得数据的传输和恢复更加可靠。最小化传输差分信号是通过异或及异或非等逡、逻辑算法将原始 8 位信号数据转换成 10 位,前 8 为数据由原始信号经运算后获得,第 9 位指示运算的方式,第 10 位用来对应直流平衡。
      一般来说,HDMI 传输癿编码格式中要包含视频数据、控制数据和数据包(数据包中包吨音频数据和附加信息数据,例如纠错码等)。 TMDS 每个通道在传输时要包含一个 2bit 的控制数据、 8bit 的视频数据或者 4bit 的数据包即可。在 HDMI 信息传输过程中,可以分为三个阶段:视频数据传输周期、控制数据传输周期和数据岛传输周期,分别对应上述的三种数据类型。
    下面介绍 TMDS 中采用的技术:
      1. 传输最小化
      8 位数据经过编码和直流平衡得到 10 位最小化数据,这仿佛增加了冗余位,对传输链路的带宽要求更高,但事实上,通过这种算法得到的 10 位数据在更长的同轴电缆中传输的可靠性增强了。下图是一个例子,说明对一个 8 位的并行 RED 数据编码、并/串转换。
    在这里插入图片描述
           图1 34 一个 8 位的并行 RED 数据编码、并/串转换
      第一步:将 8 位并行 RED 数据发送到 TMDS 収送端;
      第二步:并/串转换;
      第三步:进行最小化传输处理,加上第 9 位,即编码过程。第 9 位数据称为编码位。
      2. 直流平衡
      直流平衡(DC-balanced)就是指在编码过程中保证信道中直流偏移为零。方法是在原来的 9 位数据癿后面加上第 10 位数据,返样,传输的数据趋于直流平衡,使信号对传输线的电磁干扰减少,提高信号传输的可靠性。
      3. 差分信号
      TMDS差分传动技术是一种利用2个引脚间电压差来传送信号的技术。传输数据的数值(“0”或者“1”)由两脚间电压正负极性和大小决定。即,采用 2 根线来传输信号,一根线上传输原来的信号,另一根线上传输与原来信号相反的信号。这样接收端就可以通过让一根线上的信号减去另一根线上的信号的方式来屏蔽电磁干扰,从而得到正确的信号。
    在这里插入图片描述
                  图1 35 差分信号
      另外,还有一个显示数据通道(DDC),是用于读取表示接收端显示器的清晰度等显示能力的扩展显示标识数据(EDID)的信号线。搭载 HDCP(High-bandwidth Digital Content Protection,高带宽数字内容保护技术)的发送、接收设备之间也利用 DDC 线进行密码键的认证。
      接下来是电路设计部分,HDMI驱动部分追寻原始出处应该是迪芝伦官方,该部分代码用VHDL语言描述,为了方便移植,我将该部分代码封装成自定义IP Core,由上文可知,我们需要产生RGB888三路数据,输入给该模块,然后经过解码、串/并转换,差分输出。还需要两个时钟输入,一个是当前显示分辨率的像素时钟,一个是当前显示分辨率的像素时钟的五倍。还有一个行同步信号和场同步信号,这两个信号的产生方法和VGA是一样的,简单来说就是先产生VGA的信号,行同步信号、场同步信号RGB888的数据输入给HDMI驱动模块就可以显示了,我们要修改显示的数据,还是只需要修改VGA时序即可。
    在这里插入图片描述
                图1 36 HDMI IP核结构框图
      从上面的分析可以知道,IO模拟IP,主要有两部分组成,一是VGA时序产生,另一个是HDMI IP,整个系统结构图如下:
    在这里插入图片描述
              图1 37 基于FPGA的HDMI显示结构图
      核心操作就是产生VGA时序及产生需要显示的视频数据,本次设计共产生几种图像(格子、纯黑、纯白、纯蓝等),可以通过按键来进行切换显示的模式,用 LED 来指示处于何种模式,方便我们调试时分析与处理问题。
      本次设计产生一个720P 的图像,故其像素时钟输入应该为H_TotalV_TotalFPS=165075060HZ=74.25MHZ。这一部分程序的编写参考的是 VGA 时序,VGA 的时序是一种 RGB传输时序,其时序图如下图所示:
    在这里插入图片描述
                  图1 38 VGA时序
      首先看到有 3 个矩形,第 1 个矩形是 VGA 驱动的最大部分,里面包括所有的信息,在此基础之上有 2 个同步信号,即 HSYNC 和 VSYNC(行同步和场同步), HSYNC 可以确定一行的开始和结束, VSYNC 可以确定一场的开始和结束,但是同步信号也有时间,因此就引出 Hor Sync 和 Ver Sync(行同步时间和场同步时间)。接下来就是H Back Proch 和 V Back Porch(行消隐和场消隐),消隐存在主要是为了兼容电子管屏幕设计的。然后是第 2 个矩形,这是 Hor” Active” Video 和 Ver“Active” Video(行视频有效和场视频有效),在这个区域中是显示视频的地方。最后就是 H Front Porch 和 V Front Porch(行前肩和场前肩)。到此,一场完整视频就显示完毕了。在这里说一下第 3 个矩形,有 4 个参数 H Left Border、 H Right Border、 V Top Border 和 V Bottom Border,在不同分辨率中这4 个参数不同,在 800x600 及其以上的分辨率中这 4 个参数为 0。
      在此给出一个简化的时序图,如下图所示。一行数据包括: Hor Sync(行同步)、Hor Back Porch(行消隐)、 Hor Active Video(行视频有效)和 Hor Front Porch(行前肩);一场数据包括: Ver Sync(场同步)、 Ver Back Porch(场消隐)、 Ver Active Video(场视频有效)和 Ver Front Porch(场前肩)。
    在这里插入图片描述
                  图1 39 VGA时序
      VGA 时序主要分为行时序和场时序,行时序是以像素为单位的,场时序是以行为单位的。 VGA 行时序对行同步时间、消隐时间、行视频有效时间和行前肩时间有特定要求,列时序也是如此,如果其中一部分时序出现问题就会造成显示出现问题。常用 VGA 分辨率时序参数如下表所示。
              表1 6 VGA 常用分辨率时序参数
    在这里插入图片描述
      在这里说一下时钟频率计算,就是上文提到的第 1 个矩形和场频率有关,思考一下,很简单的。时钟频率=行最大值 x 列最大值 x 扫描频率。

    代码1 1 HDMI数据产生模块

    1.	//****************************************************************************//  
    2.	//# @Author: 碎碎思  
    3.	//# @Date:   2019-11-25 21:58:59  
    4.	//# @Last Modified by:   zlk  
    5.	//# @WeChat Official Account: OpenFPGA  
    6.	//# @Last Modified time: 2017-11-08 16:58:26  
    7.	//# Description:   
    8.	//# @Modification History: 2017-11-08 16:58:26  
    9.	//# Date                By             Version             Change Description:   
    10.	//# ========================================================================= #  
    11.	//# 2017-11-08 16:58:26  
    12.	//# ========================================================================= #  
    13.	//# |                                                                       | #  
    14.	//# |                                OpenFPGA                               | #  
    15.	//****************************************************************************//  
    16.	  
    17.	  
    18.	`timescale 1ns / 1ps  
    19.	  
    20.	module hdmi_data_gen  
    21.	    (  
    22.	    input               pix_clk,  
    23.	    input               turn_mode,  
    24.	    output [7:0]    VGA_R,  
    25.	    output [7:0]    VGA_G,  
    26.	    output [7:0]    VGA_B,  
    27.	    output          VGA_HS,  
    28.	    output          VGA_VS,  
    29.	    output          VGA_DE,  
    30.	    output [3:0]    mode  
    31.	    );  
    32.	/* 
    33.	parameter H_Total       =   1344; //2200 
    34.	parameter H_Sync        =   136; 
    35.	parameter H_Back        =   160;//2-4 
    36.	parameter H_Active  =   1024;   //1920 
    37.	parameter H_Front       =   24; 
    38.	parameter H_Start       =   296; //2-3 
    39.	parameter H_End     =   1320; 
    40.	//-------------------------------// 
    41.	// 垂直扫描参数的设定1024*600    60HZ     
    42.	//-------------------------------// 
    43.	parameter V_Total       =   628;  //1125 
    44.	parameter V_Sync        =   4; 
    45.	parameter V_Back        =   4; 
    46.	parameter V_Active  =   600;   //1080 
    47.	parameter V_Front       =   0; 
    48.	parameter V_Start       =   8; 
    49.	parameter V_End     =   628; 
    50.	*/  
    51.	  
    52.	//---------------------------------//  
    53.	// 水平扫描参数的设定1280*720  60HZ  
    54.	//--------------------------------//  
    55.	parameter H_Total       =   1650; //2200  
    56.	parameter H_Sync        =   40; //44  
    57.	parameter H_Back        =   220;//148  
    58.	parameter H_Active  =   1280;   //1920  
    59.	parameter H_Front       =   110; //88  
    60.	parameter H_Start       =   260; //192  
    61.	parameter H_End     =   1540;  //2112  
    62.	//-------------------------------//  
    63.	// 垂直扫描参数的设定1280*720    60HZ      
    64.	//-------------------------------//  
    65.	parameter V_Total       =   750;  //1125  
    66.	parameter V_Sync        =   5;   //5  
    67.	parameter V_Back        =   20; //37  
    68.	parameter V_Active  =   720;  //1080  
    69.	parameter V_Front       =   5; //3  
    70.	parameter V_Start       =   25; //42  
    71.	parameter V_End     =   745;  //1122  
    72.	  
    73.	/* 
    74.	//---------------------------------// 
    75.	// 水平扫描参数的设定1980*1080  60HZ 
    76.	//--------------------------------// 
    77.	parameter H_Total       =   2200; //2200 
    78.	parameter H_Sync        =   44; //44 
    79.	parameter H_Back        =   148;//148 
    80.	parameter H_Active  =   1920;   //1920 
    81.	parameter H_Front       =   88; //88 
    82.	parameter H_Start       =   192; //192 
    83.	parameter H_End     =   2112;  //2112 
    84.	//-------------------------------// 
    85.	// 垂直扫描参数的设定1920*1080   60HZ     
    86.	//-------------------------------// 
    87.	parameter V_Total       =   1125;  //1125 
    88.	parameter V_Sync        =   5;   //5 
    89.	parameter V_Back        =   37; //37 
    90.	parameter V_Active  =   1080;  //1080 
    91.	parameter V_Front       =   3; //3 
    92.	parameter V_Start       =   42; //42 
    93.	parameter V_End     =   1122;  //1122 
    94.	*/  
    95.	reg[11:0]   x_cnt;  
    96.	always @(posedge pix_clk)       //水平计数  
    97.	begin  
    98.	    if(1'b0)  
    99.	    x_cnt   <=   1;  
    100.	    else if(x_cnt==H_Total)  
    101.	    x_cnt   <=   1;  
    102.	    else  
    103.	    x_cnt   <=   x_cnt   +   1;  
    104.	end  
    105.	  
    106.	reg hsync_r;  
    107.	reg hs_de;  
    108.	always @(posedge pix_clk)  
    109.	begin  
    110.	    if(1'b0)  
    111.	    hsync_r <=   1'b1;  
    112.	    else if(x_cnt==1)  
    113.	    hsync_r <=   1'b0;  
    114.	    else if(x_cnt==H_Sync)  
    115.	    hsync_r <=   1'b1;  
    116.	      
    117.	    if(1'b0)  
    118.	    hs_de   <=   1'b0;  
    119.	    else if(x_cnt==H_Start)  
    120.	    hs_de   <=   1'b1;  
    121.	    else if(x_cnt==H_End)  
    122.	    hs_de   <=   1'b0;  
    123.	end  
    124.	  
    125.	reg[11:0]   y_cnt;  
    126.	always @(posedge pix_clk)  
    127.	begin  
    128.	    if(1'b0)  
    129.	    y_cnt   <=   1;  
    130.	    else if(y_cnt==V_Total)  
    131.	    y_cnt   <=   1;  
    132.	    else if(x_cnt==H_Total)  
    133.	    y_cnt   <=   y_cnt   +   1;  
    134.	end  
    135.	  
    136.	reg vsync_r;  
    137.	reg vs_de;  
    138.	always @(posedge pix_clk)  
    139.	begin  
    140.	    if(1'b0)  
    141.	    vsync_r <=   1'b1;  
    142.	    else if(y_cnt==1)  
    143.	    vsync_r <=   1'b0;  
    144.	    else if(y_cnt==V_Sync)  
    145.	    vsync_r <=   1'b1;  
    146.	      
    147.	    if(1'b0)  
    148.	    vs_de   <=   1'b0;  
    149.	    else if(y_cnt==V_Start)  
    150.	    vs_de   <=   1'b1;  
    151.	    else if(y_cnt==V_End)  
    152.	    vs_de   <=   1'b0;  
    153.	end  
    154.	  
    155.	reg[7:0]    grid_data_1;  
    156.	reg[7:0]    grid_data_2;  
    157.	always @(posedge pix_clk)           //格子图像  
    158.	begin  
    159.	    if((x_cnt[4]==1'b1)^(y_cnt[4]==1'b1))  
    160.	    grid_data_1 <=   8'h00;  
    161.	    else  
    162.	    grid_data_1 <=   8'hff;  
    163.	      
    164.	    if((x_cnt[6]==1'b1)^(y_cnt[6]==1'b1))  
    165.	    grid_data_2 <=   8'h00;  
    166.	    else  
    167.	    grid_data_2 <=   8'hff;  
    168.	end  
    169.	  
    170.	reg[23:0]   color_bar;  
    171.	always @(posedge pix_clk)  
    172.	begin  
    173.	    if(x_cnt==192)  
    174.	    color_bar   <=   24'hff0000;  
    175.	    else if(x_cnt==432)  
    176.	    color_bar   <=   24'h00ff00;  
    177.	    else if(x_cnt==672)  
    178.	    color_bar   <=   24'h0000ff;  
    179.	    else if(x_cnt==912)  
    180.	    color_bar   <=   24'hff00ff;  
    181.	    else if(x_cnt==1152)  
    182.	    color_bar   <=   24'hffff00;  
    183.	    else if(x_cnt==1392)  
    184.	    color_bar   <=   24'h00ffff;  
    185.	    else if(x_cnt==1632)  
    186.	    color_bar   <=   24'hffffff;  
    187.	    else if(x_cnt==1872)  
    188.	    color_bar   <=   24'h000000;  
    189.	    else  
    190.	    color_bar   <=   color_bar;  
    191.	end  
    192.	  
    193.	reg[16:0] key_counter;  
    194.	reg[3:0]    dis_mode;  
    195.	assign mode=dis_mode;  
    196.	always @(posedge pix_clk)       //按键处理程序  
    197.	begin  
    198.	    if(turn_mode==1'b0)  
    199.	    key_counter <=   14'b0;  
    200.	    else if((turn_mode==1'b1)&(key_counter<=17'h11704))  
    201.	    key_counter <=   key_counter +   1'b1;  
    202.	      
    203.	    if(key_counter==17'h11704)  
    204.	    begin  
    205.	            if(dis_mode==4'd12)  
    206.	            dis_mode    <=   4'd0;  
    207.	            else  
    208.	            dis_mode    <=   dis_mode    + 1'b1;  
    209.	    end  
    210.	end  
    211.	  
    212.	reg[7:0]    VGA_R_reg;  
    213.	reg[7:0]    VGA_G_reg;  
    214.	reg[7:0]    VGA_B_reg;  
    215.	always @(posedge pix_clk)  
    216.	begin    
    217.	    if(1'b0)   
    218.	        begin   
    219.	        VGA_R_reg<=0;   
    220.	       VGA_G_reg<=0;  
    221.	       VGA_B_reg<=0;        
    222.	        end  
    223.	   else  
    224.	     case(dis_mode)  
    225.	         4'd0:begin  
    226.	                    VGA_R_reg<=0;            //LCD显示彩色条  
    227.	                 VGA_G_reg<=0;  
    228.	                 VGA_B_reg<=0;  
    229.	            end  
    230.	            4'd1:begin  
    231.	                    VGA_R_reg<=8'b11111111;                 //LCD显示全白  
    232.	                 VGA_G_reg<=8'b11111111;  
    233.	                 VGA_B_reg<=8'b11111111;  
    234.	            end  
    235.	            4'd2:begin  
    236.	                    VGA_R_reg<=8'b11111111;                //LCD显示全红  
    237.	                 VGA_G_reg<=0;  
    238.	                 VGA_B_reg<=0;    
    239.	         end                
    240.	          4'd3:begin  
    241.	                    VGA_R_reg<=0;                          //LCD显示全绿  
    242.	                 VGA_G_reg<=8'b11111111;  
    243.	                 VGA_B_reg<=0;   
    244.	         end                        
    245.	         4'd4:begin       
    246.	                    VGA_R_reg<=0;                         //LCD显示全蓝  
    247.	                 VGA_G_reg<=0;  
    248.	                 VGA_B_reg<=8'b11111111;  
    249.	            end  
    250.	         4'd5:begin       
    251.	                    VGA_R_reg<=grid_data_1;               // LCD显示方格1  
    252.	                 VGA_G_reg<=grid_data_1;  
    253.	                 VGA_B_reg<=grid_data_1;  
    254.	         end                        
    255.	         4'd6:begin       
    256.	                    VGA_R_reg<=grid_data_2;               // LCD显示方格2  
    257.	                 VGA_G_reg<=grid_data_2;  
    258.	                 VGA_B_reg<=grid_data_2;  
    259.	            end  
    260.	           4'd7:begin       
    261.	                    VGA_R_reg<=x_cnt[7:0];                //LCD显示水平渐变色  
    262.	                 VGA_G_reg<=x_cnt[7:0];  
    263.	                 VGA_B_reg<=x_cnt[7:0];  
    264.	            end  
    265.	           4'd8:begin       
    266.	                    VGA_R_reg<=y_cnt[8:1];                 //LCD显示垂直渐变色  
    267.	                 VGA_G_reg<=y_cnt[8:1];  
    268.	                 VGA_B_reg<=y_cnt[8:1];  
    269.	            end  
    270.	           4'd9:begin       
    271.	                    VGA_R_reg<=x_cnt[7:0];                 //LCD显示红水平渐变色  
    272.	                 VGA_G_reg<=0;  
    273.	                 VGA_B_reg<=0;  
    274.	            end  
    275.	           4'd10:begin       
    276.	                    VGA_R_reg<=0;                          //LCD显示绿水平渐变色  
    277.	                 VGA_G_reg<=x_cnt[7:0];  
    278.	                 VGA_B_reg<=0;  
    279.	            end  
    280.	           4'd11:begin       
    281.	                    VGA_R_reg<=0;                          //LCD显示蓝水平渐变色  
    282.	                 VGA_G_reg<=0;  
    283.	                 VGA_B_reg<=x_cnt[7:0];            
    284.	            end  
    285.	           4'd12:begin       
    286.	                    VGA_R_reg<=color_bar[23:16];            //LCD显示彩色条  
    287.	                 VGA_G_reg<=color_bar[15:8];  
    288.	                 VGA_B_reg<=color_bar[7:0];            
    289.	            end  
    290.	           default:begin  
    291.	                    VGA_R_reg<=8'b11111111;                //LCD显示全白  
    292.	                 VGA_G_reg<=8'b11111111;  
    293.	                 VGA_B_reg<=8'b11111111;  
    294.	            end                     
    295.	         endcase  
    296.	end  
    297.	  
    298.	assign VGA_HS   =   hsync_r;  
    299.	assign VGA_VS   =   vsync_r;  
    300.	assign VGA_DE   =   hs_de   &   vs_de;  
    301.	assign VGA_R    =   (hs_de & vs_de)?VGA_R_reg:8'h0;  
    302.	assign VGA_G    =   (hs_de & vs_de)?VGA_G_reg:8'h0;  
    303.	assign VGA_B    =   (hs_de & vs_de)?VGA_B_reg:8'h0;  
    304.	endmodule  
    

    接下来就是顶层模块设计,设计参考图1 37,代码如下:

    1.	//****************************************************************************//  
    2.	//# @Author: 碎碎思  
    3.	//# @Date:   2019-11-25 21:58:59  
    4.	//# @Last Modified by:   zlk  
    5.	//# @WeChat Official Account: OpenFPGA  
    6.	//# @Last Modified time: 2019-12-11 20:26:10  
    7.	//# Description:   
    8.	//# @Modification History: 2019-10-09 22:17:36  
    9.	//# Date                By             Version             Change Description:   
    10.	//# ========================================================================= #  
    11.	//# 2019-10-09 22:17:36  
    12.	//# ========================================================================= #  
    13.	//# |                                                                       | #  
    14.	//# |                                OpenFPGA                               | #  
    15.	//****************************************************************************//  
    16.	  
    17.	`timescale 1ns / 1ps  
    18.	  
    19.	//  
    20.	module HDMI_display_Demon(  
    21.	    input       clk_100M,  
    22.	    input       KEY,  
    23.	      
    24.	    output HDMI1_CLK_P,  
    25.	    output HDMI1_CLK_N,  
    26.	    output HDMI1_D2_P,  
    27.	    output HDMI1_D2_N,  
    28.	    output HDMI1_D1_P,  
    29.	    output HDMI1_D1_N,  
    30.	    output HDMI1_D0_P,  
    31.	    output HDMI1_D0_N,  
    32.	      
    33.	    output HDMI2_CLK_P,  
    34.	    output HDMI2_CLK_N,  
    35.	    output HDMI2_D2_P,  
    36.	    output HDMI2_D2_N,  
    37.	    output HDMI2_D1_P,  
    38.	    output HDMI2_D1_N,  
    39.	    output HDMI2_D0_P,  
    40.	    output HDMI2_D0_N,  
    41.	      
    42.	    output  [3:0]   LED  
    43.	);  
    44.	  
    45.	wire pixclk;  
    46.	wire[7:0]   R,G,B;  
    47.	wire HS,VS,DE;  
    48.	assign VGA_HS   =   HS;  
    49.	assign VGA_VS   =   VS;  
    50.	assign  VGA_D   =   {R[7:4],G[7:2],B[7:4]};  
    51.	hdmi_data_gen u0_hdmi_data_gen  
    52.	(  
    53.	    .pix_clk            (pixclk),  
    54.	    .turn_mode          (KEY),  
    55.	    .VGA_R              (R),  
    56.	    .VGA_G              (G),  
    57.	    .VGA_B              (B),  
    58.	    .VGA_HS             (HS),  
    59.	    .VGA_VS             (VS),  
    60.	    .VGA_DE             (DE),  
    61.	    .mode                (LED)  
    62.	);  
    63.	  
    64.	wire pixclk_X5;  
    65.	//wire i2c_clk;  
    66.	wire lock;  
    67.	wire[23:0]  RGB;  
    68.	assign RGB={R,G,B};  
    69.	hdmi_display_0  u1_hdmi_display_0  
    70.	(  
    71.	   // .i2c_clk            (i2c_clk),  
    72.	    .PXLCLK_I            (pixclk),  
    73.	    .PXLCLK_5X_I         (pixclk_X5),  
    74.	    .LOCKED_I           (lock),  
    75.	    .RST_N              (lock),  
    76.	    .VGA_RGB             (RGB),  
    77.	    .VGA_HS           (HS),  
    78.	    .VGA_VS           (VS),  
    79.	    .VGA_DE              (DE),  
    80.	    .HDMI_CLK_P           (HDMI1_CLK_P),  
    81.	    .HDMI_CLK_N         (HDMI1_CLK_N),  
    82.	    .HDMI_D2_P         (HDMI1_D2_P),  
    83.	    .HDMI_D2_N         (HDMI1_D2_N),  
    84.	    .HDMI_D1_P         (HDMI1_D1_P),  
    85.	    .HDMI_D1_N         (HDMI1_D1_N),  
    86.	    .HDMI_D0_P         (HDMI1_D0_P),  
    87.	    .HDMI_D0_N         (HDMI1_D0_N)  
    88.	);  
    89.	  
    90.	hdmi_display_0  u2_hdmi_display_1  
    91.	(  
    92.	   // .i2c_clk            (i2c_clk),  
    93.	    .PXLCLK_I            (pixclk),  
    94.	    .PXLCLK_5X_I         (pixclk_X5),  
    95.	    .LOCKED_I           (lock),  
    96.	    .RST_N              (lock),  
    97.	    .VGA_RGB             (RGB),  
    98.	    .VGA_HS           (HS),  
    99.	    .VGA_VS           (VS),  
    100.	    .VGA_DE              (DE),  
    101.	    .HDMI_CLK_P        (HDMI2_CLK_P),  
    102.	    .HDMI_CLK_N        (HDMI2_CLK_N),  
    103.	    .HDMI_D2_P         (HDMI2_D2_P),  
    104.	    .HDMI_D2_N         (HDMI2_D2_N),  
    105.	    .HDMI_D1_P         (HDMI2_D1_P),  
    106.	    .HDMI_D1_N         (HDMI2_D1_N),  
    107.	    .HDMI_D0_P         (HDMI2_D0_P),  
    108.	    .HDMI_D0_N         (HDMI2_D0_N)  
    109.	);  
    110.	  
    111.	clk_wiz_0   u3_clk  
    112.	(  
    113.	    .clk_in1            (clk_100M),  
    114.	    .resetn             (1'b1),  
    115.	    .clk_out1           (pixclk),  
    116.	    .clk_out2           (pixclk_X5),  
    117.	   // .clk_out3           (i2c_clk),  
    118.	    .locked             (lock)  
    119.	);  
    120.	endmodule  
    
    

      下载过程下载完成后按中间的按键显示器会切换一次显示的图像,这些都是我们在程序部分定义的图像。
    在这里插入图片描述
                  图1 40 实验结果

    展开全文
  • 基于FPGA的HDMI显示(一)

    千次阅读 2019-12-15 21:50:39
    1.1 HDMI简介 简介略,网上很多,这里也不过多描述。 1.2 基于FPGA的HDMI接口设计   HDMI输出接口在FPGA方面应用时,主要有两种方式:一种就是如图1 22所示的方式,采用Silion Image 公司的 SIL9134 HDMI( DVI)...

    1.1 HDMI简介

    简介略,网上很多,这里也不过多描述。

    1.2 基于FPGA的HDMI接口设计

      HDMI输出接口在FPGA方面应用时,主要有两种方式:一种就是如图1 22所示的方式,采用Silion Image 公司的 SIL9134 HDMI( DVI)编码芯片,最高支持 1080P@60Hz 输出,支持 3D 输出。
      另一种方式是HDMI 接口设计全由 IO 模拟方式实现,如图1 23所示,HDMI 的信号线 D0~D2 其实是一个差分信号,在我们程序当中体现为 TMDS 类型,因此其输入信号为串行的数字信号,内部实际上是将输入的 RGB 信号进行编码,转换为 HDMI 数据(实际我们称其为 DVI)进行输出,因此在设计中通常可以将 RGB 信号单独引出,作为 RGB 输出,用来作为双显输出使用。
    在这里插入图片描述
    在这里插入图片描述

          图1 22 基于HDMI( DVI)编码芯片的HDMI输出
    在这里插入图片描述
                图1 23 直接HDMI编码输出

    1.3 HDMI时序分析

      HDMI传输由三组TMDS通道和一组TMDS clock通道组成,TMDS clock的运行频率是video信号的pixel频率,在每个cycle,每个TMDS data通道发送10bit数据。
    在这里插入图片描述
                图1 24 HDMI传输的示意图
      上图是HDMI传输的示意图,从图中可知,HDMI传输如下四种类型数据:
    (1)Preamble控制信息,图中的CTLx,可用来表示后面传输的是data island还是video data。通过channel1和2的D[1:0]传输,占用4bit。
    (2)Data Island,即数据包,如Audio数据包。通过3个channel的D[3:0]传输,占用12bit。
    (3)Video Data,视频数据。示意图中传输的是RGB格式图像,R,G,B分别通过channel2,1,0传输,每个颜色8bit,共24bit。
    (4)HSYNC, VSYNC。使用channel0的D[1:0]传输,占用2bit。
      8bit的数据在source经过TMDS encoder后得到10bit数据,经过serializer后串行输出;在sink端先进行复原成10bit的数据,再通过TMDS decoder得到8bit的源数据。
      此外,HDMI视频是stream式的传输,不涉及packet式的传输。
    在这里插入图片描述
          图1 25 传输720x480p video的hdmi timing图
      上图是传输720x480p video的hdmi timing图。
      在video data period,有效的video数据进行传输;
      在data island period,audio和auxiliary数据以包的形式进行传输;
      在control period,CTLx和HSYNC, SYNC进行传输。
      data island period和control period都是在消隐区进行。图中行消隐占用138像素,场消隐占45行。
    在这里插入图片描述
      图1 26 对时序图中描述的三种period分别传输的数据和编码类型进行说明
      上图中是对时序图中描述的三种period分别传输的数据和编码类型进行说明。video数据从8bit/channel encode后变为10bit/channel, data island的packet数据从4bit/channel encode后为10bit/channel, control数据从2bit/channel encode为10bit/channel。
      Control Period
    在这里插入图片描述
                图1 27 Control Period
      只有两种类型的preamble信息组合,CTL0:3=1000代表接下来的是video data period,CTL0:3=1010代表接下来的是data island period。HSYNC, VSYNC此时也有可能发生变化。
      Video Data Period
      video data period以2个字符(pixel)长度的leading gurad band开始,guard band如下:
    ch0: q_out[9:0] = 0b1011001100
    ch1: q_out[9:0] = 0b0100110011
    ch2: q_out[9:0] = 0b1011001100
      Data Island Period
      data island period传输audio数据和辅助数据,辅助数据包括Infoframe和其他用于音视频信息描述的数据。data island period以2个字符长度的leading guard band开始,并以2个字符宽度的trailing guard band 结束。guard band如下:
    ch0: q_out[9:0] = n.a
    ch1: q_out[9:0] = 0b0100110011
    ch2: q_out[9:0] = 0b0100110011
      data island传输的packet类型和格式详见spec说明。
      三个传输阶段的过渡过程如下图所示:
    在这里插入图片描述
            图1 28 三个传输阶段的过渡过程
      (1) 左一是control period, 分别占用三个channel的D[1:0],channel 0传输HSYNC, VSYNC, channel1,2 传输Preamble
      (2) 左二是data island period,分别占用了三个channel的D[3:0],channel 0的D[1:0]传输HSYNC, VSYNC, channel0的D[3:2]传输packet header, channel 1,2的D[3:0]传输packet。并且两端以guard band隔离
      (3)右二接下来又是control period
      (4)右一是 video data island, 占用了全部三个通道,并且开始以guard band 隔离
      Video
      支持三种pixel encoding:RGB4:4:4, YCbCr4:4:4, YCbCr4:2:2
      video format除了CEA-861-D中格式外,还会支持一些较特殊的格式
      color depth可支持一个像素24, 30, 36和48bits
      下面分别是24bit/pixel的RGB444, YCbCr422, YCbCr444的pixel encoding示意图。RGB444每个颜色占8bit, YCbCr422中Y占12bit,C占12bit,YCbCr444中Y,Cb,Cr都占用8bit。
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
        图1 29 RGB444, YCbCr422, YCbCr444的pixel encoding示意图
      Deep Color模式
      Pixel Packing
    24 bit mode: 1 pixel/group, 1 fragment/group
    30 bit mode: 4 pixel/group, 5 fragment/group
    36 bit mode: 2 pixel/group, 3 fragment/group
    48 bit mode: 1 pixel/group, 2 fragment/group
    1fragment/TMDS clock, 如30bit下的4pixel,需要5次传输完成,每次1个fragment。

      Audio
      Audio数据以Audio Sample Packet或High Bitrate Audio Stream Packet的形式传输,但是HDMI没有传输audio clock,因此sink设备需要进行audio clock regeneration。原理如下:
    在这里插入图片描述
            图1 30 audio clock regeneration原理
      128∗fs=N×fTMDS/CTS
      N和CTS会在Audio Clock Regeneration Packet中进行传输,TMDS clock可通过硬件获取,因此sink端可算出source传输的audio clock。
      Control
      InfoFrame
      Infoframe以Infoframe packet的形式传输,它的大小不超过30字节加上一个checksum字节。具体infoframe的格式及内容需要查看spec。
      AVI(Auxiliary Video Information) Infoframe
      Audio Infoframe
      HDMI Vendor Specific Infoframe, 传输4kx2k或3D格式时需要发送此packet
      EDID & DDC
      sink设备在ROM中存放EDID信息,source在收到HPD后会通过DDC通道读取EDID得到显示设备的属性。EDID包含两部分,前128字节符合EDID1.3数据结构,128字节的扩展EDID,符合CEA extension verison3。CEA extension verison3如下图所示。
    在这里插入图片描述
              图1 31 CEA extension verison3
      HDMI VSDB
      HDMI sink设备在第一个扩展EDID中包含HDMI VSDB,source在读取EDID后会根据是否有此block来判断设备是HDMI还是DVI。
      Hotplug
      source会监测HPD pin的状态,当source和sink连接后,如果HPD为高电平,说明sink设备正常可以工作,source可通过DDC读取EDID,如果为低电平,说明sink已断开。
      sink可通过拉低HPD超过100ms来向source表明EDID发生了变化,此时source会重新读取EDID。

    1.4 基于FPGA的720P HDMI显示

      未完待续

    展开全文
  • Amlogic_Android7.1 HDMI显示流程源码分析

    千次阅读 2019-12-21 16:50:36
    平台:amlogic Android version :Android7.1 Linux version 3.14.29 我这里主要是跟了一下amlogic android7.1的uboot和kernel的hdmi显示部分的流程代码,主要是为了解决一个开机概率性花屏的问题。 分析原因: 跟...

    平台:amlogic
    Android version :Android7.1
    Linux version 3.14.29
    我这里主要是跟了一下amlogic android7.1的uboot和kernel的hdmi显示部分的流程代码,主要是为了解决一个开机概率性花屏的问题。

    分析原因:

    跟uboot的环境变量设置有关:
    系统上层起来之后会在vendor那里设置环境变量colorattribute的属性值,这里会设置为
    
    ./vendor/amlogic/frameworks/services/systemcontrol/FormatColorDepth.h:31:#define UBOOTENV_COLORATTRIBUTE "ubootenv.var.colorattribute"
    ./vendor/amlogic/frameworks/services/systemcontrol/DisplayMode.cpp
    			strcpy(colorAttribute, "444,12bit");
             //save to ubootenv
             saveDeepColorAttr(outputmode, colorAttribute);
             setBootEnv(UBOOTENV_COLORATTRIBUTE, colorAttribute); //设置环境变量 colorattribute 值为444,12bit
    
    以下是log打印:
    ----------------------------------------------
    130|gtt92e:/ $ logcat | grep "setMboxOutputMode colorAttribute" -EC5           
    01-01 00:00:17.929  4107  4107 I SystemControl: display sink type:1 [0:none, 1:sink, 2:repeater], old outputmode:1080p60hz, new outputmode:1080p60hz
    01-01 00:00:17.929  4107  4107 I SystemControl: hdcp_tx 2.2 & 1.4 stop hdcp pwr
    01-01 00:00:17.973  4107  4107 I SystemControl: support current mode:[1080p60hz], deep color:[444,12bit]
    01-01 00:00:17.973  4107  4107 I SystemControl: get hdmi color attribute : [444,12bit], outputmode is: [1080p60hz] , and support color list is: [444,12bit444,10bit444,8bit422,12bit422,10bit422,8bitrgb,12bitrgb,10bitrgb,8bit]
    01-01 00:00:17.973  4107  4107 I SystemControl: set DeepcolorAttr value is different from attr sysfs value
    01-01 00:00:17.974  4107  4107 I SystemControl: setMboxOutputMode colorAttribute = 444,12bit
    01-01 00:00:17.975  4107  4107 I SystemControl: [ubootenv] update_bootenv_varible name [ubootenv.var.1080p60hz_deepcolor]: value [444,12bit] 
    01-01 00:00:17.975  4107  4107 I SystemControl: [ubootenv] update_bootenv_varible name [ubootenv.var.colorattribute]: value [444,12bit] 
    01-01 00:00:18.002  4126  4126 I         : sMaxFastTracks = 8
    01-01 00:00:18.027  4126  4126 I audioserver: ServiceManager: 0xec219420
    01-01 00:00:18.027  4126  4126 W BatteryNotifier: batterystats service unavailable!
    ----------------------------------------------
    
    get看一下环境变量的属性:
    gtt92e:/ $ getprop | grep  colorattribute                                      
    [ubootenv.var.colorattribute]: [444,12bit]
    
    
    导致在下次开机uboot的时候会get到这个环境变量值:
    ./uboot/common/cmd_hdmitx.c
                     if (getenv("colorattribute")){
                            hdmi_parse_attr(hdmitx_device.para, getenv("colorattribute")); //打印出来为444,12bit
                     }
    
    				然后在 hdmi_parse_attr函数[文件:common/hdmi_parameters.c] 会默认把hdmi tx的output_color_format设置为1,即
    				(在hdmi_parse_attr会设置色深(color depth:8bit,10bit,12bit等),彩色空间(color space:rgb,444,422)等参数)
    				void hdmi_parse_attr(struct hdmi_format_para *para, char const *name)
    				{
    					...
    				/* parse color space */
    				for (i = 0; i < sizeof(parse_cs_) / sizeof(struct parse_cs); i++) {
    					if (strstr(name, parse_cs_[i].name)) {
    						para->cs = parse_cs_[i].cs;
                            break;
    					}
    				}
    
    				/* set default value */
    				if (i == sizeof(parse_cs_) / sizeof(struct parse_cs)){
    					para->cs = HDMI_COLOR_FORMAT_444;
    					}
    					...
    				}
    				导致出现花屏问题。究其原因是有些屏不支持444,12bit的颜色格式显示所致。
    

    解决方案:目前的解决办法是:
    1、在uboot不去get这个环境变量getenv(“colorattribute”),即把这部分代码注释掉或者if 0让它不执行。
    2、强制不让它设置这个hdmi tx的颜色格式参数。

    解决方案1:
    czd@ubt144c:/work/czd/amlogic_7.1/uboot$ git diff
    diff --git a/common/cmd_hdmitx.c b/common/cmd_hdmitx.c
    index 7166b8f..3899f82 100644
    --- a/common/cmd_hdmitx.c
    +++ b/common/cmd_hdmitx.c
    @@ -207,8 +207,13 @@ static int do_output(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
                            printf("set hdmitx VIC = %d\n", hdmitx_device.vic);
                    if (strstr(argv[1], "hz420") != NULL)
                            hdmitx_device.para->cs = HDMI_COLOR_FORMAT_420;
    +/* rm by czd for UEI hdmi tx */
    +#if 0
                    if (getenv("colorattribute"))
                            hdmi_parse_attr(hdmitx_device.para, getenv("colorattribute"));
    +#endif
    +/* rm end */
    +
                    /* For RGB444 or YCbCr444 under 6Gbps mode, no deepcolor */
                    /* Only 4k50/60 has 420 modes */
    
    
    解决方案2:在hdmi_parse_attr接口函数把para->cs的参数写死为2,即设置为 HDMI_COLOR_FORMAT_422,(HDMI_COLOR_FORMAT_422在./include/amlogic/hdmi.h宏定义);
    		  或者在config_hdmi20_tx处直接把hdev->para->cs参数设置为2,即修改如下:
    	     // --------------------------------------------------------
             // Set up HDMI
             // --------------------------------------------------------
             config_hdmi20_tx(hdev->vic, para,             // pixel_repeat,
                     hdev->para->cd,                       // Pixel bit width: 4=24-bit; 5=30-bit; 6=36-bit; 7=48-bit.
                     TX_INPUT_COLOR_FORMAT,                // input_color_format: 0=RGB444; 1=YCbCr422; 2=YCbCr444; 3=YCbCr420.
                     TX_INPUT_COLOR_RANGE,                 // input_color_range: 0=limited; 1=full.
                     hdev->para->cs = 2,                   // output_color_format: 0=RGB444; 1=YCbCr422; 2=YCbCr444; 3=YCbCr420.
                     TX_OUTPUT_COLOR_RANGE                 // output_color_range: 0=limited; 1=full.
                     );		
    
    amlogic android7.1 HDMI显示的设置流程分析:
    
    uboot目录:
    涉及文件目录:
    
    amlogic【目录】
    ./board/amlogic/txlx_gtt92e_v1/txlx_gtt92e_v1.c【board的一些初始化,上电之类的】
    ./board/amlogic/configs/txlx_gtt92e_v1.h【配置环境变量和相关的宏控】
    
    common【目录】
    ./common/cmd_osd.c
    ./common/cmd_hdmitx.c
    ./common/hdmi_parameters.c
    
    display【目录】
    ./drivers/display/osd/osd_fb.c
    ./drivers/display/vout/vout.c
    
    hdmitx20【目录】
    ./arch/arm/cpu/armv8/txlx/hdmitx20/hdmitx_set.c
    ./arch/arm/cpu/armv8/txlx/hdmitx20/hdmitx_tvenc.c
    
    
    
    
    
    配置宏CONFIG_AML_HDMITX20,打开hdmitx的相关功能,编译对应的.c文件【如果后续需要添加别的宏控可以添加到这个文件】。
    在文件:board/amlogic/configs/txlx_gtt92e_v1.h中添加如下代码:
    
    /* DISPLAY & HDMITX */
    #define CONFIG_AML_HDMITX20 1
    
    outputmode的环境变量参数设置,例如配置为:outputmode=1080p60hz, 如果没有设置则会load默认的env。
    文件:board/amlogic/configs/txlx_gtt92e_v1.h
    
    			||
    			||
    			\/
    -------------------------------
    "outputmode=1080p60hz\0" \
    "setenv bootargs ${initargs} logo=${display_layer},loaded,${fb_addr} vout=${outputmode},enable panel_type=${panel_type} osd_reverse=${osd_reverse} video_reverse=${video_reverse} 
    androidboot.selinux=${EnableSelinux} androidboot.firstboot=${firstboot} jtag=${jtag}; "\
    -------------------------------
    
    1、文件:board/amlogic/txlx_gtt92e_v1/txlx_gtt92e_v1.c
    	->hdmi_tx_init();
    
    
    2、文件./common/cmd_osd.c
    	->U_BOOT_CMD_MKENT(open, 2, 0, do_osd_open, "", "")
    		->do_osd_open
    			->video_hw_init();
    					||
    					\/
    
    3、文件./drivers/display/osd/osd_fb.c
    	
    	->video_hw_init; //硬件初始化
    		->vout_init();
    		||
    		\/
    		-----------------------------------------
    		4、文件.drivers/display/vout/vout.c
    		->vout_init();
    			->vout_vmode_init(); //显示分辨率初始化
    				->outputmode = getenv("outputmode"); //获取outputmode的环境变量参数,例如UEI的配置为:outputmode is 1080p60hz,board/amlogic/configs/txlx_gtt92e_v1.h中设置
    				->vmode = vout_find_mode_by_name(outputmode); //获取outputmode的环境变量配置的分辨率mode值
    					-> mode = vout_sets[i].mode;
    				->vout_set_current_vmode(vmode); //设置当前分辨率mode
    				->width = vout_find_width_by_name(outputmode); //获取分辨率mode的宽度值
    				->height = vout_find_height_by_name(outputmode); //获取分辨率mode的高度值
    				->field_height = vout_find_field_height_by_name(outputmode); //获取分辨率mode的场高度
    			->vout_reg_write(VPP_POSTBLEND_H_SIZE, width); //寄存器写入值设置对应宽度值参数
    			->vout_axis_init(width, height); //初始化宽度和高度值
                ->vout_vinfo_init(width, height, field_height); //
    
    		-----------------------------------------	
    		||
    		\/
    5、文件./drivers/display/osd/osd_fb.c
    		->fb_addr = get_fb_addr();
    			->parent_offset = fdt_path_offset(dt_addr, "/meson-fb");
    			->fb_addr = simple_strtoul(propdata, NULL, 16);
    		
    	6、文件:./common/cmd_hdmitx.c
    		->do_hdmitx
    			->find_cmd_tbl(argv[0], &cmd_hdmi_sub[0], ARRAY_SIZE(cmd_hdmi_sub));
    				->cmd_hdmi_sub
    					->do_output(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]); //设置输出
    						->hdmitx_device.vic = hdmi_get_fmt_vic(argv[1]); //###这里获取vic的值###,VIC值定义在./uboot/include/amlogic/hdmi.h中。
    							->hdmi_parse_attr(para, name); //根据name的索引,在all_fmt_paras中查找对应的颜色深度和彩色空间,如果无该属性值,则按照默认设置处理
    								->if (strstr(name, parse_cs_[i].name)) {
    									para->cs = parse_cs_[i].cs;//从"hdmitx output FORMAT"解析字符串,包括颜色深度和彩色空间
    		
    						->hdmitx_device.para = hdmi_get_fmt_paras(hdmitx_device.vic);====  ||获取设备的hdmi显示参数值,在./common/hdmi_parameters.c中
                         	->if (getenv("colorattribute"))	//如果有环境变量值设置,获取环境变量值colorattribute,该属性值在开机起来之后会在上层有设置
    							hdmi_parse_attr(hdmitx_device.para, getenv("colorattribute")); ||  //代码在endor/amlogic/frameworks/services/systemcontrol/DisplayMode.cpp
    							
    					->do_edid(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[]);   ||  //###读取EDID数据,这里实际没有调用到###
    						  |/* current only support read 1 byte edid data */
    						->|hdmitx_device.HWOp.read_edid() [文件:arch/arm/cpu/armv8/txlx/hdmitx20/hdmitx_set.c]	
    							->hdmitx_read_edid;
    								->read_edid_8bytes(buf, addr);
    						  ||
    						  \/
    					->hdmi_tx_set(&hdmitx_device);		
    					---------------------------------------------------------------------------------||------------------
    					-> 7、文件:arch/arm/cpu/armv8/txlx/hdmitx20/hdmitx_set.c						 ||
    					->hdmi_tx_set(struct hdmitx_dev *hdev);											 ||
    						->hdmitx_hw_init(); //hdmi tx初始化											 ||
    						->hdmitx_debug();															 ||	
    						->ddc_init();																 ||
    							->ddc_pinmux_init();													 ||
    						->hdmitx_set_hw(hdev); //hdmi tx设置硬件参数                                 ||
    						->hdmitx_debug();   														 ||
    							->para = hdmi_get_fmt_paras(hdev->vic); //根据vic值获取hdmi格式参数      ||	
    									||																 ||
    									\/																 ||
    					---------------------------------------------------------------------------------\/-------------------
    					8、文件:./common/hdmi_parameters.c
    					->hdmi_get_fmt_paras
    						->for (i = 0; all_fmt_paras[i] != NULL; i++) { //####这里根据vic值与all_fmt_paras[i]->vic比对,去遍历查找all_fmt_paras结构体中对应的hdmi显示相关参数值####
    								if (vic == all_fmt_paras[i]->vic)
    									return all_fmt_paras[i];
    										->static struct hdmi_format_para *all_fmt_paras[] = {
    											...
    											&fmt_para_1920x1080p60_16x9, //例如 fmt_para_1920x1080p60_16x9:相关的clk设置,前后阶参数就在结构体fmt_para_1920x1080p60_16x9中
    											...
    											}
    											||
    											||
    											||
    					   --------------------\||/----------
    					   ---------------------\/---------
       5 static struct hdmi_format_para fmt_para_1920x1080p60_16x9 = {
       6         .vic = HDMI_1920x1080p60_16x9,
       7         .name = "1920x1080p60hz",
       8         .sname = "1080p60hz",
       9         .pixel_repetition_factor = 0,
      10         .progress_mode = 1,
      11         .scrambler_en = 0,
      12         .tmds_clk_div40 = 0,
      13         .tmds_clk = 148500,
      14         .timing = {
      15                 .pixel_freq = 148500,
      16                 .h_freq = 67500,
      17                 .v_freq = 60000,
      18                 .vsync_polarity = 1,
      19                 .hsync_polarity = 1,
      20                 .h_active = 1920,
      21                 .h_total = 2200,
      22                 .h_blank = 280,
      23                 .h_front = 88,
      24                 .h_sync = 44,
      25                 .h_back = 148,
      26                 .v_active = 1080,
      27                 .v_total = 1125,
      28                 .v_blank = 45,
      29                 .v_front = 4,
      30                 .v_sync = 5,
      31                 .v_back = 36,
      32                 .v_sync_ln = 1,
      33         },
      34 };
    					||
    					\/
    					-----------------------------------------------------------------------
    					***********************************************************************
    											
    				->hdmitx_set_pll(hdev); //设置hdmi tx pll分频
    					->set_hdmitx_clk(hdev->vic); //设置tx clk
    				->hdmitx_set_phy(hdev); //设置hdmi tx phy,phy为端口物理层
    					->set_phy_by_mode; //根据分辨率设置phy的数据传输速率
    				->hdmitx_enc(hdev->vic);  //为HDMI设置编码器
    				\/  ->set_vmode_enc_hw(vic);
    				||	->hdmi_tvenc_set(vic); //#############根据vic值选择不同的编码参数设置##############
    				||==\\	->hdmi_tvenc_set;
    					 ||		->default:
    					 ||			hdmi_tvenc_set_def(vic); //如果没有匹配的vic值,则设置默认编码参数
    					 ||				||
    					 ||				\/
    					*||*********************************************************************
    					------------------------------------------------------------------------
    					 ||
    					 \/
    					--------------------------------------------------------
    					 9、文件:arch/arm/cpu/armv8/txlx/hdmitx20/hdmitx_tvenc.c
    					 ->set_vmode_enc_hw(enum hdmi_vic vic);
    						->tvregs_setting_mode(vic); //以vic作为索引返回tvregsTab的对应reg_setting,reg_setting就是对应的hdmi参数设置结构体:第一个参数是寄存器,第二个参数是要设置值
    							->for (i = 0; i < ARRAY_SIZE(tvregsTab); i++) {
    								if (vic == tvregsTab[i].vic)
    									return tvregsTab[i].reg_setting;
    						->setreg(s++); \\###############{ 根据vic得到的参数结构体设置寄存器的值 }#############
    							->hd_write_reg(r->reg, r->val); //根据reg_setting设置对应寄存器的值
    					--------------------------------------------------------
    				->hdmitx_set_vdac(0);
    				->config_hdmi20_tx //设置HDMI up
    						||
    						\/
    					**************************************	
    					
    2274         // --------------------------------------------------------
    2275         // Set up HDMI
    2276         // --------------------------------------------------------
    2277         config_hdmi20_tx(hdev->vic, para,                 // pixel_repeat,
    2278                 hdev->para->cd,                          // Pixel bit width: 4=24-bit; 5=30-bit; 6=36-bit; 7=48-bit.
    2279                 TX_INPUT_COLOR_FORMAT,                  // input_color_format: 0=RGB444; 1=YCbCr422; 2=YCbCr444; 3=YCbCr420.
    2280                 TX_INPUT_COLOR_RANGE,                  // input_color_range: 0=limited; 1=full.
    2281                 hdev->para->cs,                       // output_color_format: 0=RGB444; 1=YCbCr422; 2=YCbCr444; 3=YCbCr420.
    2282                 TX_OUTPUT_COLOR_RANGE                // output_color_range: 0=limited; 1=full.
    2283                 );
    					
    					
    					**************************************
    					->hdmitx_hw_init(); //启动时钟并解除复位,还有一些硬件的初始化工作
    						->hd_set_reg_bits //通过设置寄存器实现
    				
    				->save_hdmitx_format(hdev->vic, (hdev->para->cs == HDMI_COLOR_FORMAT_420));
    					->save_hdmitx_format(enum hdmi_vic vic, int y420)//
    						->hd_write_reg(P_ISA_DEBUG_REG0, data32);// ############## 写入hdmi tx format参数 #################
    				
    			->hdmitx_debug();
    
    		10、文件:./uboot/arch/arm/cpu/armv8/txlx/hdmitx20/hdmitx_set.c
    				->scdc_prepare(unsigned int div 
    					->scdc_rd_sink(SINK_VER, &rx_ver); //这里判断是接的是1.4还是2.0版本的hdmi接口,(rx_ver == 1) ? "2.0" : "1.4 or below",通过读取寄存器值判断是接入什么接口hdmi
    						->scdc_wr_sink(unsigned char adr, unsigned char val);
    							->{
    							  hdmitx_wr_reg(HDMITX_DWC_I2CM_SLAVE, 0x54);
    							  hdmitx_wr_reg(HDMITX_DWC_I2CM_ADDRESS, adr);
    							  hdmitx_wr_reg(HDMITX_DWC_I2CM_DATAO, val);
    							  hdmitx_wr_reg(HDMITX_DWC_I2CM_OPERATION, 0x10);
    							  }
    
    
    
    
    
    common目录即(kernel部分):
    驱动目录:
    drivers/amlogic/hdmi/hdmi_tx_20/
    
    文件:drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_main.c
    
    		->amhdmitx_probe //从跑probe开始分析
    			->INIT_DELAYED_WORK(&hdmi_delay_event_work, hdmi_delay_event_post); //初始化延时工作队列,
    			->hdmitx_init_parameters(&hdmitx_device.hdmi_info); //hdmitx协议级接口; 在文件:./drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_video.c
    				->
    			
    			->HDMITX_Meson_Init(&hdmitx_device); //HDMI TX初始化
    				->hdmi_hwp_init(hdev);
    					->hdmitx_uboot_already_display() // 文件:./drivers/amlogic/hdmi/hdmi_tx_20/hw/hdmi_tx_hw.c
    						->get_hdmitx_format(); //获取记录HDMI TX当前hdmitx format参数,与uboot匹配(通过下面的读取寄存器值的方式)
    							->return hd_read_reg(P_ISA_DEBUG_REG0); //读取寄存器 P_ISA_DEBUG_REG0 的值,这个寄存器值在uboot中设置
    							  /* ISA_DEBUG_REG0 0x2600				//VIC值在./include/linux/amlogic/hdmi_tx/hdmi_common.h有枚举定义
    							   * bit[11]: Y420
    							   * bit[10:8]: HDMI VIC  //这里 #######获取VIC值#########,
    							   * bit[7:0]: CEA VIC
    							   */							   
    			->hdmitx_init_fmt_attr(&hdmitx_device, fmt_attr);// ############ 设置当前color format ###########
    				->memcpy(fmt_attr, "422,", 4); //例如
    				->strcat(fmt_attr, "10bit"); //例如
    
    				
    			->hdmitx_device.task = kthread_run(hdmi_task_handle, &hdmitx_device, "kthread_hdmi"); //kthread_run创建和运行内核线程,入口函数是 hdmi_task_handle
    				->hdmi_task_handle
    					->switch_set_state(&hdmi_power, hdmitx_device->hpd_state);//设置hdmi拔插状态
    					->INIT_WORK(&hdmitx_device->work_hdr, hdr_work_func); //初始化hdmi状态检测工作队列hdr_work_func
    						->hdr_work_func
    							->hdmitx_sdr_hdr_uevent(hdev); //hdmi拔插检测的uevent事件
    								->switch_set_state(&hdmi_hdr, 1); //插入hdmi?
    								->switch_set_state(&hdmi_hdr, 0); //拔出hdmi?
    					 
    				->hdmitx_edid_ram_buffer_clear(hdmitx_device); //初始化hdmi时,清除hdmitx模块edid ram和edid缓冲区
    				->INIT_DELAYED_WORK(&hdmitx_device->work_hpd_plugin, hdmitx_hpd_plugin_handler); //初始化延时工作队列hdmitx_hpd_plugin_handler,检测hdmi插入
    				->INIT_DELAYED_WORK(&hdmitx_device->work_hpd_plugout, hdmitx_hpd_plugout_handler); //初始化延时工作队列hdmitx_hpd_plugout_handler,检测hdmi拔出
    					->void hdmitx_hpd_plugin_handler(struct work_struct *work); //延时工作队列函数
    						->if (hdev->repeater_tx) //判断hdmi是否插入,设置hpd状态
    							rx_repeat_hpd_state(1); //设置hpd状态为插入hdmi
    						->hdmitx_get_edid(hdev); //获取EDID信息: 这里通过i2c通讯的方式读取edid,读取128个字节,这里读取两次,
    							||	->gpio_read_edid(hdev->EDID_buf);
    									->edid_rx_data(regaddr & 0xff, rx_data, 128); //读取128个字节的edid
    										->err = i2c_transfer(i2c_edid_client->adapter, msgs, ARRAY_SIZE(msgs));
    							||调用
    							\/
    							------------------------------------------------------------
    							文件./drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_edid.c
    							->hdmitx_edid_clear(hdev); //清除HDMI Sink的EDID的解析结果,原函数在文件./drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_edid.c中
    							->hdmitx_edid_parse(hdev); //解析读到的edid的内容--【128个字节】,
    								->ret_val = Edid_DecodeHeader(&hdmitx_device->hdmi_info, &EDID_buf[0]); //判断edid的引导码是否正确,一般是:00ffffffffffff00开头的引导码
    								->如果识别到的edid块数量为0,则  #################识别读取不到显示器edid####################
    									->if (BlockCount == 0) {
    										->hdmitx_edid_set_default_vic(hdmitx_device); //设置默认的vic值
    										->
    									}
    								->hdmitx_edid_block_parse(hdmitx_device, &(EDID_buf[i*128])); //
    									->Edid_DTD_parsing(struct rx_cap *pRXCap, unsigned char *data); //EDID DTD 详细时序解析
    										->para = hdmi_match_dtd_paras(t); //调用 hdmi_match_dtd_paras()检查t时序参数是否与VIC对应时序参数匹配
    											||
    											\/
    											文件:./drivers/amlogic/hdmi/hdmi_common/hdmi_parameters.c
    											->*hdmi_match_dtd_paras(struct dtd *t) //这里hdmi_match_dtd_paras函数的t参数会和all_fmt_paras对应的参数比对,如果一致就返回对应参数对应结构体
    												->return all_fmt_paras[i];																		\/
    													->struct hdmi_format_para *all_fmt_paras[] = { //hdmi的显示参数结构体,分辨率、clk和前后阶参数等都在这里
    														...
    														&fmt_para_3840x2160p60_16x9,
    														...
    														}
    											                     ||
    																 \/
    																	static struct hdmi_format_para fmt_para_3840x2160p60_16x9 = {
    																				.vic = HDMI_3840x2160p60_16x9,
    																				.name = "3840x2160p60hz",
    																				.sname = "2160p60hz",
    																				.pixel_repetition_factor = 0,
    																				.progress_mode = 1,
    																				.scrambler_en = 1,
    																				.tmds_clk_div40 = 1,
    																				.tmds_clk = 594000,
    																				.timing = {
    																						.pixel_freq = 594000,
    																						.frac_freq = 593407,
    																						.h_freq = 135000,
    																						.v_freq = 60000,
    																						.vsync_polarity = 1,
    																						.hsync_polarity = 1,
    																						.h_active = 3840,
    																						.h_total = 4400,
    																						.h_blank = 560,
    																						.h_front = 176,
    																						.h_sync = 88,
    																						.h_back = 296,
    																						.v_active = 2160,
    																						.v_total = 2250,
    																						.v_blank = 90,
    																						.v_front = 8,
    																						.v_sync = 10,
    																						.v_back = 72,
    																						.v_sync_ln = 1,
    																						},
    																	};
    																
    									   ->dump_dtd_info(t); //dump出hdmi的显示参数
    							------------------------------------------------------------
    						->set_disp_mode_auto(); //###########设置显示分辨率##############
    							->hdmi_get_current_vinfo
    								->info = get_current_vinfo();
    									->vinfo_s *get_current_vinfo(void)
    										->return &vinfo_1080p60hz; //这里分辨率设置为1080p60hz
    											-> ||
    											   \/
    											   -----------------------------
    											    104 const struct vinfo_s vinfo_1080p60hz = {
    												105         .name = "1080p60hz",
    												106         .mode = VMODE_1080P,
    												107         .width = 1920,
    												108         .height = 1080,
    												109         .field_height = 1080,
    												110         .aspect_ratio_num = 16,
    												111         .aspect_ratio_den  = 9,
    												112         .sync_duration_num = 60,
    												113         .sync_duration_den = 1,
    												114         .video_clk = 148500000,
    												115 };
    											   -----------------------------
    										
    						->hdmitx_edid_buf_compare_print(hdev); //打印edid buf内容到log输出
    								||
    								\/
    								---------------------------------------
    								文件:./drivers/amlogic/hdmi/hdmi_tx_20/hdmi_tx_edid.c
    								->hdmitx_edid_buf_compare_print(struct hdmitx_dev *hdmitx_device) //假设DDC成功读取EDID两次,然后比较EDID_buf和EDID_buf1。如果相同,
    																								  //只打印出EDID buf原始数据,否则打印出2个缓冲区数据
    									->for (blk_idx = 0; blk_idx < valid_blk_no; blk_idx++)
    										hdmitx_edid_blk_print(&buf0[blk_idx*128], blk_idx);									
    									->valid_blk_no = hdmitx_edid_check_valid_blocks(buf1);
    										for (blk_idx = 0; blk_idx < valid_blk_no; blk_idx++)
    											hdmitx_edid_blk_print(&buf1[blk_idx*128], blk_idx);
    								---------------------------------------
    
    							||
    							\/
    						->set_disp_mode_auto(); //
    							->hdmi_get_current_vinfo();//获取当前显示信息
    								->para = hdmi_get_fmt_name(mode, fmt_attr); //
    									->vic = hdmitx_edid_get_VIC(hdev, mode, 1); //
    									->ret = hdmitx_set_display(hdev, vic); //
    									->recalc_vinfo_sync_duration(info, hdev->frac_rate_policy);
    									->hdmitx_set_audio(hdev, &(hdev->cur_audio_param), hdmi_ch); //打开hdmi音频
    
    
    

    相关文件节点目录:./drivers/amlogic/display/vout/vout_serve.c

    相关节点:

    1|stvs9:/ # ls -l ./sys/devices/virtual/amhdmitx/amhdmitx0/
    total 0
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 attr
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 aud_cap
    -rw-rw-r-- 1 system mediadrm 4096 2020-04-30 10:36 aud_ch
    -rw-r--r-- 1 root   root     4096 2020-04-30 10:36 aud_mode
    -rw-r--r-- 1 root   root     4096 2020-04-30 10:36 aud_mute
    -rw-rw-r-- 1 system mediadrm 4096 2020-04-30 10:36 aud_output_chs
    -rw-r--r-- 1 system system   4096 2020-04-30 10:36 avmute
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 cea_cap
    -rw-rw-rw- 1 system system   4096 2020-04-30 10:36 config
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 dc_cap
    --w------- 1 root   root     4096 2020-04-30 10:36 debug
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 dev
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 disp_cap
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 disp_cap_3d
    -rw-rw-r-- 1 system system   4096 2020-04-30 10:36 disp_mode
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 div40
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 dv_cap
    -rw-r--r-- 1 root   root     4096 2020-04-30 10:36 edid
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 edid_parsing
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 frac_rate_policy
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 hdcp22_base
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 hdcp22_type
    --w------- 1 root   root     4096 2020-04-30 10:36 hdcp_byp
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 hdcp_clkdis
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 hdcp_ctrl
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 hdcp_ksv_info
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 hdcp_lstore
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 hdcp_mode
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 hdcp_pwr
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 hdcp_repeater
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 hdcp_ver
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 hdmi_init
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 hdr_cap
    -r--r--r-- 1 system system   4096 2020-04-30 10:36 hpd_state
    -rw-rw-rw- 1 root   root     4096 2020-04-30 10:36 phy
    drwxr-xr-x 2 root   root        0 2020-04-30 10:36 power
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 preferred_mode
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 rawedid
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 ready
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 rxsense_policy
    --w--w---- 1 root   root     4096 2020-04-30 10:36 sdr_hdr
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 sink_type
    lrwxrwxrwx 1 root   root        0 2020-04-30 10:36 subsystem -> ../../../../class/amhdmitx
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 support_3d
    -rw-r--r-- 1 root   root     4096 2020-04-30 10:36 uevent
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 valid_mode
    -r--r--r-- 1 root   root     4096 2020-04-30 10:36 vesa_cap
    -rw-rw-r-- 1 root   root     4096 2020-04-30 10:36 vic
    -rw-r--r-- 1 root   root     4096 2020-04-30 10:36 vid_mute
    

    还有:

    130|stvs9:/ # ls -l ./sys/class/display/    
    total 0
    -rw-r--r-- 1 media  system 4096 2020-04-30 10:36 axis
    lrwxrwxrwx 1 root   root      0 2020-04-30 10:37 display -> ../../devices/virtual/display/display
    -rw-r--r-- 1 root   root   4096 2020-04-30 10:37 fr_policy
    -rw-r--r-- 1 system system 4096 2020-04-30 10:36 mode
    -rw-rw-r-- 1 root   root   4096 2020-04-30 10:37 vinfo
    

    1、读取edid原始数据:
    stvs9:/ # cat ./sys/devices/virtual/amhdmitx/amhdmitx0/rawedid
    00ffffffffffff0025e4032301010101011d0103805022782a96a1a355539f250a5054210800818081c0a9c0d1c001010101010101014eab70b8d1a042509060640820
    4f3100001a000000fd00174c1f703c000a202020202020000000ff0053657269616c4e756d6265720a000000fc004c43442d474357513334315844015802033d704b10
    0102030405202256585a23090707830100006a030c002000383c20000067d85dc401788001e30f0004e200cae60607018b6011e3056000e77c70a0d0a0295030203a00
    204f3100001a565e00a0a0a0295030203500204f3100001a295900a0a038274030203a00204f3100001a000000000000000000000000ea

    2、设置分辨率
    stvs9:/ # echo 1080p60hz > sys/class/display/mode //设置分辨率为1080p
    stvs9:/ # cat sys/class/display/mode //查看当前设备分辨率
    1080p60hz

    3、RX所支持的色彩空间/色深模式支持的情况
    stvs9:/ $ cat /sys/class/amhdmitx/amhdmitx0/dc_cap
    420,10bit
    420,8bit
    444,12bit
    444,10bit
    444,8bit
    422,12bit
    422,10bit
    422,8bit
    rgb,12bit
    rgb,10bit
    rgb,8bit

    4、RX所支持的HDMI显示模式支持的情况
    stvs9:/ $ cat /sys/class/amhdmitx/amhdmitx0/disp_cap
    480p60hz
    720p60hz
    1080i60hz
    1080p60hz
    1080p30hz
    1080p24hz

    展开全文
  • 设置启用树莓派的HDMI显示

    万次阅读 2019-09-10 17:42:16
    树莓派所有的启动初始化都是在config.txt中完成的,因此,若插入HDMI树莓派没有显示桌面,则是没有配置HDMI。 首先在找到config.txt,两种方法: 第一种方法,将SD卡取出,用读卡器在windows上找到; 第二种方法...
  • 修改RK3399 HDMI显示分辨率

    千次阅读 2021-01-13 11:11:40
    [RK3399] HDMI正常输出4K30帧 无法输出60帧以及设置分辨率的流程分析 ** Platform: ROCKCHIP Chip: RK3399 OS: Android7.1.2 Kernel: 4.4.126* ** 【接上篇】上篇虽然HDMI能正常输出4K,但是帧率却达不到60帧,只能...
  • Zynq-PL之HDMI显示

    2021-02-01 21:22:10
    有了 《HDMI 1.4 协议浅析》的加持,那么使用 ZYNQ 搞一个 HDMI 输出来玩玩; 1、硬件原理图 首先,在硬件上,HDMI Connector 信号直接从 PL 端引出来,根据 HDMI 1.4 的协议呢,传输需要以 TMDS 差分信号进行传输...
  • 所以RK平台的hdmi显示机制是这样的: 比如你设置个HDMI的分辨率,比如1920x1080p60hz,如果你接另外一台电视有这个分辨率,就会切到这个分辨率去, 如果没有支持这个分辨率,就会切到其他相近的分辨率。 当
  • 代码下载 https://github.com/qiweiii-git/qwi06_sdp2hdmi 代码编译 1.在linux下使用./makeall.sh即可自动编译vivado工程。 如何使用linux自动编译工程请参考利用Linux自动编译Vivado工程 ...最终显示的图片 代码解...
  • FPGA - 基于FPGA的HDMI显示

    千次阅读 2021-01-22 01:21:48
    HDMI 高清晰度多媒体接口(英文:High Definition Multimedia Interface,HDMI)是一种数字化视频/音频接口技术,是适合影像传输的专用型数字化接口,其可同时传送音频和影像信号,最高数据传输速度为2.25GB/s,同时...
  • 树莓派切换到hdmi显示

    千次阅读 2019-12-13 14:48:21
    我用的是4b默认的显示方式是3.5寸的LCD 没有镜像的可以下载:4b专用镜像(默认...1、由3.5寸LCD显示切换到hdmi显示。 cd LCD-show/ ./LCD-hdmi 2、由hdmi显示切换到LCD显示。 cd LCD-show/ ./LCD35-show ...
  • rk3128 android7.1 hdmi显示

    2021-10-25 14:47:34
    1.入行嵌入式不久,也是第一次碰到hdmi需要配置才能显示的这种情况,是网友们给了我很大的帮助。 2.\kernel\arch\arm\boot\dts\lcd-b101ew05.dtsi (名字自己定义,我懒得改了) /* * RockChip. LCD_B101ew05 *...
  • 使用PYNQ_Z2开发板、ov5640摄像头及HDMI显示屏搭建的一个显示系统。
  • 一休哥将在本文中介绍一个基于Nios II的HDMI显示图片的工程。我将主要分三个部分来介绍这一工程,从而实现工程效果。 1、 Nios II的常规使用套路 2、 自定义HDMI IP核的制作 3、 Nios II显示图片 本文涉及到的...
  • 基于FPGA的HDMI显示系统的设计与实现总结
  • 下载资源后,请严格按照文档https://www.bilibili.com/read/cv4764474所述进行工程的搭建。
  • HDMI显示驱动---HD4600

    2020-12-16 16:57:52
    我们把它复制到你的桌面,右键显示包内容*/Contents/PlugIns/AppleGraphicsDevicePolicy.kext右键显示包内容/Contents/Info.plist*可以使用文本编辑打开或者其他软件,usb键盘按住win+f调出搜索,ps2按住alt+f,搜索...
  • 1.需要先开启root权限 ... ... 2.进入boot cd boot 之后的就是切换操作如下: ...在正常使用LCD的情况下,外接HDMI是没有显示的,如需启用HDMI输出,需执行以下命令,树莓派会...再等待约30秒,HDMI显示屏开始显示。 cd ...
  • 树莓派中LCD与HDMI显示的相互转换 LCD的设置 下载LCD驱动(LCD-show-171219.tar.gz)到SD卡boot根目录: https://my.oschina.net/u/2396236/blog/1637885 cd /boot cd LCD-show/ sudo ./LCD35-show(35对应3.5寸屏幕...
  • 【自我学习-zynq-7000】zedboard HDMI显示

    千次阅读 2019-12-25 19:30:10
    而随着图形可视化和数据分析和仿真的需要,需要将ZYNQ输出的信息通过HDMI接口显示在屏幕上,本节将介绍如何通过HDMI显示。 硬件:zedboard、HDMI接口显示器 软件:vivado 2017.4 SDK 2017.4 一,下载相关文件,...
  • 上一篇:基于FPGA的VGA显示设计(二) 10月10日 ~ 20日期间... 实习要求用 HDMI 接口显示,其实和VGA显示差不多的就多了两个引脚而已(de 和 hdmi_clk_o)。如下图: 虽然感觉做这个没什么意思了,但多多...
  • 在树莓派 4 之前,都是一个 HDMI 接口,所以没有这个问题。而树莓派 4B 有 2 个 HDMI 接口,可以输出双 4K。 在树莓派根目录下有一个文件config.txt, 我们需要修改里面的参数。 下面的配置为 HDMI0 输出1080P 60Hz...
  • 例子1: 是跑通官方的hdmi rx 和hdmi tx 历程。    例子2: 是去掉hdmi rx  只剩下 hdmi tx 。(这样可能更容易分析 hdmi 的软件和硬件) 3.课程是无声的, 主要是自己的学习的分享,稍微收一点辛苦...
  • 设置uboot为HDMI显示

    2019-10-22 09:17:56
    默认uboot参数没有设置默认显示格式 参考以下文章 https://www.cnblogs.com/zengjfgit/p/5139546.html http://bbs.21ic.com/icview-772662-1-60.html
  • dw-hdmi.c: HDMI驱动,包括内部I2C接口实现。 drm_edid.c: edid相关。 dw_hdmi-rockchip.c: drm框架部分。 探测引脚 HPD(Hotplug Dectect)用于监测HDMI设备是否存在,为high那么可以通过DDC去读EDID,HDM...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 13,878
精华内容 5,551
关键字:

Hdmi显示