跳转到主要内容

ZYNQ基础系列(三)VTC+VDMA+Vid_Out核 构建一个简单的显示通路的准备工作

demi 提交于

<font size="4" style="line-height: 40px;"><strong>构建一个简单的显示通路的部件</strong></font>

在上一篇ZYNQ基础系列(二) IO口模拟HDMI中,介绍了VGA到HDMI输出的IP核的使用方法,本文将先介绍三个VIVADO自带的视频输出通路相关的重要IP核,搭建一个比较简单的视频通路,为不久之后的摄像头到显示屏通路打下基础:

<pre>1&gt; Video Timing Controller
2&gt; AXI4-Stream to Video Out
3&gt; Video DMA</pre>

首先要对IP核的功能和配置有一个了解,才能做到肆无忌惮的去搭建通路

<font style="line-height: 40px;" color="red"><strong>VTC核</strong></font>

这个IP核其实可以就看做是一个时序发生器,产生显示器输出所需要的时序信号,有了此核之后,那些各种显示消隐区也就不需要怎么考虑了,省心了很多

<strong>1)引脚 </strong>

完整的引脚图如下:

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

Optional AXI4-Lite Control Interface : 用于通过AXI总线实时动态更换VTC核的参数
Detector Interface : 图中的Video Timing (input) Interface,探测器接口,用于捕捉视频时序然后处理
Generator Interface : 图中Video Timing (input) Interface,用于生成的视频时序

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

如果需要通过AXI总线对核进行配置的话,还需要去查一下各个寄存器的功能,这里暂时不需要动态配置,配置过程仅通过GUI配置一次

<strong>2)GUI配置 </strong>

第一页:

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

选项说明:

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

还是第一页:

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

现在只看时序生成的模式:

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

第二页:

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

第二页的配置尤为简单,选择分辨率,大部分的显示器都可以找的到对应的分辨率,如果没有的话,也可以自定义参数
可以看到参数后面有个范围([0-4095]),那是因为我们第一页选了4096,实际上不需要这么大

第三页:

帧同步位置,暂时不管它

注意 : 不知道是不是VIVADO版本的问题(我的是2017.4),VIVADO有个BUG,就是IP核在原理图中显示的引脚与实际不符

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

比如,clken明明是高电平有效的,他在引脚上画了个圈表示低有效,这就很糟心了,所以以后需要在原理图连线的话,都不要被表象欺骗了,最好是点进GUI配置界面看一看IP核预览(上面有图,这个GUI预览的引脚显示却是正常的)
我不是针对这一个IP核,总之,连原理图的时候,各个IP核的使能信号需要特别注意一下

<font style="line-height: 40px;" color="red"><strong>Vid_Out核</strong></font>

AXI4-Stream类型速度很快且容易处理,一般内部视频流都是这个格式,HLS做的图像处理核也是通过AXI4-Stream接口,这个HLS核一般也是放在VDMA的后面,但是AXI4-Stream终究是要转换为VIDEO接口来驱动外界的视频接收器(如显示屏),这个转换就由Vid_Out核来实现

这使得视频设计人员能够快速方便地将具有AXI4-Stream接口的视频处理模块连接到外部视频接收器,该核与VTC核协同工作,生成视频格式的时序信号(可以直接驱动VGA)

<strong>1)引脚 </strong>

完整的引脚图如下:

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

AXI4-Stream接口 : AXI4-Stream格式视频的输入接口
Video Timing Inputs接口 : VTC生成的时序输出的接入口
Video Outputs : 转换后的视频格式,可以直接驱动VGA(硬件电路允许的话)

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

<strong>2)GUI配置 </strong>

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center>
<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

<font style="line-height: 40px;" color="red"><strong>VDMA核</strong></font>

FrameBuffer帧缓存 : 每一存储单元对应屏幕上的一个像素,整个帧缓存对应一帧图像,相当于一块画布,画好之后直接通知显示设备显示

VDMA 核 : 可以方便的实现多帧缓存,也就是拥有多个画布,其最多可以控制32个画布,并可自由地进行画布切换;用户可以通过VDMA的写通道将 AXI-S类型的数据流转为Memory Map类型写入DDR,也可以通过读通道从DDR读取Memory Map类型数据以 AXI-S类型输出。VDMA本质上是一个数据搬运的核,为数据进出DDR提供了一种便捷的方案。

<strong>1)引脚 </strong>

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

虽然上面不是全部的引脚,但是几个重要的引脚和接口都已经展示出来了,下面再配一张VDMA核的框图,一起说明

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

从框图中可以看出,VDMA核主要由控制和状态寄存器、数据搬运模块、行缓冲构成,数据通过行缓冲缓存和数据搬运模块进出 DDR,实现读写数据,几个和外界通信的重要接口:
AXI4-Lite 接口(S_AXI_LITE) : PS通过该接口对VDMA实现配置
AXI4 Memory Map 读接口(M_AXI_MM2S) : 存储器的读接口(映射到存储器读)
AXI4 Memory Map 写接口(M_AXI_S2MM) : 存储器的写接口(映射到存储器写)
AXI4-S 主接口(M_AXIS_MM2S) : 存储器读出图像到AXI-S视频流
AXI4-S 从接口(S_AXIS_S2MM) : AXI-S视频流写入图像到存储器

主要引脚:

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

视频同步接口信号:

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

GenLock相关信号:

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

<strong>2)常用寄存器 </strong>

