PotatoPie 4.0 实验教程(16) —— FPGA通过LVDS实现HDMI输出显示-Anlogic-安路社区-FPGA CPLD-ChipDebug

PotatoPie 4.0 实验教程(16) —— FPGA通过LVDS实现HDMI输出显示

手机扫码

20240416075513933-1713225291635

链接直达

https://item.taobao.com/item.htm?ft=t&id=776516984361

概述

HDMI

HDMI(High Definition Multimedia Interface)是一种全数字化影像和声音发送接口, 可以发送未压缩的音频及视频信号。 HDMI 可用于机顶盒、 DVD 播放机、 个人电脑、 投影仪与电视等设备, HDMI 发送音频和视频信号采用同一条线材, 大大简化系统线路的安装难度。

TMDS

TMDS(Transition Minimized Differential signal), 过渡调制差分信号, 也被称为最小化传输差分信号, 是指通过异或及异或非等逻辑算法将原始信号数据转换成 10 位, 前 8 位数据由原始信号经运算后获得, 第 9 位指示运算的方式, 第 10 位用来对应直流平衡(DC-balanced, 就是指在编码过程中保证信道中直流偏移为零, 电平转化实现不同逻辑接口间的匹配), 转换后的数据以差分传动方式传送。其具体编码过程可查阅 HDMI1.4 标准的规格书。

这个实验我们将利用EG4 FPGA的LVDS实现HDMI TX的功能,因为EG4没有serdes,所以只能支持到HDMI1.4,且考虑到图像质量我们只支持到720P(对于我们入门图像处理学习完全够用了),至于1080P不太稳定不推荐。

本工程里面的HDMI_TX是安路提供的一个相对简单易用的版本,安路新提供的APUG058有演示1080P EDID,AUDIO等功能,但使用较复杂不便于入门,感兴趣者可以自己参考APU058。

硬件原理图

FPGA侧

可以看到实现HDMI,只需要使用FPGA侧的LVDS接口即可,在HDMI_*开头的网络即为HDMI所使用的LVDS。

20240331110857987-image

HDMI接口侧

从图上可以看到HDMI接口侧主要就一个HDMI的母座,然后就是 RCLAMP0524P 这个ESD管子,由于HDMI的母座引入静电所以加了这个。另外就是RN1 RN2两个排阻,起到一个上拉作用,阻值为 499R电阻与RX50R上拉3.3V电阻分压形成3V的共模电压 。

20240331111046168-image

工程分析

代码分析

我们看工层的层次图

20240331112102248-image

  • hdmi_720p是本工程的顶层
  • clk_hdmi_pll_inst是本工程的PLL,用于产生测试pattern画面和HDMI显示所需要的时钟
  • u3_hdmi_tx是安路早期提供的HDMI的720P的网表。
  • u_vga_tc是用来控制HDMI测试画面的时序,即 timming control的缩写。
  • u_vga_tpg就是产生HDMI的各种测试画面的数据。

接下来逐步分析顶层的每个模块。

clk_hdmi_pll

用板载10M时钟产生了两路高速时钟75M和375M,PLL IP配置如下图:

20240331113022584-image

20240331113037444-image

hdmi_tx

安路提供的简化版的720P的HDMI网表

//HDMI TX Module
hdmi_tx #(.FAMILY("EG4")) //EF2、EF3、EG4、AL3、PH1
u3_hdmi_tx
(
.PXLCLK_I        (clk_pixel),
.PXLCLK_5X_I        (clk_pixel_5x),
.RST_I         (~locked),
        
//VGA   
.VGA_HS             (VGA_HS ),
.VGA_VS             (VGA_VS ),
.VGA_DE             (VGA_DE ),
.VGA_RGB            (VGA_RGB),
    
//HDMI  
.HDMI_CLK_P         (HDMI_CLK_P),
.HDMI_D2_P          (HDMI_TX_P[2] ),
.HDMI_D1_P          (HDMI_TX_P[1] ),
.HDMI_D0_P          (HDMI_TX_P[0] )
);
  • .PXLCLK_I   就是PLL生成的75M就是pixel的像素时钟
  • .PXLCLK_5X_I  就是PLL生成的375M是串行时钟
  • .RST_I  PLL的LOCK信号取反生成HDMI的复位信号,HDMI接口是高电平复位。
  • .HDMI_* 是输出到HDMI母座的信号。
  • VGA_*是输入到HDMI TX的测试视频信号,下面介绍。
vga_tc
vga_tc#
(
.HACTIVE(1280), 
.HFP(88), 
.HSA(44),
.VACTIVE(720),
.VFP(4),
.VSA (5) 
)
u_vga_tc
(
.vtc_rstn_i(vid_rst),
.vtc_clk_i(vid_clk),
.vtc_vs_o(VGA_VS),
.vtc_hs_o(VGA_HS),
.vtc_de_o(VGA_DE)	
);

