HDMI 输出实验

这篇具有很好参考价值的文章主要介绍了HDMI 输出实验。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

FPGA教程学习

第十四章 HDMI 输出实验



前言

  1. FPGA通过HDMI编码芯片输出彩条。

实验原理

开发板有一个HDMI编码芯片,ADV7511,将 24 位 RGB 编码输出 TMDS 差分信号。
本实验使用其将RGB24视频数据显示出来。
硬件原理图如下:
HDMI 输出实验,ZYNQ学习,fpga开发
结合前面,从原理图(或者看手册,这里只是大致分析一下)上可以分析出:

  1. 编码输入是24位的数据,本实验是RGB
  2. 编码输出时TMDS 差分信号
  3. 编码芯片的配置接口是I2C
  4. HDMI接口上有I2C

实验过程

程序设计

HDMI 输出实验,ZYNQ学习,fpga开发

时钟模块(video_pll)

负责产生一个100Mhz的时钟和一个1080P的148.5Mhz的像素时钟。
生成时钟 IP 的方法是点击 Project Manager目录下的 IP Catalog,再选择 FPGA Features and Design->Clocking->Clocking Wizard 图标。然后进行设置即可。

彩条产生模块(color_bar)

是产生 8 种颜色的 VGA 格式的彩条,彩条分别为白、黄、青、绿、紫、红、蓝和黑。产生分辨率为 1920x1080 刷新率为 60Hz 的彩条,也就是所谓的 1080P 的高清视频图像。

视频时序图:
HDMI 输出实验,ZYNQ学习,fpga开发

模块要根据这个视频时序去看,用了几个寄存器来计数行场信号。
模块接口参数比较少,输入只有时钟和复位,其他都是输出。这里输出的时序是给编码芯片的。

module color_bar(
	input clk,            //像素时钟输入,1280x720@60P的像素时钟为74.25
	input rst,            //复位,高有效
	output hs,            //行同步、高有效
	output vs,            //场同步、高有效
	output de,            //数据有效
	output[7:0] rgb_r,    //像素数据、红色分量
	output[7:0] rgb_g,    //像素数据、绿色分量
	output[7:0] rgb_b     //像素数据、蓝色分量
);
//*************************************************************************\
//==========================================================================
//   Description:
//  彩条发生模块
//==========================================================================
//   Revision History:
//	Date		  By			Revision	Change Description
//--------------------------------------------------------------------------
//2013/5/7                     1.2         remove some warning
//2013/4/18                    1.1         vs timing
//2013/4/16	        		   1.0			Original
//*************************************************************************/
module color_bar(
	input clk,            //像素时钟输入,1280x720@60P的像素时钟为74.25
	input rst,            //复位,高有效
	output hs,            //行同步、高有效
	output vs,            //场同步、高有效
	output de,            //数据有效
	output[7:0] rgb_r,    //像素数据、红色分量
	output[7:0] rgb_g,    //像素数据、绿色分量
	output[7:0] rgb_b     //像素数据、蓝色分量
);
/*********视频时序参数定义******************************************/
//parameter H_ACTIVE = 16'd1280;  //行有效长度(像素时钟周期个数)
//parameter H_FP = 16'd110;       //行同步前肩长度
//parameter H_SYNC = 16'd40;      //行同步长度
//parameter H_BP = 16'd220;       //行同步后肩长度
//parameter V_ACTIVE = 16'd720;   //场有效长度(行的个数)
//parameter V_FP 	= 16'd5;        //场同步前肩长度
//parameter V_SYNC  = 16'd5;      //场同步长度
//parameter V_BP	= 16'd20;       //场同步后肩长度

