VGA显示字符

前言

        VGA(Video Graphics Array)是IBM在1987年随PS/2机一起推出的一种视频传输标准,具有分辨率高、显示速率快、颜色丰富等优点,在彩色显示器领域得到了广泛的应用。VGA技术的应用还主要基于VGA显示卡的计算机、笔记本等设备,而在一些既要求显示彩色高分辨率图像又没有必要使用计算机的设备上,VGA技术的应用却很少见到。本文对嵌入式VGA显示的实现方法进行了研究。基于这种设计方法的嵌入式VGA显示系统,实现VGA图像的显示和控制。系统具有成本低、结构简单、应用灵活的优点,可广泛应用于超市、车站、飞机场等公共场所的广告宣传和提示信息显示,也可应用于工厂车间生产过程中的操作信息显示,还能以多媒体形式应用。

正文

一、VGA显示字符

        1.项目需求

        通过vga接口,使得显示屏上显示FPGA四个字符(理论讲解)

        2.技术介绍

VGA驱动原理请参考:VGA接口驱动设计验证

本章讲解如何显示字符:  首先需要一取字模的工具,这里使用PCtoLCD2002(资料私信1发送)

输入需要取模的字符,设置字符大小:

这里设置单个字母的空间,为字符画区域

这里设置单个字母大小,设置字符的高矮胖瘦

以上需要自行设置,在下方对话框中输入需要显示的字符,先另存为.BMP文件,再次使用该软件打开保存的.BMP文件。

点击选项,进行如下图配置

点击确定,点击生成字模,保存字模,以下为字模提取结构

显示字符,确定显示起始坐标左上角坐标(字符定位点),并以该点向XY方向进行拓展,定义字符边框,定义一二维数数组存放字符数据,

parameter 	show_h = 10'd110,//字模定位点Y坐标
			show_v = 10'd100;//字模定位点X坐标
				
parameter 	show_chan = 10'd256,//图片长度
			show_kuan = 10'd32;//图片宽度

以确定的字符定位点为(0.0)定义两计数器,对字符区域重新编码,得到新的字符坐标,

wire[9:0]	char_x;//字模Y坐标
wire[9:0]	char_y;//字模X坐标
				
assign char_x =((pix_x >= show_h)&&(pix_x < (show_h + show_chan)))&&((pix_y >= show_v)&&(pix_y <(show_v + show_kuan)))?(pix_x - show_h):10'h3ff;//字模Y坐标数据生成
assign char_y =((pix_x >= show_h)&&(pix_x < (show_h + show_chan)))&&((pix_y >= show_v)&&(pix_y <(show_v + show_kuan)))?(pix_y - show_v):10'h3ff;字模X坐标数据生成

新的字符坐标与二维数组对应,以该坐标为二维数组的编号,对数组内部数据进行判断

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		vga_rgb <= show_1_rgb;
	else
		if(	((pix_x >= show_h - 1'b1)&&(pix_x < (show_h + show_chan - 1'b1)))
			&&	((pix_y >= show_v )&&(pix_y <(show_v + show_kuan)))
			&&	(char[char_y][10'd255 - char_x] == 1'b1))//对字模区域进行颜色赋值
			vga_rgb  <= show_0_rgb;
		else
			vga_rgb <= show_1_rgb;//非字模区域颜色为背景颜色
end

有数据时给目标颜色,没有数据时显示背景颜色。

         3.顶层架构

        4.端口描述

clk板载时钟(50Mhz)
rst_n复位按键(低电平有效)
vga_hs行脉冲信号
vga_vs场脉冲信号
[7:0] vga_rgb颜色数据信号,高三位表示红色,
    中间三位表示绿色,低两位表示蓝色
[9:0]vga_vx坐标
[9:0]vga_hy坐标

二、代码验证

vga_ctrl模块:原理参考VGA接口驱动设计验证

module vga_ctrl(

	input    		clk		,
	input    		rst_n		,
	input[7:0]		in_rgb	,
				
	output   		vga_hs	,
	output   		vga_vs	,
	output[9:0]   	vga_h		,//坐标
	output[9:0]   	vga_v		,//坐标
	output[7:0]  	vga_rgb
);

reg [9:0] cnt_hs;//列计数器
reg [9:0] cnt_vs;//行计数器
wire hs_en;//列有效显示区域
wire vs_en;//行有效显示区域
wire volid_en;//有效显示区域

parameter 	hs_sync = 10'd96	,//同步
				hs_bask = 10'd40	,//后沿
				hs_left = 10'd8	,//左边
				hs_vali = 10'd640	,//有效
				hs_righ = 10'd8	,//右边
				hs_fpon = 10'd8	,//前沿
				hs_tota = 10'd800	;//总共
				                   
