HDMI 输出实验

FPGA教程学习

第十四章 HDMI 输出实验


文章目录

  • FPGA教程学习
  • 前言
  • 实验原理
  • 实验过程
    • 程序设计
      • 时钟模块(video_pll)
      • 彩条产生模块(color_bar)
      • 配置数据查找表模块(lut_adv7511)
      • I2C Master 寄存器配置模块(i2c_config)
  • TODO
  • 总结
  • 参考


前言

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

实验原理

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

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

实验过程

程序设计

在这里插入图片描述

时钟模块(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 的高清视频图像。

视频时序图:
在这里插入图片描述

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

module color_bar(input clk,            //像素时钟输入,1280x720@60P的像素时钟为74.25input 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.25input 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)
beginif(rst)beginhs_reg_d0 <= 1'b0;vs_reg_d0 <= 1'b0;video_active_d0 <= 1'b0;endelsebegin // 这个地方左侧的寄存器是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)
beginif(rst)h_cnt <= 12'd0;else if(h_cnt == H_TOTAL - 1)//行计数器到最大值清零h_cnt <= 12'd0;elseh_cnt <= h_cnt + 12'd1;
end// x坐标,像素坐标,当前肩+同步+后肩结束时,输出有效像素,x用来计数有效的图像数据,或者说是x的坐标
always@(posedge clk or posedge rst)
beginif(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);elseactive_x <= active_x;
end// 场计数,或者说是行数计数,用来计数多少行,每当一行的前肩开始时就进行计数,到达最大进行清零
always@(posedge clk or posedge rst)
beginif(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;elsev_cnt <= v_cnt + 12'd1;//没到最大值,+1elsev_cnt <= v_cnt;
end// 行同步信号的输出,从前肩开始有效,到达设定的值时结束
always@(posedge clk or posedge rst)
beginif(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;elsehs_reg <= hs_reg;
end// 行数据有效信号,在一行前肩+同步+后肩内为低,图像数据有效时为高
always@(posedge clk or posedge rst)
beginif(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;elseh_active <= h_active;
end// 场同步信号,和行同步信号类似,从前肩开始有效,到达设定的值时结束
always@(posedge clk or posedge rst)
beginif(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;	elsevs_reg <= vs_reg;
end// 场数据有效信号,在前肩+同步+后肩内为低,图像数据有效时为高,h_active和v_active共同用来指示数据是否有效,作为数据使能信号DE
always@(posedge clk or posedge rst)
beginif(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;		elsev_active <= v_active;
end// 根据行坐标输出特定的像素值
always@(posedge clk or posedge rst)
beginif(rst)beginrgb_r_reg <= 8'h00;rgb_g_reg <= 8'h00;rgb_b_reg <= 8'h00;endelse if(video_active)if(active_x == 12'd0)beginrgb_r_reg <= WHITE_R;rgb_g_reg <= WHITE_G;rgb_b_reg <= WHITE_B;endelse if(active_x == (H_ACTIVE/8) * 1)beginrgb_r_reg <= YELLOW_R;rgb_g_reg <= YELLOW_G;rgb_b_reg <= YELLOW_B;end			else if(active_x == (H_ACTIVE/8) * 2)beginrgb_r_reg <= CYAN_R;rgb_g_reg <= CYAN_G;rgb_b_reg <= CYAN_B;endelse if(active_x == (H_ACTIVE/8) * 3)beginrgb_r_reg <= GREEN_R;rgb_g_reg <= GREEN_G;rgb_b_reg <= GREEN_B;endelse if(active_x == (H_ACTIVE/8) * 4)beginrgb_r_reg <= MAGENTA_R;rgb_g_reg <= MAGENTA_G;rgb_b_reg <= MAGENTA_B;endelse if(active_x == (H_ACTIVE/8) * 5)beginrgb_r_reg <= RED_R;rgb_g_reg <= RED_G;rgb_b_reg <= RED_B;endelse if(active_x == (H_ACTIVE/8) * 6)beginrgb_r_reg <= BLUE_R;rgb_g_reg <= BLUE_G;rgb_b_reg <= BLUE_B;end	else if(active_x == (H_ACTIVE/8) * 7)beginrgb_r_reg <= BLACK_R;rgb_g_reg <= BLACK_G;rgb_b_reg <= BLACK_B;endelsebeginrgb_r_reg <= rgb_r_reg;rgb_g_reg <= rgb_g_reg;rgb_b_reg <= rgb_b_reg;end			elsebeginrgb_r_reg <= 8'h00;rgb_g_reg <= 8'h00;rgb_b_reg <= 8'h00;end
endendmodule 

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

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


module lut_adv7511(input[9:0]             lut_index, // Look-up table index addressoutput reg[31:0]       lut_data   // I2C device address register address register data
);always@(*)
begincase(lut_index)//To be compatible with the 16bit register address, add 8'h008'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
endendmodule 

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接口上也有一个。

参考

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/65796.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elasticSearch+kibana+logstash+filebeat集群改成https认证

文章目录 一、生成相关证书二、配置elasticSearh三、配置kibana四、配置logstash五、配置filebeat六、连接https es的java api 一、生成相关证书 ps&#xff1a;主节点操作 切换用户&#xff1a;su es 进入目录&#xff1a;cd /home/es/elasticsearch-7.6.2 创建文件&#x…

Adobe Illustrator 2023 for mac安装教程,可用。

Adobe Illustrator 是行业标准的矢量图形应用程序&#xff0c;可以为印刷、网络、视频和移动设备创建logos、图标、绘图、排版和插图。数以百万计的设计师和艺术家使用Illustrator CC创作&#xff0c;从网页图标和产品包装到书籍插图和广告牌。此版本是2023版本&#xff0c;适配…

LeetCode(力扣)236. 二叉树的最近公共祖先Python

LeetCode236. 二叉树的最近公共祖先 题目链接代码 题目链接 https://leetcode.cn/problems/lowest-common-ancestor-of-a-binary-tree/ 代码 # Definition for a binary tree node. # class TreeNode: # def __init__(self, x): # self.val x # self.…

C语言深入理解指针(非常详细)(二)

目录 指针运算指针-整数指针-指针指针的关系运算 野指针野指针成因指针未初始化指针越界访问指针指向的空间释放 如何规避野指针指针初始化注意指针越界指针不使用时就用NULL避免返回局部变量的地址 assert断言指针的使用和传址调用传址调用例子&#xff08;strlen函数的实现&a…

The Cherno——OpenGL

The Cherno——OpenGL 1. 欢迎来到OpenGL OpenGL是一种跨平台的图形接口&#xff08;API&#xff09;&#xff0c;就是一大堆我们能够调用的函数去做一些与图像相关的事情。特殊的是&#xff0c;OpenGL允许我们访问GPU&#xff08;Graphics Processing Unit 图像处理单元&…

Python小知识 - 如何使用Python的Flask框架快速开发Web应用

如何使用Python的Flask框架快速开发Web应用 现在越来越多的人把Python作为自己的第一语言来学习&#xff0c;Python的简洁易学的语法以及丰富的第三方库让人们越来越喜欢上了这门语言。本文将介绍如何使用Python的Flask框架快速开发Web应用。 Flask是一个使用Python编写的轻量级…

Spring Boot中通过maven进行多环境配置

上文 java Spring Boot将不同配置拆分入不同文件管理 中 我们说到了&#xff0c;多环境的多文件区分管理 说到多环境 其实不止我们 Spring Boot有 很多的东西都有 那么 这就有一个问题 如果 spring 和 maven 都配置了环境 而且他们配的不一样 那么 会用谁的呢&#xff1f; 此…

《TCP/IP网络编程》阅读笔记--基于Windows实现Hello Word服务器端和客户端

目录 1--Hello Word服务器端 2--客户端 3--编译运行 3-1--编译服务器端 3-2--编译客户端 3-3--运行 1--Hello Word服务器端 // gcc hello_server_win.c -o hello_server_win -lwsock32 // hello_server_win 9190 #include <stdio.h> #include <stdlib.h> #i…

【算法刷题-双指针篇】

目录 1.leetcode-27. 移除元素2.leetcode-344. 反转字符串3.leetcode-剑指 Offer 05. 替换空格4.leetcode-206. 反转链表5.leetcode-19. 删除链表的倒数第 N 个结点6.leetcode-面试题 02.07. 链表相交7.leetcode-142. 环形链表 II8.leetcode-15. 三数之和9.leetcode-18. 四数之…

Git使用——GitHub项目回退版本

查看历史版本 使用git log命令查看项目的历史版本&#xff1a; 可以一直回车&#xff0c;直到找到想要的历史版本&#xff0c;复制commit后面的那一串id。 恢复历史版本 执行命令 git reset --hard 版本号&#xff1a; git reset --hard 39ac3ea2448e81ea992b7c4fdad9252983…

ARM 汇编基础知识

1.为什么学习汇编&#xff1f; 我们在进行嵌入式 Linux 开发的时候是绝对要掌握基本的 ARM 汇编&#xff0c;因为 Cortex-A 芯片一 上电 SP 指针还没初始化&#xff0c; C 环境还没准备好&#xff0c;所以肯定不能运行 C 代码&#xff0c;必须先用汇编语言设置好 C 环境…

七、Linux中一些符号的含义和宿主目录的介绍

1、Linux中一些符号的含义 在Linux命令行中&#xff0c;会看到如下一些符号&#xff0c;含义如下。 符号含义. 代表当前目录..代表上一层目录&#xff0c;当前目录的父目录-代表前一个目录&#xff0c;刚才从哪个目录cd过来~代表当前用户的宿主目录/代表根目录$普通用户的命…

两个线程同步执行:解决乱箭穿心(STL/Windows/Linux)

C自学精简教程 目录(必读) C并发编程入门 目录 多线程同步 线程之间同步是指线程等待其他线程执行完某个动作之后再执行&#xff08;本文情况&#xff09;。 线程同步还可以是像十字路口的红绿灯一样&#xff0c;只允许一个方向的车同行&#xff0c;其他方向的车等待。 本…

Mac 如何判断下载Mac with Intel Chip 还是 Mac with Apple Chip

如下图&#xff0c;当我们在 Mac系统 下载客户端时&#xff0c;有两种选择&#xff1a;Mac with Intel Chip 、 Mac with Apple Chip 如何判断要下载哪一种&#xff1f; 需要判断本机Mac是在Inter芯片还是Apple芯片上运行的。方法如下&#xff1a; 点击屏幕左上角Apple标志&a…

DHorse v1.3.2 发布,基于 k8s 的发布平台

版本说明 新增特性 构建版本、部署应用时的线程池可配置化&#xff1b; 优化特性 构建版本跳过单元测试&#xff1b; 解决问题 解决Vue应用详情页面报错的问题&#xff1b;解决Linux环境下脚本运行失败的问题&#xff1b;解决下载Maven安装文件失败的问题&#xff1b; 升…

Docker技术--Docker中的网络问题

1.docker中的网络通信 如果想要弄清楚docker中的网络通信问题,其实需要弄清楚这几个问题就可以:容器与容器之间的通信、容器与外部网络之间的通信、外部网络与容器之间的通信。 -a:容器与容器之间的通信,如下所示: 在默认情况下,docker使用网桥(Bridge模式)与NAT通信。这…

已解决module ‘pip‘ has no attribute ‘pep425tags‘报错问题(如何正确查看pip版本、支持、32位、64位方法汇总)

本文摘要&#xff1a;本文已解决module ‘pip‘ has no attribute ‘pep425tags‘的相关报错问题&#xff0c;并总结提出了几种可用解决方案。同时结合人工智能GPT排除可能得隐患及错误。并且最后说明了如何正确查看pip版本、支持、32位、64位方法汇总 &#x1f60e; 作者介绍&…

Lesson6---案例:人脸案例

学习目标 了解opencv进行人脸检测的流程了解Haar特征分类器的内容 1 基础 我们使用机器学习的方法完成人脸检测&#xff0c;首先需要大量的正样本图像&#xff08;面部图像&#xff09;和负样本图像&#xff08;不含面部的图像&#xff09;来训练分类器。我们需要从其中提取特…

清理docker镜像方法

首先stop ps -a里的容器&#xff0c;然后rm容器&#xff0c;最后再rmi镜像 先停止容器 rm容器 docker rmi 镜像 删除后可以发现已经不存在

编写一个这样的程序,满足五日均线,十日均线,二十日均线,六十天六日均线调头向上的选股代码

编写一个这样的程序&#xff0c;满足五日均线&#xff0c;十日均线&#xff0c;二十日均线&#xff0c;六十天六日均线调头向上的选股代码 以下是一个用C语言编写的程序&#xff0c;可以读取股票数据并筛选出满足条件的股票。程序使用了一个假设的股票数据文件格式&#xff0c…