基于FPGA的VGA控制器实现(2)

该项目的意义

上一篇博客中我们已经实现了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        : [email protected]
// 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        : [email protected]
// 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

该测试代码与上一篇博客完全一样,没做更改。

总结

创作不易,认为文章有帮助的同学们可以收藏点赞支持。(工程也都在群中)对文章有什么看法或者需要更近一步交流的同学,可以加入下面的群:
在这里插入图片描述

发布了23 篇原创文章 · 获赞 9 · 访问量 5401

猜你喜欢

转载自blog.csdn.net/zhangningning1996/article/details/104169866