Zedboard学习(二):VGA显示

2019-07-13 08:38发布

在本篇文章中,将实现在Xilinx ZYNQ上实现用PL部分驱动VGA显示12bit的彩 {MOD}图像,涉及到VGA的驱动原理,vivado上的PLL IP和ROM IP的使用以及彩 {MOD}图像coe文件的生成。最后将提供整个项目代码。 本文所使用的开发板是Miz702(兼容zedboard),软件开发环境:vivado 2015.2

一、VGA的原理

VGA的协议比较简洁,主要是有五个信号线组成,行同步信号 HSYNC,场同步信号VSYNC3条 {MOD}彩电压传输信号(RGB分别对应)。 {MOD}彩信
号的电压为
0~0.7V。本次要实现的分辨率是640*480,帧率是60Hz,所需要的时钟是25Mhz.话不多说,直接上图:
VGA 时序图
需要注意的是,VGA的时序图和参数表可以看出,每帧需要525个vsync脉冲,在每个vsync的周期中,即Tvsync,又包含着800个hsync脉冲,而图像RGB的有效时间在hsync的640个显示脉冲之中。

二、逻辑实现

//vga_sync.v VGA同步控制逻辑
  1. module vga_sync(
  2. input wire clk,
  3. input wire rst_n,
  4. output wire video_en, //数据有效
  5. output reg hsync, //场同步信号
  6. output reg vsync, //行同步信号
  7. output wire [9:0] pixel_x, //待显示待像素的x坐标
  8. output wire [9:0] pixel_y //待显示待像素的y坐标
  9. );
  10. reg [9:0] pixel_cnt;
  11. reg [9:0] line_cnt;
  12. reg v_video_en;
  13. reg h_video_en;
  14. always @(posedge clk or negedge rst_n)
  15. if(!rst_n)
  16. begin
  17. pixel_cnt <= 10'b0;
  18. end
  19. else
  20. begin
  21. pixel_cnt <= pixel_cnt + 1'b1;
  22. if(pixel_cnt == 10'd799)
  23. begin
  24. pixel_cnt <= 10'b0;
  25. end
  26. end
  27. always @(posedge clk or negedge rst_n)
  28. if(!rst_n)
  29. begin
  30. h_video_en <= 1'b1;
  31. hsync <= 1'b1;
  32. end
  33. else
  34. begin
  35. case (pixel_cnt)
  36. 10'd0:
  37. begin
  38. h_video_en <= 1'b1;
  39. end
  40. 10'd639:
  41. begin
  42. h_video_en <= 1'b0;
  43. end
  44. 10'd655:
  45. begin
  46. hsync <= 1'b0;
  47. end
  48. 10'd751:
  49. begin
  50. hsync <= 1'b1;
  51. end
  52. endcase
  53. end
  54. always @(posedge clk or negedge rst_n)
  55. if(!rst_n)
  56. begin
  57. line_cnt <= 10'b0;
  58. end
  59. else
  60. begin
  61. if(pixel_cnt == 10'd799)
  62. begin
  63. line_cnt <= line_cnt + 1'b1;
  64. end
  65. if(line_cnt == 10'd524)
  66. begin
  67. line_cnt <= 10'b0;
  68. end
  69. end
  70. always @(posedge clk or negedge rst_n)
  71. if(!rst_n)
  72. begin
  73. v_video_en <= 1'b1;
  74. vsync <= 1'b1;
  75. end
  76. else
  77. begin
  78. case(line_cnt)
  79. 10'd0:
  80. begin
  81. v_video_en <= 1'b1;
  82. end
  83. 10'd479:
  84. begin
  85. v_video_en <= 1'b0;
  86. end
  87. 10'd489:
  88. begin
  89. vsync <= 1'b0;
  90. end
  91. 10'd491:
  92. begin
  93. vsync <= 1'b1;
  94. end
  95. endcase
  96. end
  97. assign pixel_x = pixel_cnt;
  98. assign pixel_y = line_cnt;
  99. assign video_en = ((h_video_en == 1'b1) && (v_video_en == 1'b1));
  100. endmodule
//由于开发板上的PL部分时钟是100Mh的,所以需要用PLL把VGA的基准时钟时钟分频到25Mhz
//test_vga.v文件 利用上面的代码显示彩 {MOD}图像
  1. module vga_test(
  2. input wire sys_clk,
  3. input wire sys_rst_n,
  4. output wire hsync,
  5. output wire vsync,
  6. output wire [11:0] rgb,
  7. output reg led
  8. );
  9. //红_绿_蓝
  10. parameter BLACK = 12'b0000_0000_0000;
  11. parameter BLUE = 12'b0000_0000_1111;
  12. parameter GREEN = 12'b0000_1111_0000;
  13. parameter DIAN = 12'b0000_1111_1111;
  14. parameter RED = 12'b1111_0000_0000;
  15. parameter PURPLE = 12'b1111_0000_1111;
  16. parameter YELLOW = 12'b1111_1111_0000;
  17. parameter WHITE = 12'b1111_1111_1111;
  18. wire [9:0] pixel_x;
  19. wire [9:0] pixel_y;
  20. wire clk_25mhz;
  21. reg [11:0] rgb_reg;
  22. //显示静态图像640*480
  23. reg [23:0] cnt;
  24. always @(posedge clk_25mhz or negedge sys_rst_n)
  25. if(!sys_rst_n)
  26. begin
  27. cnt <= 0;
  28. led <= 0;
  29. end
  30. else
  31. begin
  32. cnt <= cnt + 1'b1;
  33. if(cnt == 24'd12500000)
  34. begin
  35. cnt <= 24'b0;
  36. led <= ~led;
  37. end
  38. end
  39. always @ (posedge clk_25mhz or negedge sys_rst_n)
  40. if(!sys_rst_n)
  41. begin
  42. rgb_reg <= 12'b0;
  43. end
  44. else
  45. begin //显示图像
  46. //rgb_reg <= q_sig;
  47. rgb_reg[3:0] <= q_sig[7:4];
  48. rgb_reg[7:4] <= q_sig[3:0];
  49. rgb_reg[11:8] <= q_sig[11:8];
  50. end
  51. always @ (posedge clk_25mhz or negedge sys_rst_n)
  52. if(!sys_rst_n)
  53. begin
  54. address_sig <= 19'b0;
  55. end
  56. else
  57. begin
  58. if(pixel_x>=0 && pixel_x<= 639 && pixel_y>=0 && pixel_y<=479)
  59. address_sig = (pixel_x + 640*pixel_y);
  60. end
  61. //////////////////////////////////////////////////////////////
  62. assign rgb = (video_en == 1'b1) ? rgb_reg:12'b0;
  63. vga_sync vga_syn_inst(
  64. .clk (clk_25mhz),
  65. .rst_n (sys_rst_n),
  66. .video_en (video_en),
  67. .hsync (hsync),
  68. .vsync (vsync),
  69. .pixel_x (pixel_x),
  70. .pixel_y (pixel_y)
  71. );
  72. reg [18:0] address_sig;
  73. wire [11:0] q_sig;
  74. rom_pic rom_pic_inst (
  75. .clka(clk_25mhz), // input wire clka
  76. .addra(address_sig), // input wire [18 : 0] addra
  77. .douta(q_sig) // output wire [11 : 0] douta
  78. );
  79. clk_wiz_0 clk_wiz_0_inst
  80. (
  81. // Clock in ports
  82. .clk_in1(sys_clk),
  83. // Clock out ports
  84. .clk_out1(clk_25mhz)
  85. );
  86. endmodule


三、生成coe文件


1.准备软件BmpToMif和Image2Lcd 下载 2.准备好640*480的彩 {MOD}图片 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:点击打开链接
百度 {MOD}链接:链接:http://pan.baidu.com/s/1mgER0VY 密码:mvkw
更多关于zynq开发相关的文章和问题请点击: http://www.osrc.cn/forum.php?mod=forumdisplay&fid=292 http://blog.csdn.net/rzjmpb