目录

VGA

1 VGA彩条显示实验

2、VGA方块移动实验

3 VGA字符显示实验


VGA是IBM公司在1987年推出的一种视频传输标准,具有分辨率高,显示速率快、颜色丰富等优点。VGA的全称是Video Graphics Array,即视频图形阵列,是一个使用模拟信号进行视频传输的标准。

VGA接口定义及各引脚功能说明如图 18.1.2所示,我们一般只用到其中的1(RED)、2(GREEN)、3(BLUE)、13(HSYNC)、14(VSYNC)信号。引脚1、2、3分别输出红、绿、蓝三原色模拟信号,电压变化范围为 0~0.714V,0V代表无色,0.714V 代表满色;引脚13、14输出TTL电平标准的行/场同步信号。

在VGA视频传输标准中,视频图像被分解为红、绿、蓝三原色信号,经过数模转换之后,在行同步(HSYNC)和场同步(VSYNC)信号的同步下分别在三个独立通道传输。VGA在传输过程中的同步时序分为行时序和场时序,

行同步时序

场同步时序

一行或一场(又称一帧)数据都分为四个部分:低电平同步脉冲、显示后沿、有效数据段以及显示前沿。

行同步信号HSYNC在一个行扫描周期中完成一行图像的显示,其中在a段维持一段时间的低电平用于数据同步,其余时间拉高;在有效数据期间(c段),红绿蓝三原色数据通道上输出一行图像信号,其余时间数据无效。

场同步信号在一个场扫描周期中完成一帧图像的显示,不同的是行扫描周期的基本单位是像素点时钟,即完成一个像素点显示所需要的时间;而场扫描周期的基本单位是完成一行图像显示所需要的时间。

640*480@60表示每一行有640个像素,一帧有480行,每秒显示60帧图像

不同分辨率的VGA时序参数

开拓者开发板上VGA接口,FPGA管脚输出的颜色数据位宽为16bit,数据格式为RGB565,即数据高5位表示红色,中间6位表示绿色,低5位表示蓝色。RGB565格式的数据一共可表示65536种颜色,此外常用的颜色数据格式还有RGB888,数据位宽越大,可以表示的颜色种类就越丰富。VGA传输的是模拟信号,因此需要对FPGA输出的RGB565颜色数据进行数模转换。可以通过专用的视频转换芯片(如ADV7123)来实现,也可以采用利用电阻匹配网络来实现数字信号到模拟信号的转换。

VGA接口原理图

1 VGA彩条显示实验

实验任务

使用开拓者开发板上的VGA接口在显示器上显示彩条,要求分辨率为640*480,刷新速率为60hz。

程序设计

VGA时序包含三个要素:像素时钟、行场同步信号、以及图像数据,时钟分频模块负责产生像素时钟,VGA驱动模块产生行场同步信号,VGA显示模块输出图像数据。

VGA彩条显示系统框图

由系统框图可知,FPGA部分包括四个模块,顶层模块(vga_colorbar)、时钟分频模块(vga_pll)、VGA显示模块(vga_display)以及VGA驱动模块(vga_driver)。其中在顶层模块中完成对另外三个模块的例化。

时钟分频模块(vga_pll)通过调用锁相环(PLL) IP核来实现。根据实验任务要求的分辨率及刷新速率,通过图可以得知本次实验中VGA显示用到的像素时钟为25.175Mhz,因为分辨率不是很高,我们可以设置锁相环IP核让其输出25Mhz的时钟作为像素时钟

VGA驱动模块(vga_driver)在像素时钟的驱动下,根据VGA时序的参数输出行同步(vga_hs)、场同步(vga_vs)信号。同时VGA驱动模块还需要输出像素点的纵横坐标,供VGA显示模块(vga_display)调用,以绘制彩条图案。

顶层模块原理图

顶层模块的代码如下:

module vga_colorbar(

input sys_clk,

input sys_rst_n,

//VGA接口

output  vga_hs,//行同步信号

output  vga_vs,//场同步信号

output  [15:0] vga_rgb//红绿蓝三原色输出

);

//wire define

wire   vga_clk_w;//PLL分频得到25Mhz时钟

wire   locked_w; //lock信号拉高表示PLL输出稳定信号

