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

本文共 5473 字,大约阅读时间需要 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 / 1psmodule 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 / 1psmodule 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;endalways # (`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/

    你可能感兴趣的文章
    MySQLIntegrityConstraintViolationException异常处理
    查看>>
    mysqlreport分析工具详解
    查看>>
    MySQLSyntaxErrorException: Unknown error 1146和SQLSyntaxErrorException: Unknown error 1146
    查看>>
    Mysql_Postgresql中_geometry数据操作_st_astext_GeomFromEWKT函数_在java中转换geometry的16进制数据---PostgreSQL工作笔记007
    查看>>
    mysql_real_connect 参数注意
    查看>>
    mysql_secure_installation初始化数据库报Access denied
    查看>>
    MySQL_西安11月销售昨日未上架的产品_20161212
    查看>>
    Mysql——深入浅出InnoDB底层原理
    查看>>
    MySQL“被动”性能优化汇总
    查看>>
    MySQL、HBase 和 Elasticsearch:特点与区别详解
    查看>>
    MySQL、Redis高频面试题汇总
    查看>>
    MYSQL、SQL Server、Oracle数据库排序空值null问题及其解决办法
    查看>>
    mysql一个字段为空时使用另一个字段排序
    查看>>
    MySQL一个表A中多个字段关联了表B的ID,如何关联查询?
    查看>>
    MYSQL一直显示正在启动
    查看>>
    MySQL一站到底!华为首发MySQL进阶宝典,基础+优化+源码+架构+实战五飞
    查看>>
    MySQL万字总结!超详细!
    查看>>
    Mysql下载以及安装(新手入门,超详细)
    查看>>
    MySQL不会性能调优?看看这份清华架构师编写的MySQL性能优化手册吧
    查看>>
    MySQL不同字符集及排序规则详解:业务场景下的最佳选
    查看>>