[X]关闭

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

文档创建者:RZJM
浏览次数:9858
最后更新:2016-06-01
本帖最后由 RZJM 于 2015-12-16 20:39 编辑

在本篇文章中,将在Xilinx ZYNQ上实现用PL部分驱动VGA显示12bit的彩色图像,涉及到VGA的驱动原理,vivado上的PLL IP和ROM IP的使用以及彩色图像coe文件的生成。最后将提供整个项目代码。
本文所使用的开发板是Miz702(兼容zedboard),软件开发环境:vivado 2015.2
一、VGA的原理
VGA的协议比较简洁,主要是有五个信号线组成,行同步信号 HSYNC,场同步信号VSYNC和3条色彩电压传输信号(R、G、B分别对应)。色彩信
号的电压为 0~0.7V。本次要实现的分辨率是640*480,帧率是60Hz,所需要的时钟是25Mhz.话不多说,直接上图:

VGA 时序图

需要注意的是,VGA的时序图和参数表可以看出,每帧需要525个vsync脉冲,在每个vsync的周期中,即Tvsync,又包含着800个hsync脉冲,而图像RGB的有效时间在hsync的640个显示脉冲之中。
二、逻辑实现
  1. //vga_sync.v  VGA同步控制逻辑
  2. module vga_sync(
  3.         input   wire            clk,
  4.         input   wire            rst_n,
  5.         output  wire            video_en,              //数据有效
  6.         output  reg             hsync,                 //场同步信号
  7.         output  reg             vsync,                 //行同步信号
  8.         output  wire    [9:0]   pixel_x,               //待显示待像素的x坐标
  9.         output  wire    [9:0]   pixel_y                //待显示待像素的y坐标
  10.         );
  11.          
  12.         reg     [9:0] pixel_cnt;
  13.         reg     [9:0] line_cnt;
  14.                   
  15.                   
  16.         reg             v_video_en;
  17.         reg             h_video_en;
  18.         
  19.       
  20.         always @(posedge clk or negedge rst_n)
  21.             if(!rst_n)
  22.                 begin
  23.                     pixel_cnt <= 10'b0;
  24.                 end
  25.             else
  26.                 begin
  27.                     pixel_cnt <= pixel_cnt + 1'b1;
  28.                     if(pixel_cnt == 10'd799)
  29.                         begin
  30.                             pixel_cnt <= 10'b0;
  31.                         end
  32.                 end
  33.                
  34.                
  35.          always @(posedge clk or negedge rst_n)
  36.             if(!rst_n)
  37.                 begin
  38.                     h_video_en <= 1'b1;
  39.                     hsync <= 1'b1;
  40.                 end
  41.             else
  42.                 begin
  43.                     case (pixel_cnt)
  44.                         10'd0:
  45.                             begin
  46.                                 h_video_en <= 1'b1;
  47.                             end
  48.                         10'd639:
  49.                             begin
  50.                                 h_video_en <= 1'b0;
  51.                             end
  52.                         10'd655:
  53.                             begin
  54.                                 hsync <= 1'b0;
  55.                             end
  56.                         10'd751:
  57.                             begin
  58.                                 hsync <= 1'b1;
  59.                             end            
  60.                     endcase
  61.                 end
  62.                
  63.                
  64.                
  65.          always @(posedge clk or negedge rst_n)
  66.             if(!rst_n)
  67.                 begin
  68.                     line_cnt <= 10'b0;
  69.                 end
  70.             else
  71.                 begin
  72.                     if(pixel_cnt == 10'd799)
  73.                         begin
  74.                             line_cnt <= line_cnt + 1'b1;
  75.                         end
  76.                     
  77.                       if(line_cnt == 10'd524)
  78.                       begin
  79.                             line_cnt <= 10'b0;
  80.                       end
  81.                 end
  82.                
  83.         always @(posedge clk or negedge rst_n)
  84.             if(!rst_n)
  85.                 begin
  86.                     v_video_en <= 1'b1;
  87.                     vsync <= 1'b1;
  88.                 end
  89.             else
  90.                 begin
  91.                     case(line_cnt)
  92.                         10'd0:
  93.                             begin
  94.                                 v_video_en <= 1'b1;
  95.                             end
  96.                         10'd479:
  97.                             begin
  98.                                 v_video_en <= 1'b0;
  99.                             end
  100.                         10'd489:
  101.                             begin
  102.                                 vsync <= 1'b0;
  103.                             end
  104.                         10'd491:
  105.                             begin
  106.                                 vsync <= 1'b1;
  107.                             end
  108.                     endcase
  109.                 end               
  110.         assign pixel_x = pixel_cnt;
  111.         assign pixel_y = line_cnt;
  112.                   
  113.         assign video_en = ((h_video_en == 1'b1) &&  (v_video_en == 1'b1));
  114.         
  115. endmodule
  116. //由于开发板上的PL部分时钟是100Mh的,所以需要用PLL把VGA的基准时钟时钟分频到25Mhz
  117. //test_vga.v文件   利用上面的代码显示彩色图像
  118. module vga_test(
  119.                     input   wire            sys_clk,
  120.                     input   wire            sys_rst_n,
  121.                     output  wire            hsync,
  122.                     output  wire            vsync,
  123.                     output  wire   [11:0]   rgb,
  124.                     output  reg             led
  125.                 );
  126. //红_绿_蓝
  127. parameter        BLACK   = 12'b0000_0000_0000;  
  128. parameter        BLUE    = 12'b0000_0000_1111;
  129. parameter        GREEN   = 12'b0000_1111_0000;
  130. parameter        DIAN    = 12'b0000_1111_1111;
  131. parameter        RED     = 12'b1111_0000_0000;
  132. parameter        PURPLE  = 12'b1111_0000_1111;
  133. parameter        YELLOW  = 12'b1111_1111_0000;
  134. parameter        WHITE   = 12'b1111_1111_1111;
  135.                                          
  136. wire    [9:0]   pixel_x;
  137. wire    [9:0]   pixel_y;
  138. wire            clk_25mhz;
  139. reg     [11:0]  rgb_reg;
  140. //显示静态图像640*480
  141. reg        [23:0] cnt;
  142. always @(posedge clk_25mhz or negedge sys_rst_n)
  143.         if(!sys_rst_n)
  144.                 begin
  145.                     cnt <= 0;
  146.                     led <= 0;
  147.                 end
  148.         else
  149.                begin
  150.                     cnt <= cnt + 1'b1;
  151.                 if(cnt == 24'd12500000)
  152.                     begin
  153.                        cnt <= 24'b0;
  154.                        led <= ~led;
  155.                     end
  156.                 end
  157. always @ (posedge clk_25mhz or negedge sys_rst_n)
  158.     if(!sys_rst_n)
  159.         begin
  160.             rgb_reg <= 12'b0;
  161.         end
  162.     else
  163.         begin                //显示图像
  164.             //rgb_reg <= q_sig;                        
  165.             rgb_reg[3:0] <= q_sig[7:4];
  166.             rgb_reg[7:4] <= q_sig[3:0];
  167.             rgb_reg[11:8] <= q_sig[11:8];        
  168.         end               
  169. always @ (posedge clk_25mhz or negedge sys_rst_n)
  170.     if(!sys_rst_n)
  171.         begin
  172.             address_sig <= 19'b0;
  173.         end
  174.     else
  175.         begin                                
  176.             if(pixel_x>=0 && pixel_x<= 639 && pixel_y>=0 && pixel_y<=479)
  177.                 address_sig = (pixel_x + 640*pixel_y);
  178.         end        
  179. //////////////////////////////////////////////////////////////               
  180. assign rgb = (video_en == 1'b1) ? rgb_reg:12'b0;
  181. vga_sync vga_syn_inst(
  182.             .clk            (clk_25mhz),
  183.             .rst_n          (sys_rst_n),
  184.             .video_en       (video_en),
  185.             .hsync          (hsync),
  186.             .vsync          (vsync),
  187.             .pixel_x        (pixel_x),
  188.             .pixel_y        (pixel_y)
  189.                        
  190.         );
  191. reg     [18:0]  address_sig;
  192. wire    [11:0]  q_sig;
  193. rom_pic rom_pic_inst (
  194.   .clka(clk_25mhz),    // input wire clka
  195.   .addra(address_sig),  // input wire [18 : 0] addra
  196.   .douta(q_sig)  // output wire [11 : 0] douta
  197. );
  198. clk_wiz_0 clk_wiz_0_inst
  199.        (
  200.        // Clock in ports
  201.         .clk_in1(sys_clk),
  202.         // Clock out ports
  203.         .clk_out1(clk_25mhz)
  204.        );
  205.                
  206. 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测试了
测试效果如图所示:

项目工程源码下载
百度网盘链接:链接:http://pan.baidu.com/s/1mgER0VY 密码:mvkw





发表评论已发布 3

uisrc

发表于 2015-11-20 10:47:48 | 显示全部楼层

版主强大!版主牛人!
越努力越幸运!加油!

开开心心做设计

发表于 2016-5-30 09:31:29 | 显示全部楼层

那个生成cor的软件在哪能下载呢?

RZJM

发表于 2016-6-1 22:44:47 | 显示全部楼层

开开心心做设计 发表于 2016-5-30 09:31
那个生成cor的软件在哪能下载呢?

vivado自己带的

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则