wire   rst_n_w;  //内部复位信号

wire [15:0] pixel_data_w;//像素点数据

wire [9:0] pixel_xpos_w;//像素点横坐标

wire [9:0] pixel_ypos_w;//像素点纵坐标

//待PLL输出稳定后,停止复位

assign rst_n_w=sys_rst_n&&locked_w;

//例化时钟分频模块

pll u_pll(

.areset(~sys_rst_n),

.inclk0(sys_clk),

.c0(vga_clk_w),//VGA时钟 25M

.locked(locked_w)

);

vga_driver u_vga_driver(

.vga_clk(vga_clk_w),

.rst_n(rst_n_w),

.vga_hs(vga_hs),

.vga_vs(vga_vs),

.vga_rgb(vga_rgb),

.pixel_data(pixel_data_w),

.pixel_xpos(pixel_xpos_w),

.pixel_ypos(pixel_ypos_w)

);

vga_display u_vga_display(

.vga_clk(vga_clk_w),

.rst_n(rst_n_w),

.pixel_xpos(pixel_xpos_w),

.pixel_ypos(pixel_ypos_w),

.pixel_data(pixel_data_w)

);

endmodule

利用IP核进行时钟分频时, 系统上电复位后PLL输出的25Mhz时钟需要经过一段时间才能到达稳定状态。 在PLL输出稳定后,标志信号locked拉高。

由于VGA驱动模块及显示模块均由PLL输出的像素时钟驱动,因此在PLL输出稳定之前,其余模块应保持复位状态。通过将系统复位信号sys_rst_n和PLL输出稳定标志信号locked进行“与”操作,得到内部复位信号rst_n_w。将该信号作为VGA驱动模块及显示模块的复位信号,可避免由于系统复位后像素时钟不稳定造成的VGA时序错误。

VGA驱动模块代码如下

module vga_driver(

input vga_clk,

input rst_n,

//VGA接口

output    vga_hs, //行同步信号

output    vga_vs, //场同步信号

output [15:0] vga_rgb,//红绿蓝三原色输出

input [15:0] pixel_data,//像素点数据

output [9:0] pixel_xpos,//像素点横坐标

output [9:0] pixel_ypos //像素点纵坐标

);

//parameter define  //定义了分辨率为640*480@60时VGA时序中的各个参数

parameter H_SYNC=10'd96;//行同步

parameter H_BACK=10'd48;//行后沿显示

parameter H_DISP=10'd640;//行有效数据

parameter H_FRONT=10'd16;//行显示前沿

parameter H_TOTAL=10'd800;//行扫描周期

parameter V_SYNC=10'd2;//场同步

parameter V_BACK=10'd33;//场显示后沿

parameter V_DISP=10'd480;//场有效数据

parameter V_FRONT=10'd10;//场显示前沿

parameter V_TOTAL=10'd525;//场扫描周期

//reg define

reg [9:0] cnt_h;

reg [9:0] cnt_v;

//wire define

wire  vga_en;

wire  data_req;

//VGA行场同步信号

assign vga_hs=(cnt_h<H_SYNC)?1'b0:1'b1;

assign vga_vs=(cnt_v<V_SYNC)?1'b0:1'b1;

//RGB565数据输出使能信号

assign vga_en=(((cnt_h>=H_SYNC+H_BACK)&&(cnt_h<H_SYNC+H_BACK+H_DISP))

&&((cnt_v>=V_SYNC+V_BACK)&&(cnt_v<V_SYNC+V_BACK+V_DISP)))

?1'b1:1'b0;

//RGB565数据输出

assign vga_rgb=vga_en?pixel_data:16'd0;

//像素点颜色数据输入请求信号

assign data_req=(((cnt_h>=H_SYNC+H_BACK-1'b1)&&(cnt_h<H_SYNC+H_BACK+H_DISP-1'b1))

&&((cnt_v>=V_SYNC+V_BACK)&&(cnt_v<V_SYNC+V_BACK+V_DISP)))

?1'b1:1'b0;

//像素点坐标

