FPGA实现VGA显示(二)——————color_bar显示及方框移动(参考开拓者FPGA开发指南)

首先感谢所有开源分享资源的博主或者机构个人,这篇主要参考开拓者FPGA开发指南。通过分析代码,理清思路。

主要分为四个模块,顶层模块,时钟分频模块,VGA显示模块,VGA驱动模块。前三个模块在任何时候都是不变的,只有最后一个模块,显示需要显示的内容。代码设计真的很巧,这里讲驱动模块单独写出来,不仅方便控制,同时仿真也很方便的可以看到结果。具体代码的理解讲在代码中展现,同时后面的字符显示,基于ROM的静态图片显示,都是基于此的。只是有一点,网上现有资源很多不是ISE的,而笔者现在还用的ISE.....;因此在调用IP的时候就很少有教程了。后面再说,这些模块可以在任何板子开发环境下运行编译成bit文件。

实验目标:实现彩条的显示,实现方框移动的显示(从第一行还是移动,一直到最后一行的最后一个,重新回到开始的位置重复),实现部分主要是在display模块显示改变的,这也是这个比较优势的地方。

模块介绍_div_clk

分频模块,生成要用的时钟周期,前面一节里边有时钟周期计算方法,可以调用pll,也可以自己写一个分频都可以。此模块主要提供显示所需要的时钟周期。因为我这里还是用的640*480@60hz,所以还是大概系统时钟的一半。

module div_clk(clk,rst_n,div_clk
    );
input clk;
inout rst_n;
output reg div_clk;

always@(posedge clk or negedge rst_n)
begin
	if(!rst_n)
		div_clk <= 1'b0;
	else 
		div_clk <= ~div_clk;
end

endmodule

模块介绍_vga_diver

此模块主要两个功能,每一个功能由两个输出组成。

功能一:输出vga_hs,vga_vs这两个时序信号,用来点亮屏幕,时序的控制由厂家提供的文档为基准。

功能二:输出颜色控制,这个主要是将x,y分别输出到下一个模块,即vga_display模块,可以控制每一行每一个像素,然后给颜色。

module vga_driver(
	vga_clk,rst_n,pixel_data,
	vga_hs,vga_vs,
	vga_rgb,x_pixel,y_pixel
    );
//---------------------------------
input 				vga_clk		;
input 				rst_n		;
input 		[15:0]	pixel_data	;
//---------------------------------
output 				vga_hs		;	
output 				vga_vs		;
output  	[15:0]	vga_rgb		;
output 		[ 9:0]	y_pixel		;//y像素坐标
output 		[ 9:0]	x_pixel		;//x像素坐标
//---------------------------------
parameter Hor_Total_Time 		= 10'd800	;		//行显示帧长
parameter Hor_Sync		 		= 10'd96	;		//行同步脉冲
parameter Hor_Back_Porch 		= 10'd48	;		//行显示后沿(同显示前沿,这里由两个时段合成)	
parameter Hor_Addr_Time 		= 10'd640	;		//行显示区域
parameter Hor_Front_Porch		= 10'd16	;		//行显示前沿
//---------------------------------
parameter Ver_Total_Time 		= 10'd525	;		//列显示帧长
parameter Ver_Sync		 		= 10'd2		;		//列同步脉冲
parameter Ver_Back_Porch 		= 10'd33	;		//列显示后沿(同显示前沿,这里由两个时段合成)	
parameter Ver_Addr_Time 		= 10'd480	;		//列显示区域
parameter Ver_Front_Porch		= 10'd10	;		//列显示前沿
//---------------------------------
//两个计数器

//行计数器
reg [9:0] x_cnt;
always@(posedge vga_clk or negedge rst_n)
begin
	if(!rst_n)
		x_cnt <= 10'd1;
	else 
		if(x_cnt == Hor_Total_Time)
			x_cnt <= 10'd1;
		else 
			x_cnt <= x_cnt + 1'b1;
