基于VerilogHDL的VGA驱动设计

基于VerilogHDL的VGA驱动设计

VGA简介

VGA接口共有15针,分成3排,每排5个孔,显卡上应用最为广泛的接口类型,绝大多数显卡都带有此种接口。它传输红、绿、蓝模拟信号以及同步信号(水平和垂直信号)。基于FPGA设计来驱动VGA也可以达到我们平时所看到的显示结果。以Quartus II软件作为开发环境,Verilog HDL硬件描述语言描述VGA驱动各功能模块,不仅可以很方便的调整内部逻辑电路,优化性能,还可以显示不同的效果。 FPGA的工作速度比较快、处理像素点的速度也比较快,所以具有较好的性能和稳定性。
在这里插入图片描述

设计流程

我大概的设计思路如下:
我们设计一个东西时,思路很重要。当我们要通过驱动VGA来显示时,那么我们就先要选择显示的内容,即选择图片并确定控制这张图片的大小。为什么要控制大小呢?我们后面接着说。之后我们要让这个图片以什么模式显示,则我们就要选择显示模式。然后我们要按照所选的显示模式,设置该模式所需要的工作时钟,若学习板上的时钟不足以支持工作,那么我们就要使用的锁相环定制出所需要的时钟频率。当我们获取足够的时钟频率后,我们就可以真正的进行设计VGA的驱动了。当我们选择好显示模式时,那意味着我们的同步时序模块就可以定下来了。我们要根据所选模式的时序图来设计同步时序模块。一些要点我们会在后面详细说明。当我们选择的图片直接给我们的开发板,它是读不懂的。所以我们要把先把图片转换成开发板能读懂的文件,然后我们在把文件存到我们的开发板里面去,这时候我们就要考虑,我们开发板最多可以存多少东西呢?所以我们的显示的图片的大小会受到限制,不像电脑主机有非常之多的内存。当我们完成把图片转换成开发板能读得懂文件后,我们就可以设计输出模块了。我们的输出模块是在同步时序模块的基础是建立的,我们输出模块是根据图片的大小来设计的。完成我能的所有的准备模块之后,我们需要一个总的模块将全部模块连接在一起,然后我们就可以进行测试了。这就是我设计的大概过程。

流程图
在这里插入图片描述
显示模式表
在这里插入图片描述

VGA的协议

**VGA 协议主要由 5 个输入信号组成,亦是 HSYNC Signal,VSYNC Signal, R,G,B Signal。说简单一点, HSYNC Signal 是 “水平同步信号”(horizontal Synchronize) , VSYNC Signal 是“垂直同步信号”( vertical Synchronize) , R, G ,B Signal 是“ 红色-绿色-蓝色 颜色信号” 。这一点我们可以通过VGA接口的引脚图就可以知道。

以800X600@60为例
在这里插入图片描述

其中VSYNC Signal为行像素,HSYNC Signal为列像素。1 个行像素 = 1056 个列像素。水平同步信号和垂直同步信号同样分为四段同步段(a和o)、 后廊段(b和p)、激活段(c和q)、前廊段(d和r)。由时序图我们可以知道同步段电平是拉低的,后廊段将电平拉高、激活段保持高电平、前廊段将电平拉低。而我们要显示的图形是在激活段中显示的,列像素 > 216 && 列像素 < 1017 && 行像素 >27&& 行像素 <627。时序读懂,其他都好做。
105662860=39790080
至少需要一个40MHz晶振

根据时钟需求,定制时钟频率,再根据时序图搭建同步模块,再根据图片大小建立输出模块,最后用一个总层来把关联端口关联起来。
对输出信息处理,生成mif文件再把文件存进FPGA的ROM(即生成对应的ROM)。
如对输出信息有分辨率要求,提高RGB的位,将RGB位提到8位,则2^8=256,可高度还原输出,不然可能产生失真。代码如下

module sync_module//同步模块

(

CLK, RSTn,

VSYNC_Sig, HSYNC_Sig, Ready_Sig,

Column_Addr_Sig, Row_Addr_Sig

 );	
 input CLK;

input RSTn;


output VSYNC_Sig;//行同步信号


output HSYNC_Sig;//列同步信号


output Ready_Sig;//有效区域信号


output [10:0]Column_Addr_Sig;//有效区域像素点列坐标


output [10:0]Row_Addr_Sig;

//有效区域像素点行坐标


/********************************/


reg [10:0]Count_H;//水平方向计数变量


