FPGA学习笔记——VGA

正文

参考《Verilog HDL那些事儿建模篇》而作。
VGA分为VGA硬件接口和VGA协议。VGA硬件接口没什么。下面先介绍VGA协议。
VGA 协议主要由 5 个输入信号组成:HSYNC Signal, VSYNC Signal, RGB Signal。 说简单一点,HSYNC Signal 是“列同步信号”, VSYNC Signal 是“行同步信号”, RGB Signal 是“红色、绿色、蓝色、颜色信号”。

在这里插入图片描述
VGA扫描一帧屏幕是由“m行扫描”和“n列填充”组成。以800 x 600 x 60HZ(一下涉及到的所有与分辨率有关的都以他为例)为例:
扫描次序如下:
扫描第 0 行 - 在第 0 行,列填充 0~799。
扫描第 1 行 - 在第 1 行,列填充 0 ~ 799。
扫描第 2 行 - 在第 2 行,列填充 0 ~ 799。
扫描第 m 行 - 在第 m 行,列填充 0 ~ 799。
扫描第 598 行 - 在第 598 行,列填充 0 ~ 799。
直到描第 599 行- 在第 599 行,列填充 0 ~ 799

宏观上,一帧屏幕的显示是由 600 行从上至下扫描,800 列从左至右填充,然而微观上,一行的行 扫描是由超过 800 个列填充完成。

这是 HSYNC 和 VSYCNC 的时序图

这是时序图的信息

HSYNC Signal用来控制“列填充”。
a(同步段):拉低128个列像素(这里的像素和图像的像素不太一样,下面会介绍)。
b(后廊段):拉高88个列像素。
c(激活段):拉高800个列像素。
d(前廊段):拉高40个列像素。
所以一列总共有1056个列像素。

VSYNC Signal 是用来控制“行扫描”。
o(同步段):拉低4个行像素。
p(后廊段):拉高23个行像素。
q(激活段):拉高600个行像素。
r(前廊段):拉高一个行像素。
所以一行总共有628个行像素。

一个行像素是以列像素为单位:一个行像素 = 1056个列像素。
一个列像素以时间为单位:一个列像素 = 25ns;一个行像素 = 1056 x 25ns = 2.64us。
显示图像的有效部分
上图表示 HSYNC Signal 只有在的 C 段 (红色部分)和 VSYNC Signal 的 q 段 (黄色部分)的激活段,数据的输入才有效。
交叉部分的表达式可以描述为:列像素 > 216 && 列像素 < 1017 && 行像素 > 27 && 行像素 < 627。
先实现VGA驱动模块:
在这里插入图片描述
PLL模块用于输出40MHZ的时钟频率,同步模块对 HSYNC Signal 和 VSYNC Signal 进行控制,用于控制VGA的时序。VGA控制模块用于图像的显示控制。
下面先实现同步模块:

