OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 545|回复: 0

[国产FPGA] 《ATK-DFPGL22G 之FPGA开发指南》第二十五章 HDMI方块移动实验

[复制链接]

1070

主题

1081

帖子

2

精华

超级版主

Rank: 8Rank: 8

积分
4443
金钱
4443
注册时间
2019-5-8
在线时间
1199 小时
发表于 2023-11-24 18:07:25 | 显示全部楼层 |阅读模式
本帖最后由 正点原子运营 于 2023-11-24 18:07 编辑

第二十五章 HDMI方块移动实验

1)实验平台:正点原子 ATK-DFPGL22G开发板

2) 章节摘自【正点原子】ATK-DFPGL22G之FPGA开发指南_V1.0


4)全套实验源码+手册+视频下载地址:http://www.openedv.com/docs/boards/fpga/zdyz-PGL22G.html

5)正点原子官方B站:https://space.bilibili.com/394620890

6)FPGA技术交流QQ群:435699340

155537c2odj87vz1z9vj6l.jpg

155537nfqovl2gg9faaol9.png

在HDMI彩条显示实验中,我们成功地在显示器上显示出了静态的彩条图案。本章我们通过在屏幕上显示一个移动的小方块,来给大家演示如何使用HDMI接口显示动态图案。
本章包括以下几个部分:
1.1          简介
1.2          实验任务
1.3          硬件设计
1.4          程序设计
1.5          下载验证

1.1 简介
我们在“HDMI彩条显示实验”中对HDMI视频传输标准作了详细的介绍,包括HDMI接口定义、行场同步时序、以及显示分辨率等。如果大家对这部分内容不是很熟悉的话,请参考“HDMI彩条显示实验”中的简介部分。

1.2 实验任务
本章的实验任务是使用ATK-DFPGL22G开发板上的HDMI接口在显示器上显示一个不停移动的方块,要求方块移动到边界处时能够改变移动方向。显示分辨率为1280*720,刷新速率为60hz。

1.3 硬件设计
HDMI接口部分的硬件设计原理及本实验中各端口信号的管脚分配与“HDMI彩条显示实验”完全相同,请参考“HDMI彩条显示实验”中的硬件设计部分。

