该项目的意义
上一篇博客中我们已经实现了VGA显示彩条的实现,但是经过上面的文章我们也只能是对VGA时序做了简单的了解,该时序如何再工程中得到应用,任然是一个问题,接下来,我们将以两篇博客来解释VGA在工程中的应用。
该工程的功能
该工程的功能是为了实现VGA显示器上一个白框成45度移动,移动的路线如下图:
对上面的图形进行简单的描述入下:
1、小白框水平方向偏移量x:0-440pixel
2、移动条件:扫描完一幅图像时,移动一个像素点cnt_h799 && cnt_v524时,移动
列操作同行操作一样,如此一来便实现了白框的45度方向移动。
工程时序
与前面的博客一样,这里我们给出工程的时序,与上一篇文章结合可以很简单的学会VGA操作原理。该工程的简要时序如下:
由上面的时序图再结合下面的工程代码,相信大家可以掌握该VGA时序
工程代码
这里直接给出所写的工程代码,是在上一篇博客的基础上更改而来的,代码如下:
`timescale 1ns / 1ps
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : vga_drive.v
// Create Time : 2020-02-03 20:08:42
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module vga_drive(
input vga_clk ,
input rst_n ,
output reg hsync ,
output reg vsync ,
output reg [ 7:0] vga_data
);
//========================================================================================\
//**************Define Parameter and Internal Signals**********************************
//========================================================================================/
localparam H_TOTAL_TIME = 800 ;
localparam H_ADDR_TIME = 640 ;
localparam H_SYNC_TIME = 96 ;
localparam H_BACK_PORCH = 40 ;
localparam H_LEFT_BORDER = 8 ;
localparam V_TOTAL_TIME = 525 ;
localparam V_ADDR_TIME = 480 ;
localparam V_SYNC_TIME = 2 ;
localparam V_BACK_PORCH = 25 ;
localparam V_LEFT_BORDER = 8 ;
localparam HIGH = 200 ;
localparam WIDTH = 200 ;
reg [12:0] cnt_h ;
reg [12:0] cnt_v ;
reg [ 8:0] x ;
reg [ 8:0] y ;
reg flag_x ;
reg flag_y ;
//========================================================================================\
//************** Main Code **********************************
//========================================================================================/
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
cnt_h <= 13'd0;
else if(cnt_h == (H_TOTAL_TIME-1'd1))
cnt_h <= 13'd0;
else
cnt_h <= cnt_h + 1'b1;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
cnt_v <= 13'd0;
else if(cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
cnt_v <= 13'd0;
else if(cnt_h == (H_TOTAL_TIME-1'd1))
cnt_v <= cnt_v + 1'b1;
else
cnt_v <= cnt_v;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
hsync <= 1'b1;
else if(cnt_h == (H_TOTAL_TIME-1'd1))
hsync <= 1'b1;
else if(cnt_h >= (H_SYNC_TIME-1'b1))
hsync <= 1'b0;
else
hsync <= hsync;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
vsync <= 1'b1;
else if(cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
vsync <= 1'b1;
else if(cnt_v >= (V_SYNC_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
vsync <= 1'b0;
else
vsync <= vsync;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
x <= 9'd0;
else if(flag_x == 1'b0 && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
x <= x + 1'b1;
else if(flag_x == 1'b1 && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
x <= x - 1'b1;
else
x <= x;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
flag_x <= 1'b0;
else if(x >= (H_ADDR_TIME-HIGH-1'b1) && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
flag_x <= 1'b1;
else if(x <= 1'b1 && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
flag_x <= 1'b0;
else
flag_x <= flag_x;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
y <= 9'd0;
else if(flag_y == 1'b0 && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
y <= y + 1'b1;
else if(flag_y == 1'b1 && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
y <= y - 1'b1;
else
y <= y;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
flag_y <= 1'b0;
else if(y >= (V_ADDR_TIME-WIDTH-1'b1) && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
flag_y <= 1'b1;
else if(y <= 1'b1 && cnt_v == (V_TOTAL_TIME-1'b1) && cnt_h == (H_TOTAL_TIME-1'd1))
flag_y <= 1'b0;
else
flag_y <= flag_y;
always @(posedge vga_clk or negedge rst_n)
if(rst_n == 1'b0)
vga_data <= 8'd0;
else if(cnt_h>= (H_SYNC_TIME+H_BACK_PORCH+H_LEFT_BORDER-1'b1+x) && cnt_h < (H_SYNC_TIME+H_BACK_PORCH+H_LEFT_BORDER-1'b1+x+HIGH) && cnt_v >= (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+y) && cnt_v < (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+y+WIDTH))//白色区域
vga_data <= 8'b111_111_11;
else if(cnt_h >= (H_SYNC_TIME+H_BACK_PORCH+H_LEFT_BORDER-1'b1) && cnt_h < (H_SYNC_TIME+H_BACK_PORCH+H_LEFT_BORDER+H_ADDR_TIME-1'b1))begin
if(cnt_v >= (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER) && cnt_v < (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+13'd160))
vga_data <= 8'b111_000_00;
else if(cnt_v >= (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+160) && cnt_v < (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+13'd320))
vga_data <= 8'b000_111_00;
else if(cnt_v >= (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+320) && cnt_v < (V_SYNC_TIME+V_BACK_PORCH+V_LEFT_BORDER+13'd480))
vga_data <= 8'b000_000_11;
else
vga_data <= 8'd0;
end else
vga_data <= 8'd0;
endmodule
测试代码
为了方便同学们调试程序,这里给出该工程的测试代码。
`timescale 1ns / 1ps
`define CLOCK 40
// *********************************************************************************
// Project Name : OSXXXX
// Author : zhangningning
// Email : nnzhang1996@foxmail.com
// Website :
// Module Name : vga_tb.v
// Create Time : 2020-02-03 21:05:31
// Editor : sublime text3, tab size (4)
// CopyRight(c) : All Rights Reserved
//
// *********************************************************************************
// Modification History:
// Date By Version Change Description
// -----------------------------------------------------------------------
// XXXX zhangningning 1.0 Original
//
// *********************************************************************************
module vga_tb;
reg vga_clk ;
reg rst_n ;
wire hsync ;
wire vsync ;
wire [ 7:0] vga_data ;
initial begin
vga_clk = 1'b0;
rst_n <= 1'b0;
#(`CLOCK*100)
rst_n <= 1'b1;
end
always #(`CLOCK/2) vga_clk = ~vga_clk;
vga_drive vga_drive_inst(
.vga_clk (vga_clk ),
.rst_n (rst_n ),
.hsync (hsync ),
.vsync (vsync ),
.vga_data (vga_data )
);
endmodule
该测试代码与上一篇博客完全一样,没做更改。
总结
创作不易,认为文章有帮助的同学们可以收藏点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群: