FPG—VGA显示器字符显示(附代码)

目录

1.实操

1.1 字符取模

1.2 顶层模块

1.3 图像数据生成模块

1.3.1 模块框图

1.3.2 波形图绘制

1.3.3 代码编写

1.3.4 仿真验证

2.总结

      本例程大部分与VGA显示驱动内容相同,只是显示部分改变了,故此主要讲显示字符的方法。如有对VGA显示驱动不了解的朋友,建议先看这篇 http://t.csdn.cn/QqQzi 。

      由之前讲VGA显示彩条的原理可知显示的本质就是点阵,将有用信息与背景色区分就可以显示信息,例如军训时很火的方阵以及平时见到的广告牌。

      实验目标:在 VGA 显示器中心位置显示金色“天天向上”四个字,字符外的背景颜色为黑色。每个汉字大小为 56*56, 字模点阵为 64*64, VGA 显示模式为 640*480@60。

1.实操

1.1 字符取模

字符取模的基本原理

      一般使用 0、 1 的组合来描述点阵,点阵中的每一个数据项表示单个像素点,我们使用单比特来表示,字符显示部分的数据项赋值为 1,非字符显示部分的数据项赋值为 0。这种赋值方式不包含颜色信息,只是区分点阵背景和字符信息。字符点阵示例,具体见下图。

字符取模操作流程

1. 生成一个整体字模

      打开字符取模软件“PCtoLCD2002”,设置相关参数,将点阵大小设置为 64*64,字宽*字高设置为 56*56,字体随意;在下方文字输入框中输入要显示字符“天天向上”;注意,此处先不要进行字模生成,因为此处生成字模会得到四个字符各自对应的字模,不方便后续代码编写。

      将生成的字符点阵保存为 BMP 图片格式,保存为 BMP格式的目的就是为了将四个单独字符合成一个整体。

    再返回读取保存的 BMP 图片,四个字符已合为一个整体。

2. 设置字模输出的相关参数,生成字模、保存字模

     将模式调为图形模式后,在点击 “选项” 按照下图所示, 设置字模输出的相关参数。

     生成字模、保存字模

 字模保存完毕,字模点阵大小为 256*64。

       注意(1)进行下一次的字模生成,要将模式调回 字符模式 后再进行相关参数设置,否则无法修改参数设置,(2)汉字占两个字节,数字、字母和特殊符号占两个字节,在配置点阵大小时需注意。

1.2 顶层模块

       顶层模块设计如下图。

       以上模块除图像数据生成模块,其他模块在前面发布的VGA 显示器驱动设计与验证文章中已经详细说明,故不重复。

1.3 图像数据生成模块

1.3.1 模块框图

        图像数据生成模块,模块功能是以 VGA 时序控制模块传入的图像有效显示区域像素点坐标(pix_x,pix_y)为约束条件, 产生 VGA 图像像素点色彩信息 pix_data 并回传给 VGA 时序控制模块。在字符显示区域 pi_data 赋值为金色,其他区域均为黑色。模块框图,具体见下图。
 

   图像数据生成模块包含 4 路输入、 1 路输出,共 5 路信号,输入输出信号简介,具体见下表。

1.3.2 波形图绘制

第一部分:输入信号

      本模块的输入信号包括四路,时钟信号、复位信号和 VGA 驱动控制模块传入的有效显示区域的坐标信号 pix_x、 pix_y。时钟信号和复位信号无需多说,对于坐标信号 pix_x、pix_y,在之前的文章有详细讲解,在此不再过多叙述。
  第二部分:字符点阵显示区域坐标信号的设计与实现
      首先确定字符有效显示区域,区域大小与字符点阵大小相同,显示区域的像素点与字模点阵中数据项对应,当字模点阵中的数据项数值为“1”时,赋值字符颜色给对应像素点;当字模点阵中的数据项数值为“0”时,赋值点阵背景颜色给对应像素点。所以为了确定字符点阵显示区域256*64
声明两个变量 char_x、 char_y,两变量组成字符点阵显示区域坐标,在字符点阵有效显示区域内, char_x 信号 0-255 循环计数, char_y信号 0-63 循环计数 ,根据坐标(char_x,char_y)寻找字符点阵对应的数据项,根据数据项的数值,赋予对应坐标像素点颜色信息。 char_x、 char_y 信号波形具体见下图。

 第三部分: 输出图像数据信号的波形设计与实现

       设计本模块的目的是生成 VGA 图像像素点色彩信息回传给 VGA 时序控制模块,我们声明像素点色彩信息 pix_data 信号。在字符点阵显示区域内、字符点阵数据项数值为“1”时, pix_data 根据为字符颜色;其他区域均赋值为背景色。

