本文共 5473 字,大约阅读时间需要 18 分钟。
以下是经过优化后的文章内容:
本项目旨在实现VGA显示器上的白框进行45度移动。通过前一篇博客中对VGA时序的简单了解,我们认识到实际应用中如何将这些时序有效结合,是一个持续探索的问题。本系列两篇文章将详细阐述VGA时序在工程中的具体应用。
该工程的主要目标是实现VGA显示器上一个白框沿45度路径移动。移动路线的实现依赖于VGA时序的有效控制,从而完成精确的图像偏移。具体而言,这一过程涉及两个关键维度:横向偏移量和移动条件的控制。
cnt_h
和垂直计数器cnt_v
满足特定条件(如cnt_h
达到H_TOTAL_TIME
减去1时,同时cnt_v
达到V_ADDR_TIME
减去1)时,调整横向偏移量,从而实现45度移动。本项目的时序设计基于传统VGA时序控制,具体包括以下几个关键部分:
cnt_h
和cnt_v
按照预定义的VGA时序循环更新,保证图像完整扫描。hsync
和vsync
信号的生成,确保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/