end
//列计数器
reg [9:0] y_cnt;
always@(posedge vga_clk or negedge rst_n)
begin
	if(!rst_n)
		y_cnt <= 10'd1;
	else 
		if(y_cnt == Ver_Total_Time && x_cnt == Hor_Total_Time)
			y_cnt <= 10'd1;
		else 
			if(x_cnt == Hor_Total_Time)
				y_cnt <= y_cnt + 1'b1;
end
//VGA行场同步信号
assign vga_hs = (x_cnt < Hor_Sync) ? 1'b1 : 1'b0;
assign vga_vs = (y_cnt < Ver_Sync) ? 1'b1 : 1'b0;
//VGA输出
reg vga_en;
always@(*)
begin
	vga_en <= (x_cnt > (Hor_Sync + Hor_Back_Porch) && x_cnt <= (Hor_Sync + Hor_Back_Porch + Hor_Addr_Time) && y_cnt > (Ver_Sync + Ver_Back_Porch) && y_cnt <= (Ver_Sync + Ver_Back_Porch + Ver_Addr_Time));
end
assign vga_rgb = (vga_en) ? pixel_data	:	16'd0;
assign x_pixel = (vga_en) ? (x_cnt - (Hor_Sync + Hor_Back_Porch)	 )	:		10'd0;
assign y_pixel = (vga_en) ? (y_cnt - (Ver_Sync + Ver_Back_Porch)	 )	:		10'd0;


endmodule

模块介绍_vga_display

控制每一行,每一列的像素点作为输入,输出位像素数据。display1为方框移动

module vga_display1(vga_clk,rst_n,
	x_pixel,y_pixel,pixel_data
    );