1.3.3 代码编写

`timescale  1ns/1ns

module  vga_pic
(
    input   wire            vga_clk     ,   
    input   wire            sys_rst_n   ,   
    input   wire    [9:0]   pix_x       ,   //输入有效显示区域像素点X轴坐标
    input   wire    [9:0]   pix_y       ,   //输入有效显示区域像素点Y轴坐标

    output  reg     [15:0]  pix_data        //输出像素点色彩信息
);

parameter   CHAR_B_H=   10'd192 ,   //字符开始X轴坐标
            CHAR_B_V=   10'd208 ;   //字符开始Y轴坐标

parameter   CHAR_W  =   10'd256 ,   //字符宽度
            CHAR_H  =   10'd64  ;   //字符高度

parameter   BLACK   =   16'h0000,   //黑色
            WHITE   =   16'hFFFF,   //白色
            GOLDEN  =   16'hFEC0;   //金色

wire    [9:0]   char_x  ;   //字符显示X轴坐标
wire    [9:0]   char_y  ;   //字符显示Y轴坐标

//reg   define
reg     [255:0] char    [63:0]  ;   //位宽  与  列高

//字符显示坐标,组合逻辑0-255
assign  char_x  =   (((pix_x >= CHAR_B_H) && (pix_x < (CHAR_B_H + CHAR_W)))   //pix_x < (CHAR_B_H + CHAR_W)也可以写成 pix_x <= (CHAR_B_H + CHAR_W -1'b1)
                    && ((pix_y >= CHAR_B_V) && (pix_y < (CHAR_B_V + CHAR_H))))  
                    ? (pix_x - CHAR_B_H) : 10'h3FF;
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_V) : 10'h3FF;

//char:“天天向上”字符数据(粘贴字模提取其中生成的数据)
always@(posedge vga_clk)
    begin
        char[0]     <=  256'h0000000000000000000000000000000000000000000000000000000000000000;
        char[1]     <=  256'h0000000000000000000000000000000000000000000000000000000000000000;
        char[2]     <=  256'h0000000000000000000000000000000000000080000000000000000000000000;
        char[3]     <=  256'h00000000000000000000000000000000000001E0000000000000008000000000;
        char[4]     <=  256'h00000000003000000000000000200000000001F000000000000000E000000000;
        char[5]     <=  256'h00000000007800000000000000300000000001E000000000000000FC00000000;
        char[6]     <=  256'h0000000000FC00000000000000780000000001C000000000000000F000000000;
        char[7]     <=  256'h00FFFFFFFFFE00000000000000FC00000000038000000000000000E000000000;
        char[8]     <=  256'h007FFFFFFFFF0000007FFFFFFFFE00000000038000000000000000E000000000;
        char[9]     <=  256'h003C00F80000000000200078000000000000030000000000000000E000000000;
        char[10]    <=  256'h000000F80000000000000078000000000000020000020000000000E000000000;
        char[11]    <=  256'h000000F80000000000000078000000000080060000030000000000E000000000;
        char[12]    <=  256'h000000F800000000000000700000000000E0040000078000000000E000000000;
        char[13]    <=  256'h000000F800000000000000700000000000FFFFFFFFFFC000000000E000000000;
        char[14]    <=  256'h000000F800000000000000700000000000E0000000078000000000E000000000;
        char[15]    <=  256'h000000F800000000000000700000000000E0000000070000000000E000000000;
        char[16]    <=  256'h000000F800000000000000700000000000E0000000070000000000E000000000;
        char[17]    <=  256'h000000F800000000000000700000000000E0000000070000000000E000000000;
        char[18]    <=  256'h000000F800000000000000700000000000E0000000070000000000E000100000;
        char[19]    <=  256'h000000F800000000000000700000000000E0000000070000000000E000380000;
        char[20]    <=  256'h000000F800070000000000700002000000E0000000070000000000E0007C0000;
        char[21]    <=  256'h000000F8000F8000000000700007000000E0000000070000000000E000FE0000;
        char[22]    <=  256'h000000F8001FC00000000070000F800000E0300010070000000000FFFFFF0000;
        char[23]    <=  256'h1FFFFFFFFFFFE00000000070001FC00000E038003C070000000000E000000000;
        char[24]    <=  256'h1FFFFFFFFFFFF0000FFFFFFFFFFFE00000E01FFFFC070000000000E000000000;
        char[25]    <=  256'h0F8001F700000000040000E20000000000E01C0038070000000000E000000000;
        char[26]    <=  256'h000001F700000000000000E20000000000E01C0038070000000000E000000000;
        char[27]    <=  256'h000001F700000000000000E20000000000E01C0038070000000000E000000000;
        char[28]    <=  256'h000001F380000000000001E30000000000E01C0038070000000000E000000000;
        char[29]    <=  256'h000003E380000000000001E10000000000E01C0038070000000000E000000000;
        char[30]    <=  256'h000003E380000000000001C18000000000E01C0038070000000000E000000000;
        char[31]    <=  256'h000003E1C0000000000001C18000000000E01C0038070000000000E000000000;
        char[32]    <=  256'h000007C1C0000000000003C0C000000000E01C0038070000000000E000000000;
        char[33]    <=  256'h000007C1E000000000000380C000000000E01C0038070000000000E000000000;
        char[34]    <=  256'h00000780E0000000000007806000000000E01C0038070000000000E000000000;
        char[35]    <=  256'h00000F80F0000000000007006000000000E01C0038070000000000E000000000;
        char[36]    <=  256'h00000F807800000000000F003000000000E01FFFF8070000000000E000000000;
        char[37]    <=  256'h00001F007800000000000E003800000000E01C0038070000000000E000000000;
        char[38]    <=  256'h00003E003C00000000001E001800000000E03C0038070000000000E000000000;
        char[39]    <=  256'h00003E003E00000000001C001C00000000E03C0038070000000000E000000000;
        char[40]    <=  256'h00007C001F000000000038000E00000000E0380000070000000000E000000000;
        char[41]    <=  256'h0000F8000F800000000070000F00000000E0200000070000000000E000000000;
        char[42]    <=  256'h0001F0000FC000000000E00007C0000000E0000000070000000000E000000000;
        char[43]    <=  256'h0003E00007F000000001E00003E0000000E0000000070000000000E000000000;
        char[44]    <=  256'h0007C00003F800000003800001F0000000E0000000070000000000E000008000;
        char[45]    <=  256'h000F800001FE00000007000000FC000000E0000000070000000000E00001C000;
        char[46]    <=  256'h001F000000FF8000000E0000007F000000E0000000070000000000E00003E000;
        char[47]    <=  256'h003E0000007FF000001C0000003FE00000E000000FFF0000000000E00007F000;
        char[48]    <=  256'h00780000003FFC0000300000001FF80000E0000003FF00001FFFFFFFFFFFF800;
        char[49]    <=  256'h01F00000001FF80000E00000000FE00000E00000007F00000800000000000000;
        char[50]    <=  256'h07C000000007C000018000000003C00000E00000003E00000000000000000000;
        char[51]    <=  256'h0F00000000038000060000000001800000E00000001C00000000000000000000;
        char[52]    <=  256'h1C00000000000000180000000000000000800000000000000000000000000000;
        char[53]    <=  256'h0000000000000000000000000000000000000000000000000000000000000000;
        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'h0000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000 00000;
    end

//pix_data:输出像素点色彩信息,根据当前像素点坐标指定当前像素点颜色数据
always@(posedge vga_clk or negedge sys_rst_n)
    if(sys_rst_n == 1'b0)
        pix_data    <= BLACK;
    else    if((((pix_x >= (CHAR_B_H ))  
                && (pix_x < (CHAR_B_H + CHAR_W )))  //pix_x提前打一拍 【191-446】
                && ((pix_y >= CHAR_B_V) && (pix_y < (CHAR_B_V + CHAR_H))))
                && (char[char_y][10'd255 - char_x] == 1'b1))  //二维数组,当像素点为1时给金色
        pix_data    <=  GOLDEN;
    else
        pix_data    <=  BLACK;

endmodule

代码重难点积累:

(1)复制字模时,以notepad++打开 .txt 文件,复制格式不会出错。

(2)2char[char_y][10'd255 - char_x] == 1'b1 使用二位数组定位要显示的像素点。

1.3.4 仿真验证

`timescale  1ns/1ns

