Yindow

【红色飓风Nano二代测评】VGA驱动

0
阅读(2525)

经过这两天的摸索,以及做了以上几个测评,现在对Xilinx的开发流程基本了解了,现在就将我在QuartusII上面的一个VGA显示的工程移植过来,进一步的加深印象。

我在接触Xilinx开发的时候确实碰到了好多纠结的问题,归纳起来就是对这个东西的不熟悉。不过不要紧,闻道有先后,术业有专攻,学习是个快乐的过程。希望在今后的日子里和大家共同进步。

首先我们来看看什么是VGA时序,VGA显示接口的时序主要是需要考虑行同步信号(HSYNC),场同步信号(VSYNC),以及三个基本颜色信号(RGB)。VGA显示采用逐行扫描方式。扫描是从屏幕的左上方开始,从左到右,从上到下。每扫完一行,电子束回到左边下一行的开始位置,期间对电子束进行行消隐。并在每行结束时,用行同步信号对行进行同步,扫描完所有行后,再用场同步信号对场进行同步,并使电子束回到屏幕的左上方,同时对场进行消隐,并预备下一次扫描。该方法的关键是对时序的控制。至于VGA的时序图百度谷歌上面大把的,大家可以去了解下。

这个只是一个VGA驱动测试的模块,如果后续需要丰富功能,该模块可以发出一个读取FIFO信号,然后将RGB颜色线信号从FIFO中读出,FIFO这边再连接到DDR3上面,这样就可以将DDR3中的图片啊什么的显示出来了。显示器其实就是一个能够将ram中数据通过不同颜色显示出来的器件。昨天刚在网上买了一本怎么构建嵌入式系统的书,网上的资料讲的很杂,而且DDR3IP核配置我这边还有点问题,等书一到,学习了这方面的知识我就试试更加复杂的功能,后续有时间的话再加上个摄像头玩玩。

 

  module VGA
  (
  	input clk,	//50MHz
  	input rst_n,
  
  	output hsync,//场同步扫描
  	output vsync,//行同步扫描
  	output ENAB,
  	output OCLK,
  	
  	output RORL,
  	output UORD,
  	
  	output[5:0] vga_r,
  	output[5:0] vga_g,
  	output[5:0] vga_b	//显示颜色数据信号	
  );
  
  reg clk_25M;
  always @ (posedge clk or negedge rst_n)
  begin
  	if(!rst_n)
  		begin
  			clk_25M <= 1'b0;
  		end
  	else
  		begin
  			clk_25M <= 	!clk_25M;
  		end
  end
  
  assign OCLK = clk_25M;
  
  assign RORL = 1'b1;
  assign UORD = 1'b0;
  
  //-----------------------------------------
  reg[9:0] x_cnt;	//行坐标
  reg[9:0] y_cnt;	//列坐标
  
  always @ (posedge clk_25M or negedge rst_n)
  	if(!rst_n) x_cnt <= 10'd0;
  	else if(x_cnt == 10'd799) x_cnt <= 10'd0;
  	else x_cnt <= x_cnt + 1'b1;
  	
  always @ (posedge clk_25M or negedge rst_n)
  	if(!rst_n) y_cnt <= 10'd0;
  	else if(y_cnt == 10'd525) y_cnt <= 10'd0;
  	else if(x_cnt == 10'd799) y_cnt <= y_cnt + 1'b1;
  //--------------------------------------------
  //场同步 行同步	
  reg hsync_r,vsync_r;
  always @ (posedge clk_25M or negedge rst_n)	//场同步
  	if(!rst_n) hsync_r <= 1'b1;
  	else if(x_cnt == 10'd0) hsync_r <= 1'b0;
  	else if(x_cnt == 10'd96) hsync_r <= 1'b1;
  
  always @ (posedge clk_25M or negedge rst_n)	//行同步	
  	if(!rst_n) vsync_r <= 1'b1;
  	else if(y_cnt == 10'd0) vsync_r <= 1'b0;
  	else if(y_cnt == 10'd2) vsync_r <= 1'b1;
  	
  assign hsync = hsync_r;
  assign vsync = vsync_r;
  //--------------------------------------------
  //有效标志位的产生
  reg valid_yr;
  always @ (posedge clk_25M or negedge rst_n)
  	if(!rst_n) valid_yr <= 1'b0;
  	else if(y_cnt == 10'd34) valid_yr <= 1'b1;
  	else if(y_cnt == 10'd514) valid_yr <= 1'b0;
  
  //VGA有效显示区标志位
  reg valid_r;	
  always @ (posedge clk_25M or negedge rst_n)
  	if(!rst_n) valid_r <= 1'b0;
  	else if((x_cnt == 10'd45) && valid_yr)	valid_r <= 1'b1;
  	else if((x_cnt == 10'd685) && valid_yr)valid_r <= 1'b0;
  	
  assign ENAB = valid_r;
  
  /*always @ (posedge clk_25M or negedge rst_n)
  	if(!rst_n) VGA_FRAME_O <= 1'b0;
  	else if((y_cnt < 10'd34)) VGA_FRAME_O <= 1'b1;	
  	else VGA_FRAME_O <= 1'b0;*/
  
  reg[17:0] color;
  
  always @ (posedge clk_25M or negedge rst_n)
  begin
  	if(!rst_n)
  		begin
  			color <= 18'd0;
  		end
  	else if((y_cnt >= 10'd34) && (y_cnt < 10'd194))
  		begin
  			color <= 18'b111111_000000_000000;
  		end
  	else if((y_cnt >= 10'd194) && (y_cnt < 10'd354))
  		begin
  			color <= 18'b000000_111111_000000;
  		end
  	else if((y_cnt >= 10'd354) && (y_cnt < 10'd514))
  		begin
  			color <= 18'b000000_000000_111111;
  		end
  end
  
  assign vga_r = color[17:12];
  assign vga_g = color[11: 6];
  assign vga_b = color[ 5: 0];
  
  
  
  endmodule


 

这个软件写起来相对简单,主要是我这个并行的VGA屏连线比较麻烦,RGB六位颜色线,加上时钟、时能、行列扫描等。为了区分这些线还专门在线上贴了小标签。

效果如下图1所示

 

1 VGA显示效果图

 

 

图2 VGA仿真图1