Verilog实现VGA字符显示
实现目标
在显示器中以640*480的分辨率显示0-9、A-Z、‘:’、‘*’的任意字符,字符大小为7*8的像素规模。
实现原理
1、基本的VGA显示
所有VGA显示差不多都是基于下面这一段Verilog代码的,时钟分频、行同步信号hs、场同步信号vs、rgb颜色值,这些都是必不可少的,还要注意的是对于640*480的分辨率,显示器真正可显示的区域为行计数介于31~510、列计数介于144~783之间(实际上对不同的显示器可能会有几个像素的差异),在这个范围之外都必须把rgb值设置为全0,否则会对显示造成干扰。
下面代码效果为在显示器屏幕中央显示一个绿色矩形方块。
// vga_display.v `timescale 1ns / 1ps module vga_display( input clk, input rst, output reg [2:0] r, output reg [2:0] g, output reg [1:0] b, output hs, output vs ); // 显示器可显示区域 parameter UP_BOUND = 31; parameter DOWN_BOUND = 510; parameter LEFT_BOUND = 144; parameter RIGHT_BOUND = 783; // 屏幕中央的矩形方块 parameter up_pos = 211; parameter down_pos = 330; parameter left_pos = 384; parameter right_pos = 543; wire pclk; reg [1:0] count; reg [9:0] hcount, vcount; // 获得像素时钟25MHz assign pclk = count[1]; always @ (posedge clk or posedge rst) begin if (rst) count <= 0; else count <= count+1; end // 列计数与行同步 assign hs = (hcount < 96) ? 0 : 1; always @ (posedge pclk or posedge rst) begin if (rst) hcount <= 0; else if (hcount == 799) hcount <= 0; else hcount <= hcount+1; end // 行计数与场同步 assign vs = (vcount < 2) ? 0 : 1; always @ (posedge pclk or posedge rst) begin if (rst) vcount <= 0; else if (hcount == 799) begin if (vcount == 520) vcount <= 0; else vcount <= vcount+1; end else vcount <= vcount; end // 设置显示信号值 always @ (posedge pclk or posedge rst) begin if (rst) begin r <= 0; g <= 0; b <= 0; end else if (vcount>=UP_BOUND && vcount<=DOWN_BOUND && hcount>=LEFT_BOUND && hcount<=RIGHT_BOUND) begin if (vcount>=up_pos && vcount<=down_pos && hcount>=left_pos && hcount<=right_pos) begin r <= 3'b000; g <= 3'b111; b <= 2'b00; end else begin r <= 3'b000; g <= 3'b000; b <= 2'b00; end end else begin r <= 3'b000; g <= 3'b000; b <= 2'b00; end end endmodule
2、基于RAM和字模的VGA显示
我们都知道电脑有显存,它存储了显示器每个像素应该显示的rgb颜色值,显存不断被刷新,于是可以显示动态的图像。基于此,最简单的想法就是可以在Verilog里面定义一个640*480的8位寄存器二维数组作为VGA显示的显存,然后在reset信号使能的时候对每个数组单元赋值,这样我们就用一个数组存储了一幅静态图像,然后在VGA扫描显示的时候,分别根据寄存器数组的值来设置各个像素的rgb值。
显然,上面的方法是可行的,只不过工程浩大,难以实现!试想,要在屏幕显示一个7*8的字符就要分别设置56个寄存器的值,而且每个寄存器都要根据不同的字符设置不同的值,这是多么可怕的事情!
除此之外,可以考虑通过一个通用的RAM_set模块来一次性设置一个字符对应的寄存器的值。以显示两个字符为例(字符颜色白色,背景黑色),通过Verilog声明一个长度为14的8位寄存器数组reg [7:0] p[13:0],因为两个字符占用2*7*8=14*8个像素,所以p[i][j]=0表示第i+1列第j+1行像素为黑色,反之1为白色。这样的话,就可以分别把p[13:7]、p[6:0]通过RAM_set来设置。RAM_set模块可以根据要显示的不同字符的字模给寄存器赋不同的值。
图1 常见字符字模图
实现代码
下面的代码实现在显示器屏幕中央显示两个字符"3D"。
// vga_char_display.v `timescale 1ns / 1ps module vga_char_display( input clk, input rst, output reg [2:0] r, output reg [2:0] g, output reg [1:0] b, output hs, output vs ); // 显示器可显示区域 parameter UP_BOUND = 31; parameter DOWN_BOUND = 510; parameter LEFT_BOUND = 144; parameter RIGHT_BOUND = 783; // 屏幕中央两个字符的显示区域 parameter up_pos = 267; parameter down_pos = 274; parameter left_pos = 457; parameter right_pos = 470; wire pclk; reg [1:0] count; reg [9:0] hcount, vcount; wire [7:0] p[13:0]; RAM_set u_ram_1 ( .clk(clk), .rst(rst), .data(6'b00_0011), .col0(p[0]), .col1(p[1]), .col2(p[2]), .col3(p[3]), .col4(p[4]), .col5(p[5]), .col6(p[6]) ); RAM_set u_ram_2 ( .clk(clk), .rst(rst), .data(6'b00_1101), .col0(p[7]), .col1(p[8]), .col2(p[9]), .col3(p[10]), .col4(p[11]), .col5(p[12]), .col6(p[13]) ); // 获得像素时钟25MHz assign pclk = count[1]; always @ (posedge clk or posedge rst) begin if (rst) count <= 0; else count <= count+1; end // 列计数与行同步 assign hs = (hcount < 96) ? 0 : 1; always @ (posedge pclk or posedge rst) begin if (rst) hcount <= 0; else if (hcount == 799) hcount <= 0; else hcount <= hcount+1; end // 行计数与场同步 assign vs = (vcount < 2) ? 0 : 1; always @ (posedge pclk or posedge rst) begin if (rst) vcount <= 0; else if (hcount == 799) begin if (vcount == 520) vcount <= 0; else vcount <= vcount+1; end else vcount <= vcount; end // 设置显示信号值 always @ (posedge pclk or posedge rst) begin if (rst) begin r <= 0; g <= 0; b <= 0; end else if (vcount>=UP_BOUND && vcount<=DOWN_BOUND && hcount>=LEFT_BOUND && hcount<=RIGHT_BOUND) begin if (vcount>=up_pos && vcount<=down_pos && hcount>=left_pos && hcount<=right_pos) begin if (p[hcount-left_pos][vcount-up_pos]) begin r <= 3'b111; g <= 3'b111; b <= 2'b11; end else begin r <= 3'b000; g <= 3'b000; b <= 2'b00; end end else begin r <= 3'b000; g <= 3'b000; b <= 2'b00; end end else begin r <= 3'b000; g <= 3'b000; b <= 2'b00; end end endmodule
// RAM_set.v `timescale 1ns / 1ps module RAM_set( input clk, input rst, input [5:0] data, output reg [7:0] col0, output reg [7:0] col1, output reg [7:0] col2, output reg [7:0] col3, output reg [7:0] col4, output reg [7:0] col5, output reg [7:0] col6 ); always @(posedge clk or negedge rst) begin if (!rst) begin col0 <= 8'b0000_0000; col1 <= 8'b0000_0000; col2 <= 8'b0000_0000; col3 <= 8'b0000_0000; col4 <= 8'b0000_0000; col5 <= 8'b0000_0000; col6 <= 8'b0000_0000; end else begin case (data) 6'b00_0000: // "0" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1110; col2 <= 8'b0101_0001; col3 <= 8'b0100_1001; col4 <= 8'b0100_0101; col5 <= 8'b0011_1110; col6 <= 8'b0000_0000; end 6'b00_0001: // "1" begin col0 <= 8'b0000_0000; col1 <= 8'b0000_0000;; col2 <= 8'b0100_0010; col3 <= 8'b0111_1111; col4 <= 8'b0100_0000; col5 <= 8'b0000_0000;; col6 <= 8'b0000_0000; end 6'b00_0010: // "2" begin col0 <= 8'b0000_0000; col1 <= 8'b0100_0010; col2 <= 8'b0110_0001; col3 <= 8'b0101_0001; col4 <= 8'b0100_1001; col5 <= 8'b0100_0110; col6 <= 8'b0000_0000; end 6'b00_0011: // "3" begin col0 <= 8'b0000_0000; col1 <= 8'b0010_0010; col2 <= 8'b0100_0001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0011_0110; col6 <= 8'b0000_0000; end 6'b00_0100: // "4" begin col0 <= 8'b0000_0000; col1 <= 8'b0001_1000; col2 <= 8'b0001_0100; col3 <= 8'b0001_0010; col4 <= 8'b0111_1111; col5 <= 8'b0001_0000; col6 <= 8'b0000_0000; end 6'b00_0101: // "5" begin col0 <= 8'b0000_0000; col1 <= 8'b0010_0111; col2 <= 8'b0100_0101; col3 <= 8'b0100_0101; col4 <= 8'b0100_0101; col5 <= 8'b0011_1001; col6 <= 8'b0000_0000; end 6'b00_0110: // "6" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1110; col2 <= 8'b0100_1001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0011_0010; col6 <= 8'b0000_0000; end 6'b00_0111: // "7" begin col0 <= 8'b0000_0000; col1 <= 8'b0110_0001; col2 <= 8'b0001_0001; col3 <= 8'b0000_1001; col4 <= 8'b0000_0101; col5 <= 8'b0000_0011; col6 <= 8'b0000_0000; end 6'b00_1000: // "8" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_0110; col2 <= 8'b0100_1001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0011_0110; col6 <= 8'b0000_0000; end 6'b00_1001: // "9" begin col0 <= 8'b0000_0000; col1 <= 8'b0010_0110; col2 <= 8'b0100_1001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0011_1110; col6 <= 8'b0000_0000; end 6'b00_1010: // "A" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1100; col2 <= 8'b0001_0010; col3 <= 8'b0001_0001; col4 <= 8'b0001_0010; col5 <= 8'b0111_1100; col6 <= 8'b0000_0000; end 6'b00_1011: // "B" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0100_1001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0011_0110; col6 <= 8'b0000_0000; end 6'b00_1100: // "C" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1110; col2 <= 8'b0100_0001; col3 <= 8'b0100_0001; col4 <= 8'b0100_0001; col5 <= 8'b0010_0010; col6 <= 8'b0000_0000; end 6'b00_1101: // "D" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0100_0001; col3 <= 8'b0100_0001; col4 <= 8'b0100_0001; col5 <= 8'b0011_1110; col6 <= 8'b0000_0000; end 6'b00_1110: // "E" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0100_1001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0100_0001; col6 <= 8'b0000_0000; end 6'b00_1111: // "F" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0000_1001; col3 <= 8'b0000_1001; col4 <= 8'b0000_1001; col5 <= 8'b0000_0001; col6 <= 8'b0000_0000; end 6'b01_0000: // "G" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1110; col2 <= 8'b0100_0001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0011_1010; col6 <= 8'b0000_0000; end 6'b01_0001: // "H" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0000_1000; col3 <= 8'b0000_1000; col4 <= 8'b0000_1000; col5 <= 8'b0111_1111; col6 <= 8'b0000_0000; end 6'b01_0010: // "I" begin col0 <= 8'b0000_0000; col1 <= 8'b0000_0000; col2 <= 8'b0100_0001; col3 <= 8'b0111_1111; col4 <= 8'b0100_0001; col5 <= 8'b0000_0000; col6 <= 8'b0000_0000; end 6'b01_0011: // "J" begin col0 <= 8'b0000_0000; col1 <= 8'b0010_0000; col2 <= 8'b0100_0001; col3 <= 8'b0100_0001; col4 <= 8'b0011_1111; col5 <= 8'b0000_0001; col6 <= 8'b0000_0000; end 6'b01_0100: // "K" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0000_1000; col3 <= 8'b0001_0100; col4 <= 8'b0010_0010; col5 <= 8'b0100_0001; col6 <= 8'b0000_0000; end 6'b01_0101: // "L" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0100_0000; col3 <= 8'b0100_0000; col4 <= 8'b0100_0000; col5 <= 8'b0100_0000; col6 <= 8'b0000_0000; end 6'b01_0110: // "M" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0000_0010; col3 <= 8'b0000_1100; col4 <= 8'b0000_0010; col5 <= 8'b0111_1111; col6 <= 8'b0000_0000; end 6'b01_0111: // "N" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0000_0010; col3 <= 8'b0000_0100; col4 <= 8'b0000_1000; col5 <= 8'b0111_1111; col6 <= 8'b0000_0000; end 6'b01_1000: // "O" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1110; col2 <= 8'b0100_0001; col3 <= 8'b0100_0001; col4 <= 8'b0100_0001; col5 <= 8'b0011_1110; col6 <= 8'b0000_0000; end 6'b01_1001: // "P" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0000_1001; col3 <= 8'b0000_1001; col4 <= 8'b0000_1001; col5 <= 8'b0000_0110; col6 <= 8'b0000_0000; end 6'b01_1010: // "Q" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1110; col2 <= 8'b0100_0001; col3 <= 8'b0101_0001; col4 <= 8'b0110_0001; col5 <= 8'b0111_1110; col6 <= 8'b0000_0000; end 6'b01_1011: // "R" begin col0 <= 8'b0000_0000; col1 <= 8'b0111_1111; col2 <= 8'b0000_1001; col3 <= 8'b0001_1001; col4 <= 8'b0010_1001; col5 <= 8'b0100_0110; col6 <= 8'b0000_0000; end 6'b01_1100: // "S" begin col0 <= 8'b0000_0000; col1 <= 8'b0010_0110; col2 <= 8'b0100_1001; col3 <= 8'b0100_1001; col4 <= 8'b0100_1001; col5 <= 8'b0011_0010; col6 <= 8'b0000_0000; end 6'b01_1101: // "T" begin col0 <= 8'b0000_0000; col1 <= 8'b0000_0001; col2 <= 8'b0000_0001; col3 <= 8'b0111_1111; col4 <= 8'b0000_0001; col5 <= 8'b0000_0001; col6 <= 8'b0000_0000; end 6'b01_1110: // "U" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1111; col2 <= 8'b0100_0000; col3 <= 8'b0100_0000; col4 <= 8'b0100_0000; col5 <= 8'b0011_1111; col6 <= 8'b0000_0000; end 6'b01_1111: // "V" begin col0 <= 8'b0000_0000; col1 <= 8'b0001_1111; col2 <= 8'b0010_0000; col3 <= 8'b0100_0000; col4 <= 8'b0010_0000; col5 <= 8'b0001_1111; col6 <= 8'b0000_0000; end 6'b10_0000: // "W" begin col0 <= 8'b0000_0000; col1 <= 8'b0011_1111; col2 <= 8'b0100_0000; col3 <= 8'b0011_0000; col4 <= 8'b0100_0000; col5 <= 8'b0011_1111; col6 <= 8'b0000_0000; end 6'b10_0001: // "X" begin col0 <= 8'b0000_0000; col1 <= 8'b0110_0011; col2 <= 8'b0001_0100; col3 <= 8'b0000_1000; col4 <= 8'b0001_0100; col5 <= 8'b0110_0011; col6 <= 8'b0000_0000; end 6'b10_0010: // "Y" begin col0 <= 8'b0000_0000; col1 <= 8'b0000_0011; col2 <= 8'b0000_0100; col3 <= 8'b0111_1000; col4 <= 8'b0000_0100; col5 <= 8'b0000_0011; col6 <= 8'b0000_0000; end 6'b10_0011: // "Z" begin col0 <= 8'b0000_0000; col1 <= 8'b0110_0001; col2 <= 8'b0101_0001; col3 <= 8'b0100_1001; col4 <= 8'b0100_0101; col5 <= 8'b0100_0011; col6 <= 8'b0000_0000; end 6'b11_1110: // " " begin col0 <= 8'b0000_0000; col1 <= 8'b0000_0000; col2 <= 8'b0000_0000; col3 <= 8'b0000_0000; col4 <= 8'b0000_0000; col5 <= 8'b0000_0000; col6 <= 8'b0000_0000; end 6'b11_1111: // ":" begin col0 <= 8'b0000_0000; col1 <= 8'b0000_0000; col2 <= 8'b0011_0110; col3 <= 8'b0011_0110; col4 <= 8'b0000_0000; col5 <= 8'b0000_0000; col6 <= 8'b0000_0000; end default: // "*" begin col0 <= 8'b0000_0000; col1 <= 8'b0010_0010; col2 <= 8'b0001_0100; col3 <= 8'b0000_1000; col4 <= 8'b0001_0100; col5 <= 8'b0010_0010; col6 <= 8'b0000_0000; end endcase end end endmodule
相关推荐
在这个实验中,“fpga 实现vga字符显示”是一个利用FPGA来驱动VGA显示器,实现字符显示的技术。VGA(Video Graphics Array)是传统的计算机显示器接口,常见于各种个人电脑上。在这里,我们将探讨如何通过FPGA控制...
标题中的“基于Verilog的VGA显示汉字字符的例子”指的是使用Verilog硬件描述语言实现的在VGA(Video Graphics Array)显示器上显示汉字字符的技术。Verilog是一种广泛使用的硬件描述语言,用于设计数字电子系统,...
通过以上各个步骤,我们可以实现一个基于FPGA的VGA字符显示系统,不仅展示了数字逻辑设计的基本原理,也体现了嵌入式系统设计的实际应用。这样的项目对于学习FPGA设计和数字系统构建具有很高的实践价值。
【FPGA VGA字符显示】是电子工程领域中一个常见的实践项目,主要涉及到数字逻辑设计、硬件描述语言(如VHDL或Verilog)以及视频显示技术。在这个项目中,FPGA(Field-Programmable Gate Array)作为核心处理器,通过...
本项目“fpga-Verilog-图片-文字vga显示”涉及了如何使用FPGA通过Verilog语言实现VGA(Video Graphics Array)显示器来显示图片和文字,这是数字系统设计中的一个重要实践。 VGA是一种广泛使用的显示接口标准,它...
本文档是一个用于生成 VGA 字符显示的数字电路设计,使用 Verilog HDL 语言编写,目标设备为 Cyclone EP1C3T144C8 FPGA。该设计主要实现了 VGA 视频接口的控制和字符显示。 知识点1:VGA 视频接口 * VGA 视频接口...
内容摘要:请看csdn博文 csdn博文链接如下: ... 注意!注意!...3、图像字符叠加,利用VGA时序的特点,在图像指定位置叠加字符,视频实时输出; 4、纯verilog实现实时时钟计数,并叠加到输出视频中;
FPGA设计VGA接口显示字符Verilog设计Quartus工程源码文件,FPGA型号Cyclone4E系列中的EP4CE10F17C8,Quartus版本18.0。 module vga_char( input sys_clk, //系统时钟 input sys_rst_n, //复位信号 //VGA接口 ...
为了实现字符显示,本研究采用了Verilog硬件描述语言来设计时序逻辑和字符存储器。通过这种方式,可以在较为简单的条件下实现字符显示,同时降低了硬件成本。此外,通过微小的改动即可适应不同的分辨率需求,极大地...
在本项目中,我们关注的是如何使用FPGA(Field-Programmable Gate Array)通过Verilog语言实现VGA(Video Graphics Array)图像和字符显示。VGA是一种标准的视频显示接口,广泛应用于显示器与计算机之间的连接,能...
这个实验的目标是使用Verilog语言来实现VGA(Video Graphics Array)显示器上汉字的显示。Verilog是一种硬件描述语言,它允许工程师以类似于编程语言的方式描述数字系统的逻辑和行为。下面将详细阐述这一实验涉及的...
ISE13.2下的VGA格子显示程序 verilog
在Verilog中实现VGA,需要编写代码来生成合适的行同步、场同步信号,以及像素数据,以驱动VGA显示器显示图像。VGA显示图片自动切换功能意味着设计中可能包含帧缓冲区和定时控制器,以在不同图像间平滑过渡。 3. ...
基于FPGA的VGA接口实现和字符显示_贾伟伟.caj 基于FPGA的VGA接口显示技术_刘占军.caj 基于FPGA的VGA控制原理_薛枫 - 副本.caj 基于FPGA的VGA控制原理_薛枫.caj 基于FPGA的VGA显示实验方法_徐吉锋.caj 基于FPGA的实时...
本话题聚焦于如何使用Verilog通过VGA(Video Graphics Array)接口在屏幕上显示一个汉字,具体设置为800x600分辨率,刷新率为72Hz。 VGA是一种模拟显示接口标准,最初由IBM引入,至今仍被许多显示器支持。它定义了...
在“VGA显示hello world和彩条verilog代码”这个项目中,我们将探讨如何使用Verilog来实现一个简单的VGA(Video Graphics Array)显示器驱动,展示“hello world”文本以及彩色条纹。 VGA是广泛使用的模拟显示标准...
本项目“基于FPGA(DE2)的VGA汉字显示”利用DE2开发板,结合VGA(Video Graphics Array,视频图形阵列)技术,实现了在电脑显示屏上动态显示汉字的功能。 VGA是一种模拟显示标准,广泛应用于显示器与计算机之间的...
标题中的“fpga字符OSD显示VGA输出例子”指的是一个使用FPGA(Field-Programmable Gate Array)实现字符Over-Lay(OSD)显示在VGA(Video Graphics Array)输出上的示例项目。这个项目对于FPGA初学者来说是...
在这个名为“VGA_text.rar_VGA Text_vga verilog”的压缩包中,我们可以看到一个用Verilog语言实现的VGA文本显示项目。Verilog是一种硬件描述语言,常用于数字电路设计,包括FPGA(Field-Programmable Gate Array)...