这个模块开头的参数HACTIVE、HFP、HSA、VACTIVE、VFP、VSA提供了所需测试视频的行场参数,这些具体的数值是由视频电子标准协会(英语:Video Electronics Standards Association,简称“VESA”)标准提供的,这些参数的对应关系如下图,其中HTOTAL和VTOTAL在模块内部自动计算了。

localparam HTOTAL = HACTIVE + HFP + HSA + HBP;
localparam VTOTAL = VACTIVE + VFP + VSA + VBP;

20240331114933742-image

下面看看接口:

  • .vtc_rstn_i(vid_rst),  复位也由PLL LOCK信号得到。
  • .vtc_clk_i(vid_clk), 时钟,与HDMI的像素时钟PXCLK_I是同一个时钟。
  • .vtc_vs_o(VGA_VS), 场同步信号
  • .vtc_hs_o(VGA_HS), 行同步信号
  • .vtc_de_o(VGA_DE),行有效(数据有效信号)

vga_tpg

vga_tpg u_vga_tpg	
(
.tpg_clk_i(vid_clk),
.tpg_vs_i(VGA_VS),
.tpg_hs_i(VGA_HS),
.tpg_de_i(VGA_DE),
.tpg_vs_o(),
.tpg_hs_o(),
.tpg_de_o(),	
.tpg_data_o(VGA_RGB)		
);

端口说明

  • .tpg_clk_i(vid_clk), 时钟,同为HDMI的像素时钟PXCLK_I。
  • .tpg_vs_i(VGA_VS), vtc模块输出的场同步
  • .tpg_hs_i(VGA_HS), vtc模块输出的行同步
  • .tpg_de_i(VGA_DE), vtc模块输出的行有效
  • .tpg_vs_o(),
  • .tpg_hs_o(),
  • .tpg_de_o(),
  • .tpg_data_o(VGA_RGB), 产生的测试数据

这个模块的作用就是用来生成视频的测试数据,主要就是依据下面这段代码显示不同的测试数据。

case(pattern_id[10:7])
               ...
		'd4: begin     
			r_reg <= grid_data;                 //方格
			g_reg <= grid_data;
			b_reg <= grid_data;
		end
		'd5: begin
			r_reg <= 0; 
			b_reg <= 0;
			g_reg <= 0;
		end
		'd6: begin
			r_reg <= 8'b11111111;               //白
			g_reg <= 8'b11111111;
			b_reg <= 8'b11111111;
		end
		'd7: begin
			r_reg <= 8'b11111111;              //红
			g_reg <= 0;
			b_reg <= 0;  
		end			  
		'd8: begin
			r_reg <= 0;                         //绿
			g_reg <= 8'b11111111;
			b_reg <= 0; 
		end					  
		'd9: begin     
			r_reg <= 0;                         //蓝
			g_reg <= 0;
			b_reg <= 8'b11111111;
		end
		'd10: begin    
			r_reg <= h_cnt[7:0];                //水平渐变
			g_reg <= h_cnt[7:0];
			b_reg <= h_cnt[7:0];
		end
		'd11: begin     
			r_reg <= v_cnt[7:0];                 //垂直渐变
			g_reg <= v_cnt[7:0];
			b_reg <= v_cnt[7:0];
		end
		'd12: begin     
			r_reg <= v_cnt[7:0];                 //红垂直渐变
			g_reg <= 0;
			b_reg <= 0;
		end
		'd13: begin     
			r_reg <= 0;                          //绿垂直渐变
			g_reg <= h_cnt[7:0];
			b_reg <= 0;
		end
		'd14: begin     
			r_reg <= 0;                          //蓝垂直渐变
			g_reg <= 0;
			b_reg <= h_cnt[7:0];			
		end
                ...		  
    endcase

工程约束分析

管脚约束

可以看到P11是我们板载的10M时钟,其它就是HDMI的管脚,IO电平标准是LVDS33,需要注安路的TD工具只需要约速P端,工具会自动锁定N端。

set_pin_assignment	{ sysclk_i     }	{ LOCATION = P11; }
#HDMI TX
set_pin_assignment	{ HDMI_CLK_P   }	{ LOCATION = P47; IOSTANDARD = LVDS33; }
set_pin_assignment	{ HDMI_TX_P[0] }	{ LOCATION = P55; IOSTANDARD = LVDS33; }
set_pin_assignment	{ HDMI_TX_P[1] }	{ LOCATION = P61; IOSTANDARD = LVDS33; }
set_pin_assignment	{ HDMI_TX_P[2] }	{ LOCATION = P64; IOSTANDARD = LVDS33; }

时序约束

第一行约束板载的主时钟为10M,第二行让TD工具自动推导PLL的时序约束。

create_clock -name SYS_CLK -period 100 -waveform {0 50} [get_ports {sysclk_i}]
derive_pll_clocks

实验结果

部分测试画面显示结果如下图(密集恐聚症^_^),更多测试画面快下到载板子自己看看吧!

20240326130955913-image

20240326131225485-image

20240326131242125-image

20240401084923158-image

20240401084951982-image

请登录后发表评论

    没有回复内容