赞
踩
文章目录
我们在上一篇文章中已经对VGA视频传输标准作了详细的介绍,包括VGA接口协议、行/场同步时序、以及显示分辨率等,也实现了基于VGA接口标准的等宽彩条的显示实验,如果对VGA的基本概念不是很熟悉的话,可以去看看VGA彩条显示这部分的内容。
在上篇文章的结尾,提高还可以利用VGA接口标准来显示其他图片、字符,在本次文章中,我们就一起来完成VGA的字符显示的内容,达到一个复习巩固的效果。
本篇的实验任务就是使用VGA接口标准,在显示器的中间显示“卡布奇洛”这四个汉字。
显示模式:640*480@60
点阵大小:64*64
字符大小:56*56
字符(包括汉字、字母和符号等)的本质是点阵,在VGA屏幕上体现为字符显示区域内像素点的集合。字符的大小决定了字符显示区域内像素点的数目,而字符的样式(字体、颜色等)则决定了各像素点的颜色值。因此,我们在进行字符显示之前,先要对指定的字符进行字符取模,获得该字符的点阵数据。
为了获得指定字符的点阵数据,就需要对字符进行取模处理,字模的提取可以通过字符取模软件来实现,我们这里所使用的取模软件为PCtoLCD2002来提取“卡布奇洛”这四个汉字的字模,下面就是使用PCtoLCD2002软件进行字符取模的过程。
① 双击打开PCtoLCD2002字符取模软件,将模式修改为字符模式。
② 根据显示要求修改点阵大小与字符大小,我这里点阵大小为64*64,字符大小为56*56。
③ 在点阵大小与字符大小设置完成后,我们在输入框中输入我们要生成字符的汉字,我这里输入的是“卡布奇洛”。
④ 这时就显示出了字模,但是这时不要生成字模,因为这时生成字模是单个汉字的字模,不是我们需要的整体的字模。这时我们点击另存为,保存到我们项目工程的doc文件夹下,保存的格式为.bmp格式。
⑤ 保存完成过后,在软件的文件目录下选择打开,打开刚刚保存的字模,然后打开选项进行字模的配置。
⑥ 参数设置完成后点击确定,然后点击生成字模,保存字模。
⑦ 最后就可以看到我们的doc文件夹下有生成的字模数据了。
到此为止呢我们的字模生成算是完成了,我们保存的字模的点阵大小是256*64,因为我们一个点阵是64*64,而我们有四个点阵,也就是64*4=256,所以我们的整体字模的点阵大小就是256*64。
由于本次实验工程是在上一个实验工程上进行了修改,所以上一个实验工程的一些模块是可以直接进行复用的,这里主要需要更改VGA的显示模块,其余两个模块可以进行复用。
① VGA字符显示顶层模块:
/*====================================* filename : vga_char_top.v description : VGA字符显示顶层模块 time : 2022-12-29 author : 卡夫卡与海 *=====================================*/ module vga_char_top( input clk ,//系统时钟 input rst_n ,//复位 output vga_hsync ,//行同步信号 output vga_vsync ,//场同步信号 output [15:0] vga_rgb //数据输出(红绿蓝) ); //信号定义 wire vga_clk ;//vga工作时钟 25MHZ wire locked ; wire vga_reset ; wire [9:0] pix_x ; wire [9:0] pix_y ; wire [15:0] pix_data ; assign vga_reset = rst_n && locked; //模块例化 //PLL CLK_PLL CLK_PLL_inst ( .areset (~rst_n ), .inclk0 (clk ), .c0 (vga_clk), .locked (locked ) ); //vga控制模块 vga_control u_vga_control( /*input */.clk_25 (vga_clk ),//时钟 25MHZ /*input */.rst_n (vga_reset),//复位 /*input [15:0] */.pix_data (pix_data ),//输入图像数据 /*output [9:0] */.pix_x (pix_x ),//横坐标 /*output [9:0] */.pix_y (pix_y ),//纵坐标 /*output */.hsync (vga_hsync),//行同步信号 /*output */.vsync (vga_vsync),//场同步信号 /*output [15:0] */.vga_rgb (vga_rgb ) //输出图像数据(RGB565格式) ); //vga显示模块 vga_display u_vga_display( /*input */.clk_25 (vga_clk ),//VGA驱动时钟 /*input */.rst_n (vga_reset),//复位 /*input [9:0] */.pix_x (pix_x ),//横坐标 /*input [9:0] */.pix_y (pix_y ),//纵坐标 /*output reg [15:0] */.pix_data (pix_data ) //数据 ); endmodule
② VGA控制模块:
- /*===============================*
- filename : vga_control.v
- description : VGA控制模块
- time : 2022-12-28
- author : 卡夫卡与海
- *================================*/
-
- module vga_control(
- input clk_25 ,//时钟 25MHZ
- input rst_n ,//复位
-
- input [15:0] pix_data ,//输入图像数据
-
- output [9:0] pix_x ,//横坐标
- output [9:0] pix_y ,//纵坐标
- output hsync ,//行同步信号
- output vsync ,//场同步信号
- output [15:0] vga_rgb //输出图像数据(RGB565格式)
- );
- //参数定义
- //显示模式:640*480@60
- parameter H_SYNC = 96 ,//行同步
- H_BACK = 48 ,//行显示后沿
- H_DISP = 640,//行有效数据
- H_FRONT = 16 ,//行显示前沿
- H_TOTAL = 800;//行扫描周期
-
- parameter V_SYNC = 2 ,//场同步
- V_BACK = 33 ,//场显示后沿
- V_DISP = 480,//场有效数据
- V_FRONT = 10 ,//场显示前沿
- V_TOTAL = 525;//场扫描周期
-
- //信号定义
- reg [9:0] cnt_h ;//行计数器
- reg [9:0] cnt_v ;//场计数器
-
- wire rgb_vaild ;//数据有效信号
- wire data_req ;//数据请求信号
-
- //cnt_h
- always @(posedge clk_25 or negedge rst_n)begin
- if(!rst_n)begin
- cnt_h <= 10'd0;
- end
- else begin
- if(cnt_h < H_TOTAL - 1)begin
- cnt_h <= cnt_h + 1'b1;
- end
- else begin
- cnt_h <= 10'd0;
- end
- end
- end
- //cnt_v
- always @(posedge clk_25 or negedge rst_n)begin
- if(!rst_n)begin
- cnt_v <= 10'd0;
- end
- else if(cnt_h == H_TOTAL - 1)begin
- if(cnt_v < V_TOTAL - 1)begin
- cnt_v <= cnt_v + 1'b1;
- end
- else begin
- cnt_v <= 10'd0;
- end
- end
- end
-
- //rgb_vaild 数据输出有效信号
- assign rgb_vaild = ((cnt_h >= H_BACK + H_SYNC)
- &&(cnt_h < H_SYNC + H_BACK + H_DISP)
- &&(cnt_v >= V_SYNC + V_BACK)
- &&(cnt_v < V_SYNC + V_BACK + V_DISP))
- ? 1'b1 : 1'b0;
-
- //data_req 像素点颜色数据输入请求信号
- assign data_req = (((cnt_h >= H_SYNC + H_BACK - 1)
- && (cnt_h < H_SYNC + H_BACK + H_DISP - 1))
- && ((cnt_v >= V_SYNC + V_BACK)
- && (cnt_v < V_SYNC + V_BACK + V_DISP)))
- ? 1'b1 : 1'b0;
-
- //输出
- //pix_x 横坐标
- assign pix_x = (data_req==1'b1)?(cnt_h - (H_SYNC+H_BACK-1)):10'h3ff;
-
- //pix_y 纵坐标
- assign pix_y = (data_req==1'b1)?(cnt_v - (V_SYNC+V_BACK-1)):10'h3ff;
-
- //hsync
- assign hsync = (cnt_h <= H_SYNC - 1) ? 1'b0 : 1'b1;
-
- //vsync
- assign vsync = (cnt_v <= V_SYNC - 1) ? 1'b0 : 1'b1;
-
- //vga_rgb
- assign vga_rgb = (rgb_vaild == 1'b1) ? pix_data : 16'd0;
-
-
- endmodule
③ VGA显示模块:
- /*===============================*
- filename : vga_display.v
- description : VGA显示模块
- time : 2022-12-29
- author : 卡夫卡与海
- *================================*/
-
- module vga_display(
- input clk_25 ,//VGA驱动时钟
- input rst_n ,//复位
-
- input [9:0] pix_x ,//横坐标
- input [9:0] pix_y ,//纵坐标
- output reg [15:0] pix_data //数据
- );
- //参数定义
- parameter CHAR_B_H = 10'd192 ,//字符开始横坐标
- CHAR_B_V = 10'd208 ;//字符开始纵坐标
-
- parameter CHAR_W = 10'd256 ,//字符宽度
- CHAR_H = 10'd56 ;//字符深度
-
- //颜色参数 RGB565格式
- parameter BLACK = 16'h0000,//黑色(背景色)
- GOLDEN = 16'hFEC0;//金色(字符颜色)
-
- //信号定义
- wire [9:0] char_x ;//字符横坐标
- wire [9:0] char_y ;//字符纵坐标
-
- reg [255:0] char [63:0] ;
-
- //char_x
- assign char_x = (((pix_x >= CHAR_B_H)&&(pix_x < (CHAR_B_H + CHAR_W)))
- &&((pix_y >= CHAR_B_V)&&(pix_y < (CHAR_B_V + CHAR_H))))
- ? (pix_x - CHAR_B_H) : 10'h3ff;
- //char_y
- assign char_y = (((pix_x >= CHAR_B_H)&&(pix_x < (CHAR_B_H + CHAR_W)))
- &&((pix_y >= CHAR_B_V)&&(pix_y < (CHAR_B_V + CHAR_H))))
- ? (pix_y - CHAR_B_H) : 10'h3ff;
-
- //char
- always @(posedge clk_25)begin
- char[0] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[1] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[2] <= 256'h0000000000000000000000000000000000000020000000000000000000000000;
- char[3] <= 256'h000000C00000000000000030000000000000003C000000000000000000000000;
- char[4] <= 256'h000000F8000000000000003C000000000000003E000000000000000000000000;
- char[5] <= 256'h0000007C000000000000003E000000000000001C000000000000000E00000000;
- char[6] <= 256'h0000007C000000000000003C000000000000001C000000000000000F00000000;
- char[7] <= 256'h0000003C000000000000003C000000000000001C000000000000000F80000000;
- char[8] <= 256'h0000003C0000000000000078000000000000001C000000000000000F80000000;
- char[9] <= 256'h0000003C1F00000000000078000000000000001C1C000000000C000F00000000;
- char[10] <= 256'h0000003DFF80000000000070001F00000000001FFF000000000F000E00000000;
- char[11] <= 256'h0000003FFE000000000000701FFFC000000001FFFF000000000F801E1F000000;
- char[12] <= 256'h0000003FC0000000000000FFFFFFE00000007FFF800000000007C01FFF800000;
- char[13] <= 256'h0000003C0000000000007FFFFFFFC00000003FFC000000000003C03FFF800000;
- char[14] <= 256'h000000180000000000FFFFFC000000000000003800000000000180701F000000;
- char[15] <= 256'h0000001800000000007FFDC0000000000000003800000000000000701E000000;
- char[16] <= 256'h0000001800000000003E03C7800000000000007C00000000000000E01E000000;
- char[17] <= 256'h000000180000000000000383C000000000000077C0000000000001C03C000000;
- char[18] <= 256'h00000018007FC00000000783C0000000000000E3E00000000000038038000000;
- char[19] <= 256'h000000181FFFE00000000703C0000000000001C1F0000000000007F078000000;
- char[20] <= 256'h0000001FFFFFE00000000E03C000000000000380F00000000200083870000000;
- char[21] <= 256'h000001FFFFC0000000001E0380000000000007003000000007C0001EE0000000;
- char[22] <= 256'h0000FFFF0000000000001C038000000000000E00001FE00003F0000FE0000000;
- char[23] <= 256'h07FFFFF8000000000000380380E00000000038000FFFF00001F00003C0000000;
- char[24] <= 256'h07FFF07C0000000000007803BFF8000000004007FFFFF80000F00007E0000000;
- char[25] <= 256'h01FE003C0000000000007FFFFFFC000000000FFFFFF020000070000FF0000000;
- char[26] <= 256'h0000003C000000000000EFFFC07C0000007FFFFE780000000000000F7C000000;
- char[27] <= 256'h00000038000000000001CE03807C000007FFFC003C0000000000001E3E000000;
- char[28] <= 256'h00000018000000000003CE038078000003FC00003C0000000001003C1F800000;
- char[29] <= 256'h00000018E000000000078E03803800000000006038000000000200780FC00000;
- char[30] <= 256'h00000018F8000000000F0E0380380000000001F838000000000200F007F00000;
- char[31] <= 256'h000000187E000000001E0E038038000000039FFC38000000000601C001FC0000;
- char[32] <= 256'h000000183F000000003C0E03803800000001F83C38000000000C078000FF8000;
- char[33] <= 256'h000000181F80000000700E03807800000001C03838000000000C0F00007FF800;
- char[34] <= 256'h000000180FC0000000E00E03807800000001C0383800000000181C00003FF000;
- char[35] <= 256'h0000001807E0000001800E03907000000000C030380000000018780006000000;
- char[36] <= 256'h0000001803E0000007000E038FF000000000C070380000000038E0007F800000;
- char[37] <= 256'h0000001800E0000008001E0387F000000000C3F03C00000000730F1FFFE00000;
- char[38] <= 256'h000000180000000000001C0381F000000000FFF83C00000000F007FF03F00000;
- char[39] <= 256'h000000180000000000001C0381E000000000F0003C00000000E0078003F00000;
- char[40] <= 256'h000000180000000000000C0380C000000000C0003C00000003E0078003E00000;
- char[41] <= 256'h00000018000000000000080380800000000040003C00000003E0038003C00000;
- char[42] <= 256'h00000038000000000000000380000000000000003C00000003C0038003800000;
- char[43] <= 256'h00000038000000000000000380000000000000003C00000003C0038003800000;
- char[44] <= 256'h00000038000000000000000380000000000000003C00000003C0038007000000;
- char[45] <= 256'h00000038000000000000000380000000000000003C00000001C0038007000000;
- char[46] <= 256'h000000780000000000000003800000000000000C3C00000001C00383FF800000;
- char[47] <= 256'h0000007800000000000000038000000000000007FC000000008003FFFF800000;
- char[48] <= 256'h0000007800000000000000018000000000000003F8000000000001FF80000000;
- char[49] <= 256'h0000003800000000000000018000000000000001F80000000000018000000000;
- char[50] <= 256'h0000003800000000000000018000000000000000F80000000000010000000000;
- char[51] <= 256'h0000001000000000000000010000000000000000F00000000000000000000000;
- char[52] <= 256'h0000000000000000000000010000000000000000600000000000000000000000;
- char[53] <= 256'h0000000000000000000000010000000000000000000000000000000000000000;
- char[54] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[55] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[56] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[57] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[58] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[59] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[60] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[61] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[62] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- char[63] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
- end
-
- //pix_data
- always @(posedge clk_25 or negedge rst_n)begin
- if(!rst_n)begin
- pix_data <= BLACK;
- end
- else if(((pix_x >= CHAR_B_H-1)&&(pix_x < (CHAR_B_H + CHAR_W-1)))
- &&((pix_y >= CHAR_B_V)&&(pix_y < (CHAR_B_V + CHAR_H)))
- &&(char[char_x][char_y] == 1'b1))begin
- pix_data <= GOLDEN;
- end
- else begin
- pix_data <= BLACK;
- end
- end
- endmodule
④ VGA仿真模块:
- /*==================================*
- filename : vga_top_tb.v
- description : VGA顶层模块仿真
- time : 2022-12-28
- author : 卡夫卡与海
- *===================================*/
- `timescale 1ns/1ns
-
- module vga_top_tb();
- reg clk ;//50MHZ
- reg rst_n ;
-
- wire hsync ;
- wire vsync ;
- wire [15:0] vga_rgb ;
-
- //产生时钟、复位
- initial begin
- clk = 1'b1;
- rst_n = 1'b0;
- #20
- rst_n = 1'b1;
- end
- always #10 clk = ~clk;
- //模块例化
- vga_char_top u_vga_char_top(
- /*input */.clk (clk ),//系统时钟
- /*input */.rst_n (rst_n ),//复位
- /*output */.vga_hsync (hsync ),//行同步信号
- /*output */.vga_vsync (vsync ),//场同步信号
- /*output [15:0] */.vga_rgb (vga_rgb) //数据输出(红绿蓝)
- );
- endmodule
由于我这里设备问题,这次就没有进行上板验证了,接下来也就是绑定引脚进行上板验证就可以了,感兴趣的小伙伴可自行上板,看看效果如何,哈哈!
本篇文章是在上一篇的基础上进行改进的,有许多原理性的内容可以参考上一篇文章,这里只是完成了上次遗留下来的问题罢了。字符显示的原理也是很清晰的,最重要的就是要抓住字符显示的范围,以及对字符显示进行赋值操作,和彩条显示原理差不多。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。