对vga模块搞了好几天,vga接口时序不难,就是行计数,列计数,对应到每一个像素上去。这里我先把vga控制模块的程序付上。采用的是小梅哥的程序。屏幕是800X600,配置的时钟是40M.注意改变屏幕尺寸时记得重新配置pll.我就是拿着小梅哥的例子直接用,结果屏幕显示输入信号超出范围。
/*============================================================================
*
*  LOGIC CORE:          VGA驱动模块		
*  MODULE NAME:         VGA_CTRL()
*  COMPANY:             芯航线电子工作室
*                       http://xiaomeige.taobao.com
*	author:					小梅哥
*	author QQ Group:472607506
*  REVISION HISTORY:  
*
*    Revision 1.0  01/01/2016     Description: Initial Release.
*
*  FUNCTIONAL DESCRIPTION:
===========================================================================*/
module VGA_CTRL(
	Clk_40M,	//系统输入时钟25MHZ
	Rst_n,	//复位输入,低电平复位
	data_in,	//待显示数据
	hcount,		//VGA行扫描计数器
	vcount,		//VGA场扫描计数器
	VGA_RGB,	//VGA数据输出
	VGA_HS,		//VGA行同步信号
	VGA_VS,		//VGA场同步信号
	VGA_BLK,		//VGA 场消隐信号
	VGA_CLK		//VGA DAC输出时钟
);
			
	//----------------模块输入端口----------------
	input  Clk_40M;          //系统输入时钟25MHZ
	input  Rst_n;
	input  [23:0]data_in;     //待显示数据
	//----------------模块输出端口----------------
	output [10:0]hcount;
	output [9:0]vcount;
	output [23:0]VGA_RGB;  //VGA数据输出
	output VGA_HS;           //VGA行同步信号
	output VGA_VS;           //VGA场同步信号
	output VGA_BLK;		//VGA 场消隐信号
	output VGA_CLK;		//VGA DAC输出时钟
	
	//将VGA控制器时钟信号取反输出,作为DAC数据锁存信号
	assign VGA_CLK = ~Clk_40M;
	//----------------内部寄存器定义----------------
	reg [10:0] hcount_r;     //VGA行扫描计数器
	reg [9:0] vcount_r;     //VGA场扫描计数器
	//----------------内部连线定义----------------
	wire hcount_ov;
	wire vcount_ov;
	wire dat_act;//有效显示区标定
	//VGA行、场扫描时序参数表
	parameter VGA_HS_end=10‘d127,
				 hdat_begin=10‘d216,
				 hdat_end=10‘d1016,
				 hpixel_end=11‘d1055,
				 VGA_VS_end=10‘d3,
				 vdat_begin=10‘d26,
				 vdat_end=10‘d626,
				 vline_end=10‘d627;
	assign hcount=dat_act?(hcount_r-hdat_begin):11‘d0;
	assign vcount=dat_act?(vcount_r-vdat_begin):10‘d0;
	//**********************VGA驱动部分**********************
	//行扫描
	always@(posedge Clk_40M or negedge Rst_n)
	if(!Rst_n)
		hcount_r<=11‘d0;
	else if(hcount_ov)
		hcount_r<=11‘d0;
	else
		hcount_r<=hcount_r+11‘d1;
assign hcount_ov=(hcount_r==hpixel_end);
	//场扫描
	always@(posedge Clk_40M or negedge Rst_n)
	if(!Rst_n)
		vcount_r<=10‘d0;
	else if(hcount_ov) begin
		if(vcount_ov)
			vcount_r<=10‘d0;
		else
			vcount_r<=vcount_r+10‘d1;
	end
	else 
		vcount_r<=vcount_r;
		
	assign 	vcount_ov=(vcount_r==vline_end);
	//数据、同步信号输出
	assign dat_act=((hcount_r>=hdat_begin)&&(hcount_r<hdat_end))
					&&((vcount_r>=vdat_begin)&&(vcount_r<vdat_end));
					
	assign VGA_BLK = dat_act;
					
	assign VGA_HS=(hcount_r>VGA_HS_end);
	assign VGA_VS=(vcount_r>VGA_VS_end);
	assign VGA_RGB=(dat_act)?data_in:24‘h000000;
		