寄存器都是小端格式:

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

MM2S,也就是从DDR中读数据:

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

类似的S2MM(往DDR写数据):

<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

以MM2S为例大致说明重要寄存器的配置:

1 &gt; MM2S_VDMACR(00h)

MM2S的控制寄存器,重要的在后四位

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center>
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

注:具体可以查看手册PARK_PTR_REG(28h)寄存器,使用park模式,可以通过操作RdFrmPtrRef和WrFrmPtrRef,实现帧缓存任意切换

2 &gt; MM2S_VDMASR(04h)

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

重要的是bit0:Halted位,指示VDMA是否停止运行(1=停止),只读

3 &gt; MM2S_START_ADDRESS (5C~98h)

<pre> Xil_Out32((VDMA_BASEADDR + 0x5c), VIDEO_BASEADDR0);
Xil_Out32((VDMA_BASEADDR + 0x60), VIDEO_BASEADDR1);
Xil_Out32((VDMA_BASEADDR + 0x64), VIDEO_BASEADDR2);</pre>

用于存放帧存的起始地址,上述代码为只有3个帧存时的配置

帧存最多可以达到32个,但是5C~98h只够写16个,于是就需要配合MM2S_REG_INDEX(14h)寄存器,MM2S_REG_INDEX=1时:5Ch就是第17个帧存的起始地址

4 &gt; MM2S_FRMDLY_STRIDE(58h)

MM2S帧延迟(24-28bit)和跨度(0-15bit)寄存器

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

帧延迟:( Genlock Mode为Slave时有效),指定从接口比主接口至少要延迟多少个帧

跨度:相邻两行的第一个像素间的距离

5 &gt; MM2S_HSIZE(54h)和MM2S_VSIZE(50h)

假如是RGB 800*600(每个像素点3个字节)
MM2S_HSIZE用于指定一行有多少字节:800*3
MM2S_VSIZE用于指定有多少行:600(配置完就开始工作,所以对这个寄存器的配置,必须放在最后)

往DDR写数据的S2MM的相关寄存器与这些类似,具体的查看手册

<strong>3)SDK配置 </strong>

初始化配置的关键代码:

<pre>/* 帧存地址参数 */
#define DDR_BASEADDR 0x00000000
#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 DDR_BASEADDR + 0x3000000
#define VIDEO_BASEADDR2 DDR_BASEADDR + 0x4000000
/* 分辨率参数800*600分辨率 */
#define H_STRIDE 800
#define H_ACTIVE 800
#define V_ACTIVE 600
/*****************往DDR写数据设置**********************/
Xil_Out32((VDMA_BASEADDR + 0x030), 0x00000003);//使能循环模式
Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0);//帧存0地址
Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1);//帧存1地址
Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2);//帧存2地址
Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*4)); //跨度设置(800 * 4) bytes
Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*4)); //行宽设置(800* 4) bytes
Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE); //行数设置(600)
/*****************从DDR读数据设置**********************/
Xil_Out32((VDMA_BASEADDR + 0x000), 0x3);//使能循环模式
Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0);//帧存0地址
Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1);//帧存1地址
Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2);//帧存2地址
Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*4)); //跨度设置(800 * 4) bytes
Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*4)); //行宽设置(800* 4) bytes
Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); //行数设置(600)</pre>

<strong>4)GUI配置 </strong>

第一页:

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center>
<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

第二页:

<center><img width="600" src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center>
<center><img src="http://xilinx.eetrend.com/files/2019-12/%E5%8D%9A%E5%AE%A2/100046526-86…; alt=""></center><br>

【注】同步锁相模式: 四种方式,以S2MM(写通道为例),读通道可以类比出来

(1)Master模式
该通道不会跳过或重复任一帧数据,并把当前帧的编号输出到s2mm_frame_ptr_out 端口。
通道不会检测 s2mm_frame_ptr_in端口提供的帧编号。
Slave通道应跟随Master通道变化,但有一定的延迟。延迟大小预定义在寄存器s2mm_frmdly_stride[28:24]

(2)Slave模式
该通道会通过跳过或重复一些帧的方式,尝试与Master同步,会对s2mm_frame_ptr_in 端口进行采样,获取Master的帧编号,为了实现状态反馈,通道会把当前帧的编号输出到s2mm_frame_ptr_out 端口
指定通道工作在Slave模式,必须进行如下操作:
将 GenlockEn置位(S2MM_VDMACR[3]=1),使能主从通道间的 Genlock 同步
将 GenlockSrc置位(S2MM_VDMACR[7]=1),使能内部 Genlock 模式
如果在GUI配置中同时使能读写通道,该位默认置位
当 GenlockSRC置位时,VDMA 默认支持内部同步锁相总线(就没有必要在外部对帧指针端口 *_frame_ptr_out 和 *_frame_ptr_in进行连接了)
根据主从通道的帧率,使用 s2mm_frmdly_stride[28:24]设定合适的延迟时间。

(3)动态Master模式
动态 Master与Master的区别在于,主通道会跳过从通道正在操作的帧。动态 Master检测到Slave正在操作某帧的话,就会跳过该帧,在其他帧缓存中循环操作

(4)动态Slave模式
Dynamic Slave通道会操作Dynamic Master通道上一周期操作的帧,当动态 Slave比Master慢的时候,Slave会适当跳过一些帧

版权声明:本文为CSDN博主「long_fly」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/long_fly/article/details/78968043