实验三:VGA显示实验
实验三 VGA显示实验报告
目录
- 实验目的
- 实验内容
- 原理描述
- Verilog HDL设计源代码
- Testbench仿真代码及仿真结果
- XDC文件配置
- 下板测试
- 实验体会
实验目的
利用VGA接口,在显示屏上显示横条纹和彩色棋盘格。
实验内容
原理描述
vga介绍
VGA(Video Graphics Array)主要用于老式CRT显示器,核心原理是通过加热阴极发射电子,经过聚焦和偏转,最终击打在涂有三色荧光粉的屏幕上发光。VGA接口有15针,分三排,每排五个。本实验用到RGB彩色分量信号和HSYNC(行同步)、VSYNC(场同步)信号。
- HSYNC:行同步信号,单位为像素。
- VSYNC:场同步信号,单位为行。
- RGB:红绿蓝三基色信号。
时序
- 行时序以像素为单位,利用计数器按像素时钟计满后清零,再拉低同步信号。
- 场时序以行为单位,行计数器满一行,场计数器加1,满一场后清零,再拉低同步信号。
数据显示
在Hor Active Video和Ver Active Video均有效期间,向RGB分量送数据,即可在屏幕显示图案。FPGA输出的RGB为数字信号,通过电阻网络或数模转换芯片转换为模拟信号输出。FPGA输出的RGB三基色共16位,Red占5位、Green占6位、Blue占5位。
注意事项
- 行时序是“像素”为单位,场时序是“行”为单位。
- VGA工业标准要求同步信号为负极性(负脉冲)。
- 行、场时序有具体的同步、消隐、有效、前肩等规范。
Verilog HDL设计源代码
`timescale 1ns / 1ps
//
// Company:
// Engineer:
//
// Create Date: 2023/04/29 17:06:31
// Design Name:
// Module Name: vga
// Project Name:
// Target Devices:
// Tool Versions:
// Description: VGA显示横条纹、竖条纹和彩色棋盘格
//
//module vga(input clock, // 系统输入时钟 100MHzinput [1:0] switch, // 显示内容选择output [2:0] disp_RGB,// VGA 数据输出output hsync, // VGA 行同步信号output vsync // VGA 场同步信号
);reg [9:0] hcount; // 行扫描计数器
reg [9:0] vcount; // 场扫描计数器
reg [2:0] data;
reg [2:0] h_dat;
reg [2:0] v_dat;
reg [1:0] cnt;
wire hcount_ov;
wire vcount_ov;
wire dat_act;
reg vga_clk;// VGA时序参数
parameter hsync_end = 10'd95,hdat_begin = 10'd143,hdat_end = 10'd783,hpixel_end = 10'd799,vsync_end = 10'd1,vdat_begin = 10'd34,vdat_end = 10'd514,vline_end = 10'd524;// 4分频
always @(posedge clock) beginif(cnt == 3) begincnt <= 1;vga_clk <= ~vga_clk;end elsecnt <= cnt + 1;
end// 行扫描
always @(posedge vga_clk) beginif(hcount_ov)hcount <= 10'd0;elsehcount <= hcount + 10'd1;
end
assign hcount_ov = (hcount == hpixel_end);// 场扫描
always @(posedge vga_clk) beginif(hcount_ov) beginif(vcount_ov)vcount <= 10'd0;elsevcount <= vcount + 10'd1;end
end
assign vcount_ov = (vcount == vline_end);// 数据、同步信号输出
assign dat_act = ((hcount >= hdat_begin) && (hcount < hdat_end)) &&((vcount >= vdat_begin) && (vcount < vdat_end));
assign hsync = (hcount > hsync_end);
assign vsync = (vcount > vsync_end);
assign disp_RGB = (dat_act) ? data : 3'h00;// 显示数据处理
always @(posedge vga_clk) begincase(switch[1:0])2'd0: data <= h_dat; // 横彩条2'd1: data <= v_dat; // 竖彩条2'd2: data <= (v_dat ^ h_dat); // 棋盘格2'd3: data <= (v_dat ~^ h_dat);// 棋盘格endcase
end// 竖彩条
always @(posedge vga_clk) beginif(hcount < 223)v_dat <= 3'h7; // 白else if(hcount < 303)v_dat <= 3'h6; // 黄else if(hcount < 383)v_dat <= 3'h5; // 青else if(hcount < 463)v_dat <= 3'h4; // 绿else if(hcount < 543)v_dat <= 3'h3; // 紫else if(hcount < 623)v_dat <= 3'h2; // 红else if(hcount < 703)v_dat <= 3'h1; // 蓝elsev_dat <= 3'h0; // 黑
end// 横彩条
always @(posedge vga_clk) beginif(vcount < 94)h_dat <= 3'h7; // 白else if(vcount < 154)h_dat <= 3'h6; // 黄else if(vcount < 214)h_dat <= 3'h5; // 青else if(vcount < 274)h_dat <= 3'h4; // 绿else if(vcount < 334)h_dat <= 3'h3; // 紫else if(vcount < 394)h_dat <= 3'h2; // 红else if(vcount < 454)h_dat <= 3'h1; // 蓝elseh_dat <= 3'h0; // 黑
endendmodule
Testbench仿真代码及仿真结果
module testbench();reg clk;reg [1:0] switch;wire [2:0] disp_RGB;wire hsync;wire vsync;vga uut(.clock(clk),.switch(switch),.disp_RGB(disp_RGB),.hsync(hsync),.vsync(vsync));initial beginclk = 0;switch = 2'b00;repeat(10000) begin#5 clk = ~clk;end$stop;endalways @(posedge clk) begin$display("switch=%b, hsync=%b, vsync=%b, disp_RGB=%b", switch, hsync, vsync, disp_RGB);end
endmodule
XDC文件配置
set_property IOSTANDARD LVCMOS33 [get_ports {disp_RGB[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {disp_RGB[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {disp_RGB[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {switch[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {switch[0]}]
set_property PACKAGE_PIN A4 [get_ports {disp_RGB[2]}]
set_property PACKAGE_PIN A6 [get_ports {disp_RGB[1]}]
set_property PACKAGE_PIN D8 [get_ports {disp_RGB[0]}]
set_property PACKAGE_PIN V10 [get_ports {switch[1]}]
set_property PACKAGE_PIN U11 [get_ports {switch[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports clock]
set_property IOSTANDARD LVCMOS33 [get_ports hsync]
set_property IOSTANDARD LVCMOS33 [get_ports vsync]
set_property PACKAGE_PIN E3 [get_ports clock]
set_property PACKAGE_PIN B11 [get_ports hsync]
set_property PACKAGE_PIN B12 [get_ports vsync]
下板测试
- Switch=00:显示横彩条
- Switch=01:显示竖彩条
- Switch=10:显示棋盘格(异或实现)
- Switch=11:显示棋盘格(同或实现)
实验体会
-
理清原理与整体流程
在实验过程中首当其冲的是搞清楚实验原理,这里有vga显示原理,信号传输原理以及行,场扫描,其次就是脑子里有个大概框架,要知道第一步实现什么,第二步实现什么,这样会使我们的代码更有条理性,而且在这个实验中养成了一个很好的习惯就是加一段长长的注释符,并写上下面这一段代码的作用,使得代码已读易懂,方便后面发现错误时改错。 -
代码注释和模块化习惯
在遇到问题时多思考,本来我的打算是写两个实验来满足老师显示竖条纹和棋盘格,但是前面的时序功能都一样,所以就加一个选择信号Switch[1:0],来实现一个实验显示竖条纹和棋盘格。这里棋盘格的实现是用了异或。 -
善用选择信号优化设计
遇到功能需求时,不必重复写多个实验,只需通过switch信号选择即可,如本实验用switch切换横条、竖条和棋盘格。 -
基础功能需熟练掌握
计数器和分频是很基础和重要的功能,在FPGA开发中必不可少,需要熟练掌握分频器和计数器,在设计分频器时可以自己拿笔在纸上选取几个时钟进行分析。 -
硬件代码无debug,思路和细节更重要
硬件描述代码没有debug功能,我们需要理清我们的思路,注意细节,尽量减少低级错误,以减少改代码的工作量。 -
分析与优化分频器
多分析分频原理,第二种分频方法是通过纸面分析得到的,虽然一开始有些困难,但实践后更易理解。
主要是计数三个周期后赋值为1而不是0。
附:实验相关代码和配置见上方各小节,可直接用于开发板实现与仿真验证。