HDMI字符显示实验

2023-09-14 21:00:33

FPGA教程学习

第十五章 HDMI字符显示实验


前言

在HDMI输出彩条的基础上输出osd叠加信息。


实验原理

实验通过字符转换工具将字符转换为 16 进制 coe 文件存放到单端口的 ROM IP 核中,再从
ROM 中把转换后的数据读取出来显示到 HDMI 上。
大致过程是将视频时序再经过一次处理模块,替换其中特定位置的数据,除了数据其余均不发生变化。

程序设计

在这里插入图片描述
与之前的彩条显示多了一个osd叠加模块。

像素点坐标模块

该模块输入信号和输出信号一致,主要是为了计数像素的坐标。

module timing_gen_xy(
	input                   rst_n,   
	input                   clk,
	input                   i_hs,    
	input                   i_vs,    
	input                   i_de,    
	input[23:0]             i_data,  
	output                  o_hs,    
	output                  o_vs,    
	output                  o_de,    
	output[23:0]            o_data,  
	output[11:0]            x,        // video position X
	output[11:0]            y         // video position y
);

计数的原理:
场信号在前肩到同步时是上升沿,表示是一副图像的开始,可以根据场信号的上升沿(或者下降沿,一个就行)来将行计数清零,即第零行。行递增计数的话使用DE信号的下降沿进行计数,当DE变为无效时,说明已经输出了一行像素点。
而行信号表示是一行的开始,这里没有用到,直接使用了DE信号,DE信号表示像素点有效,即有效像素点的开始,跳过行前肩+行同步+行后肩,用来计数一行的像素点。

注意数据也需要进行两次延时。

字符叠加模块

由上面的模块已经获取到了当前的坐标,接下来只要知道字符起始位置和需要叠加的字符,将输出的数据进行替换即可。如果当前坐标(像素点)需要叠加,就设置为需要的颜色,否则保持不变即可。

确定区域位置,使用一个寄存器表示,坐标在叠加区域的话就设置为有效。

//OSD区域设置,起始坐标为(9,9),区域大小根据生成的字符长宽设置
always@(posedge pclk)
begin
	if(pos_y >= 12'd9 && pos_y <= 12'd9 + OSD_HEGIHT - 12'd1 && pos_x >= 12'd9 && pos_x  <= 12'd9 + OSD_WIDTH - 12'd1)
		region_active <= 1'b1;
	else
		region_active <= 1'b0;
end

rom读取,在叠加区域内开始计数,实际计数的是像素点,但是一次读取数据为8bit,所以将低三位去掉即可。

