VGA显示8色彩条RGB888(一)

目录

1.color bar (彩条)颜色编码

2.VGA驱动原理

3.设计思路

4.模块代码

4.1顶层代码

4.2分频时钟模块

 4.3 vga_driver模块

 五、仿真结果图​

 六、makefile脚本


1.color bar (彩条)颜色编码

这里使用的编码方式是RGB888,一个像素R,G,B分量各占八位。

8色彩条是指白色,青色,黄色,品红色,绿色,蓝色,红色,黑色,他们都是R,G,B分量各取0或者255(2*2*2=8)组成。

详细编码方案见常用RGB编码颜色见常用RGB颜色表_yh13572438258的博客-CSDN博客

2.VGA驱动原理

VGA显示器的驱动原理,大家知道,我们的显示器是不同的分辨率,而大多显示器的分辨率都是接近4:3的,所以我们采用640×480@60Hz这样的一个分辨率来实验。

下图是不同显示分辨率模式下的标准约束,显示前后沿又称为消隐前后肩。

开发板与VGA接口的电路图:

电路中的信号名总共有两类:VGA的场同步和行同步信号(VGA_VS,VGA_HS),控制VGA颜色的(R,G,B)。

行同步和场同步,是来驱动我们的VGA显示的两个信号,而GRB是控制VGA显示的颜色。

下面这个图是基于640×480@60Hz这个分辨率的具体参数:

而下面这个图是关于VGA显示的时序图,这只是咱们让显示器亮起来的一个时序图,并不指定在什么区域显示什么颜色。Blacking区又叫消隐区,由前肩,同步脉冲,后肩组成。行场同步信号又叫水平垂直同步信号。

接下来解释下这个图中信号,HSync和VSync分别是行同步信号和场同步信号,而其中的Video部分,就是显示的信号,但是真正有效的区域还是属于video中的“Addressable”Video,其余部分都是无效的,就是说在其他部分,都让其输出信号为“0”.可能这样说起来还是显得比较空洞,大家看下面这个图就会显得比较直接了。

 

 在我们理解VGA时序的时候,我们也可以把VGA显示理解成“扫描”,而VGA扫描的开始是从屏幕的左上角开始,然后开始扫描第一行,第一行扫描完了,扫第二行,一直扫到屏幕的最后一行,然后回到初始位置开始扫描。在扫描的过程中,每一行的开始,有一个同步信号,就是图中的HSync,扫完整个屏幕结束后重新开始扫描有一个场同步信号VSync.

3.设计思路

主要使用两个计数器,分别来计行信号刷新到了哪个像素点和场信号计到了哪一行。然后在场信号计到了某一行的时候,就控制显示的颜色。当然,最重要的一点,需要记得给行信号和场信号加上同步信号(我们的板子上的同步信号是为低电平,同步信号为高或低,需要根据需要的同步信号的极性而定)。Horizontal synchronization = HS 行同步信号,Vertical synchronization = VS 场同步信号。

3.1Pixel clock = 25.175MHz说明每一个像素点刷新的时钟频率为25.175MHz,可以取25MHz,但开发板上的时钟为50MHz,可以二分频,也可以调用PLL这个ip核来生成我们的25MHz时钟。

3.2Hor Total Time = 31.778; // (usec) = 100 chars = 800 Pixels  代表每一行占用800个像素点(实际显示的只有640个像素点)

3.3Ver Total Time = 16.683; // (msec) = 525 lines  代表每一场有525行

3.4.根据其他的参数可以得知,行同步占用刷新96个像素点的时间,场同步占用2行,而行信号的有效显示为146~(146+640),场信号的有效显示为35~(35+480)。在其余的区域,是不给VGA显示信息的,就是说我们输出的RGB为0。

3.5若要使我们的显示器显示出8种颜色,我们可以先给显示的有效区域分成8个部分,640/8=80在一行有效区域的0~80显示一种颜色,在80~160列显示另外一种颜色,..........,以此类推,在剩下的560~640显示第三种颜色。

3.6顶层模块连接图

4.模块代码

4.1顶层代码

如下:


module vga_top(
    clk,
    rst_n,
	vga_hs,
    vga_vs,
    data_en,
	vga_rgb
    );
input clk ;
input rst_n;
output vga_hs;
output vga_vs;
output [23:0] vga_rgb;
output data_en;
 
 
wire [9:0]   w_h_pixel;
wire [9:0]   w_v_pixel;
wire           w_clk;
wire [23:0] pixel_data;
 
div_clk u1(
	.clk 						(clk 		),
	.rst_n						(rst_n		),
	.div_clk					(w_clk      )
    );
 
vga_driver u2(
	.vga_clk					(w_clk      ),
	.rst_n						(rst_n		),
	.pixel_data					(pixel_data ),
	.vga_hs						(vga_hs		),
	.vga_vs						(vga_vs		),
    .data_en                    (data_en    ),
	.vga_rgb					(vga_rgb	),
	.h_pixel					(w_h_pixel	),
	.v_pixel					(w_v_pixel	)
    );
 
vga_display u3(
	.vga_clk					(w_clk      ),
	.rst_n						(rst_n		),
	.h_pixel					(w_h_pixel	),
	.v_pixel					(w_v_pixel	),
    .data_en                    (data_en    ),
	.pixel_data					(pixel_data )
    );
endmodule

4.2分频时钟模块

如下:

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

 4.3 vga_driver模块

 如下:

module vga_driver(
	vga_clk,
    rst_n,
    pixel_data,
	vga_hs,
    vga_vs,
    data_en,
	vga_rgb,
    h_pixel,
    v_pixel
    );
  //---------------------------------
  input 				vga_clk		;
  input 				rst_n		;
  input 		[23:0]	pixel_data	;
  //---------------------------------
  output 				vga_hs		;//horizontal synchronization	
  output 				vga_vs		;//vertical synchronization
  output     	[23:0]	vga_rgb		;
  output 		[ 9:0]	h_pixel		;//horizontal valid pixel position 
  output 		[ 9:0]	v_pixel		;//vertical valid pixel position
  output reg            data_en     ;
  //---------------------------------
  parameter Hor_Total_Time 		= 10'd800	;		//horizontal sync signal cycles
  parameter Hor_Sync		    = 10'd96	;		//horizontal sync pulse width
  parameter Hor_Back_Porch 		= 10'd48	;		//horizontal back porch
  parameter Hor_Active_Time 	= 10'd640	;		//horizontal active screen size
  parameter Hor_Front_Porch		= 10'd16	;		//horizontal front porch
  //---------------------------------
  parameter Ver_Total_Time 		= 10'd525	;		//vertical sync signal cycles
  parameter Ver_Sync		 	= 10'd2		;		//vertical sync pulse width
  parameter Ver_Back_Porch 		= 10'd33	;		//vertical back porch	
  parameter Ver_Active_Time 	= 10'd480	;		//vertical active screen size
  parameter Ver_Front_Porch		= 10'd10	;		//vertical front porch
  //---------------------------------
  
   
  // Horizontal position counter.
  reg [9:0] h_cnt;
  always@(posedge vga_clk or negedge rst_n)
  begin
  	if(!rst_n)
        h_cnt <= 10'd1;                 //Count from 1, no 0
  	else 
  		if(h_cnt == Hor_Total_Time)
  			h_cnt <= 10'd1;
  		else 
  			h_cnt <= h_cnt + 1'b1;
  end
  
  //Vertical position counter.
  reg [9:0] v_cnt;
  always@(posedge vga_clk or negedge rst_n)
  begin
  	if(!rst_n)
  		v_cnt <= 10'd1;
  	else 
  		if(v_cnt == Ver_Total_Time && h_cnt == Hor_Total_Time)
  			v_cnt <= 10'd1;
  		else 
  			if(h_cnt == Hor_Total_Time)
  				v_cnt <= v_cnt + 1'b1;
  end
  
  //HSYNC and VSYNC  signal derivation.
  assign vga_hs = (h_cnt < Hor_Sync) ? 1'b1 : 1'b0;  //HSYNC polarization: this is 1 - positive
  assign vga_vs = (v_cnt < Ver_Sync) ? 1'b1 : 1'b0;  //VSYNC polarization: this is 1 - positive
  
  
  //Data enable (blanking) signal derivation.
  
  always@(*)
    begin
  	data_en <= (h_cnt > (Hor_Sync + Hor_Back_Porch) && h_cnt <= (Hor_Sync + Hor_Back_Porch + Hor_Active_Time) && v_cnt > (Ver_Sync + Ver_Back_Porch) && v_cnt <= (Ver_Sync + Ver_Back_Porch + Ver_Active_Time));
  
    end
  
  
  assign vga_rgb = (data_en) ? pixel_data	:	24'd0;
  assign h_pixel = (data_en) ? (h_cnt - (Hor_Sync + Hor_Back_Porch)	 )	:		10'd0;
  assign v_pixel = (data_en) ? (v_cnt - (Ver_Sync + Ver_Back_Porch)	 )	:		10'd0;
 
 
