VGA verilog学习
1 目标:实现[email protected]的色块显示。
1.1图片
1.1.1实际效果:
1.1.2示波器测量到的水平同步信号:
1.1.3示波器测量到的垂直同步信号:
1.2 有关键注释的源代码
`timescale 1ns / 1ns
//先用1位来试一下
module VGA(
input wire clk_100m,//100M时钟输入
output wire led7, //LED灯指示正在运行
output reg hsync,//水平同步
output reg vsync,//垂直同步
output vga_red, //1位的红色信号
output vga_green, //1位的绿色信号
output vga_blue //1位的蓝色信号
);
wire clk_vga;//VGA显示所用时钟
wire locked;//指示时钟已经稳定
clk_wiz_0 clk_ip_div//时钟IP核产生clk_vga
(
.clk_out1(clk_vga), // output clk_out1
.clk_in1(clk_100m), // input clk_in1
.locked(locked)
);
div_clk divclk(//自己写的计数分频
.clk_in_100m(clk_100m) ,
.clk_2hz(led7)
);
parameter//当前分辨率下面的参数。规定死的
ta=11'd128,tb=11'd88,tc=11'd800,td=11'd40,
te=11'd1056,to=11'd4,tp=11'd23,tq=11'd600,
tr=11'd1,ts=11'd628;
reg [10:0] x_counter=1;
reg [10:0] y_counter=1;
always @( posedge clk_vga)//产生水平计数和垂直计数。
begin
if(locked==0)
x_counter<=0;
else
begin
if(x_counter==te)
begin
if(y_counter==ts) begin y_counter <= 0; x_counter<=0;end
else begin y_counter <= y_counter+1; x_counter<=0;end
end
else x_counter<=x_counter+1;
end
end
always @( posedge clk_vga )//水平同步信号
begin
if(x_counter<ta) hsync<=0;
else hsync<=1;
end
always @( posedge clk_vga )//垂直同步信号
begin
if(y_counter<to) vsync<=0;
else vsync<=1;
end
reg [2:0] colour=3'b000;
always @( x_counter or y_counter ) //颜色显示部分
begin
if(x_counter<ta+tb) colour<=3'b000;//黑
else if(x_counter<ta+tb+100) colour<=3'b001;//蓝
else if(x_counter<ta+tb+200) colour<=3'b010;//绿
else if(x_counter<ta+tb+300) colour<=3'b011;//青
else if(x_counter<ta+tb+400) colour<=3'b100;//红
else if(x_counter<ta+tb+500) colour<=3'b101;//粉
else if(x_counter<ta+tb+600) colour<=3'b110;//黄
else if(x_counter<ta+tb+700) colour<=3'b111;//白
else colour<=3'b000;//黑
end
//*赋予颜色
assign vga_red = colour[2];
assign vga_green = colour[1];
assign vga_blue = colour[0];
endmodule
1.4补充显示,在任意位置显示色块。
先上效果图:
1.4 源代码,其实就在上面的基础上加了几行。大部分和上面是重复的。
`timescale 1ns / 1ns
//先用1位来试一下
module VGA(
input wire clk_100m,//100M时钟输入
output wire led7, //LED灯指示正在运行
output reg hsync,//水平同步
output reg vsync,//垂直同步
output vga_red, //1位的红色信号
output vga_green, //1位的绿色信号
output vga_blue //1位的蓝色信号
);
wire clk_vga;//VGA显示所用时钟
wire locked;//指示时钟已经稳定
clk_wiz_0 clk_ip_div//时钟IP核产生clk_vga
(
.clk_out1(clk_vga), // output clk_out1
.clk_in1(clk_100m), // input clk_in1
.locked(locked)
);
div_clk divclk(//自己写的计数分频
.clk_in_100m(clk_100m) ,
.clk_2hz(led7)
);
parameter//当前分辨率下面的参数。规定死的
ta=11'd128,tb=11'd88,tc=11'd800,td=11'd40,
te=11'd1056,to=11'd4,tp=11'd23,tq=11'd600,
tr=11'd1,ts=11'd628;
reg [10:0] x_counter=1;
reg [10:0] y_counter=1;
always @( posedge clk_vga)//产生水平计数和垂直计数。
begin
if(locked==0)
x_counter<=0;
else
begin
if(x_counter==te)
begin
if(y_counter==ts) begin y_counter <= 0; x_counter<=0;end
else begin y_counter <= y_counter+1; x_counter<=0;end
end
else x_counter<=x_counter+1;
end
end
always @( posedge clk_vga )//水平同步信号
begin
if(x_counter<ta) hsync<=0;
else hsync<=1;
end
always @( posedge clk_vga )//垂直同步信号
begin
if(y_counter<to) vsync<=0;
else vsync<=1;
end
reg valid=0; //有效视觉区域
reg [10:0] x_pos=0,y_pos=0;
reg block_vld=0;//显示的块
always @ ( posedge clk_vga )
begin
valid <= (x_counter > ta+tb) && (x_counter < ta+tb+800) && (y_counter > to) && (y_counter < to+tp+600);
block_vld <= (x_pos > 400) && (x_pos < 500) && (y_pos > 300) && (y_pos < 600);
end
always @ ( posedge clk_vga )
begin
if (valid) begin//坐标的转换
x_pos <= x_counter - ta-tb;
y_pos <= y_counter -(to);
end
else ;
end
reg [2:0] colour=3'b000;
always @( posedge clk_vga)
begin
if (block_vld && valid) colour <= 3'b100;
else if (valid) colour <= 3'b011;
else colour <= 3'b000;
end
//*赋予颜色
assign vga_red = colour[2];
assign vga_green = colour[1];
assign vga_blue = colour[0];
endmodule
还行