//---------------------------------
input    			  vga_clk	;
input 					rst_n	;
input 		[9:0]	  x_pixel	;
input 		[9:0]	  y_pixel	;
//---------------------------------
output 	reg	[15:0]	  pixel_data;
//---------------------------------
parameter side 					= 10'd40    ;		//边框
parameter block 				= 10'd40    ;		//方格
//---------------------------------
//---------------------------------
parameter Hor_Total_Time 		= 10'd800	;		//行显示帧长
parameter Hor_Sync		 		= 10'd96	;		//行同步脉冲
parameter Hor_Back_Porch 		= 10'd48	;		//行显示后沿(同显示前沿,这里由两个时段合成)	
parameter Hor_Addr_Time 		= 10'd640	;		//行显示区域
parameter Hor_Front_Porch		= 10'd16	;		//行显示前沿
//---------------------------------
parameter Ver_Total_Time 		= 10'd525	;		//列显示帧长
parameter Ver_Sync		 		= 10'd2		;		//列同步脉冲
parameter Ver_Back_Porch 		= 10'd33	;		//列显示后沿(同显示前沿,这里由两个时段合成)	
parameter Ver_Addr_Time 		= 10'd480	;		//列显示区域
parameter Ver_Front_Porch		= 10'd10	;		//列显示前沿
//---------------------------------
parameter white = 16'b11111_111111_11111   ;
parameter black = 16'b00000_000000_00000   ;
parameter red   = 16'b11111_000000_00000   ;
parameter green = 16'b00000_111111_00000   ;
parameter bule  = 16'b00000_000000_11111   ;
//---------------------------------
reg [24:0] cnt_1s;		//25_000_000		12_500_000
reg move_en;
always@(posedge vga_clk or negedge rst_n )
begin
	if(!rst_n)
		begin 
			cnt_1s <= 25'd1;
			move_en <= 1'b0;
		end
	else 
		if(cnt_1s == 25'd25_000_000)
			begin
				cnt_1s <= 25'd1;
				move_en <= 1'b1;
			end
		else 
			begin
				cnt_1s <= cnt_1s + 1'b1;
				move_en <= 1'b0;
			end
end
reg [9:0] block_x;
reg [9:0] block_y;
always@(posedge vga_clk or negedge rst_n)
begin
	if(!rst_n)
		begin
			block_x <= 10'd40;
			block_y <= 10'd40;
		end
	else 
		if(move_en)
			begin
				if(block_x == 10'd520 && block_y == 10'd360 )
					begin 
						block_x <= 10'd40;
						block_y <= 10'd40;
					end
				else 
					if(block_x == 10'd520) 
						begin
							block_y <= block_y + 10'd80;
							block_x <= 10'd40;			
						end
					else 
						block_x <= block_x + 10'd80;
			end
end
always@(posedge vga_clk or negedge rst_n)
begin
	if(!rst_n)
		pixel_data <= black;
	else 
		if(x_pixel <= ( side - 1'b1 ) || x_pixel >= (560 + side - 1'b1) || y_pixel <= side - 1'b1 || y_pixel >= (400 + side - 1'b1) )
			pixel_data <= bule;
		else 
			if(x_pixel >= ( block_x - 1'b1 ) && (block_x + 10'd80) >= x_pixel && y_pixel >= ( block_y - 1'b1 )  && y_pixel <= (block_y + 10'd80) )
				pixel_data <= black;
			else 
				pixel_data <= white; 
end

endmodule

display为彩条显示

module vga_display(
	vga_clk,rst_n,
	x_pixel,y_pixel,pixel_data
    );
//---------------------------------
input    			  vga_clk	;
input 					rst_n	;
input 		[9:0]	  x_pixel	;
input 		[9:0]	  y_pixel	;
//---------------------------------
output 	reg	[15:0]	  pixel_data;
//---------------------------------
parameter Hor_Addr_Time 		= 10'd640	;		//行显示区域
parameter Ver_Addr_Time 		= 10'd480	;		//列显示区域
//---------------------------------
parameter white = 16'b11111_111111_11111   ;
parameter black = 16'b00000_000000_00000   ;
parameter red   = 16'b11111_000000_00000   ;
parameter green = 16'b00000_111111_00000   ;
parameter bule  = 16'b00000_000000_11111   ;
//---------------------------------
//判断行和场的像素位置输出控制颜色

always@(posedge vga_clk or negedge rst_n)
begin
	if(!rst_n)
		pixel_data <= 16'd0;
	else 
		if(x_pixel <= (Hor_Addr_Time / 5 - 1'b1 ) * 1 ) 
			pixel_data <= white;
		else
			if(x_pixel <= (Hor_Addr_Time / 5 - 1'b1 ) * 2 ) 
				pixel_data <= black;
			else 
				if(x_pixel <= (Hor_Addr_Time / 5 - 1'b1 ) * 3 )
					pixel_data <= red;
				else 
					if(x_pixel <= (Hor_Addr_Time / 5 - 1'b1 ) * 4 )
						pixel_data <= green;
					else
						pixel_data <= bule;
end

endmodule

模块介绍_vga_top

module top_vga(clk,rst_n,
	vga_hs,vga_vs,
	vga_rgb
    );
input clk ;
input rst_n;
output vga_hs;
output vga_vs;
output [15:0] vga_rgb;


wire [9:0] w_x_pixel;
wire [9:0] w_y_pixel;
wire w_clk;
wire [15:0] pixel_data;

div_clk A(
	.clk 						(clk 		),
	.rst_n						(rst_n		),
	.div_clk					(w_clk		)
    );

vga_driver B(
	.vga_clk					(w_clk		),
	.rst_n						(rst_n		),
	.pixel_data					(pixel_data ),
	.vga_hs						(vga_hs		),
	.vga_vs						(vga_vs		),
	.vga_rgb					(vga_rgb	),
	.x_pixel					(w_x_pixel	),
	.y_pixel					(w_y_pixel	)
    );

vga_display1 C(
	.vga_clk					(w_clk		),
	.rst_n						(rst_n		),
	.x_pixel					(w_x_pixel	),
	.y_pixel					(w_y_pixel	),
	.pixel_data					(pixel_data )
    );
endmodule

 

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值