module  tb_vga_colorbar();

wire            hsync       ;
wire    [15:0]  rgb         ;
wire            vsync       ;

//reg   define
reg             sys_clk     ;
reg             sys_rst_n   ;

initial
    begin
        sys_clk     =   1'b1;
        sys_rst_n   <=  1'b0;
        #200
        sys_rst_n   <=  1'b1;
    end

//sys_clk:产生时钟
always  #10 sys_clk = ~sys_clk  ;


vga_colorbar    vga_colorbar_inst
(
    .sys_clk    (sys_clk    ),  
    .sys_rst_n  (sys_rst_n  ),  

    .hsync      (hsync      ),  
    .vsync      (vsync      ),  
    .rgb        (rgb        )   
);

endmodule

2.总结

      设计思想在于显示有效区域是传输数据。

说明:

       本人使用的是野火家Xilinx Spartan6系列开发板及配套教程主要用于自我学习,以上内容如有疑惑或错误欢迎评论区指出,或者移步B站观看野火家视频教程。

开发软件:ise14.7     仿真:modelsim 10.5 

如需上述资料私信或留下邮箱。

  • 4
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论
VHDL(VHSIC硬件描述语言)是一种用于描述数字电路的硬件描述语言。要实现一个VGA显示图片的VHDL代码,需要考虑以下几个方面: 1. 分辨率设置:VGA的标准分辨率为640x480,因此需要定义一个足够大的像素缓冲区存储图片数据。 2. 图片加载:VHDL代码需要读取图像数据并将其加载到像素缓冲区中,可以通过读取图片文件或者在代码中硬编码来实现。 3. 时序控制:VGA显示需要精确控制水平同步(HSYNC)和垂直同步(VSYNC)信号的时序,以及行和列的扫描顺序。需要定义适当的计数器和状态机来生成这些时序信号。 4. 像素输出:根据VGA的时序信号,代码需要从像素缓冲区中读取适当的像素数据,并将其输出到视频输出接口。 以下是一个简单的VGA显示图片的VHDL代码示例: ```vhdl library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity VGA_Display is Generic ( WIDTH : integer := 640; HEIGHT : integer := 480; H_SYNC_PULSE : integer := 96; H_FRONT_PORCH : integer := 16; H_BACK_PORCH : integer := 48; V_SYNC_PULSE : integer := 2; V_FRONT_PORCH : integer := 10; V_BACK_PORCH : integer := 33 ); Port ( clk : in std_logic; vga_r : out std_logic_vector(3 downto 0); vga_g : out std_logic_vector(3 downto 0); vga_b : out std_logic_vector(3 downto 0); vga_hsync : out std_logic; vga_vsync : out std_logic ); end VGA_Display; architecture Behavioral of VGA_Display is signal h_count : integer range 0 to WIDTH - 1 := 0; signal v_count : integer range 0 to HEIGHT - 1 := 0; signal pixel_r : std_logic_vector(3 downto 0) := (others => '0'); signal pixel_g : std_logic_vector(3 downto 0) := (others => '0'); signal pixel_b : std_logic_vector(3 downto 0) := (others => '0'); begin process(clk) begin if rising_edge(clk) then if h_count = WIDTH - 1 then h_count <= 0; if v_count = HEIGHT - 1 then v_count <= 0; else v_count <= v_count + 1; end if; else h_count <= h_count + 1; end if; if h_count >= H_SYNC_PULSE + H_BACK_PORCH and h_count < H_SYNC_PULSE + H_BACK_PORCH + WIDTH and v_count >= V_SYNC_PULSE + V_BACK_PORCH and v_count < V_SYNC_PULSE + V_BACK_PORCH + HEIGHT then -- Get pixel data from the image buffer based on h_count and v_count -- Assign pixel data to pixel_r, pixel_g, pixel_b else pixel_r <= (others => '0'); pixel_g <= (others => '0'); pixel_b <= (others => '0'); end if; end if; end process; vga_r <= pixel_r; vga_g <= pixel_g; vga_b <= pixel_b; vga_hsync <= '1' when (h_count < H_SYNC_PULSE) else '0'; vga_vsync <= '1' when (v_count < V_SYNC_PULSE) else '0'; end Behavioral; ``` 以上代码是一个简单的VGA显示图片的VHDL代码示例,需要根据实际需求进行修改和完善。在代码的适当位置,需要添加读取图片数据的逻辑,以及与外部存储器或FPGA内存的接口。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

咖啡0糖

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

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

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

打赏作者

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

抵扣说明:

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

余额充值