【ZYNQ-7000开发之一】PL部分驱动VGA显示静态彩色图像

原创 2015年11月18日 22:34:55

在本篇文章中,将实现在Xilinx ZYNQ上实现用PL部分驱动VGA显示12bit的彩色图像,涉及到VGA的驱动原理,vivado上的PLL IP和ROM IP的使用以及彩色图像coe文件的生成。最后将提供整个项目代码。

本文所使用的开发板是Miz702(兼容zedboard),软件开发环境:vivado 2015.2

一、VGA的原理

VGA的协议比较简洁,主要是有五个信号线组成,行同步信号 HSYNC,场同步信号VSYNC3条色彩电压传输信号(RGB分别对应)。色彩信
号的电压为
0~0.7V。本次要实现的分辨率是640*480,帧率是60Hz,所需要的时钟是25Mhz.话不多说,直接上图:


VGA 时序图


需要注意的是,VGA的时序图和参数表可以看出,每帧需要525个vsync脉冲,在每个vsync的周期中,即Tvsync,又包含着800个hsync脉冲,而图像RGB的有效时间在hsync的640个显示脉冲之中。

二、逻辑实现

//vga_sync.v  VGA同步控制逻辑
module vga_sync(
        input   wire            clk,
        input   wire            rst_n,
        output	wire		video_en,              //数据有效
        output  reg             hsync,                 //场同步信号
        output  reg             vsync,                 //行同步信号
        output  wire    [9:0]   pixel_x,               //待显示待像素的x坐标
        output  wire    [9:0]   pixel_y                //待显示待像素的y坐标 
        );
         
        reg     [9:0] pixel_cnt;
        reg     [9:0] line_cnt;
		  
		  
        reg             v_video_en;
        reg             h_video_en;
        
       
        always @(posedge clk or negedge rst_n)
            if(!rst_n)
                begin
                    pixel_cnt <= 10'b0;
                end
            else
                begin
                    pixel_cnt <= pixel_cnt + 1'b1;
		    if(pixel_cnt == 10'd799)
			begin
			    pixel_cnt <= 10'b0;
			end
                end
                
               
         always @(posedge clk or negedge rst_n)
            if(!rst_n)
                begin
                    h_video_en <= 1'b1;
		    hsync <= 1'b1;
                end
            else
                begin
                    case (pixel_cnt) 
                        10'd0:
                            begin
                                h_video_en <= 1'b1;
                            end
                        10'd639:
                            begin
                                h_video_en <= 1'b0;
                            end 
                        10'd655:
                            begin
                                hsync <= 1'b0;
                            end 
                        10'd751:
                            begin
                                hsync <= 1'b1;
                            end             
                    endcase
                end
                
                
               
         always @(posedge clk or negedge rst_n)
            if(!rst_n)
                begin
                    line_cnt <= 10'b0;
                end
            else
                begin
                    if(pixel_cnt == 10'd799)
                        begin
                            line_cnt <= line_cnt + 1'b1;
                        end 
                    
                      if(line_cnt == 10'd524)
                      begin
                            line_cnt <= 10'b0;
                      end 
                end
                
        always @(posedge clk or negedge rst_n)
            if(!rst_n)
                begin
                    v_video_en <= 1'b1;
				    vsync <= 1'b1;
                end
            else
                begin
                    case(line_cnt)
                        10'd0:
                            begin
                                v_video_en <= 1'b1;
                            end 
                        10'd479:
                            begin
                                v_video_en <= 1'b0;
                            end 
                        10'd489:
                            begin
                                vsync <= 1'b0;
                            end 
                        10'd491:
                            begin
                                vsync <= 1'b1;
                            end 
                    endcase
                end               
 
        assign pixel_x = pixel_cnt;
        assign pixel_y = line_cnt;
		  
	assign video_en = ((h_video_en == 1'b1) &&  (v_video_en == 1'b1)); 
        
endmodule
//由于开发板上的PL部分时钟是100Mh的,所以需要用PLL把VGA的基准时钟时钟分频到25Mhz


//test_vga.v文件   利用上面的代码显示彩色图像
module vga_test(
                    input   wire            sys_clk,
                    input   wire            sys_rst_n,
                    output  wire            hsync,
                    output  wire            vsync,
                    output  wire   [11:0]   rgb,
		    output  reg	            led
                );
//红_绿_蓝
parameter	BLACK   = 12'b0000_0000_0000;  
parameter	BLUE    = 12'b0000_0000_1111;
parameter	GREEN   = 12'b0000_1111_0000;
parameter	DIAN	= 12'b0000_1111_1111;
parameter	RED     = 12'b1111_0000_0000;
parameter	PURPLE  = 12'b1111_0000_1111;
parameter	YELLOW  = 12'b1111_1111_0000;
parameter	WHITE   = 12'b1111_1111_1111;
					 
wire    [9:0]   pixel_x;
wire    [9:0]   pixel_y;
wire 	        clk_25mhz;
reg	[11:0]  rgb_reg;


//显示静态图像640*480
reg		[23:0] cnt;
always @(posedge clk_25mhz or negedge sys_rst_n)
	if(!sys_rst_n)
		begin
		    cnt <= 0;
		    led <= 0;
		end 
	else
	       begin
		    cnt <= cnt + 1'b1;
		if(cnt == 24'd12500000)
		    begin 
		       cnt <= 24'b0;
		       led <= ~led;
	            end 
		end 
always @ (posedge clk_25mhz or negedge sys_rst_n)
    if(!sys_rst_n)
        begin
            rgb_reg <= 12'b0;
        end 
    else
        begin				//显示图像
	    //rgb_reg <= q_sig;			
	    rgb_reg[3:0] <= q_sig[7:4];
	    rgb_reg[7:4] <= q_sig[3:0];
	    rgb_reg[11:8] <= q_sig[11:8];	
	end		
always @ (posedge clk_25mhz or negedge sys_rst_n)
    if(!sys_rst_n)
        begin
            address_sig <= 19'b0;
        end 
    else
	begin				
	    if(pixel_x>=0 && pixel_x<= 639 && pixel_y>=0 && pixel_y<=479)
		address_sig = (pixel_x + 640*pixel_y);
	end	



//////////////////////////////////////////////////////////////		
assign rgb = (video_en == 1'b1) ? rgb_reg:12'b0;

vga_sync vga_syn_inst(
            .clk            (clk_25mhz),
            .rst_n          (sys_rst_n),
            .video_en       (video_en),
            .hsync          (hsync),
            .vsync          (vsync),
            .pixel_x        (pixel_x),
            .pixel_y        (pixel_y)
                       
        );

reg     [18:0]  address_sig;
wire    [11:0]  q_sig;

rom_pic rom_pic_inst (
  .clka(clk_25mhz),    // input wire clka
  .addra(address_sig),  // input wire [18 : 0] addra
  .douta(q_sig)  // output wire [11 : 0] douta
);

clk_wiz_0 clk_wiz_0_inst 
       (
       // Clock in ports
        .clk_in1(sys_clk),
        // Clock out ports
        .clk_out1(clk_25mhz)
       );
               
endmodule




三、生成coe文件

1.准备软件BmpToMif和Image2Lcd 下载

2.准备好640*480的彩色图片

3.打开Image2Lcd ,并且打开待显示的图片,并且按照下图配置参数:


4.配置完毕后,点击保存

5.打开BmpToMif,选择数据文件,打开刚才生成的bin文件,字长改为12,点击生成Mif文件(弹出的窗口可以选择否)。


6.用excel 打开生成的mif文件,选中这一列


7.然后在菜单栏中选择 数据->分列


8.选择分隔符号,下一步


9.选择其他,输入冒号(注意是英文的冒号),下一步

10.然后,按Ctrl+H,把分号换成逗号,(最后一组数据是分号)。


11.到此为止,图片的数据就准备好了,下面把数据添加到vivado,的coe文件里面。打开vivado,点击 IP Catalog ,搜索rom,双击 Block memory Cenerator


12.Memor type 选择Signal Poart ROM,Port A Opation按照如图所示配置


13.然后选择 Other Options(也可以先做好coe文件在此选择)

点击Edit,选择YES,输入文件名


14.radix 必须是2,vector可以先随便输,save,close

15.打开刚才新建的coe文件,按照如图所示的格式把生成的图像数据复制进来,注意最后一行数据以分号结束


16.至此,coe文件已经生成好了,ROM初始化的时候,会加载,供我们读取,显示在VGA上。


四、下面写好代码,生成bit文件后,就可以把代码烧到ZYNQ测试了


测试效果如图所示:


项目工程源码下载

oschina:点击打开链接

百度网盘链接:链接:http://pan.baidu.com/s/1mgER0VY 密码:mvkw


更多关于zynq开发相关的文章和问题请点击:

http://www.osrc.cn/forum.php?mod=forumdisplay&fid=292

http://blog.csdn.net/rzjmpb




Zedboard学习(七):VGA显示

VGA硬件接口到zedboard官方给出的原理图中查看: RGB信号,各四位;这里的设计是使用了电阻分压模拟了DAC芯片实现了4X4X4的RGB信号,如果要更好的显示效果还是建议使用专门的DAC...
  • hongbin_xu
  • hongbin_xu
  • 2017年08月02日 18:48
  • 1159

【ZYNQ-7000开发之十一】VGA RLT代码封装成AXI Stream

本编文章将对VGA的RTL代码,封装成AXI Stream,并且在vivado 里用TPG进行测试本篇文章的VGA RTL代码在【ZYNQ-7000开发之一】基础上修改,封装好的VGA Stream可...
  • RZJMPB
  • RZJMPB
  • 2016年01月29日 21:28
  • 3031

zynq设备树详解

设备树历史最详解 zynq设备树历史最详解 注:由于内核版本的演变,设备树成了任何使用较高版本Linux系统的设备平台所必须文件,然国内相关技术文档严重不足,本文是国外技术专栏的翻译,原文...
  • a746742897
  • a746742897
  • 2016年10月13日 09:19
  • 3344

zedboard 使用自制IP+HDMI显示

话说玩这块板子,也有好长时间了,实在是不怎么溜。连数据显示都搞了很久,这可是数据的一扇窗户啊。 不能看始终不过瘾是不。 好像大多使用的还是VGA的驱动方式,更通用,更简单。但是现在可是高清的时代,...
  • wejoncy
  • wejoncy
  • 2015年05月27日 22:04
  • 2400

-03-实时Prewitt边缘检测,第一步:硬件平台搭建【ARM NEON加速】

在上面的一篇里文章”-02-实时Prewitt边缘检测,640×480 @60fps【ARM NEON加速】 “里,提到了实时Prewitt边缘检测的硬件平台,展示了处理效果,还分享了视频 下面将详细...
  • vacajk
  • vacajk
  • 2017年03月19日 23:36
  • 1566

【ZedBoard实验随笔】OV7670 摄像头 简单总结

简单记录了OV7670调试过程一点心得。
  • mcupro
  • mcupro
  • 2016年09月08日 13:19
  • 3997

VGA视频调试总结

近几天在调试VGA接口,出现的问题是视频输出到显示器严重偏色。这里的偏色在GUI界面上尤为严重。单纯的看视频窗口的话只是偏暗色一些。从硬件角度来看,一般R、G、B三个信号当中的一个或者多个的发生不正常...
  • wxf_126
  • wxf_126
  • 2012年08月28日 00:13
  • 906

任意Mif文件生成器 BmpToMif

  • 2013年12月06日 00:15
  • 275KB
  • 下载

BmpToMif(Mif文件生成器)

  • 2010年03月30日 00:47
  • 272KB
  • 下载

BMP图片如何生成mif文件

rt,现在想用FPGA在VGA上显示图片。目前已经能驱动VGA显示,现在的想法是将一幅BMP格式的图片取模,然后存入FPGA中的ROM中,再例化到工程中。网上搜到了两款软件:Image2Lcd(简称I...
  • qq1403487323
  • qq1403487323
  • 2016年11月25日 10:13
  • 438
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【ZYNQ-7000开发之一】PL部分驱动VGA显示静态彩色图像
举报原因:
原因补充:

(最多只允许输入30个字)