Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >FPGA VGA显示协议

FPGA VGA显示协议

原创
作者头像
AnieaLanie
修改于 2022-06-07 03:38:20
修改于 2022-06-07 03:38:20
1.5K00
代码可运行
举报
文章被收录于专栏:铁子的专栏铁子的专栏
运行总次数:0
代码可运行

FPGA VGA显示协议

协议原理简述

协议包含的信号:HS行同步信号,VS场同步信号,RGB三种颜色信号一共5种信号。

RGB分为RGB888,RGB565和RGB332三种不同长度的颜色信号,RGB888表示红绿蓝三个信号各占8个比特,RGB则红绿蓝分别占5,6,5个比特。

VGA协议扫描屏幕的顺序是从左到右,从上到下,从左上到右下。

根据VGA协议的定义,VGA的行同步信号HSYNC,在每一行开始时产生一个高电平脉冲,场同步信号在每一帧开始时产生一个高电平脉冲。

行同步(横轴),场同步(纵轴),以及它们会产生的脉冲信号:

VGA协议各种信号的参数来源,根据数据手册(640x480,60HZ和75HZ):

程序实现

时钟分频模块

640x480像素的VGA协议所需时钟频率25MHZ,使用clk IP核进行时钟分频

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//端口定义  
module vga_colorbar_top(
       input    wire                sys_clk ,
       input    wire                sys_rst,
       
       output   wire                vga_hs,         // 输出到vga接口的行同步信号
       output   wire                vga_vs,         // 输出到vga接口的场同步信号
       output   wire    [15:0]  vga_rgb         // 输出到vga接口的像素数据
);// 25MHZ时钟信号定义
wire clk_w ;
​
pll_clk pll_25MHz(
    .inclk0 (sys_clk), // (输入)50MHZ基准时钟
    .c3     (clk_w) // (输出)25MHZ分频时钟
 );

VGA驱动模块

计数信号:

pixel_hpos用来计算当前刷新到了哪一行,pixel_vpos用来计算当前刷新到了哪一列。当刷新到640列时vga_vs产生脉冲1,当刷新倒480行时vga_hs产生脉冲1。

图像数据(加载外部图像数据):pixel_data[15:0],其中[4:0]是蓝色,[10:5]是绿色,[15:11]是红色

vga_rgb[15:0]表示输出RGB颜色信号,接入到显示器的信号

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 对变量的声明
module vga_driver(
    input   wire            clk_25MHz,  //时钟,25MHZ
    input   wire                rst, // 复位信号,低电平有效
    input   wire        [15:0]  pixel_data, //RGB--565,即pixel_data[15:11]控制R、pixel_data[10:5]控制G、pixel_data[4:0]控制B
    
    output  wire        [  9:0] pixel_hpos, //pixel_data的行坐标
    output  wire        [  9:0] pixel_vpos, //pixel_data的列坐标
    output  wire                vga_hs,     //行同步信号
    output  wire                vga_vs,     //列同步信号
    output  wire        [15:0]  vga_rgb     //输出到VGA接口的颜色数据
);//内部参量定义,vga时序参数60HZ
parameter           H_SYNC      = 10'd96;   // 同步期
parameter           H_BACK      = 10'd48;   // 显示后沿
parameter           H_DISP      = 10'd640;      // 显示区域
parameter           H_FRONT     = 10'd16;   // 显示前沿
parameter           H_PRIOD     = 10'd800;      // 行周期总长度
 