endmodule 
接下来是图片的处理,我选着了一张自己喜欢的图片,从jpg->bmp->mif文件,也是费了一点功夫。而且bmp文件应再处理一次,我把像素变为100X56,rgb888格式。这样配置rom时可以节省不少资源(也可以配置成rgb565)。但还是最后用了46%的存储资源,我用的芯片是ep4cf10c8n.
rom和pll的配置大家自己去弄。
接下来是图片数据如何输入到屏幕上。这个方法是在规定的像素点,对应的去读取相应地址rom的数据。
接下来我贴一下代码。
module imgdata_send(
	Clk,
	Rst_n,
	hcount,//行
	vcount,//列
	data_in
);
	input Clk;
	input Rst_n;
	
	input [10:0]hcount;
	input [9:0]vcount;
	
	output [23:0]data_in;
	
	
	wire img_ack;//图片数据使能
	
	localparam  img_h = 100,//图片横向像素电个数。
				   img_v = 56,//图片竖向像素电个数。
					vga_hm=800,//屏幕横向像素电个数
					vga_vm= 600,//屏幕竖向像素电个数
					img_hbegin = 250,//图片显示横向初始位置
	reg [13:0]addr;     //rom的地址
	wire [23:0]img_data;   //地址的内容
	
	vga_rom  vga_rom(
	.address(addr),
	.clock(Clk),
	.q(img_data)
	);
assign img_ack = ((hcount >= img_hbegin && hcount < img_hbegin + img_h)|| && (vcount >= img_vbegin && vcount < img_vbegin + img_v))?1‘b1:1‘b0; //我们想要图片显示位置区域内,信号为高
	always@(posedge Clk or negedge Rst_n)
	if(!Rst_n)
		addr <= 14‘d0;  //初始化
	else if(img_ack)
		addr <= ((hcount - img_hbegin) + (vcount - img_vbegin)*img_h);//计算地址,
	else 
		addr <= 14‘d0;
	assign data_in = img_ack ? img_data : 24‘h0;//数据赋值
endmodule
下面是效果。原图我找不到了,只能用bmp文件再一次转为png文件。所以图片很小。


下面是编译之后的顶层文件netlist viewer.一开始我还很担心vga_ctrl模块与rom模块形成一个反馈,但是发现担心是多余的。接下来我当时学习一下sdrom模块的使用。如何让电脑显示更清晰的图片。

附上顶层模块描述:
module vga_top(
	Clk,
	Rst_n,
	VGA_RGB,	
	VGA_HS,	
	VGA_VS,	
	VGA_BLK,	
   VGA_CLK
	
);
	input Clk;
	input Rst_n;
	output [23:0]VGA_RGB;	
	output VGA_HS;	
	output VGA_VS;
	output VGA_BLK;	
	output VGA_CLK;
	
	wire Clk_40M;
	wire [10:0]hcount;
	wire [9:0]vcount;
	wire [23:0]data_in;
VGA_CTRL VGA_CTRL(
	.Clk_40M(Clk_40M),	//系统输入时钟25MHZ
	.Rst_n(Rst_n),	//复位输入,低电平复位
	.data_in(data_in),	//待显示数据
	.hcount(hcount),		//VGA行扫描计数器
	.vcount(vcount),		//VGA场扫描计数器
	.VGA_RGB(VGA_RGB),	//VGA数据输出
	.VGA_HS(VGA_HS),		//VGA行同步信号
	.VGA_VS(VGA_VS),		//VGA场同步信号
	.VGA_BLK(VGA_BLK),		//VGA 场消隐信号
	.VGA_CLK	(VGA_CLK)	//VGA DAC输出时钟
);
imgdata_send imgdata_send(
	.Clk(Clk),
	.Rst_n(Rst_n),
	.hcount(hcount),
	.vcount(vcount),
	.data_in(data_in)
);
vga_pll vga_pll(
	.inclk0(Clk),
	.c0(Clk_40M)
);
endmodule
原文:https://www.cnblogs.com/wyjalx/p/13341966.html