当前位置:   article > 正文

【FPGA】十、VGA字符显示_vga显示字符

vga显示字符

文章目录

前言

一、实验任务

二、字符取模

三、程序设计

总结


前言

        我们在上一篇文章中已经对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字符显示顶层模块:

  1. /*====================================*
  2. filename : vga_char_top.v
  3. description : VGA字符显示顶层模块
  4. time : 2022-12-29
  5. author : 卡夫卡与海
  6. *=====================================*/
  7. module vga_char_top(
  8. input clk ,//系统时钟
  9. input rst_n ,//复位
  10. output vga_hsync ,//行同步信号
  11. output vga_vsync ,//场同步信号
  12. output [15:0] vga_rgb //数据输出(红绿蓝)
  13. );
  14. //信号定义
  15. wire vga_clk ;//vga工作时钟 25MHZ
  16. wire locked ;
  17. wire vga_reset ;
  18. wire [9:0] pix_x ;
  19. wire [9:0] pix_y ;
  20. wire [15:0] pix_data ;
  21. assign vga_reset = rst_n && locked;
  22. //模块例化
  23. //PLL
  24. CLK_PLL CLK_PLL_inst (
  25. .areset (~rst_n ),
  26. .inclk0 (clk ),
  27. .c0 (vga_clk),
  28. .locked (locked )
  29. );
  30. //vga控制模块
  31. vga_control u_vga_control(
  32. /*input */.clk_25 (vga_clk ),//时钟 25MHZ
  33. /*input */.rst_n (vga_reset),//复位
  34. /*input [15:0] */.pix_data (pix_data ),//输入图像数据
  35. /*output [9:0] */.pix_x (pix_x ),//横坐标
  36. /*output [9:0] */.pix_y (pix_y ),//纵坐标
  37. /*output */.hsync (vga_hsync),//行同步信号
  38. /*output */.vsync (vga_vsync),//场同步信号
  39. /*output [15:0] */.vga_rgb (vga_rgb ) //输出图像数据(RGB565格式)
  40. );
  41. //vga显示模块
  42. vga_display u_vga_display(
  43. /*input */.clk_25 (vga_clk ),//VGA驱动时钟
  44. /*input */.rst_n (vga_reset),//复位
  45. /*input [9:0] */.pix_x (pix_x ),//横坐标
  46. /*input [9:0] */.pix_y (pix_y ),//纵坐标
  47. /*output reg [15:0] */.pix_data (pix_data ) //数据
  48. );
  49. endmodule