always @ ( posedge CLK or negedge RSTn )
  if( !RSTn )

    Count_H <= 11'd0;

  else if( Count_H == 11'd1056 )//列方向共 1056
    Count_H <= 11'd0;
  else
    Count_H <= Count_H + 1'b1;


/********************************/

reg [10:0]Count_V;//垂直方向计数变量


always @ ( posedge CLK or negedge RSTn )

  if( !RSTn )

    Count_V <= 11'd0;

  else if( Count_V == 11'd628 )

    Count_V <= 11'd0;

  else if( Count_H == 11'd1056 )//一行结束

    Count_V <= Count_V + 1'b1;



/********************************/


reg isReady;


always @ ( posedge CLK or negedge RSTn )

  if( !RSTn )

    isReady <= 1'b0;

  //else if( ( Count_H > 11'd216 && Count_H < 11'd1017 ) &&( Count_V > 11'd27 && Count_V < 11'd627 ) )//C 段 Q 段
  else if( ( Count_H > 11'd572 && Count_H < 11'd636) &&( Count_V > 11'd313 && Count_V < 11'd377 ) )//C 段 Q 段控制显示范围
    isReady <= 1'b1;

  else

    isReady <= 1'b0;



/*********************************/

//垂直、水平同步信号产生;有效区域信号驱动输出

assign VSYNC_Sig = ( Count_V <= 11'd4 ) ? 1'b0 : 1'b1;


assign HSYNC_Sig = ( Count_H <= 11'd128 ) ? 1'b0 : 1'b1;


assign Ready_Sig = isReady;


/********************************/

assign Column_Addr_Sig = isReady ? Count_H - 11'd572 : 11'd0;// 确保列地址从0开始
assign Row_Addr_Sig = isReady ? Count_V - 11'd313 : 11'd0; // 确保行地址从0开始



endmodule
//产生有效区域像素点的坐标

//输出模块
module vga_control_module(



CLK, RSTn,
Ready_Sig, Column_Addr_Sig, Row_Addr_Sig,
Red_Rom_Data, Green_Rom_Data, Blue_Rom_Data,
Rom_Addr,
Red_Sig, Green_Sig, Blue_Sig


);


input CLK;

input RSTn;

input Ready_Sig;
input [63:0]Red_Rom_Data;
input [63:0]Green_Rom_Data;
input [63:0]Blue_Rom_Data;


output [5:0]Rom_Addr;


input [10:0]Column_Addr_Sig;

input [10:0]Row_Addr_Sig;

output Red_Sig;

output Green_Sig;

output Blue_Sig;


//reg isRectangle;//矩形标志寄存器

//读取行地址低6位
reg [5:0]m;

always @ ( posedge CLK or negedge RSTn )
  if( !RSTn )
    m <= 6'd0;
  else if( Ready_Sig && Row_Addr_Sig < 64 )
    m <= Row_Addr_Sig[5:0];
  else
    m <= 6'd0;
	 

	 
//读取列地址低6位
reg [5:0]n;

always @ ( posedge CLK or negedge RSTn )
  if( !RSTn )
    n <= 6'd0;
  else if( Ready_Sig && Column_Addr_Sig < 64 )
    n <= Column_Addr_Sig[5:0];
  else
    n <= 6'd0;
	 




  

assign Rom_Addr = m; //输出存储器地址



 /************************************/

assign Red_Sig = Ready_Sig ? Red_Rom_Data[ 6'd63 - n ] : 1'b0;//读取存储器内容“逐行扫描”,"高位在前"
assign Green_Sig = Ready_Sig ? Green_Rom_Data[ 6'd63 - n ] : 1'b0;


assign Blue_Sig =  Ready_Sig ? Blue_Rom_Data[ 6'd63 - n ] : 1'b0;

endmodule
/***********************************/
///
//顶层
module vga_module

 (


CLK, RSTn,

VSYNC_Sig, HSYNC_Sig,

Red_Sig, Green_Sig, Blue_Sig);


input CLK;

input RSTn;

output VSYNC_Sig;

output HSYNC_Sig;

output Red_Sig;

output Green_Sig;

output Blue_Sig;


 /*************************************/


wire CLK_40Mhz;


 PLL_40MHz U1

 (
.inclk0( CLK ),// input - from top

.c0( CLK_40Mhz )// output - inter global


 );


 /**************************************/


wire [10:0]Column_Addr_Sig;

wire [10:0]Row_Addr_Sig;

wire Ready_Sig;


 sync_module U2

 (


.CLK( CLK_40Mhz ),


.RSTn( RSTn ),


.VSYNC_Sig( VSYNC_Sig ),// output - to U3

.HSYNC_Sig( HSYNC_Sig ),// output - to U3

.Column_Addr_Sig( Column_Addr_Sig ), // output - to U3

.Row_Addr_Sig( Row_Addr_Sig ),// output - to U3

.Ready_Sig( Ready_Sig )// output - to U3

 );


/******************************************/
wire[63:0]Red_Rom_Data;

Red_rom U3
(
.clock(CLK_40Mhz),
.address(Rom_Addr),
.q(Red_Rom_Data)
);
//
wire[63:0]Green_Rom_Data;

Green_rom U4
(
.clock(CLK_40Mhz),
.address(Rom_Addr),
.q(Green_Rom_Data)
);

//
wire[63:0]Blue_Rom_Data;

Blue_rom U5
(
.clock(CLK_40Mhz),
.address(Rom_Addr),
.q(Blue_Rom_Data)
);
//


wire[5:0]Rom_Addr;
 vga_control_module U6
 (

.CLK( CLK_40Mhz ),

.RSTn( RSTn ),

.Ready_Sig( Ready_Sig ),// input - from U2

.Column_Addr_Sig( Column_Addr_Sig ), // input - from U2

.Row_Addr_Sig( Row_Addr_Sig ),// input - from U2
.Red_Rom_Data(Red_Rom_Data),
.Green_Rom_Data(Green_Rom_Data),
.Blue_Rom_Data(Blue_Rom_Data),
.Rom_Addr(Rom_Addr),

.Red_Sig( Red_Sig ),// output - to top

.Green_Sig( Green_Sig ),// output - to top

.Blue_Sig( Blue_Sig )// output - to top


);


endmodule
 /*******************************************/


对应时钟和ROM文件用Quartus II生成即可。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值