parameter H_ACTIVE = 16'd1920;
parameter H_FP = 16'd88;
parameter H_SYNC = 16'd44;
parameter H_BP = 16'd148; 
parameter V_ACTIVE = 16'd1080;
parameter V_FP 	= 16'd4;
parameter V_SYNC  = 16'd5;
parameter V_BP	= 16'd36;
parameter H_TOTAL = H_ACTIVE + H_FP + H_SYNC + H_BP;//行总长度
parameter V_TOTAL = V_ACTIVE + V_FP + V_SYNC + V_BP;//场总长度
/*********彩条RGB color bar颜色参数定义*****************************/
parameter WHITE_R 		= 8'hff;
parameter WHITE_G 		= 8'hff;
parameter WHITE_B 		= 8'hff;
parameter YELLOW_R 		= 8'hff;
parameter YELLOW_G 		= 8'hff;
parameter YELLOW_B 		= 8'h00;                              	
parameter CYAN_R 		= 8'h00;
parameter CYAN_G 		= 8'hff;
parameter CYAN_B 		= 8'hff;                             	
parameter GREEN_R 		= 8'h00;
parameter GREEN_G 		= 8'hff;
parameter GREEN_B 		= 8'h00;
parameter MAGENTA_R 	= 8'hff;
parameter MAGENTA_G 	= 8'h00;
parameter MAGENTA_B 	= 8'hff;
parameter RED_R 		= 8'hff;
parameter RED_G 		= 8'h00;
parameter RED_B 		= 8'h00;
parameter BLUE_R 		= 8'h00;
parameter BLUE_G 		= 8'h00;
parameter BLUE_B 		= 8'hff;
parameter BLACK_R 		= 8'h00;
parameter BLACK_G 		= 8'h00;
parameter BLACK_B 		= 8'h00;
reg hs_reg;//定义一个寄存器,用于行同步
reg vs_reg;//定义一个寄存器,用户场同步
reg hs_reg_d0;//hs_reg一个时钟的延迟
              //所有以_d0、d1、d2等为后缀的均为某个寄存器的延迟
reg vs_reg_d0;//vs_reg一个时钟的延迟
reg[11:0] h_cnt;//用于行的计数器
reg[11:0] v_cnt;//用于场(帧)的计数器
reg[11:0] active_x;//有效图像的的坐标x
reg[11:0] active_y;//有效图像的坐标y
reg[7:0] rgb_r_reg;//像素数据r分量
reg[7:0] rgb_g_reg;//像素数据g分量
reg[7:0] rgb_b_reg;//像素数据b分量
reg h_active;//行图像有效
reg v_active;//场图像有效
wire video_active;//一帧内图像的有效区域h_active & v_active
reg video_active_d0;
assign hs = hs_reg_d0;
assign vs = vs_reg_d0;
assign video_active = h_active & v_active;
assign de = video_active_d0;
assign rgb_r = rgb_r_reg;
assign rgb_g = rgb_g_reg;
assign rgb_b = rgb_b_reg;



always@(posedge clk or posedge rst)
begin
	if(rst)
		begin
			hs_reg_d0 <= 1'b0;
			vs_reg_d0 <= 1'b0;
			video_active_d0 <= 1'b0;
		end
	else
		begin // 这个地方左侧的寄存器是hs,vs,de的输出,hs_reg和vs_reg有关系
			hs_reg_d0 <= hs_reg;
			vs_reg_d0 <= vs_reg;
			video_active_d0 <= video_active;
		end
end

// 行计数,每次记一行的时钟个数,也就是一行的第几个时钟
always@(posedge clk or posedge rst)
begin
	if(rst)
		h_cnt <= 12'd0;
	else if(h_cnt == H_TOTAL - 1)//行计数器到最大值清零
		h_cnt <= 12'd0;
	else
		h_cnt <= h_cnt + 12'd1;
end