parameter           V_SYNC      = 10'd2;        // 同步期
parameter           V_BACK      = 10'd33;   // 显示后沿
parameter           V_DISP      = 10'd480;     // 显示区域
parameter           V_FRONT     = 10'd10;   // 显示前沿
parameter           V_PRIOD = 10'd525;  // 列周期总长度//内部参量定义,vga时序参数75HZ
//parameter           H_SYNC    = 10'd64;   // 同步期
//parameter           H_BACK    = 10'd120;  // 显示后沿
//parameter           H_DISP    = 10'd640;      // 显示区域
//parameter           H_FRONT   = 10'd16;   // 显示前沿
//parameter           H_PRIOD   = 10'd840;      // 行周期总长度
// 
//parameter           V_SYNC    = 10'd3;        // 同步期
//parameter           V_BACK    = 10'd16;   // 显示后沿
//parameter           V_DISP    = 10'd480;     // 显示区域
//parameter           V_FRONT   = 10'd1;    // 显示前沿
//parameter           V_PRIOD   = 10'd500;  // 列周期总长度// 确定像素当前坐标
assign  pixel_hpos = pixel_data_require ? (cnt_h - (H_SYNC + H_BACK - 1'b1)) : 10'd0;
assign  pixel_vpos = pixel_data_require ? (cnt_v - (V_SYNC + V_BACK - 1'b1)) : 10'd0;// 确定像素数据
assign vga_rgb = vga_en ? pixel_data:16'd0;

输出颜色竖条

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 判断当前坐标的像素数据
always @ (posedge clk_25MHz or negedge rst)begin
    if(!rst)begin
        // pixel_data <= 16'd0;
        pixel_data <= BLACK;
    end
    else begin
        if(pic_area == 1'b0)begin
            if (pixel_hpos >= 0 && pixel_hpos <= (H_DISP / 5) * 1)
                pixel_data <= WHITE;
            else if (pixel_hpos >= (H_DISP / 5) * 1 && pixel_hpos < (H_DISP / 5) * 2)
                pixel_data <= BLACK;
            else if (pixel_hpos >= (H_DISP / 5) * 2 && pixel_hpos < (H_DISP / 5) * 3)
                pixel_data <= RED;
            else if (pixel_hpos >=(H_DISP / 5) * 3 && pixel_hpos < (H_DISP / 5) * 4)
                pixel_data <= GREEN;
            else
                pixel_data <= BLUE;
        end
    end
end

写入图片,显示姓名

利用RAM存储图片数据,读取成VGA像素数据,并显示到显示器上

第一步,利用matlab或者软件将图片转化为mif文件

然后利用RAM IP核加载mif图片:

RAM IP核需要根据图片大小配置参数,RAM IP核具体参数配置如下:https://blog.csdn.net/qq_37899920/article/details/123594833

实例化RAM核,并且将图片显示出来

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 例化RAM
reg [13:0]wraddr;
reg [12:0]rdaddr;
reg rden;
reg wren;
reg [7:0]wrdata;
wire [15:0]rddata;RAM RAM1(
        .data(wrdata),
        .rdaddress(rdaddr),
        .rdclock(clk_25MHz),
        .rden(rden),
        .wraddress(wraddr),
        .wrclock(clk_25MHz),
        .wren(wren),
        .q(rddata)
    );
    
// 确定RAM读使能信号
always@(posedge clk_25MHz or negedge rst)begin
    if(!rst)begin
        rden <= 1'b0;
    end
    else begin
        rden <= 1'b1;
    end
end
​
// 确定RAM读地址信号
always@(posedge clk_25MHz or negedge rst)begin
    if(!rst)begin
        rdaddr <= 13'd0;
    end
    else begin
        if(pic_area == 1'b1)begin
            rdaddr <=(pixel_hpos - PIC_HPOS) + ((pixel_vpos == 10'd0)?16'd0:((pixel_vpos - 1'b1)* PIC_WIDTH));
        end
    end
end
​
// 确定RAM写端口的各信号
always@(*)begin
    wraddr <= 14'd0;
    wren <= 1'b0;
    wrdata <= 8'd0;
end
​
// 判断当前坐标的像素数据
always @ (posedge clk_25MHz or negedge rst)begin
    if(!rst)begin
        pixel_data <= BLACK;
    end
    else begin
        if(pic_area == 1'b0)begin
            if (pixel_hpos >= 0 && pixel_hpos <= (H_DISP / 5) * 1)
                pixel_data <= WHITE;
            else if (pixel_hpos >= (H_DISP / 5) * 1 && pixel_hpos < (H_DISP / 5) * 2)
                pixel_data <= BLACK;
            else if (pixel_hpos >= (H_DISP / 5) * 2 && pixel_hpos < (H_DISP / 5) * 3)
                pixel_data <= RED;
            else if (pixel_hpos >=(H_DISP / 5) * 3 && pixel_hpos < (H_DISP / 5) * 4)
                pixel_data <= GREEN;
            else
                pixel_data <= BLUE;
        end
        else begin
            pixel_data <= rddata; // 显示图片
        end
    end
end

若加入延时信号

行同步信号控制电子束从右侧返回起点,而场同步信号控制电子束从底部返回起点。

在两个信号的回扫时间内,不传输图像,此时显示器不显示图像。

在640 * 480,25MHZ显示周期中,每一行扫描所需周期约为800 * 1/(25 * 10^6)s = 32us,每一帧所需扫描周期约为800 * 525 * 1 /(25 * 10^6)s = 16.8ms。

行消隐信号

每次行或列扫描完成后,是同步信号的回扫时间,分别在行列方向产生一条移动的同步带,这条带内,显示器不显示图像(全黑)。

为了让同步带消失,要让它叠加在消隐信号之上。

当不同步时,行同步带出现在下一行的开始,场同步带出现在下一帧的开始。行同步带从右移动到左边,表示行同步信号回扫完毕,列同步带从下边移动到上边,表示场同步信号回扫完毕。

延时设计

设计行延时1.2us,场延时1ms,各占行场周期的一部分。

通过节拍计数器延时:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// VGA行场同步信号计数器
reg         [9:0]   cnt_h;
reg         [9:0]   cnt_v;
reg         [9:0]   cnt_h2; // 用于延时
reg         [9:0]   cnt_v2; // 用于延时// 节拍器,手动延时
reg [14:0] jiepai = 0;
reg [14:0] jiepai2 = 0;
reg startyanshi = 0;
reg startyanshi2 = 0;// 行列计数
always @ (posedge clk_25MHz or negedge rst) begin
    if (!rst) begin
        cnt_h <= 10'd0;
        cnt_h2 <= 10'd0;
        jiepai <= 10'd0;
        startyanshi <= 1;
    end
    else begin
        if(startyanshi==1) begin
            if(jiepai==1) begin // 前半段延时30*(1/(25*10^6)) = 1.2*10^-6s = 1.2us
                jiepai <= 0;
                startyanshi <= 0; // 一次延时结束(一行的开头的延时结束)// 节拍器和cnt_h2计数之间会有一个错误的上升沿的延时,消去它
                if (cnt_h2 <= H_PRIOD - 1'b1) begin
                    cnt_h2 <= cnt_h2 + 1'b1;
                end
                else begin
                    cnt_h2 <= 10'd0;
                end
                
            end
            else jiepai <= jiepai+1;
        end
        else begin // 后半段
            if (cnt_h2 <= H_PRIOD - 1'b1) begin
                cnt_h2 <= cnt_h2 + 1'b1;
            end
            else begin
                cnt_h2 <= 10'd0;
                jiepai <= 10'd0;
                startyanshi <= 1; // 每行开头(结束)重置延时
            end
        end
​
        if (cnt_h <= H_PRIOD - 1'b1) begin
            cnt_h <= cnt_h + 1'b1;
        end
        else begin
            cnt_h <= 10'd0;
        end
    end
end
​
always @ (posedge clk_25MHz or negedge rst) begin
    if(!rst)begin
        cnt_v <= 10'd0;
        cnt_v2 <= 10'd0;
        jiepai2 <= 10'd0;
        startyanshi2 <= 1;
    end
    else begin
        if(startyanshi2==1) begin
            if(jiepai2==2500) begin // 前半段延时25000*(1/(25*10^6)) = 1*10^-3s = 1ms
                jiepai2 <= 0;
                startyanshi2 <= 0; // 一次延时结束(一行的开头的延时结束)
            end
            else jiepai2 <= jiepai2+1;
        end
        else begin
            if (cnt_h == H_PRIOD - 1'b1) begin
                if(cnt_v2 <= V_PRIOD - 1'b1)
                    cnt_v2 <= cnt_v2 + 1'b1;
                else begin
                    cnt_v2 <= 10'd0;
                    jiepai2 <= 10'd0;
                    startyanshi2 <= 1; // 每行开头(结束)重置延时
                end
            end
        end
​
        if (cnt_h == H_PRIOD - 1'b1) begin
            if(cnt_v <= V_PRIOD - 1'b1)
                cnt_v <= cnt_v + 1'b1;
            else begin
                cnt_v <= 10'd0;
            end
        end
    end
end

显示效果:

给场同步信号添加延时1ms:

给场同步信号添加延时1ms
给场同步信号添加延时1ms

给场同步信号添加延时1ms,行同步信号添加延时1us:

给场同步信号添加延时1ms,行同步信号添加延时1us
给场同步信号添加延时1ms,行同步信号添加延时1us

参考

[1] 咸鱼FPGA.VGA协议 cnblogs

[2] Kevin.VGA显示器驱动

[3] 星河带悦流.FPGA实现VGA接口——保存图片至ROM/RAM显示 csdn

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
FPGA零基础学习:图像显示系统设计
大侠好,欢迎来到FPGA技术江湖。本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2021/03/23
5230
FPGA零基础学习:图像显示系统设计
FPGA零基础学习:VGA协议驱动设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2021/03/23
1.1K0
FPGA零基础学习:VGA协议驱动设计
源码系列:基于FPGA的VGA驱动设计(附源工程)
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
FPGA技术江湖
2020/12/29
1K0
源码系列:基于FPGA的VGA驱动设计(附源工程)
Verilog——基于FPGA的贪吃蛇游戏(VGA显示)
最近在做Verilog程序课设,做了一个有关贪吃蛇的小游戏,写一篇博客来记录一下自己的创作过程。大部分的内容直接采用了设计报告的原话,有不足之处还望大家多多指教。
全栈程序员站长
2022/07/31
2.7K0
基于FPGA的VGA/LCD显示控制器系统设计(中)
今天给大侠带来基于FPGA的VGA/LCD显示控制器设计,由于篇幅较长,分三篇。今天带来第二篇,中篇,VGA 显示原理以及VGA/LCD 显示控制器的基本框架,话不多说,上货。
FPGA技术江湖
2021/05/21
1.6K0
基于FPGA的VGA/LCD显示控制器系统设计(中)
基于FPGA的HDMI显示(二)
  本次设计采用了 IO 模拟的方式实现 HDMI 的功能。与采用专用 HDMI 芯片相比,此方案具有成本更低、效果不输于采用专用芯片的效果、经过测试,兼容性方面也要比专用芯片要好、最大输出图像分辨率 1080P、图像传输稳定等显著的优势。   具体硬件电路上面已经提到过了,这里简单分析一下。
碎碎思
2020/06/30
3.6K0
基于FPGA的实时图像边缘检测系统设计(下)
今天给大侠带来基于FPGA的实时图像边缘检测系统设计,由于篇幅较长,分三篇。今天带来第三篇,下篇,话不多说,上货。
FPGA技术江湖
2021/04/19
7150
基于FPGA的实时图像边缘检测系统设计(下)
学员学习笔记分享:FPGA之HDMI、以太网篇
高清多媒体接口(High Definition Multimedia Interface)是一种全数字化视频和声音发送接口,可以发送未压缩的音频及视频信号。HDMI可用于机顶盒、DVD播放机、个人计算机、电视、游戏主机、综合扩大机、数字音响与电视机等设备。HDMI可以同时发送音频和视频信号,由于音频和视频信号采用同一条线材,大大简化系统线路的安装难度。
FPGA技术江湖
2023/04/03
6800
学员学习笔记分享:FPGA之HDMI、以太网篇
【FPGA实验】数码管动态显示
静态显示: 每一个管脚都用固定的一个电平去控制。 优点:能够做到”同时” 缺点:管脚太多
zstar
2022/06/14
6910
【FPGA实验】数码管动态显示
基于FPGA的VGA/LCD显示控制器系统设计(下)
今天给大侠带来基于FPGA的VGA/LCD显示控制器设计,由于篇幅较长,分三篇。今天带来第三篇,下篇,程序的仿真与测试以及总结,话不多说,上货。
FPGA技术江湖
2021/05/21
7630
基于FPGA的5寸LCD显示屏的显示控制
数字图像处理是指将图像信号转换成数字信号并利用计算机对其进行处理的过程。图像处理最早出现于 20 世纪 50 年代,当时的电子计算机已经发展到一定水平,人们开始利用计算机来处理图形和图像信息。数字图像处理作为一门学科大约形成于 20 世纪 60 年代初期。早期的图像处理的目的是改善图像的质量,它以人为对象,以改善人的视觉效果为目的。图像处理中,输入的是质量低的图像,输出的是改善质量后的图像,常用的图像处理方法有图像增强、复原、编码、压缩等。
FPGA开源工作室
2019/10/29
1.8K0
基于FPGA的5寸LCD显示屏的显示控制
FPGA零基础学习:SDR SDRAM 驱动设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2020/12/30
8050
FPGA零基础学习:SDR SDRAM 驱动设计
FPGA零基础学习:UART协议驱动设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2021/03/23
8960
FPGA零基础学习:UART协议驱动设计
源码系列:基于FPGA的数字电压表(AD)设计
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
FPGA技术江湖
2020/12/29
1.5K0
源码系列:基于FPGA的数字电压表(AD)设计
【FPGA】课程设计:简单计时器闹钟
视频地址:https://live.csdn.net/v/embed/213189
zstar
2022/06/14
1.2K0
【FPGA】课程设计:简单计时器闹钟
源码系列:基于FPGA的电子琴设计(附源工程)
大侠好,欢迎来到FPGA技术江湖,江湖偌大,相见即是缘分。大侠可以关注FPGA技术江湖,在“闯荡江湖”、"行侠仗义"栏里获取其他感兴趣的资源,或者一起煮酒言欢。
FPGA技术江湖
2020/12/29
1.8K1
源码系列:基于FPGA的电子琴设计(附源工程)
FPGA实现的SPI协议(二)—-基于SPI接口的FLASH芯片M25P16的使用「建议收藏」
FPGA实现的SPI协议(二)—-基于SPI接口的FLASH芯片M25P16的使用
全栈程序员站长
2022/11/03
1.5K0
FPGA实现的SPI协议(二)—-基于SPI接口的FLASH芯片M25P16的使用「建议收藏」
FPGA零基础学习之Vivado-RTC实时时钟系统设计
本系列将带来FPGA的系统性学习,从最基本的数字电路基础开始,最详细操作步骤,最直白的言语描述,手把手的“傻瓜式”讲解,让电子、信息、通信类专业学生、初入职场小白及打算进阶提升的职业开发者都可以有系统性学习的机会。
FPGA技术江湖
2023/08/22
5040
FPGA零基础学习之Vivado-RTC实时时钟系统设计
FPGA实现uart_FPGA的EMU接口
UART即通用异步收发传输接口(Universal Asynchronous Receiver/Transmitter),简称串口,是一种常用的通信接口,其协议原理就不赘述了,不了解的可以自己查阅资料。(不赘述不代表不重要,相反,对于每一个FPGA设计,充分理解原理是基础和前提,而FPGA和Verilog只是工具。)用FPGA来实现UART,关键就是要将UART收发数据时的时序用Verilog描述出来。
全栈程序员站长
2022/10/05
7140
FPGA实现uart_FPGA的EMU接口
【收藏】FPGA数字IC刷题58个Verilog代码及讲解(状态机、跨时钟、同步/异步FIFO、DMUX、奇数/小数分频)
牛客 Verilog 刷题入门篇1~24 + 进阶篇1~34 题解代码,所有代码均能通过测试,配合视频讲解效果更佳。本文给出代码,部分题目给出必要说明。 很多题目本身出题有些问题,着重理解题目,没必要钻牛角尖。
FPGA探索者
2022/11/01
2.9K0
【收藏】FPGA数字IC刷题58个Verilog代码及讲解(状态机、跨时钟、同步/异步FIFO、DMUX、奇数/小数分频)
推荐阅读
相关推荐
FPGA零基础学习:图像显示系统设计
更多 >
LV.0
这个人很懒,什么都没有留下~
作者相关精选
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验