module sync
(
 CLK,
 RSTn,
 HSYNC_Sig,
 VSYNC_Sig,
 Ready_Sig,
 Column_Addr_Sig,
 Row_Addr_Sig
);
 input CLK;
 input RSTn;
 output HSYNC_Sig;    //HSYNC信号线,控制“列填充”
 output VSYNC_Sig;    //VSYNC信号线,控制“行扫描”
 output Ready_Sig;    //数据输入的有效时间标志位,1表示可以输入数据
 output [10:0] Column_Addr_Sig; //列像素地址信号
 output [10:0] Row_Addr_Sig;  //行像素地址信号
 
 //列像素计数器
 reg [10:0] count_H;
 always @ (posedge CLK , negedge RSTn)
 begin
  if(!RSTn)
   count_H <= 11'd0;
  else if(count_H == 11'd1056)
   count_H <= 11'd0;
  else 
   count_H <= count_H + 1'b1;
 end
 
 //行像素计数器
 reg [10:0] count_V;
 always @ (posedge CLK , negedge RSTn)
 begin
  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;
 end 
 
 
 reg isReady;
 always @ (posedge CLK , negedge RSTn)
 begin
  if(!RSTn) 
   isReady <= 1'b0;
  else if((count_H > 11'd216 && count_H < 11'd1017) &&
    (count_V > 11'd27 && count_V < 11'd627))  //数据输入有效区域
   isReady <= 1'b1;        //表示可以输入数据了
  else
   isReady <= 1'b0;
 end
 
 assign VSYNC_Sig = (count_V <= 11'd4) ? 1'b0 : 1'b1;  //表示出时序图的时序,o,p,q,r,段
 assign HSYNC_Sig = (count_H <= 11'd128) ? 1'b0 : 1'b1; //表示出时序图的时序,a,b,c,d,段
 assign Ready_Sig = isReady;        
 
 assign Column_Addr_Sig = isReady ? (count_H - 11'd217) : 11'd0;//可以输入数据时顺便输出一下现在的列像素
 assign Row_Addr_Sig = isReady ? (count_V - 11'd28) : 11'd0; //可以输入数据时顺便输出一下现在的行像素
 
endmodule

然后是VGA控制模块:

module vga_control
(
 CLK,
 RSTn,
 Ready_Sig,
 Column_Addr_Sig,
 Row_Addr_Sig,
 Red_Sig,
 Green_Sig,
 Blue_Sig
);
 input CLK;
 input RSTn;
 input Ready_Sig;
 input [10:0] Column_Addr_Sig;
 input [10:0] Row_Addr_Sig;
 output Red_Sig;
 output Green_Sig;
 output Blue_Sig;
 
 reg isRectangl;
 always @ ( posedge CLK or negedge RSTn ) 
 begin
  if(!RSTn)
   isRectangl <= 1'b0;
  else if( Column_Addr_Sig > 11'd0 && Row_Addr_Sig < 11'd100)
   isRectangl <= 1'b1;
  else
   isRectangl <= 1'b0;
 end
 
 //所有颜色信号被赋予同样的表达式,这表示了在 799 x 100 
 //(显示部分的像素是800 x 600,然后isRectangl是在Row_Addr_Sig < 11'd100时置一)
 //的区域内显示白色的矩形。
 assign Red_Sig = (Ready_Sig && isRectangl) ? 1'b1 : 1'b0;
 assign Green_Sig = (Ready_Sig && isRectangl) ? 1'b1 : 1'b0;
 assign Blue_Sig = (Ready_Sig && isRectangl) ? 1'b1 : 1'b0;
 
endmodule

然后是PLL模块,我直接复制的例程暂时还不懂原理:
这编辑器我是服了,粘贴太多直接卡死,保存都不行,我贴个链接想用的去下载吧,也可以去网上找找fpga的pll模块的使用方法。
pll_module的代码
最后是顶层模块,把这些功能都连接起来:

module vga
(
 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_module U1
 (
  .inclk0(CLK),
  .c0(CLK_40MHZ)
 );
 
 wire [10:0]Column_Addr_Sig;
 wire [10:0]Row_Addr_Sig;
 wire Ready_Sig;
 sync U2 
 (
  .CLK(CLK_40MHZ),
  .RSTn(RSTn),
  .VSYNC_Sig(VSYNC_Sig),
  .HSYNC_Sig(HSYNC_Sig),
  .Column_Addr_Sig(Column_Addr_Sig),
  .Row_Addr_Sig(Row_Addr_Sig),
  .Ready_Sig(Ready_Sig)
 );
 vga_control U3
 (
  .CLK(CLK_40MHZ),
  .RSTn(RSTn),
  .Ready_Sig(Ready_Sig),
  .Column_Addr_Sig(Column_Addr_Sig),
  .Row_Addr_Sig(Row_Addr_Sig),
  .Red_Sig(Red_Sig),
  .Green_Sig(Green_Sig),
  .Blue_Sig(Blue_Sig)
 );
 
endmodule

代码就这些,他的RTL图如下图:
在这里插入图片描述

然后配置引脚并下载到开发板中(不知道怎么配置和下载的可以去看看我的quartus2的使用教程),效果如图:
在这里插入图片描述
还是挺有成就感的,接下来让屏幕显示图像。

FPGA自学笔记——设计与验证JMB FPGA(可编程逻辑门阵)是一种可编程的硬件平台,可以实现各种数字电路的设计与验证。本文将简要介绍使用FPGA自学设计与验证JMB(低功耗、高效能、集成度高的多媒体芯片)的过程。 首先,我们需要了解JMB的功能和特性。JMB是一种面向多媒体应用的芯片,具备低功耗、高效能和高集成度的优势。我们需要详细研究JMB的硬件架构和内部模块,包括处理器核、存储器模块、图像和音频处理模块等。 接下来,我们可以使用FPGA开发板来设计和验证JMB。首先,我们需要熟悉FPGA设计工具,例如Vivado或Quartus等。这些工具提供了图形化界面和硬件描述语言(HDL)等设计方法。我们可以使用HDL编写JMB的功能模块,并将其综合为FPGA可执的位流文件。 在设计完成后,我们需要验证JMB的功能和性能。我们可以使用仿真工具(例如ModelSim或ISE Simulator)来模拟JMB在不同情况下的为。通过设计测试程序并运仿真,我们可以验证JMB的各个模块是否正确地工作,是否满足设计要求。 在验证完成后,我们可以将位流文件下载到FPGA开发板中进智能芯片的物理实现和测试。通过与外部设备的连接以及相关测试程序的运,我们可以验证JMB在实际硬件中的功能和性能。 总结起来,学习FPGA设计与验证JMB,我们需要熟悉JMB的硬件架构和内部模块,并使用FPGA开发工具进设计与验证。通过仿真和物理实现测试,我们可以验证JMB的功能和性能。这些过程需要理论知识和实践经验的结合,希望这些笔记能够给你提供一些参考和指导。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值