assign pixel_xpos=data_req?(cnt_h-(H_SYNC+H_BACK-1'b1)):10'd0;

assign pixel_ypos=data_req?(cnt_v-(V_SYNC+V_BACK-1'b1)):10'd0;

//行计数器对像素时钟计数

always @(posedge vga_clk or negedge rst_n) begin

if(!rst_n)

cnt_h<=10'd0;

else begin

if(cnt_h<H_TOTAL-1'b1)

cnt_h<=cnt_h+1'b1;

else

cnt_h<=10'd0;

end

end

//场计数器对行计数,

//扫描一个行后cnt_v加1,计满一个行扫描周期后清零并重新计数

always@(posedge vga_clk or negedge rst_n) begin

if(!rst_n)

cnt_v<=10'd0;

else if(cnt_h==H_TOTAL-1'b1) begin

if(cnt_v<V_TOTAL-1'b1)

cnt_v<=cnt_v+1'b1;

else

cnt_v<=10'd0;

end

end

endmodule

由于坐标输出后下一个时钟周期才能接收到像素点的颜色数据,因此数据请求信号data_req比数据输出使能信号vga_en提前一个时钟周期。

VGA显示模块的代码

module vga_display(

input vga_clk,//VGA驱动时钟

input rst_n,//复位信号

input [9:0] pixel_xpos,//像素点横坐标

input [9:0] pixel_ypos,//像素点纵坐标

output reg [15:0] pixel_data //像素点数据

);

parameter H_DISP=10'd640;   //分辨率一行

parameter V_DISP=10'd480;   //分辨率一列

parameter WHITE=16'b11111_111111_11111;//RGB565白色

parameter BLACK=16'd00000_000000_00000;//RGB565黑色

parameter RED=16'd11111_000000_00000;//红色

parameter GREEN=16'b00000_111111_00000;//绿色

parameter BLUE=16'b00000_000000_11111;//蓝色

//根据当前像素点坐标指定当前像素点颜色数据,在屏幕上显示彩条

always @(posedge vga_clk or negedge rst_n) begin

if(!rst_n)

pixel_data<=16'd0;

else begin

if((pixel_xpos>=0)&&(pixel_xpos<(H_DISP/5)*1))

pixel_data<=WHITE;

else if((pixel_xpos>=(H_DISP/5)*1)&&(pixel_xpos<(H_DISP/5)*2))

pixel_data<=BLACK;

else if((pixel_xpos>=(H_DISP/5)*2)&&(pixel_xpos<(H_DISP/5)*3))

pixel_data<=RED;

else if((pixel_xpos>=(H_DISP/5)*3)&&(pixel_xpos<(H_DISP/5)*4))

pixel_data<=GREEN;

else

pixel_data<=BLUE;

end

end

endmodule

2、VGA方块移动实验

实验任务:

使用开拓者开发板上的VGA接口在显示器上显示一个不停移动的方块,要求方块移动到边界处时能够改变移动方向。显示分辨率为640*480@60;

程序设计:

在“VGA彩条显示实验”中,我们利用VGA驱动模块输出的像素点的横坐标,在VGA显示模块中完成了彩条图案的绘制。而在本次实验中,为了完成方块的显示,需要同时使用像素点的横坐标和纵坐标来绘制方块所在的矩形区域,另外还需要知道矩形区域左上角的顶点坐标。由于VGA显示的图像在行场同步信号的同步下不停的刷新,因此只要连续改变方块左上角顶点的坐标,并在新的坐标点处重新绘制方块,即可实现方块移动的效果。

VGA显示模块代码如下:

module vga_display(

input vga_clk,//VGA驱动时钟

input rst_n,//复位信号

input [9:0] pixel_xpos,//像素点横坐标

input [9:0] pixel_ypos,//像素点纵坐标

output reg [15:0] pixel_data //像素点数据

);

parameter H_DISP=10'd640;   //分辨率一行

parameter V_DISP=10'd480;   //分辨率一列

parameter SIDE_W=10'd40;  //边框宽度

parameter BLOCK_W=10'd40; //方框宽度

parameter WHITE=16'b11111_111111_11111;//背景颜色白色

parameter BLACK=16'd00000_000000_00000;//方块颜色黑色

parameter BLUE=16'b00000_000000_11111; //边框颜色蓝色

//reg define

reg [9:0] block_x;   //方块左上角横坐标

reg [9:0] block_y;   //方块左上角纵坐标

reg [21:0] div_cnt;  //时钟分频计数器

reg       h_direct;  //方块水平移动方向,1:右移,0:左移

reg       v_direct;  //方块竖直移动方向,1:向下,0:向上

//wire define

wire move_en;  //方块移动使能信号,频率为100hz

assign move_en=(div_cnt==22'd250000-1'b1)?1'b1:1'b0;

//通过对vga驱动时钟计数,实现时钟分频,频率为100hz

always @(posedge vga_clk or negedge rst_n) begin

if(!rst_n)

div_cnt<=22'd0;

else begin

if(div_cnt<22'd25000-1'b1)

div_cnt<=div_cnt+1'b1;

else

div_cnt<=22'd0;   //计数达10ms清零

end

end

//当方块移动到边界时,改变移动方向

always @(posedge vga_clk or negedge rst_n) begin

if(!rst_n) begin

h_direct<=1'b1; //方块初始水平向右移动

v_direct<=1'b1; //方块初始竖直向下移动

end

else begin

if(block_x==SIDE_W-1'b1)  //到达左边界时,水平向右

h_direct<=1'b1;

else if(block_x==H_DISP-SIDE_W-BLOCK_W)  //到达右边界时,水平向左

h_direct<=1'b0;

else

h_direct<=h_direct;

if(block_y==SIDE_W-1'b1) //到达上边界时,竖直向下

v_direct<=1'b1;

else if(block_y==H_DISP-SIDE_W-BLOCK_W)   //到达下边界时,竖直向上

v_direct<=1'b0;

else

v_direct<=v_direct;

end

end

//根据方块移动方向,改变其纵横坐标

always@(posedge vga_clk or negedge rst_n) begin

if(!rst_n) begin

block_x<=22'd100;//方块初始位置横坐标

block_y<=22'd100;//方块初始位置纵坐标

end

else if(move_en) begin

if(h_direct)

block_x<=block_x+1'b1;//方块向右移动

else

block_y<=block_y+1'b1;//方块向左移动

if(v_direct)

block_y<=block_y+1'b1;//方向向下移动

else

block_y<=block_y-1'b1;//方向向上移动

end

else begin

block_x<=block_x;

block_y<=block_y;

end

end

//给不同的区域绘制不同的颜色

always@(posedge vga_clk or negedge rst_n) begin

if(!rst_n)

pixel_data<=BLACK;

else begin

if((pixel_xpos<SIDE_W)||(pixel_xpos>=H_DISP-SIDE_W)

||(pixel_ypos<SIDE_W)||(pixel_ypos>=V_DISP-SIDE_W))

pixel_data<=BLUE;//绘制边框为蓝色

else if((pixel_xpos>=block_x)||(pixel_xpos<block_x+BLOCK_W)

||(pixel_ypos>=block_y)||(pixel_ypos<block_y+BLOCK_W))

pixel_data<=BLACK;//绘制边框为黑色

else

pixel_data<=WHITE;//绘制背景为白色

end

end

endmodule

由于VGA驱动时钟相对于方块移动速度而言过快,我们通过计数器对时钟计数,得到一个频率为100hz的脉冲信号move_en,用它作为使能信号来控制方块的移动。根据方块的移动方向,在使能信号move_en到来时改变其左上角顶点的纵横坐标值。当move_en的频率为100hz时,方块每秒钟在水平和竖直方向上分别移动100个像素点的距离,也可以通过调整move_en的频率,来加快或减慢方块移动的速度。

3 VGA字符显示实验

实验任务:

实验任务是使用开拓者开发板上的VGA接口在显示器的屏幕中心位置显示汉字“天津科技大学”。显示分辨率为640*480,刷新速率为60hz,每个汉字的大小为16*16。

字符(包括汉字、字母和符号等)的本质都是点阵,在VGA屏幕上体现为字符显示区域内像素点的集合。字符的大小决定了字符显示区域内像素点的数目,而字符的样式(字体、颜色等)则决定了各像素点的颜色值。因此,在显示字符之前,我们需要先指定字符的大小、样式,然后获取该字符的点阵,这个过程我们称之为“提取字模”,或简称“取模”。

一般使用0和1的组合来描述字符的点阵排列:点阵中每个像素点用一位(1 bit)数据来表示, 其中用于表征字符的像素点用数字1来表示, 其他的像素点作为背景用数字0来表示。“每行显示数据”是以字节(Byte)为单位的,而一个字节的数据为8个bit,即可以表示一行点阵中的8个像素点。

实验程序如下:

module vga_display(

input vga_clk,//VGA驱动时钟

input rst_n,//复位信号

input [9:0] pixel_xpos,//像素点横坐标

input [9:0] pixel_ypos,//像素点纵坐标

output reg [15:0] pixel_data //像素点数据

);

parameter H_DISP=10'd640;   //分辨率一行

parameter V_DISP=10'd480;   //分辨率一列

parameter POS_X=10'd288;  //字符区域起始点横坐标

parameter POS_Y=10'd232; //字符区域起始点纵坐标

parameter WIDTH=10'd96;//字符区域宽度

parameter HEIGHT=10'd16;//字符区域高度

parameter RED=16'b11111_000000_00000;//字符颜色红色

parameter BLACK=16'd00000_000000_00000;//屏幕颜色黑色

parameter BLUE=16'b00000_000000_11111; //字符域背景颜色蓝色

//reg define

reg [95:0] char [15:0]; //二维字符数组

//wire define

wire [9:0] x_cnt;

wire [9:0] y_cnt;

assign x_cnt=pixel_xpos-POS_X;//像素点相对于字符区域起始点水平坐标

assign y_cnt=pixel_ypos-POS_Y;//像素点相对于字符区域起始点竖直坐标

//给字符数组赋值,显示汉字“天津科技大学”,汉字大小为16*16

always @(posedge vga_clk) begin

char[0]<=96'h000000400810102001002208;

char[1]<=96'h3FF820401D10102001001108;

char[2]<=96'h010013F8F090102001001110;

char[3]<=96'h01001048109013FE01000020;

char[4]<=96'h010087FE1010FC2001007FFE;

char[5]<=96'h01004048FD101020FFFE4002;

char[6]<=96'hFFFE4BF81090102001008004;

char[7]<=96'h01000840389015FC01001FE0;

char[8]<=96'h028010403410188402800040;

char[9]<=96'h028013F8501E308802800180;

char[10]<=96'h0440E04053F0D0480440FFFE;

char[11]<=96'h044020409010105004400100;

char[12]<=96'h082027FC1010102008200100;

char[13]<=96'h101020401010105010100100;

char[14]<=96'h200820401010518820080500;

char[15]<=96'hC006004010102606C0060200;

end

//给不同的区域绘制不同的颜色

always@(posedge vga_clk or negedge rst_n) begin

if(!rst_n)

pixel_data<=BLACK;

else begin

if((pixel_xpos>=POS_X)||(pixel_xpos<POS_X+WIDTH)

||(pixel_ypos>=POS_Y)||(pixel_ypos<POS_Y+HEIGHT))begin

if(char[y_cnt][10'd95-x_cnt])

pixel_data<=RED;//绘制字符为蓝色

else

pixel_data<=BLUE;//绘制字符区域背景为黑色

end

else

pixel_data<=BLACK;//绘制屏幕为黑色

end

end

endmodule

FPGA图像音频通信接口:VGA相关推荐

  1. FPGA图像工程师的六脉神剑——“选扫掌仿习练”

    图像工程师的六脉神剑--"选扫掌仿习练" --不是每个人都能成为一代宗师,因为在一个时代宗师只有少数人,成不了宗师,可以选择成为门派高手,立足武林的六合一之路无外乎秘密武器.江湖规 ...

  2. DE2-115 FPGA开发板的VGA显示

    目录 一.VGA简介 二.VGA实现代码 三.参考博客 一.VGA简介 VGA(Video Graphics Array)视频图形阵列是IBM于1987年提出的一个使用模拟信号的电脑显示标准.VGA接 ...

  3. 浅谈FPGA与音频处理器的结合

    FPGA通常是面向通信行业,尽管其主要开发者仍然专注于通信应用, 但他们越来越关注存储和服务器市场. 但是, 广阔的工业市场又如何呢? 通常, 工业市场的要求并不像存储.服务器或通信应用程序所要求的那 ...

  4. FPGA图像加速解决方案来了

    FPGA图像加速解决方案来了 参考文章: (1)FPGA图像加速解决方案来了 (2)https://www.cnblogs.com/alifpga/p/9285759.html 备忘一下.

  5. python图像音频处理-通过图像傅里叶变换判断相位和幅度的重要性

    python图像音频处理-判断相位和幅度的重要性 这一步骤思想很简单.分别将两个图像或两个音频做FFT,再选取图像1/音频1的幅度,结合上图像2/音频2的相位,再做IFFT.看返回的图像或音频更接近图 ...

  6. 复旦微电子fpga数据手册_专注FPGA图像加速领域 深维科技跨入发展快车道

    日前,在2019赛灵思开发者大会(美洲站)上,深维科技正式面向全球发布ThunderImage三款重磅图像加速产品:全球最快的JPEG2JPEG缩略图方案.超高性能的JPEG2WebP转码方案及世界级 ...

  7. 基于DE2-115 FPGA开发板的VGA显示

    文章目录 一.VGA简介 二.基于DE2-115 FPGA开发板的VGA显示 一.VGA简介 VGA的全称是Video Graphics Array,即视频图形阵列,是一个使用模拟信号进行视频传 输的 ...

  8. FPGA图像仿真平台搭建,模拟摄像头时序---开源代码

    FPGA图像处理中,有些时候写算法的时候,需要查看图像算法处理之后的效果如何,来验证自己算法的正确性,可能身边没有板子,我们可以通过仿真结果,来验证算法的正确性. 源文件免费下载:FPGA图像处理仿真 ...

  9. 采用FPGA实现音频模数转换器

    摘 要 简要分析sigma-deIta(∑一△)架构模数转换器(ADC)原理,提出一种基于FPGA内部LVDS(Low Voltage Differential Signaling)接收器的音频ADC ...

  10. 基于FPGA的音频处理芯片的设计

    基于FPGA的音频处理芯片的设计 时间:2009-01-07 10:00:18 来源:维库电子市场 作者:刘虹 黄涛 徐成 1 引言 随着数字技术日益广泛的应用,以现场可编程门阵列FPGA(Field ...

最新文章

  1. InnerHTML、InnerText、outerHTML、outerText的区别
  2. SpringBoot 中发布ApplicationEventPublisher,监听ApplicationEvent 异步操作
  3. 制作keil5的pack
  4. 重磅:某国产操作系统发布,称完全可替代Windows 7,由华为牵头制作!
  5. mysql语句的执行顺序_SQL语句完整的执行顺序(02)
  6. 从XaaS到Java EE – 2012年哪一种该死的云最适合我?
  7. python 字符串replace函数_01-Python里字符串的常用操作方法--replace()函数
  8. 解决pod没有权限问题
  9. 对话Ruby创始人松本行弘、阿里高级技术专家朴灵!
  10. 学习Axure RP原型设计
  11. 一文读懂微生物扩增子16s测序
  12. VMware虚拟机 centos8 解决全屏问题
  13. 结构光、双目、ToF——三种3D技术对比
  14. Linux攻关之基础模块三 文件命令
  15. 《C专家编程》学习笔记
  16. Python小游戏:BMI指数的计算
  17. MST53XXB 35V,200mA,1.9uA,低压线性稳压器
  18. echarts 无数据时提示文字
  19. SpringBoot-AOP环绕通知记录日志/鉴权
  20. jQuery中的slideUp()、slideDown()、hide()、show() 的比较

热门文章

  1. BAT、头条的时长战争:百度逆势领跑
  2. 基于ET6框架的资源热更
  3. 前端工程化--yeoman使用
  4. 虚拟打印机可以设置默认保存路径吗
  5. 微服务业务日志收集方案
  6. 网易云接口加直链下载vip歌曲
  7. 【信息系统项目管理师】第十六章 变更管理思维导图
  8. 罗技鼠标 903 底部按键是干嘛的,板载模式
  9. 关于Hsql无法插入的问题
  10. 对抗神经网络学习(简单的理解)