1.4 程序设计
图 25.4.1是根据本章实验任务画出的系统框图。其中,时钟生成IP核(pll_clk)生成1280*720分辨率所需的像素时钟75MHz、以及TMDS编码驱动IP核所需的像素时钟的5倍频率即75 * 5 = 375MHz。视屏驱动模块(video_driver)负责产生RGB时序,并输出来自RGB显示模块(video_display)的RGB数据。RGB数据被送入TMDS编码驱动模块(rgb2dvi_0)并最后输出到HDMI接口。                              
image001.png
图 25.4.1 HDMI方块移动实验系统框图
在“HDMI彩条显示实验”中,我们利用RGB驱动模块输出的像素点的横坐标,在RGB显示模块中完成了彩条图案的绘制。而在本次实验中,为了完成方块的显示,需要同时使用像素点的横坐标和纵坐标来绘制方块所在的矩形区域,另外还需要知道矩形区域左上角的顶点坐标。由于RGB显示的图像在行场同步信号的同步下不停的刷新,因此只要连续改变方块左上角顶点的坐标,并在新的坐标点处重新绘制方块,即可实现方块移动的效果。
各模块端口及信号连接如图 25.4.2所示:
image003.png
图 25.4.2 顶层模块原理图
图 25.4.2中的顶层模块(hdmi_block_move_top)、时钟分频IP核(pll_clk)、TMDS编码驱动模块(rgb2dvi_0)以及视频驱动模块(video_driver)均与“HDMI彩条显示实验”完全相同,只对视频显示模块(video _display)作了修改。因此,这里我们重点讲解视频显示模块,其他部分大家可以参考“HDMI彩条显示实验”。
视频显示模块的代码如下:
  1. 1   module  video_display(
  2. 2        input            pixel_clk,                //驱动时钟
  3. 3        input            sys_rst_n,                //复位信号
  4. 4        
  5. 5        input      [10:0 pixel_xpos,               //像素点横坐标
  6. 6        input      [10:0 pixel_ypos,               //像素点纵坐标   
  7. 7        output reg [23:0 pixel_data                //像素点数据
  8. 8        );   
  9. 9   
  10. 10  //parameter define   
  11. 11  parameter  H_DISP = 11'd1280;                  //分辨率--行
  12. 12  parameter  V_DISP = 11'd720;                   //分辨率--列
  13. 13  
  14. 14  localparam SIDE_W  = 11'd40;                    //屏幕边框宽度
  15. 15  localparam BLOCK_W = 11'd40;                   //方块宽度
  16. 16  localparam BLUE    = 24'b00000000_00000000_11111111;    //屏幕边框颜色 蓝色
  17. 17  localparam WHITE   =24'b11111111_11111111_11111111;    //背景颜色 白色
  18. 18  localparam BLACK   =24'b00000000_00000000_00000000;    //方块颜色 黑色
  19. 19  
  20. 20  //reg define
  21. 21  reg [10:0 block_x =SIDE_W ;                             //方块左上角横坐标
  22. 22  reg [10:0 block_y =SIDE_W ;                             //方块左上角纵坐标
  23. 23  reg [21:0 div_cnt;                             //时钟分频计数器
  24. 24  reg        h_direct;                            //方块水平移动方向,1:右移,0:左移
  25. 25  reg        v_direct;                            //方块竖直移动方向,1:向下,0:向上
  26. 26  
  27. 27  //wire define   
  28. 28  wire move_en;                                   //方块移动使能信号,频率为100hz
  29. 29  
  30. 30  //*****************************************************
  31. 31  //**                    main code
  32. 32  //*****************************************************
  33. 33  assign move_en = (div_cnt == 22'd750000) ? 1'b1 : 1'b0;
  34. 34  
  35. 35  //通过对vga驱动时钟计数,实现时钟分频
  36. 36  always @(posedge pixel_clk ) begin         
  37. 37       if (!sys_rst_n)
  38. 38           div_cnt <= 22'd0;
  39. 39       else begin
  40. 40           if(div_cnt < 22'd750000)
  41. 41               div_cnt <= div_cnt + 1'b1;
  42. 42           else
  43. 43               div_cnt <= 22'd0;                   //计数达10ms后清零
  44. 44       end
  45. 45  end
  46. 46  
  47. 47  //当方块移动到边界时,改变移动方向
  48. 48  always @(posedge pixel_clk ) begin         
  49. 49       if (!sys_rst_n) begin
  50. 50           h_direct <= 1'b1;                      //方块初始水平向右移动
  51. 51           v_direct <= 1'b1;                      //方块初始竖直向下移动
  52. 52       end
  53. 53       else begin
  54. 54           if(block_x == SIDE_W - 1'b1)            //到达左边界时,水平向右
  55. 55               h_direct <= 1'b1;               
  56. 56           else                                    //到达右边界时,水平向左
  57. 57           if(block_x == H_DISP - SIDE_W - BLOCK_W)
  58. 58               h_direct <= 1'b0;               
  59. 59           else
  60. 60               h_direct <= h_direct;
  61. 61               
  62. 62           if(block_y == SIDE_W - 1'b1)            //到达上边界时,竖直向下
  63. 63               v_direct <= 1'b1;               
  64. 64           else                                    //到达下边界时,竖直向上
  65. 65           if(block_y == V_DISP - SIDE_W - BLOCK_W)
  66. 66               v_direct <= 1'b0;               
  67. 67           else
  68. 68               v_direct <= v_direct;
  69. 69       end
  70. 70  end
  71. 71  
  72. 72  //根据方块移动方向,改变其纵横坐标
  73. 73  always @(posedge pixel_clk ) begin         
  74. 74       if (!sys_rst_n) begin
  75. 75           block_x <= SIDE_W;                     //方块初始位置横坐标
  76. 76           block_y <= SIDE_W;                     //方块初始位置纵坐标
  77. 77       end
  78. 78       else if(move_en) begin
  79. 79           if(h_direct)
  80. 80               block_x <= block_x + 1'b1;          //方块向右移动
  81. 81           else
  82. 82               block_x <= block_x - 1'b1;          //方块向左移动
  83. 83               
  84. 84           if(v_direct)
  85. 85               block_y <= block_y + 1'b1;          //方块向下移动
  86. 86           else
  87. 87               block_y <= block_y - 1'b1;          //方块向上移动
  88. 88       end
  89. 89       else begin
  90. 90           block_x <= block_x;
  91. 91           block_y <= block_y;
  92. 92       end
  93. 93  end
  94. 94  
  95. 95  //给不同的区域绘制不同的颜色
  96. 96  always @(posedge pixel_clk ) begin         
  97. 97       if (!sys_rst_n)
  98. 98           pixel_data <= BLACK;
  99. 99       else begin
  100. 100          if(  (pixel_xpos < SIDE_W) || (pixel_xpos >= H_DISP - SIDE_W)
  101. 101            || (pixel_ypos < SIDE_W) || (pixel_ypos >= V_DISP - SIDE_W))
  102. 102              pixel_data <= BLUE;                 //绘制屏幕边框为蓝色
  103. 103          else
  104. 104          if(  (pixel_xpos >= block_x) && (pixel_xpos < block_x +BLOCK_W)
  105. 105            && (pixel_ypos >= block_y) && (pixel_ypos < block_y +BLOCK_W))
  106. 106              pixel_data <= BLACK;                //绘制方块为黑色
  107. 107          else
  108. 108              pixel_data <= WHITE;                //绘制背景为白色
  109. 109      end
  110. 110 end
  111. 111
  112. 112 endmodule
复制代码
代码中14至18行声明了一系列的参数,方便大家修改边框尺寸、方块大小、以及各部分的颜色等。其中边框尺寸和方块宽度均以像素点为单位。当方块的宽度确定时,如果我们知道方块左上方顶点的坐标,就能轻而易举的画出整个方块区域。因此,我们将方块的移动简化为其左上角顶点的移动。
由于像素时钟相对于方块移动速度而言过快,我们通过计数器对时钟计数,得到一个频率为100hz的脉冲信号move_en,用它作为使能信号来控制方块的移动(33~45行)。方块的移动方向分为水平方向h_direct和竖直方向v_direct,由代码的47至70行可知,当方块移动到上下边框时,竖直移动方向改变;当方块移动到左右边框时,水平移动方向改变。代码72至93行根据方块的移动方向,在使能信号move_en到来时改变其左上角顶点的纵横坐标值。当move_en的频率为100hz时,方块每秒钟在水平和竖直方向上分别移动100个像素点的距离,也可以通过调整move_en的频率,来加快或减慢方块移动的速度。
代码第95至110行根据RGB驱动模块输出的纵横坐标判断当前像素点所在的区域,对不同区域中的像素点赋以不同的颜色值,从而实现边框、方块以及背景颜色的绘制。

1.5 下载验证
编译工程并生成比特流.sbit文件。然后将HDMI电缆的一端与ATK-DFPGL22G开发板上HDMI插座相连接,另一端与显示器的HDMI接口相连接,如下图所示。
image005.png
图 25.5.1开发板HDMI连接图
最后将下载器一端连电脑,另一端与开发板上的JTAG端口连接,连接电源线并打开电源开关。
接下来我们下载比特流.sbit文件,验证HDMI显示方块移动的功能。下载完成后观察显示器显示的图案如下图所示,图中的黑色方块能够不停的移动,且碰撞到蓝色边框时能改变移动方向,说明HDMI方块移动程序下载验证成功。
image008.jpg
图 25.5.2  HDMI方块移动效果图
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

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

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2024-6-10 02:25

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表