博客
关于我
基于FPGA的VGA控制器实现(2)
阅读量:707 次
发布时间:2019-03-17

本文共 5614 字,大约阅读时间需要 18 分钟。

以下是经过优化后的文章内容:

FPGA实现VGA白框45度移动

项目意义

本项目旨在实现VGA显示器上的白框进行45度移动。通过前一篇博客中对VGA时序的简单了解,我们认识到实际应用中如何将这些时序有效结合,是一个持续探索的问题。本系列两篇文章将详细阐述VGA时序在工程中的具体应用。

工程功能

该工程的主要目标是实现VGA显示器上一个白框沿45度路径移动。移动路线的实现依赖于VGA时序的有效控制,从而完成精确的图像偏移。具体而言,这一过程涉及两个关键维度:横向偏移量和移动条件的控制。

  • 横向偏移量控制(x):ranging from 0 to 440 pixels
  • 移动条件控制:在扫描一幅图像的过程中,当水平计数器cnt_h和垂直计数器cnt_v满足特定条件(如cnt_h达到H_TOTAL_TIME减去1时,同时cnt_v达到V_ADDR_TIME减去1)时,调整横向偏移量,从而实现45度移动。
  • 工程时序

    本项目的时序设计基于传统VGA时序控制,具体包括以下几个关键部分:

  • 计数器控制:确保cnt_hcnt_v按照预定义的VGA时序循环更新,保证图像完整扫描。
  • 同步信号控制:通过hsyncvsync信号的生成,确保VGA时序的正确同步。
  • 偏移量更新:根据预设规则,增加或减少横向偏移量,以实现白框的移动效果。
  • 工程代码

    以下为本次项目的核心Verilog代码,基于前一篇博客的基础进行优化和扩展:

    timescale 1ns / 1ps
    module vga_drive(
    input vga_clk,
    input rst_n,
    output hsync,
    output vsync,
    output [7:0] vga_data
    );
    // 定义参数和内部信号
    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;
    // 主要逻辑
    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'b1))
    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'b1)))
    cnt_v <= 13'd0;
    else if (cnt_h == (H_TOTAL_TIME-1'b1))
    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'b1))
    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'b1)))
    vsync <= 1'b1;
    else if ((cnt_v >= (V_SYNC_TIME-1'b1)) && (cnt_h == (H_TOTAL_TIME-1'b1)))
    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'b1)))
    x <= x + 1'b1;
    else if ((flag_x == 1'b1) && (cnt_v == (V_TOTAL_TIME-1'b1)) && (cnt_h == (H_TOTAL_TIME-1'b1)))
    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'b1)))
    flag_x <= 1'b1;
    else if ((x <= 1'b1) && (cnt_v == (V_TOTAL_TIME-1'b1)) && (cnt_h == (H_TOTAL_TIME-1'b1)))
    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'b1)))
    y <= y + 1'b1;
    else if ((flag_y == 1'b1) && (cnt_v == (V_TOTAL_TIME-1'b1)) && (cnt_h == (H_TOTAL_TIME-1'b1)))
    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'b1)))
    flag_y <= 1'b1;
    else if ((y <= 1'b1) && (cnt_v == (V_TOTAL_TIME-1'b1)) && (cnt_h == (H_TOTAL_TIME-1'b1)))
    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)))
    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
    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

    总结

    在实际工程应用中,VGA时序控制是实现图形显示核心的一部分。本项目通过对VGA时序的深入理解,完成了横向偏移控制的实现,为VGA显示器的应用开辟了新的可能性。通过适当调整横向偏移量和垂直位置信号,可以实现图像的精确移动和显示效果。

    如需进一步技术支持或了解具体实现细节,请随时留言或加入相关技术社区!

    转载地址:http://nesez.baihongyu.com/

    你可能感兴趣的文章
    nginx + etcd 动态负载均衡实践(四)—— 基于confd实现
    查看>>
    Nginx + Spring Boot 实现负载均衡
    查看>>
    Nginx + uWSGI + Flask + Vhost
    查看>>
    Nginx - Header详解
    查看>>
    Nginx - 反向代理、负载均衡、动静分离、底层原理(案例实战分析)
    查看>>
    nginx 1.24.0 安装nginx最新稳定版
    查看>>
    nginx 301 永久重定向
    查看>>
    nginx css,js合并插件,淘宝nginx合并js,css插件
    查看>>
    Nginx gateway集群和动态网关
    查看>>
    Nginx Location配置总结
    查看>>
    Nginx log文件写入失败?log文件权限设置问题
    查看>>
    Nginx Lua install
    查看>>
    nginx net::ERR_ABORTED 403 (Forbidden)
    查看>>
    Nginx SSL私有证书自签,且反代80端口
    查看>>
    Nginx upstream性能优化
    查看>>
    Nginx 中解决跨域问题
    查看>>
    nginx 代理解决跨域
    查看>>
    Nginx 动静分离与负载均衡的实现
    查看>>
    Nginx 反向代理 MinIO 及 ruoyi-vue-pro 配置 MinIO 详解
    查看>>
    nginx 反向代理 转发请求时,有时好有时没反应,产生原因及解决
    查看>>