// x坐标,像素坐标,当前肩+同步+后肩结束时,输出有效像素,x用来计数有效的图像数据,或者说是x的坐标
always@(posedge clk or posedge rst)
begin
	if(rst)
		active_x <= 12'd0;
	else if(h_cnt >= H_FP + H_SYNC + H_BP - 1)//计算图像的x坐标
		active_x <= h_cnt - (H_FP[11:0] + H_SYNC[11:0] + H_BP[11:0] - 12'd1);
	else
		active_x <= active_x;
end

// 场计数,或者说是行数计数,用来计数多少行,每当一行的前肩开始时就进行计数,到达最大进行清零
always@(posedge clk or posedge rst)
begin
	if(rst)
		v_cnt <= 12'd0;
	else if(h_cnt == H_FP  - 1)//在行数计算器为H_FP - 1的时候场计数器+1或清零
		if(v_cnt == V_TOTAL - 1)//场计数器到最大值了,清零
			v_cnt <= 12'd0;
		else
			v_cnt <= v_cnt + 12'd1;//没到最大值,+1
	else
		v_cnt <= v_cnt;
end

// 行同步信号的输出,从前肩开始有效,到达设定的值时结束
always@(posedge clk or posedge rst)
begin
	if(rst)
		hs_reg <= 1'b0;
	else if(h_cnt == H_FP - 1)//行同步开始了...
		hs_reg <= 1'b1;
	else if(h_cnt == H_FP + H_SYNC - 1)//行同步这时候要结束了
		hs_reg <= 1'b0;
	else
		hs_reg <= hs_reg;
end

// 行数据有效信号,在一行前肩+同步+后肩内为低,图像数据有效时为高
always@(posedge clk or posedge rst)
begin
	if(rst)
		h_active <= 1'b0;
	else if(h_cnt == H_FP + H_SYNC + H_BP - 1)
		h_active <= 1'b1;
	else if(h_cnt == H_TOTAL - 1)
		h_active <= 1'b0;
	else
		h_active <= h_active;
end

// 场同步信号,和行同步信号类似,从前肩开始有效,到达设定的值时结束
always@(posedge clk or posedge rst)
begin
	if(rst)
		vs_reg <= 1'd0;
	else if((v_cnt == V_FP - 1) && (h_cnt == H_FP - 1))
		vs_reg <= 1'b1;
	else if((v_cnt == V_FP + V_SYNC - 1) && (h_cnt == H_FP - 1))
		vs_reg <= 1'b0;	
	else
		vs_reg <= vs_reg;
end

// 场数据有效信号,在前肩+同步+后肩内为低,图像数据有效时为高,h_active和v_active共同用来指示数据是否有效,作为数据使能信号DE
always@(posedge clk or posedge rst)
begin
	if(rst)
		v_active <= 1'd0;
	else if((v_cnt == V_FP + V_SYNC + V_BP - 1) && (h_cnt == H_FP - 1))
		v_active <= 1'b1;
	else if((v_cnt == V_TOTAL - 1) && (h_cnt == H_FP - 1))
		v_active <= 1'b0;		
	else
		v_active <= v_active;
end

// 根据行坐标输出特定的像素值
always@(posedge clk or posedge rst)
begin
	if(rst)
		begin
			rgb_r_reg <= 8'h00;
			rgb_g_reg <= 8'h00;
			rgb_b_reg <= 8'h00;
		end
	else if(video_active)
		if(active_x == 12'd0)
			begin
				rgb_r_reg <= WHITE_R;
				rgb_g_reg <= WHITE_G;
				rgb_b_reg <= WHITE_B;
			end
		else if(active_x == (H_ACTIVE/8) * 1)
			begin
				rgb_r_reg <= YELLOW_R;
				rgb_g_reg <= YELLOW_G;
				rgb_b_reg <= YELLOW_B;
			end			
		else if(active_x == (H_ACTIVE/8) * 2)
			begin
				rgb_r_reg <= CYAN_R;
				rgb_g_reg <= CYAN_G;
				rgb_b_reg <= CYAN_B;
			end
		else if(active_x == (H_ACTIVE/8) * 3)
			begin
				rgb_r_reg <= GREEN_R;
				rgb_g_reg <= GREEN_G;
				rgb_b_reg <= GREEN_B;
			end
		else if(active_x == (H_ACTIVE/8) * 4)
			begin
				rgb_r_reg <= MAGENTA_R;
				rgb_g_reg <= MAGENTA_G;
				rgb_b_reg <= MAGENTA_B;
			end
		else if(active_x == (H_ACTIVE/8) * 5)
			begin
				rgb_r_reg <= RED_R;
				rgb_g_reg <= RED_G;
				rgb_b_reg <= RED_B;
			end
		else if(active_x == (H_ACTIVE/8) * 6)
			begin
				rgb_r_reg <= BLUE_R;
				rgb_g_reg <= BLUE_G;
				rgb_b_reg <= BLUE_B;
			end	
		else if(active_x == (H_ACTIVE/8) * 7)
			begin
				rgb_r_reg <= BLACK_R;
				rgb_g_reg <= BLACK_G;
				rgb_b_reg <= BLACK_B;
			end
		else
			begin
				rgb_r_reg <= rgb_r_reg;
				rgb_g_reg <= rgb_g_reg;
				rgb_b_reg <= rgb_b_reg;
			end			
	else
		begin
			rgb_r_reg <= 8'h00;
			rgb_g_reg <= 8'h00;
			rgb_b_reg <= 8'h00;
		end
end

endmodule 

配置数据查找表模块(lut_adv7511)

这个模块就是根据输入的下标输出设定好的值。


module lut_adv7511(
	input[9:0]             lut_index, // Look-up table index address
	output reg[31:0]       lut_data   // I2C device address register address register data
);

always@(*)
begin
	case(lut_index)
		//To be compatible with the 16bit register address, add 8'h00
		8'd0 	: 	lut_data	<= 	{8'h72,24'h004100};   //16'h4110; 	
		8'd1    : 	lut_data	<= 	{8'h72,24'h00d6c0};			
		8'd2 	: 	lut_data	<= 	{8'h72,24'h005512};			
		8'd3 	: 	lut_data	<= 	{8'h72,24'h001500};  //input id = 0x0 = 0000 = 24 bit RGB 4:4:4 or YCbCr 4:4:4 (separate syncs)
		8'd4    : 	lut_data	<= 	{8'h72,24'h00d03c};
		8'd5    : 	lut_data	<= 	{8'h72,24'h00af04};	
		8'd6    : 	lut_data	<= 	{8'h72,24'h004c04};	
		8'd7    : 	lut_data	<= 	{8'h72,24'h004000};		
		8'd8 	: 	lut_data	<= 	{8'h72,24'h009803};
		8'd9 	: 	lut_data	<= 	{8'h72,24'h009ae0};	
		8'd10	: 	lut_data	<=	{8'h72,24'h009c30};	
		8'd11	: 	lut_data	<= 	{8'h72,24'h009d61};	
		8'd12	: 	lut_data	<= 	{8'h72,24'h00a2a4};	
		8'd13	: 	lut_data	<= 	{8'h72,24'h00a3a4};	
		8'd14	: 	lut_data	<= 	{8'h72,24'h00e0d0};	
		8'd15	: 	lut_data	<= 	{8'h72,24'h00f900};
		
		default:lut_data <= {8'hff,16'hffff,8'hff};
	endcase
end

endmodule 

I2C Master 寄存器配置模块(i2c_config)

这个模块使用了查找表模块,输出对应的下标,将查找的数据作为输入。然后这里还有一大堆使用I2C读写的代码,以后再看。

module i2c_config(
	input              rst,
	input              clk,
	input[15:0]        clk_div_cnt,
	input              i2c_addr_2byte,
	output reg[9:0]    lut_index,
	input[7:0]         lut_dev_addr,
	input[15:0]        lut_reg_addr,
	input[7:0]         lut_reg_data,
	output reg         error,
	output             done,
	inout              i2c_scl,
	inout              i2c_sda
);

TODO

  1. 分析I2C读写代码
  2. 了解视频时序
  3. 查看编码芯片数据手册

总结

本实验通过使用I2C配置编码芯片,构建模拟图像输出视频时序模块,完成了使用HDMI输出模拟图像(彩条)的功能。通过本次实验,了解了HDMI输出、视频时序、I2C读写的一些知识点。HDMI输出的是差分信号,芯片输出是可能需要编码芯片进行编码,不能够直接输出。视频时序中有前肩、后肩、同步等术语,行场信号是一个重要的知识点,要熟悉行场信号的构造。I2C是一个常用的配置接口,实验中的编码芯片由I2C进行配置,HDMI接口上也有一个。文章来源地址https://www.toymoban.com/news/detail-706809.html

参考

  1. 8k,4k,2k视频时序参数分享
  2. HDMI中的视频时序分析
  3. 基于FPGA的视频时序生成

到了这里,关于HDMI 输出实验的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • (七)零基础FPGA图像处理——HDMI彩条显示实验

    此篇为专栏 《FPGA学习笔记》 的第七篇,记录我的学习FPGA的一些开发过程和心得感悟,刚接触FPGA的朋友们可以先去此专栏置顶 《FPGA零基础入门学习路线》来做最基础的扫盲。 本篇内容基于笔者实际开发过程和正点原子资料撰写,将会详细讲解此FPGA实验的全流程, 诚挚 地

    2024年02月03日
    浏览(59)
  • ZYNQ之FPGA 片内ROM读写测试实验

    FPGA本身是SRAM架构的,断电之后程序就会消失,那么如何利用FPGA实现一个ROM呢,我们可以利用FPGA内部的RAM资源实现ROM,但这不是真正意义上的ROM,而是每次上电都会把初始化的值先写入RAM。Vivado软件中提供了ROM的IP核 , 我们只需通过IP核例化一个ROM,根据ROM的读时序来读取R

    2024年02月07日
    浏览(45)
  • FPGA实现HDMI输入转SDI视频输出,提供4套工程源码和技术支持

    FPGA实现HDMI输入转SDI视频输出,提供4套工程源码和技术支持 FPGA实现SDI视频编解码目前有两种方案: 一是使用专用编解码芯片,比如典型的接收器GS2971,发送器GS2972,优点是简单,比如GS2971接收器直接将SDI解码为并行的YCRCB,GS2972发送器直接将并行的YCRCB编码为SDI视频,缺点是

    2024年02月08日
    浏览(52)
  • 008-关于FPGA/ZYNQ直接处理图像传感器数据输出的若干笔记(裸板采集思路)

    最近也是未来需要考虑做的一件事情是,如何通过FPGA/ZYNQ去做显微镜图像观测下的图像采集传输与后续的处理。目前显微镜观测领域通常是以PC端连接工业相机接口,这个接口可以是USB3.0,可以是网口,也可以是其它传输方式。常常通过工业相机输出的为视频流数据,厂商会

    2024年01月23日
    浏览(59)
  • FPGA实现HDMI转LVDS视频输出,纯verilog代码驱动,提供4套工程源码和技术支持

    FPGA实现HDMI转LVDS视频输出,纯verilog代码驱动,提供工程源码和技术支持 LVDS协议作为中等速率的差分信号,在笔记本电脑和手机等消费电子领域应用广泛,FPGA实现LVDS视频协议也有广泛应用,一般在军工和医疗领域,LVDS视频相比RGB并行视频传输而言,图像质量和IO数量都有优

    2024年03月20日
    浏览(45)
  • Zynq和FPGA区别——快速认识Zynq开发

    ZYNQ包含了2个部分,双核的ARM和FPGA。根据Xilinx提供的手册,用ARM实现的模块被称为PS,而用FPGA实现的模块被称为PL。简单的说FPA更偏向于逻辑,不跑系统。 ZYNQ内部包含PS和PL两部分,ZYNQ开发有一下四种方式: ZYNQ是赛灵思公司(Xilinx)推出的新一代全可编程片上系统,它将处

    2024年02月16日
    浏览(55)
  • 【FPGA开发】HDMI通信协议解析及FPGA实现

      笔者在这里使用的开发板是正点原子的达芬奇开发板,FPGA型号为XC7A35TFGG484-2。参考的课程是正点原子的课程手把手教你学达芬奇达芬奇Pro之FPGA开发篇。   HDMI,全称为High Definition Multimedia Interface,即高清多媒体接口。它不仅可以传输视频信号,还可以传输音频信号。上

    2024年02月21日
    浏览(48)
  • FPGA基于XDMA实现PCIE X8视频采集HDMI输出 提供工程源码和QT上位机程序和技术支持

    PCIE(PCI Express)采用了目前业内流行的点对点串行连接,比起 PCI 以及更早期的计算机总线的共享并行架构,每个设备都有自己的专用连接,不需要向整个总线请求带宽,而且可以把数据传输率提高到一个很高的频率,达到 PCI 所不能提供的高带宽,是目前各行业高速接口的优

    2024年02月01日
    浏览(49)
  • FPGA基于XDMA实现PCIE X4视频采集HDMI输出 提供工程源码和QT上位机程序和技术支持

    PCIE(PCI Express)采用了目前业内流行的点对点串行连接,比起 PCI 以及更早期的计算机总线的共享并行架构,每个设备都有自己的专用连接,不需要向整个总线请求带宽,而且可以把数据传输率提高到一个很高的频率,达到 PCI 所不能提供的高带宽,是目前各行业高速接口的优

    2024年02月02日
    浏览(48)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包