//产生ROM的读地址,在region_active有效时,地址加1
always@(posedge pclk)
begin
	if(pos_vs_d1 == 1'b1 && pos_vs_d0 == 1'b0)
		osd_ram_addr <= 16'd0;
	else if(region_active == 1'b1)
		osd_ram_addr <= osd_ram_addr + 16'd1;
end

osd_rom osd_rom_m0 (
	.clka                       (pclk                    ),   
	.ena                        (1'b1                    ),     
	.addra                      (osd_ram_addr[15:3]      ), 	//生成的字符一个点为1bit,由于数据宽度为8bit,因此8个周期检查一次数据
	.douta                      (q                       )  
);

有了字符叠加区域和字符值,可以进行数据替换,注意这里是依次将8位数据替换,osd_x是像素的横坐标,取低三位作为像素点的计数下标即可。

always@(posedge pclk)
begin
	if(region_active_d0 == 1'b1)
		if(q[osd_x[2:0]] == 1'b1)  //检查bit位是否是1,如果是1,将此像素设为红色
			v_data <= 24'hff0000;
		else
			v_data <= pos_data;	   //否则保持原来的值
	else
		v_data <= pos_data;
end

实验结果

直接跑的demo,这里截个官方的图放在这里。
在这里插入图片描述

知识点

  1. rom的创建和初始数据(coe文件设置)的设置。
  2. rom的读时序。
  3. 视频时序。
  4. 边沿检测。
    当前一状态和当前状态不同的时候,可认为采样到了边沿信号。
    当前一状态为高电平,当前状态为低电平时,说明是下降沿。
    当前一状态为低电平,当前状态为高电平时,说明是下降沿。

i_vs,vs_d0 ,vs_d1三个信号去分析的话,要把整个过程理解成并行的,vs_d0 、vs_d1是两个记录状态的寄存器,理解成串行vs->d0->d1是错的。d0是vs的上一个状态,d1是d0上一个状态的记录,或者说,d0是vs延时一个周期的信号,d1是d0延时一个周期的信号。d0可以看作最新的状态,d1是上一个状态,d0&~d1是上升沿。同理可以分析DE的边沿。
在这里插入图片描述

assign vs_edge 		= vs_d0 & ~vs_d1;  		//VS posedge
assign de_falling 	= ~de_d0 & de_d1;		//DE negedge
always@(posedge clk)
begin
	de_d0 		<= i_de;
	de_d1 		<= de_d0;
	vs_d0 		<= i_vs;
	vs_d1 		<= vs_d0;
	hs_d0 		<= i_hs;
	hs_d1 		<= hs_d0;
end

总结

本实验在HDMI显示彩条的基础上,通过对视频时序的处理以及像素数据的替换,将rom中的字模叠加到画面中,实现了OSD信息的叠加。

更多推荐

iOS xcframework项目提示“ld: framework not found”

iOSxcframework项目提示“ld:frameworknotfound”问题描述公司有一个项目,同时引用了.framework和.xcframework,但是使用xcode编译的时候,xcodebuildarchive-project${project_Name}.xcodeproj-target${targe

FreeRTOS移植以及核心功能

文章目录freertos和ucos区别,优缺点比较移植步骤核心功能内存管理(5种内存管理策略)FreeRTOS任务调度算法有三种时间管理通信管理栈管理freertos和ucos区别,优缺点比较FreeRTOS(FreeReal-TimeOperatingSystem)和uC/OS(Micro-controllerOpe

使用Leaflet对WMS做空间几何范围查询

一、需求使用GeoServer发布的WMS服务对WMS做空间范围查询,默认情况下WMS支持点击查询,网上有很多的资料不在赘述。那么WMS做几何查询该怎么实现呢?二、实现路径查询WMS查询的服务参数,WMS支持三种请求方式:GetCapabilities、GetMap、GetFeatureInfo。其中GetCapabi

Transaction - 记一次 Spring 事务联合 Redis 挂了引发的生产事故

问题描述java.lang.RuntimeException:java.lang.IllegalStateException:Alreadyvalue[…数据源信息…]boundtothread[[Ljava.lang.String;@231b1ae0.container-0-C-1]上述问题是本次问题的最终结果,但并

springboot和vue:二、springboot特点介绍+热部署热更新

springboot特点介绍能够使用内嵌的Tomcat、Jetty服务器,不需要部署war文件。提供定制化的启动器Starters,简化Maven配置,开箱即用。纯Java配置,没有代码生成,也不需要XML配置。提供了生产级的服务监控方案,如安全监控、应用监控、健康检测等。热部署热更新SpringBoot提供了spri

SSD上 NVIDIA Jetson Orin NANO系統如何刷

对于AI计算性能高达40TOPS的JetsonOrinNano开发套件来说,如果缺少性能够好的存储相匹配,会让总体执行效益大打折扣。为此,NVIDIA在JetsonOrinNano开发套件上配置2个M.2接口(如下图),最高能安装2片高速PCIe总线的NVMe高速存储设备,这样大大提升了这个产品的实用性。由于M.2设备

Java中常见的线程池

一、Java中常见的线程池1.为什么使用线程池重用线程池的线程,避免因为线程的创造和销毁所带来的性能开销。有效控制线程池的最大并发数,避免大量的线程之间因抢占系统资源而阻塞。能够对线程进行简单的管理,并提供一些特定的操作,如:定时、定期、单线程、并发数控制等功能。2.线程池可能带来的风险死锁任何多线程应用程序都有死锁风

stm32单片机之外部脉冲捕获例程

stm32单片机之外部脉冲捕获例程定时器通道1来捕获外部脉冲,并且当脉冲到来时,通过HAL库的回调函数来处理这个事件。#include"stm32f4xx_hal.h"//定义一个TIM_HandleTypeDef结构体TIM_HandleTypeDefhtim1;voidSystemClock_Config(void

轻量级软件FastGithub实现稳定访问github

当我们想访问全球最大的“同性交友网站”https://github.com/时,总会出现无法访问的界面,令人非常苦恼:幸运的是,有一种轻量级的软件可以帮助我们稳定地访问GitHub,那就是FastGithub。什么是FastGithub?FastGithub是一个简洁且专一的软件,它可以帮助你稳定地访问GitHub。F

深入浅出学Verilog--数据类型

1、数值类型在Verilog可以用4种数值来描述其构建的电路的电平逻辑,除了event类型和real类型外,几乎所有的数据类型都可以用这4种数值来表示。0:代表逻辑0,或者条件“假”1:代表逻辑1,或者条件“真”x或X:代表未知值。意味着不确定,可能是逻辑0,也可能是逻辑1。z或Z:代表高阻态,一般用于3态缓冲电路(t

【Linux】常用工具(下)

Linux常用工具一、Linux项目自动化构建工具-make/Makefile1.依赖关系和依赖方法2.伪目标3.make/Makefile具有依赖性的推导能力(语法扩展)4.编写一个进度条代码(1)缓冲区(2)\n和\r(3)进度条代码二、Linux版本控制器-git1.gitclone2.gitconfig3.gi

热文推荐