② VGA控制模块:

  1. /*===============================*
  2. filename : vga_control.v
  3. description : VGA控制模块
  4. time : 2022-12-28
  5. author : 卡夫卡与海
  6. *================================*/
  7. module vga_control(
  8. input clk_25 ,//时钟 25MHZ
  9. input rst_n ,//复位
  10. input [15:0] pix_data ,//输入图像数据
  11. output [9:0] pix_x ,//横坐标
  12. output [9:0] pix_y ,//纵坐标
  13. output hsync ,//行同步信号
  14. output vsync ,//场同步信号
  15. output [15:0] vga_rgb //输出图像数据(RGB565格式)
  16. );
  17. //参数定义
  18. //显示模式:640*480@60
  19. parameter H_SYNC = 96 ,//行同步
  20. H_BACK = 48 ,//行显示后沿
  21. H_DISP = 640,//行有效数据
  22. H_FRONT = 16 ,//行显示前沿
  23. H_TOTAL = 800;//行扫描周期
  24. parameter V_SYNC = 2 ,//场同步
  25. V_BACK = 33 ,//场显示后沿
  26. V_DISP = 480,//场有效数据
  27. V_FRONT = 10 ,//场显示前沿
  28. V_TOTAL = 525;//场扫描周期
  29. //信号定义
  30. reg [9:0] cnt_h ;//行计数器
  31. reg [9:0] cnt_v ;//场计数器
  32. wire rgb_vaild ;//数据有效信号
  33. wire data_req ;//数据请求信号
  34. //cnt_h
  35. always @(posedge clk_25 or negedge rst_n)begin
  36. if(!rst_n)begin
  37. cnt_h <= 10'd0;
  38. end
  39. else begin
  40. if(cnt_h < H_TOTAL - 1)begin
  41. cnt_h <= cnt_h + 1'b1;
  42. end
  43. else begin
  44. cnt_h <= 10'd0;
  45. end
  46. end
  47. end
  48. //cnt_v
  49. always @(posedge clk_25 or negedge rst_n)begin
  50. if(!rst_n)begin
  51. cnt_v <= 10'd0;
  52. end
  53. else if(cnt_h == H_TOTAL - 1)begin
  54. if(cnt_v < V_TOTAL - 1)begin
  55. cnt_v <= cnt_v + 1'b1;
  56. end
  57. else begin
  58. cnt_v <= 10'd0;
  59. end
  60. end
  61. end
  62. //rgb_vaild 数据输出有效信号
  63. assign rgb_vaild = ((cnt_h >= H_BACK + H_SYNC)
  64. &&(cnt_h < H_SYNC + H_BACK + H_DISP)
  65. &&(cnt_v >= V_SYNC + V_BACK)
  66. &&(cnt_v < V_SYNC + V_BACK + V_DISP))
  67. ? 1'b1 : 1'b0;
  68. //data_req 像素点颜色数据输入请求信号
  69. assign data_req = (((cnt_h >= H_SYNC + H_BACK - 1)
  70. && (cnt_h < H_SYNC + H_BACK + H_DISP - 1))
  71. && ((cnt_v >= V_SYNC + V_BACK)
  72. && (cnt_v < V_SYNC + V_BACK + V_DISP)))
  73. ? 1'b1 : 1'b0;
  74. //输出
  75. //pix_x 横坐标
  76. assign pix_x = (data_req==1'b1)?(cnt_h - (H_SYNC+H_BACK-1)):10'h3ff;
  77. //pix_y 纵坐标
  78. assign pix_y = (data_req==1'b1)?(cnt_v - (V_SYNC+V_BACK-1)):10'h3ff;
  79. //hsync
  80. assign hsync = (cnt_h <= H_SYNC - 1) ? 1'b0 : 1'b1;
  81. //vsync
  82. assign vsync = (cnt_v <= V_SYNC - 1) ? 1'b0 : 1'b1;
  83. //vga_rgb
  84. assign vga_rgb = (rgb_vaild == 1'b1) ? pix_data : 16'd0;
  85. endmodule

③ VGA显示模块:

  1. /*===============================*
  2. filename : vga_display.v
  3. description : VGA显示模块
  4. time : 2022-12-29
  5. author : 卡夫卡与海
  6. *================================*/
  7. module vga_display(
  8. input clk_25 ,//VGA驱动时钟
  9. input rst_n ,//复位
  10. input [9:0] pix_x ,//横坐标
  11. input [9:0] pix_y ,//纵坐标
  12. output reg [15:0] pix_data //数据
  13. );
  14. //参数定义
  15. parameter CHAR_B_H = 10'd192 ,//字符开始横坐标
  16. CHAR_B_V = 10'd208 ;//字符开始纵坐标
  17. parameter CHAR_W = 10'd256 ,//字符宽度
  18. CHAR_H = 10'd56 ;//字符深度
  19. //颜色参数 RGB565格式
  20. parameter BLACK = 16'h0000,//黑色(背景色)
  21. GOLDEN = 16'hFEC0;//金色(字符颜色)
  22. //信号定义
  23. wire [9:0] char_x ;//字符横坐标
  24. wire [9:0] char_y ;//字符纵坐标
  25. reg [255:0] char [63:0] ;
  26. //char_x
  27. assign char_x = (((pix_x >= CHAR_B_H)&&(pix_x < (CHAR_B_H + CHAR_W)))
  28. &&((pix_y >= CHAR_B_V)&&(pix_y < (CHAR_B_V + CHAR_H))))
  29. ? (pix_x - CHAR_B_H) : 10'h3ff;
  30. //char_y
  31. assign char_y = (((pix_x >= CHAR_B_H)&&(pix_x < (CHAR_B_H + CHAR_W)))
  32. &&((pix_y >= CHAR_B_V)&&(pix_y < (CHAR_B_V + CHAR_H))))
  33. ? (pix_y - CHAR_B_H) : 10'h3ff;
  34. //char
  35. always @(posedge clk_25)begin
  36. char[0] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  37. char[1] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  38. char[2] <= 256'h0000000000000000000000000000000000000020000000000000000000000000;
  39. char[3] <= 256'h000000C00000000000000030000000000000003C000000000000000000000000;
  40. char[4] <= 256'h000000F8000000000000003C000000000000003E000000000000000000000000;
  41. char[5] <= 256'h0000007C000000000000003E000000000000001C000000000000000E00000000;
  42. char[6] <= 256'h0000007C000000000000003C000000000000001C000000000000000F00000000;
  43. char[7] <= 256'h0000003C000000000000003C000000000000001C000000000000000F80000000;
  44. char[8] <= 256'h0000003C0000000000000078000000000000001C000000000000000F80000000;
  45. char[9] <= 256'h0000003C1F00000000000078000000000000001C1C000000000C000F00000000;
  46. char[10] <= 256'h0000003DFF80000000000070001F00000000001FFF000000000F000E00000000;
  47. char[11] <= 256'h0000003FFE000000000000701FFFC000000001FFFF000000000F801E1F000000;
  48. char[12] <= 256'h0000003FC0000000000000FFFFFFE00000007FFF800000000007C01FFF800000;
  49. char[13] <= 256'h0000003C0000000000007FFFFFFFC00000003FFC000000000003C03FFF800000;
  50. char[14] <= 256'h000000180000000000FFFFFC000000000000003800000000000180701F000000;
  51. char[15] <= 256'h0000001800000000007FFDC0000000000000003800000000000000701E000000;
  52. char[16] <= 256'h0000001800000000003E03C7800000000000007C00000000000000E01E000000;
  53. char[17] <= 256'h000000180000000000000383C000000000000077C0000000000001C03C000000;
  54. char[18] <= 256'h00000018007FC00000000783C0000000000000E3E00000000000038038000000;
  55. char[19] <= 256'h000000181FFFE00000000703C0000000000001C1F0000000000007F078000000;
  56. char[20] <= 256'h0000001FFFFFE00000000E03C000000000000380F00000000200083870000000;
  57. char[21] <= 256'h000001FFFFC0000000001E0380000000000007003000000007C0001EE0000000;
  58. char[22] <= 256'h0000FFFF0000000000001C038000000000000E00001FE00003F0000FE0000000;
  59. char[23] <= 256'h07FFFFF8000000000000380380E00000000038000FFFF00001F00003C0000000;
  60. char[24] <= 256'h07FFF07C0000000000007803BFF8000000004007FFFFF80000F00007E0000000;
  61. char[25] <= 256'h01FE003C0000000000007FFFFFFC000000000FFFFFF020000070000FF0000000;
  62. char[26] <= 256'h0000003C000000000000EFFFC07C0000007FFFFE780000000000000F7C000000;
  63. char[27] <= 256'h00000038000000000001CE03807C000007FFFC003C0000000000001E3E000000;
  64. char[28] <= 256'h00000018000000000003CE038078000003FC00003C0000000001003C1F800000;
  65. char[29] <= 256'h00000018E000000000078E03803800000000006038000000000200780FC00000;
  66. char[30] <= 256'h00000018F8000000000F0E0380380000000001F838000000000200F007F00000;
  67. char[31] <= 256'h000000187E000000001E0E038038000000039FFC38000000000601C001FC0000;
  68. char[32] <= 256'h000000183F000000003C0E03803800000001F83C38000000000C078000FF8000;
  69. char[33] <= 256'h000000181F80000000700E03807800000001C03838000000000C0F00007FF800;
  70. char[34] <= 256'h000000180FC0000000E00E03807800000001C0383800000000181C00003FF000;
  71. char[35] <= 256'h0000001807E0000001800E03907000000000C030380000000018780006000000;
  72. char[36] <= 256'h0000001803E0000007000E038FF000000000C070380000000038E0007F800000;
  73. char[37] <= 256'h0000001800E0000008001E0387F000000000C3F03C00000000730F1FFFE00000;
  74. char[38] <= 256'h000000180000000000001C0381F000000000FFF83C00000000F007FF03F00000;
  75. char[39] <= 256'h000000180000000000001C0381E000000000F0003C00000000E0078003F00000;
  76. char[40] <= 256'h000000180000000000000C0380C000000000C0003C00000003E0078003E00000;
  77. char[41] <= 256'h00000018000000000000080380800000000040003C00000003E0038003C00000;
  78. char[42] <= 256'h00000038000000000000000380000000000000003C00000003C0038003800000;
  79. char[43] <= 256'h00000038000000000000000380000000000000003C00000003C0038003800000;
  80. char[44] <= 256'h00000038000000000000000380000000000000003C00000003C0038007000000;
  81. char[45] <= 256'h00000038000000000000000380000000000000003C00000001C0038007000000;
  82. char[46] <= 256'h000000780000000000000003800000000000000C3C00000001C00383FF800000;
  83. char[47] <= 256'h0000007800000000000000038000000000000007FC000000008003FFFF800000;
  84. char[48] <= 256'h0000007800000000000000018000000000000003F8000000000001FF80000000;
  85. char[49] <= 256'h0000003800000000000000018000000000000001F80000000000018000000000;
  86. char[50] <= 256'h0000003800000000000000018000000000000000F80000000000010000000000;
  87. char[51] <= 256'h0000001000000000000000010000000000000000F00000000000000000000000;
  88. char[52] <= 256'h0000000000000000000000010000000000000000600000000000000000000000;
  89. char[53] <= 256'h0000000000000000000000010000000000000000000000000000000000000000;
  90. char[54] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  91. char[55] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  92. char[56] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  93. char[57] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  94. char[58] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  95. char[59] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  96. char[60] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  97. char[61] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  98. char[62] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  99. char[63] <= 256'h0000000000000000000000000000000000000000000000000000000000000000;
  100. end
  101. //pix_data
  102. always @(posedge clk_25 or negedge rst_n)begin
  103. if(!rst_n)begin
  104. pix_data <= BLACK;
  105. end
  106. else if(((pix_x >= CHAR_B_H-1)&&(pix_x < (CHAR_B_H + CHAR_W-1)))
  107. &&((pix_y >= CHAR_B_V)&&(pix_y < (CHAR_B_V + CHAR_H)))
  108. &&(char[char_x][char_y] == 1'b1))begin
  109. pix_data <= GOLDEN;
  110. end
  111. else begin
  112. pix_data <= BLACK;
  113. end
  114. end
  115. endmodule

④ VGA仿真模块:

  1. /*==================================*
  2. filename : vga_top_tb.v
  3. description : VGA顶层模块仿真
  4. time : 2022-12-28
  5. author : 卡夫卡与海
  6. *===================================*/
  7. `timescale 1ns/1ns
  8. module vga_top_tb();
  9. reg clk ;//50MHZ
  10. reg rst_n ;
  11. wire hsync ;
  12. wire vsync ;
  13. wire [15:0] vga_rgb ;
  14. //产生时钟、复位
  15. initial begin
  16. clk = 1'b1;
  17. rst_n = 1'b0;
  18. #20
  19. rst_n = 1'b1;
  20. end
  21. always #10 clk = ~clk;
  22. //模块例化
  23. vga_char_top u_vga_char_top(
  24. /*input */.clk (clk ),//系统时钟
  25. /*input */.rst_n (rst_n ),//复位
  26. /*output */.vga_hsync (hsync ),//行同步信号
  27. /*output */.vga_vsync (vsync ),//场同步信号
  28. /*output [15:0] */.vga_rgb (vga_rgb) //数据输出(红绿蓝)
  29. );
  30. endmodule

        由于我这里设备问题,这次就没有进行上板验证了,接下来也就是绑定引脚进行上板验证就可以了,感兴趣的小伙伴可自行上板,看看效果如何,哈哈!


总结

        本篇文章是在上一篇的基础上进行改进的,有许多原理性的内容可以参考上一篇文章,这里只是完成了上次遗留下来的问题罢了。字符显示的原理也是很清晰的,最重要的就是要抓住字符显示的范围,以及对字符显示进行赋值操作,和彩条显示原理差不多。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/799338
推荐阅读
相关标签
  

闽ICP备14008679号