文章目录
一、VGA协议二、实现1、创建项目2、时钟分频3、提取字模4、图片显示
三、代码实现1、VGA Driver2、数据显示模块3、按键消抖4、顶层模块5、TCL引脚绑定脚本
四、RTL原理图五、实现效果六、总结七、参考资料
本次实验所需工具:
链接:
https://pan.baidu.com/s/1VYLHUd4uXtw_9jGiLIKaig?pwd=u1d5
提取码:u1d5
一、VGA协议
VGA(Video Graphics Array)视频图形阵列是 IBM 于1987年提出的一个使用模拟信号的电脑显示标准。VGA具有分辨率高、显示速率快、颜色丰富等优点。VGA 接口不但是CRT 显示设备的标准接口,同样也是 LCD 液晶显示设备的标准接口,具有广泛的应用范围。使用原理:显示器扫描方式分为逐行扫描和隔行扫描:逐行扫描是扫描从屏幕左上角一点开始,从左向右逐点扫描,每扫描完一行,电子束回到屏幕的左边下一行的起始位置,在这期间,每行结束时,用行同步信号进行同步;当扫描完所有的行,形成一帧,用场同步信号进行场同步,并使扫描回到屏幕左上方,开始下一帧。隔行扫描是指电子束扫描时每隔一行扫一线,完成一屏后在返回来扫描剩下的线,隔行扫描的显示器闪烁的厉害,会让使用者的眼睛疲劳。在此我们选择逐行扫描的方式。
二、实现
1、创建项目
首先,利用Quartus Ⅱ创建相关项目,具体可参照博主以前的博客。
2、时钟分频
按照下图所示在IP核中搜索PLL,并进行时钟分频 ![在这里插入图片描述](https://img-blog.csdnimg.cn/53af9a614d2d4ccb9e667606ecfc272b.png)
基础时钟选择50M:
![在这里插入图片描述](https://img-blog.csdnimg.cn/6ecac4551f3c48b6849e3f02d053525b.png)
取消勾选输出
![在这里插入图片描述](https://img-blog.csdnimg.cn/5140db569d1940289b492d95cb064959.png)
c0默认输出50M即可,c1分频到25M,如需其他时钟频率可以自己进行设置
![在这里插入图片描述](https://img-blog.csdnimg.cn/d23b729d33cf4e2ebf82553a1ea5c0f6.png)
勾选如下选项后finish
![在这里插入图片描述](https://img-blog.csdnimg.cn/cb672eae1cd34b6c9b52fda5daa26f9e.png)
3、提取字模
在字模提取工具里面输入需要显示的字符并设置字符大小为64*64 ![在这里插入图片描述](https://img-blog.csdnimg.cn/c01ed72de23f476ba5acbe9055da3817.png)
点击左上角文件->另存为BMP文件
![在这里插入图片描述](https://img-blog.csdnimg.cn/cf9c72b9e38f4bb79067ecfd388dfd60.png)
再点击文件-打开,把保存的BMP图片打开得到整体的字符 再点击选项按如下参数设置
![在这里插入图片描述](https://img-blog.csdnimg.cn/fb57a9d018964e7fb7288676e05ac08e.png)
最后点击生成字模并保存字模为文本文件
![在这里插入图片描述](https://img-blog.csdnimg.cn/65d0c351076d4ba4bd53530dd86c145d.png)
4、图片显示
显示图片前需要使用工具把图片转为HEX文件,同时图片分辨率不能太高,否则会超出FPGA储存上限 转换工具设置如下(该工具只可转换24位图片): 由于图片数据太多因此需要使用ROM来存储数据 操作如下: 打开Quartus,在左侧工具栏搜索ROM ![在这里插入图片描述](https://img-blog.csdnimg.cn/85d964173b544766a2f7b027d28c09f4.png)
点击后创建文件名
在弹出的设置界面,选择图片位数,图片内存大小为各位选择图片的分辨率大小,例:10×10的图片,则选择100
![在这里插入图片描述](https://img-blog.csdnimg.cn/f249ba279795452ea1cd03d44d3860e5.png)
取消勾选下列选项
![在这里插入图片描述](https://img-blog.csdnimg.cn/03fc11cb2be44a0497ff3b01de20f477.png)
找到刚才生成的图片文件: ![在这里插入图片描述](https://img-blog.csdnimg.cn/1bf7e5d38fce49b0b4519561ae314a12.png)
最后勾选以下选项
![在这里插入图片描述](https://img-blog.csdnimg.cn/2162999941db4a588d587e52b41fbc02.png)
三、代码实现
1、VGA Driver
module vga_dirve (input wire clk, //系统时钟
input wire rst_n, //复位
input wire [ 15:0 ] rgb_data, //16位RGB对应值
output wire vga_clk, //vga时钟 25M
output reg h_sync, //行同步信号
output reg v_sync, //场同步信号
output reg [ 11:0 ] addr_h, //行地址
output reg [ 11:0 ] addr_v, //列地址
output wire [ 4:0 ] rgb_r, //红基色
output wire [ 5:0 ] rgb_g, //绿基色
output wire [ 4:0 ] rgb_b //蓝基色
);
// 640 * 480 60HZ
localparam H_FRONT = 16; // 行同步前沿信号周期长
localparam H_SYNC = 96; // 行同步信号周期长
localparam H_BLACK = 48; // 行同步后沿信号周期长
localparam H_ACT = 640; // 行显示周期长
localparam V_FRONT = 11; // 场同步前沿信号周期长
localparam V_SYNC = 2; // 场同步信号周期长
localparam V_BLACK = 31; // 场同步后沿信号周期长
localparam V_ACT = 480; // 场显示周期长
// 800 * 600 72HZ
// localparam H_FRONT = 40; // 行同步前沿信号周期长
// localparam H_SYNC = 120; // 行同步信号周期长
// localparam H_BLACK = 88; // 行同步后沿信号周期长
// localparam H_ACT = 800; // 行显示周期长
// localparam V_FRONT = 37; // 场同步前沿信号周期长
// localparam V_SYNC = 6; // 场同步信号周期长
// localparam V_BLACK = 23; // 场同步后沿信号周期长
// localparam V_ACT = 600; // 场显示周期长
localparam H_TOTAL = H_FRONT + H_SYNC + H_BLACK + H_ACT; // 行周期
localparam V_TOTAL = V_FRONT + V_SYNC + V_BLACK + V_ACT; // 列周期
reg [ 11:0 ] cnt_h ; // 行计数器
reg [ 11:0 ] cnt_v ; // 场计数器
reg [ 15:0 ] rgb ; // 对应显示颜色值
// 对应计数器开始、结束、计数信号
wire flag_enable_cnt_h ;
wire flag_clear_cnt_h ;
wire flag_enable_cnt_v ;
wire flag_clear_cnt_v ;
wire flag_add_cnt_v ;
wire valid_area ;
// 25M时钟 行周期*场周期*刷新率 = 800 * 525* 60
wire clk_25 ;
// 50M时钟 1040 * 666 * 72
wire clk_50 ;
//PLL
pll pll_inst (
.areset ( ~rst_n ),
.inclk0 ( clk ),
.c0 ( clk_50 ), //50M
.c1 ( clk_25 ), //25M
);
//根据不同分配率选择不同频率时钟
assign vga_clk = clk_25;
// 行计数
always @( posedge vga_clk or negedge rst_n ) begin
if ( !rst_n ) begin
cnt_h |