parameter 	vs_sync = 10'd2	,//同步   
				vs_bask = 10'd25	,//后沿	  
				vs_left = 10'd8	,//上边   
				vs_vali = 10'd480	,//有效 
				vs_righ = 10'd8	,//底边   
				vs_fpon = 10'd2	,//前沿   
				vs_tota = 10'd525	;//总共				

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		cnt_hs <= 10'd0;
	else
		if(cnt_hs < hs_tota - 10'd1)
			cnt_hs <= cnt_hs + 10'd1;
		else
			cnt_hs <= 10'd0;
end 

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		cnt_vs <= 10'd0;
	else
		if(cnt_hs ==  hs_tota - 10'd1)
			if(cnt_vs < vs_tota - 10'd1)
				cnt_vs <= cnt_vs + 10'd1;
			else 
				cnt_vs <= 10'd0;
		else
			cnt_vs <= cnt_vs;
end 

assign vga_hs = (cnt_hs < hs_sync)?1'b0:1'b1;//行同步信号赋值

assign vga_h  = (volid_en == 1'b1)?(cnt_hs - (hs_sync + hs_bask + hs_left)):10'd0;//行坐标(Y)

assign vga_vs = (cnt_vs < vs_sync)?1'b0:1'b1;//场同步信号赋值

assign vga_v  = (volid_en == 1'b1)?(cnt_vs - (vs_sync + vs_bask + vs_left)):10'd0;//列坐标(X)

assign hs_en = ((cnt_hs >= hs_sync + hs_bask + hs_left )&&(cnt_hs <= hs_sync + hs_bask + hs_left + hs_vali))?1'b1:1'b0;

assign vs_en = ((cnt_vs >= vs_sync + vs_bask + vs_left )&&(cnt_vs <= vs_sync + vs_bask + vs_left + vs_vali))?1'b1:1'b0;

assign volid_en = hs_en & vs_en;//显示区域

assign vga_rgb = (volid_en == 1'b1)?in_rgb:8'd0;

endmodule 

vga_data模块:保存字符取模结果,进行RGB数据生成

module vga_data(

     input                  clk     	,
     input                  rst_n   	,
     input[9:0]				pix_x		,
	 input[9:0]				pix_y		,
	 
	 output reg[7:0]		vga_rgb

);

parameter 	show_h = 10'd110,//字模定位点Y坐标
			show_v = 10'd100;//字模定位点X坐标
				
parameter 	show_chan = 10'd256,//图片长度
			show_kuan = 10'd32;//图片宽度

parameter 	show_1_rgb = 8'b000_000_00,//背景
			show_0_rgb = 8'b111_100_00;//图片颜色

reg [255:0]	char	[31:0];
wire[9:0]	char_x;//字模Y坐标
wire[9:0]	char_y;//字模X坐标
				
assign char_x =((pix_x >= show_h)&&(pix_x < (show_h + show_chan)))&&((pix_y >= show_v)&&(pix_y <(show_v + show_kuan)))?(pix_x - show_h):10'h3ff;//字模Y坐标数据生成
assign char_y =((pix_x >= show_h)&&(pix_x < (show_h + show_chan)))&&((pix_y >= show_v)&&(pix_y <(show_v + show_kuan)))?(pix_y - show_v):10'h3ff;字模X坐标数据生成

always@(posedge clk)//生成的字模数据
begin
	char[0  ] <= 256'h0000000000000000000000000001000000200000000100000020000000010000; 
	char[1  ] <= 256'h0020000000010000003FFFFFFFFF0000003FFFFFFFFF0000003FFFFFFFFF0000;
	char[2  ] <= 256'h003FFFFFFFFF0000003000180001000000300018000100000030001800010000;
	char[3  ] <= 256'h0030001800010000003000180000000000300018000000000030001800000000;
	char[4  ] <= 256'h003000180000000000300018000000000030003C000000000030007E00000000;
	char[5  ] <= 256'h003803FFE00000000038000000000000003C000000000000003E000000000000;
	char[6  ] <= 256'h003F8000000000000003C0000000000000006000000000000000000000000000;
	char[7  ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
	char[8  ] <= 256'h0000000000000000000000000001000000200000000100000020000000010000;
	char[9  ] <= 256'h0020000000010000003FFFFFFFFF0000003FFFFFFFFF0000003FFFFFFFFF0000;
	char[10 ] <= 256'h003FFFFFFFFF0000003000060001000000300006000100000030000600010000;
	char[11 ] <= 256'h0030000600010000003000060000000000300006000000000030000600000000;
	char[12 ] <= 256'h00300006000000000038000E000000000038000E00000000001C001C00000000;
	char[13 ] <= 256'h001E003C00000000000F80F800000000000FFFF8000000000007FFF000000000;
	char[14 ] <= 256'h0001FFC00000000000007F000000000000000000000000000000000000000000;
	char[15 ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
	char[16 ] <= 256'h00000000000000000000000000000000000000FFE000000000000FFFFE000000;
	char[17 ] <= 256'h00007FFFFF8000000000FFFFFFE000000003FE001FF800000007E00000FC0000;
	char[18 ] <= 256'h000F0000003C0000001E0000000E0000001C0000000600000038000000070000;
	char[19 ] <= 256'h0030000000030000003000000003000000300000000300000030000100030000;
	char[20 ] <= 256'h00300001000300000018000100060000001C0001800E0000001E0001FFFC0000;
	char[21 ] <= 256'h001F8001FFF80000001FF001FFF8000000003801FFF800000000000180000000;
	char[22 ] <= 256'h0000000100000000000000010000000000000001000000000000000000000000;
	char[23 ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
	char[24 ] <= 256'h00000000000100000000000000010000000000000003000000000000001F0000;
	char[25 ] <= 256'h0000000001FF0000000000001FE3000000000001FC0100000000001FC0010000;
	char[26 ] <= 256'h000001FCC000000000001FC0C00000000001FC00C0000000001FC000C0000000;
	char[27 ] <= 256'h003E0000C0000000007F0000C0000000007FF000C0000000003FFF00C0000000;
	char[28 ] <= 256'h0001FFF0C000000000001FFFC0000000000001FFFC0100000000001FFFC10000;
	char[29 ] <= 256'h00000001FFFF0000000000000FFF00000000000000FF000000000000000F0000;
	char[30 ] <= 256'h0000000000030000000000000001000000000000000100000000000000000000;
	char[31 ] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
end

always @(posedge clk,negedge rst_n)
begin
	if(rst_n == 0)
		vga_rgb <= show_1_rgb;
	else
		if(	((pix_x >= show_h - 1'b1)&&(pix_x < (show_h + show_chan - 1'b1)))
			&&	((pix_y >= show_v )&&(pix_y <(show_v + show_kuan)))
			&&	(char[char_y][10'd255 - char_x] == 1'b1))//对字模区域进行颜色赋值
			vga_rgb  <= show_0_rgb;
		else
			vga_rgb <= show_1_rgb;//非字模区域颜色为背景颜色
end

endmodule 

顶层模块:顶层连线

module vga_driver(

	input 			clk		,	
	input 			rst_n		,
	
	output 			vga_hs	,//行脉冲信号,由列计数器控制产生
	output			vga_vs	,//场脉冲信号,由行计数器控制产生
	output[9:0]   	vga_h		,//坐标
	output[9:0]   	vga_v		,//坐标
	output[7:0]   	vga_rgb/*颜色数据信号,高三位表示红色,
	中间三位表示绿色,低两位表示蓝色*/
);

wire vga_clk;//25.2mhz
wire locked;
wire [7:0]in_rgb;

vga_pll	vga_pll_inst (
	.areset ( ~rst_n ),
	.inclk0 ( clk ),
	.c0 ( vga_clk ),
	.locked ( locked )
);

vga_ctrl vga_ctrl_inst(

			.clk		(clk)		,//vga_clk
			.rst_n	(locked)	,
			.in_rgb	(in_rgb) ,
			
			.vga_hs	(vga_hs)	,
			.vga_vs	(vga_vs)	,
			.vga_h 	(vga_h)	,
			.vga_v 	(vga_v)	,
			.vga_rgb	(vga_rgb)
);

vga_data vga_data_inst(

    .clk    (clk    )	,
    .rst_n  (locked )	,
	 .pix_x	(vga_h  )	,
	 .pix_y	(vga_v  )	,
             
	 .vga_rgb(in_rgb)

);
endmodule 

仿真代码

`timescale 1ns/1ps
module vga_driver_tb;

	reg 			clk	;
	reg 			rst_n	;
	
	wire 			vga_hs;
	wire 			vga_vs;
	wire[9:0]   vga_h	;//坐标
	wire[9:0]   vga_v	;//坐标	
	wire[7:0] 	vga_rgb;

vga_driver vga_driver_instx(

			.clk		(clk)		,
			.rst_n	(rst_n)	,
			
			.vga_hs	(vga_hs)	,//行脉冲信号,由列计数器控制产生
			.vga_vs	(vga_vs)	,//场脉冲信号,由行计数器控制产生
			.vga_h	(vga_h)	,
			.vga_v	(vga_v)	,
			.vga_rgb	(vga_rgb)/*颜色数据信号,高三位表示红色,
			中间三位表示绿色,低两位表示蓝色*/
);

initial clk = 0;
always #10 clk = ~clk;

initial begin
	rst_n = 0;
	#200
	rst_n = 1;
	#1000
	$stop;
end 

endmodule 

三、仿真验证

该实验仿真需等较长时间,这里只讲解到有vga数据输出

这里可以看到有数据产出

放大仿真图进行分析,输出第一次数据变化与(116 . 111),而字符起始坐标为(100 . 110)这是由于字符在(100 . 110)显示的是字模提取后的字符背景区域,而(116 . 111)是字符区域。

参考资料

VGA接口驱动设计验证

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

张明阳.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值