HDMI字符显示实验

FPGA教程学习

第十五章 HDMI字符显示实验

文章目录


前言

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


实验原理

实验通过字符转换工具将字符转换为 16 进制 coe 文件存放到单端口的 ROM IP 核中,再从

ROM 中把转换后的数据读取出来显示到 HDMI 上。

大致过程是将视频时序再经过一次处理模块,替换其中特定位置的数据,除了数据其余均不发生变化。

程序设计

与之前的彩条显示多了一个osd叠加模块。

像素点坐标模块

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

c 复制代码
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信号表示像素点有效,即有效像素点的开始,跳过行前肩+行同步+行后肩,用来计数一行的像素点。

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

字符叠加模块

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

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

c 复制代码
//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,所以将低三位去掉即可。

c 复制代码
//产生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是像素的横坐标,取低三位作为像素点的计数下标即可。

c 复制代码
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的边沿。

c 复制代码
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信息的叠加。

相关推荐
Hello-FPGA7 小时前
基于RFSOC FPGA ZCU216 的CoaXPress 采集demo
fpga开发
9527华安8 小时前
FPGA基于ADV7182解码PAL视频,Video Processing Subsystem去隔行,提供6套工程源码和技术支持
fpga开发·音视频·pal·adv7182
hahaha60169 小时前
数字图像时域滤波或者3D降噪算法FPGA实现
算法·计算机视觉·fpga开发
GateWorld9 小时前
Xilinx 7系列FPGA时钟网络详解
fpga开发·时钟网络·xilinx 7系列
szxinmai主板定制专家21 小时前
X86 工控机 vs RK3588 异构主控:AMR 控制器 BOM、散热、长期运维对比
运维·stm32·单片机·嵌入式硬件·fpga开发·am62x
szxinmai主板定制专家1 天前
AMR 项目落地:机器人控制器硬件定制化需求复盘
arm开发·单片机·fpga开发·系统架构·机器人·am62x
FPGA小迷弟2 天前
FPGA 与卫星:从星载硬件到在轨智能的完整技术解析
fpga开发·架构·fpga·1024程序员节·无线电
NamoAmitabha1282 天前
CPU 内部结构是什么?---deepseek
fpga开发
abc light2 天前
ARM 裸机开发(6)——时钟树与定时器
arm开发·单片机·fpga开发
156082072193 天前
JFMZQ28DR、JFMZQ68DR、RFsoc XCZU47DR、XCZU48DR 信号处理板
fpga开发·信号处理