Verilog实现VGA显示控制器
具体原理就不详细讲了,这里给出完整的代码以及Nexys3开发板的引脚文件。
最终实现的效果是:
以 640*480 的分辨率在显示器屏幕显示一个矩形方块,方块在屏幕中以 45 度的角度、60 像素/秒的速度移动,到达屏幕边沿的时候反弹。
// 设计文件:vga_controller.v `timescale 1ns / 1ps module vga_controller( input clk, input rst, output reg [2:0] r, output reg [2:0] g, output reg [1:0] b, output hs, output vs ); parameter UP_BOUND = 31; parameter DOWN_BOUND = 510; parameter LEFT_BOUND = 144; parameter RIGHT_BOUND = 783; reg h_speed, v_speed; reg [9:0] up_pos, down_pos, left_pos, right_pos; wire pclk; reg [1:0] count; reg [9:0] hcount, vcount; // 获得像素时钟25MHz assign pclk = count[1]; always @ (posedge clk) begin if (rst) count <= 0; else count <= count+1; end // 列计数与行同步 assign hs = (hcount < 96) ? 0 : 1; always @ (posedge pclk or posedge rst) begin if (rst) hcount <= 0; else if (hcount == 799) hcount <= 0; else hcount <= hcount+1; end // 行计数与场同步 assign vs = (vcount < 2) ? 0 : 1; always @ (posedge pclk or posedge rst) begin if (rst) vcount <= 0; else if (hcount == 799) begin if (vcount == 520) vcount <= 0; else vcount <= vcount+1; end else vcount <= vcount; end // 显示方块 always @ (posedge pclk or posedge rst) begin if (rst) begin r <= 0; g <= 0; b <= 0; end else begin if (vcount>=up_pos && vcount<=down_pos && hcount>=left_pos && hcount<=right_pos) begin r <= 3'b000; g <= 3'b111; b <= 2'b00; end else begin r <= 3'b000; g <= 3'b000; b <= 2'b00; end end end // 每一帧动画之后根据方块当前位置调整速度 always @ (negedge vs or posedge rst) begin if (rst) begin h_speed <= 1; v_speed <= 0; end else begin if (up_pos == UP_BOUND) v_speed <= 1; else if (down_pos == DOWN_BOUND) v_speed <= 0; else v_speed <= v_speed; if (left_pos == LEFT_BOUND) h_speed <= 1; else if (right_pos == RIGHT_BOUND) h_speed <= 0; else h_speed <= h_speed; end end // 每一帧动画之后根据速度值更新方块的位置 always @ (posedge vs or posedge rst) begin if (rst) begin up_pos <= 391; down_pos <= 510; left_pos <= 384; right_pos <= 543; end else begin if (v_speed) begin up_pos <= up_pos+1; down_pos <= down_pos+1; end else begin up_pos <= up_pos-1; down_pos <= down_pos-1; end if (h_speed) begin left_pos <= left_pos+1; right_pos <= right_pos+1; end else begin left_pos <= left_pos-1; right_pos <= right_pos-1; end end end endmodule
// Nexys3开发板引脚文件 NET "clk" LOC = "V10"; NET "rst" LOC = "C9"; NET "r[0]" LOC = "U7"; NET "r[1]" LOC = "V7"; NET "r[2]" LOC = "N7"; NET "g[0]" LOC = "P8"; NET "g[1]" LOC = "T6"; NET "g[2]" LOC = "V6"; NET "b[0]" LOC = "R7"; NET "b[1]" LOC = "T7"; NET "hs" LOC = "N6"; NET "vs" LOC = "P7";