endmodule

4.4 vga_display 模块代码

module vga_display(
	vga_clk,
    rst_n,
	h_pixel,
    v_pixel,
    data_en,
    pixel_data
    );
//---------------------------------
input    			  vga_clk	;
input 					rst_n	;
input 		[9:0]	  h_pixel	;
input 		[9:0]	  v_pixel	;
input                 data_en   ;
//---------------------------------
output 	reg	[23:0]	  pixel_data;
//---------------------------------
parameter Hor_Active_Time 		= 10'd640	;		//horizontal active screen size
parameter Ver_Active_Time 		= 10'd480	;		//vertical active screen size
//---------------------------------
// color bars, RGB888
parameter WHITE   = 24'hffffff   ;
parameter CYAN    = 24'h00ffff   ;
parameter YELLOW  = 24'hffff00   ;
parameter MAGENTA = 24'hff00ff   ;
parameter BLUE    = 24'h0000ff   ;
parameter GREEN   = 24'h00ff00   ;
parameter RED     = 24'hff0000   ;
parameter BLACK   = 24'h000000   ;

//---------------------------------
 
always@(posedge vga_clk or negedge rst_n)
begin
	if(!rst_n)
		pixel_data <= 24'd0;
	else 
        if(h_pixel <= (Hor_Active_Time / 8) * 1  - 1'b1 )     //h_pixel begin from 0
			pixel_data <= WHITE;
		else
            if(h_pixel <= (Hor_Active_Time / 8)* 2  - 1'b1 ) 
				pixel_data <= CYAN;
			else 
			    if(h_pixel <= (Hor_Active_Time / 8)* 3  - 1'b1 )
                        pixel_data <= YELLOW;
				else 
					if(h_pixel <= (Hor_Active_Time / 8)* 4  - 1'b1 )
						pixel_data <= MAGENTA;
					else
                        if(h_pixel <= (Hor_Active_Time / 8)* 5  - 1'b1 )
						pixel_data <= BLUE;
                        else
                            if(h_pixel <= (Hor_Active_Time / 8)* 6  - 1'b1 )
						    pixel_data <=GREEN ;
                            else
                                if(h_pixel <= (Hor_Active_Time / 8)* 7  - 1'b1 )
						        pixel_data <= RED;
                                else
						            pixel_data <= BLACK;
end
 
endmodule

4.5 测试代码

`timescale 1ns/1ps

module vga_top_tb;

	reg		       clk;
	reg	         rst_n;
	
	wire [7:0] vga_rgb;
	wire	    vga_hs;
	wire		vga_vs;
    wire       data_en;

    vga_top vga_inst (

		.clk	         (clk			),
		.rst_n			 (rst_n	    	),		                   
		.vga_rgb		 (vga_rgb		),
		.vga_hs			 (vga_hs		),
        .data_en         (data_en       ),
		.vga_vs			 (vga_vs		)
	);

	initial clk = 1;
	always #10 clk = ~ clk;
	
	initial 
		begin
			rst_n = 0;
			# 201
			
			rst_n = 1;
				repeat (3)
					@ (posedge vga_vs);
			
			$stop;
		end 

    initial begin
      $fsdbAutoSwitchDumpfile (1000,"vga_top.fsdb",13,"fsdb.log");
      $fsdbDumpvars ;
      $fsdbDumpflush;
    end

endmodule

 五、仿真结果图

 六、makefile脚本

vcs:
	vcs -sverilog -full64 +cli+4 vga_top.v vga_driver.v vga_display.v vga_top_tb.v div_clk.v  \
	-timescale=1ns/1ps \
	-Mupdate +lint=all +notimingcheck +v2k  \
	-P ${DEBUSSY_HOME}/share/PLI/VCS/LINUX64/novas.tab \
	${DEBUSSY_HOME}/share/PLI/VCS/LINUX64/pli.a \
	+race=all \
	-R \
	-l run.log
verdi:
	verdi -sv vga_top.v vga_driver.v vga_display.v vga_top_tb.v div_clk.v +define+GLS -top vga_top_000 &

驱动原理主要参考http://dengkanwen.com/70.html 

代码参考链接:https://blog.csdn.net/qq_41467882/article/details/87078721

  • 1
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值