接下来介绍的IP主要是对于本项目中具有一定作用的模块,在保留较高自由度的同时,也作为软核出现(但并不意味着前面的都是硬核),更有利于开发者进行后端设计。
1.AXI Video Direct Memory Access(VDMA IP)
1.1 从DMA到VDMA
首先要明确我们为什么要用DMA,同时VDMA相较于一般的DMA又有什么针对视频传输的优越性,在此基础上才能对该IP有更全面深入的认识。
DMA,全称Direct Memory Access,即直接存储器访问。DMA传输将数据从一个地址空间复制到另一个地址空间,提供在外设和存储器之间或者存储器和存储器之间的高速数据传输。CPU无时不刻的在处理着大量的事务,但有些事情却没有那么重要,比方说数据的复制和存储数据,如果我们把这部分的CPU资源拿出来,让CPU去处理其他的复杂计算事务,就可以更好地利用CPU资源。
在本项目中,一方面涉及到连续的视频流数据存储,另一方面硬件加速模块也无时无刻不在吞吐着大量数据,如果把这些任务全部交给CPU,显然会严重拖慢系统速度。
同样,DMA的数据传输也非常的“简单粗暴”,用户将源地址、目标地址、传输数据量这三个目标参数设定好后,DMA控制器就会启动数据传输,当剩余传输数据量为0时,达到传输终点,结束DMA传输 ,当然,DMA 还有循环传输模式 当到达传输终点时会重新启动DMA传输。将这个过程用AXI总线封装起来,就构成了AXI-DMA IP核。
VDMA则在DMA的基础上加入了帧缓存和双/多缓冲机制,另外,VDMA可以很好地契合Zynq内部架构,缩短开发周期。
-
帧缓存机制:简称帧缓存或显存,它是屏幕所显示画面的一个直接映象,又称为位映射图(Bit Map)或光栅。帧缓存的每一存储单元对应屏幕上的一个像素,整个帧缓存对应一帧图像。
-
双缓冲机制:类似于乒乓读写,对双缓冲其实就是开辟了两块缓冲空间,多缓冲就是多块,该机制将屏幕读取与视频数据写入的数据流分开,两者分别在不同地址进行,当某一帧写完后就立刻切换到另一个缓存地址接着写下一帧,同时屏幕开始读取在刚刚地址空间写完的数据,循环往复。
此外,VDMA还具有很多优势,具体列举如下所示:
使视频流能够高带宽直接接入内存。
高效的二维DMA操作。
独立的异步读写通道操作。
Gen-Lock帧存同步机制。
最多支持32个帧存。
支持视频格式动态切换。
猝发长度和行缓存深度可调节。
处理器可以控制IP的初始化、状态、中断和管理寄存器。
基础AXI流数据位宽为8的整数倍,如8
1.2 VDMA基础配置
现在,我们打开VDMA的配置界面,可以看到如下接口,我们根据其功能,可以大致将其分为5组AXI总线:

- AXI4-Lite接口(S_AXI_LITE):PS通过该接口来配置VDMA
- AXI4读接口(M_AXI_MM2S):映射到存储器读
- AXI4写接口(M_AXI_S2MM):映射到存储器写
- AXI4-Stream主接口(M_AXI_MM2S):AXI Stream视频流读出图像
- AXI4-Stream从接口(S_AXI_S2MM):AXI Stream视频流写入图像
各种总线都有自己的时钟信号,但这些时钟是异步的,并不需要用同一个时钟。但在设计过程中,如无特别需求,可以使用相同的时钟以降低设计难度。
前缀S_、M_分别表示Slave和Master;后缀MM2S、S2MM说明数据流向是从memory map到stream还是从stream到memory map。
通过该配置图也可以发现并不是每个端口都一定使能,我们可以通过只使能读/写通道disable掉一些端口。
关于VDMA为什么采用不同种类的AXI接口实现功能,会在后面进行详细介绍。
1.3 VDMA高级配置
除了上述所说AXI总线信号之外,该IP还内置了视频同步接口信号和GenLock相关信号,下面分别进行介绍:
视频同步接口信号
mm2s_fsync:MM2S帧同步输入。使能该信号后,VDMA操作开始于fsync每个下降沿。该信号至少要持续一个m_axis_mm2s_aclk时钟周期ss2m_fsync:S2MM帧同步输入。使能该信号后,VDMA操作开始于fsync每个下降沿。该信号至少要持续一个s_axis_s2mm_aclk时钟周期
GenLock相关信号
Genlock,同步锁相,可以使一套或多套系统与同一同步源实现同步。能够使视频的刷新和外部视频源保持一致。当提供了一个适当的信号后,系统就会把它的显示刷新率和这个信号进行锁定 。
在许多视频应用中,输入端产生数据的速率往往不同于输出端数据速率,为了避免由速率不一致导致的潜在错误,帧缓冲的使用是很有必要的。帧缓冲机制开辟多个缓冲页,用于保存数据,输入和输出端分别操作不同的帧存,从而避免了冲突。
VDMA的锁相同步特性正是用于阻止读、写通道同时操作同一个帧存。VDMA的每个通道都可以选择自己的操作类型(同步锁相主/从或者动态同步锁相主/从),利用该特性,禁止主从接口同时访问同一缓存,从而保持同步。
VDMA支持四种形式的锁相同步,分别如下所示:
Genlock Master
-
读通道(MM2S):当配置为Genlock Master时,该通道不会跳过或者重复任一帧数据,并把当前帧的编号输出在mm2s_frame_ptr_out端口。通道不会检测mm2s_frame_ptr_in端口提供的帧编号。Genlock Slave通道应跟随Genlock Master通道变化,但有一定的延迟。延迟大小预定义在寄存器中(*frmdly_stride[28:24])。
-
写通道(S2MM):当配置为Genlock Master时,该通道不会跳过或者重复任一帧数据,并把当前帧的编号输出到s2mm_frame_ptr_out端口。通道不会检测s2mm_frame_ptr_in端口提供的帧编号。Genlock Slave通道应跟随Genlock Master通道变化,但有一定的延迟。延迟大小预定义在寄存器中(*frmdly_stride[28:24])。
Genlock Slave
-
读通道(MM2S):当配置为Genlock Slave时,该通道会通过跳过或者重复一些帧的方式,尝试与Genlock Master同步。通道会对mm2s_frame_ptr_in端口进行采样,获取Genlock Master的帧编号。为了实现状态反馈,通道会把当前帧的编号输出到mm2s_frame_ptr_out端口。
-
写通道(S2MM):当配置为Genlock Slave时,该通道会通过跳过或者重复一些帧的方式,尝试与Genlock Master同步。通道会对s2mm_frame_ptr_in端口进行采样,获取Genlock Master的帧编号。为了实现状态反馈,通道会把当前帧的编号输出到s2mm_frame_ptr_out端口。
Dynamic Genlock Master
动态Genlock Master与Genlock Master的区别在于,主通道会跳过从通道正在操作的帧。举例而言,对于三帧存而言,动态Genlock Master会按照0,1,2,0,1,2的顺序循环使用帧存,一旦检测到Master即将操作Slave正在操作的帧,就会跳过该帧继续循环。因此,如果Slave通道一直在操作帧存1,那么Master通道就会在帧0和帧2之间来回切换。
Dynamic Genlock Slave
Dynamic Genlock Slave通道会操作Dynamic Genlock Master通道上一周期操作的帧。
1.4 VDMA寄存器简介
VDMA为开发者预留了很大的自主配置空间,借此我们可以实现一系列自定义配置,这些配置主要是通过AXI-Lite配置寄存器实现的。
关于各寄存器的详细介绍可以阅读Xilinx官方的文档,这里仅就其中部分内容做概括性介绍,方便我们快速知道哥哥寄存器的地址和功能。同时要注意这里的地址都是偏移量,实际地址由开发者自己决定的基地址偏移得到。
| 寄存器名称 | 偏移地址 | 详细描述 |
|---|---|---|
MM2S_VDMACR |
00h | MM2S VDMA控制寄存器 |
MM2S_VDMASR |
04h | MM2S VDMA状态寄存器 |
MM2S_REG_INDEX |
14h | MM2S寄存器索引 |
PARK_PRT_REG |
28h | MM2S和S2MM Park指针寄存器 |
VDMA_VERSION |
2Ch | VDMA版本寄存器 |
S2MM_VDMACR |
30h | S2MM VDMA控制寄存器 |
S2MM_VDMASR |
34h | S2MM VDMA状态寄存器 |
S2MM_VDMA_IRQ_MASK |
3Ch | S2MM错误中断掩码寄存器 |
S2MM_REG_INDEX |
44h | S2MM寄存器索引 |
MM2S_VSIZE |
50h | MM2S垂直方向显示大小寄存器 |
MM2S_HSIZE |
54h | MM2S水平方向显示大小寄存器 |
MM2S_FRMDLY_STRIDE |
58h | MM2S帧延迟和跨度寄存器 |
MM2S_START_ADDRESS(1~16) |
5Ch~98h | MM2S帧存起始地址(1~16) |
S2MM_VSIZE |
A0h | S2MM垂直方向显示大小寄存器 |
S2MM_HSIZE |
A4h | S2MM水平方向显示大小寄存器 |
S2MM_FRMDLY_STRIDE |
A8h | S2MM帧延迟和跨度寄存器 |
S2MM_START_ADDRESS(1~16) |
ACh~E8h | S2MM帧存起始地址(1~16) |
2.Video Timing Controller(VTC IP)
2.1 IP概览
这是一个Xilinx官方提供的视频时序生成IP,开发者可以借此快速生成视频时序以进行后续处理,同时该IP内置了可选的AXI-Lite接口和可选的中断控制端口
,支持AXI-Lite接口协议,即支持ARM对内部寄存器的动态配置。一般是在HDMI显示输出的分辨率,需要动态改变的情况下才使用AXI-Lite接口,所以在较简单的设计中可以不使能。
该IP相关配置如下图所示,从中可以看出这些信号并不总是有效的,可以根据需要选择或关闭其中部分接口。

其中Generation为时序生成端口,可以将用户配置的时序信号输出用于后续的视频控制,Detection为时序检测端口,可以检测用户生成的时序信号是否合理,两者至少使能一个才能正常生成该IP。而有关视频输出的具体时序要求(即行有效,帧有效,数据使能等)的作用和性质在此不做赘述,默认读者已经具备了这方面的知识。
该IP可以直接设置常用分辨率(1080P、720P、480P)也可以根据开发需要自定义时序,对应设置在Video Mode处,但当自定义时序时,下列的所有参数需要合理配置。以下做简单介绍。
现在假设我们得到了一块屏幕,需要对其进行自定义分辨率设计,我们首先需要根据该屏幕的尺寸大小找到相关参数。例如如下是对1024*600的参数说明:

Horizontal Settings
$active\ size = 1024$,直接输入即可
$Frame\ size = 1344$,直接输入即可
$Sync\ start = active\ size + Front\ porch = 1024+150 = 1174$
$Sync\ end = active\ size + Front\ porch + Hsync\ width = 1024+150+10 = 1184$
Frame/Field 0 Vertical Settings
$active\ size = 600$,直接输入即可
$Frame\ size = 635$,直接输入即可
$Sync\ start = active\ size + Front\ porch = 600+7 = 607$
$Sync\ end = active\ size + Front\ porch + Hsync\ width = 600+7+5= 612$
其余属于微调设置,一般用不到,可以保持默认或者置零。
2.2 端口介绍
下面就该IP的输入输出端口进行简单介绍:
通用接口
| 信号名称 | 方向 | 位宽 | 描述 |
|---|---|---|---|
clk |
input | 1 | IP核时钟 |
clken |
input | 1 | IP核时钟使能,高有效 |
det_clken |
input | 1 | 时序检测时钟使能,高有效 |
gen_clken |
input | 1 | 时序生成时钟使能,高有效 |
resetn |
input | 1 | IP核同步复位,低有效 |
irq |
output | 1 | 中断请求输出,上升沿触发 |
intc_if |
output | 32 | 当“Include INTC Interface”或C_HSA_INTC_IF选中时生效 |
时序检测接口(视频时序输入接口)
| 信号名称 | 方向 | 位宽 | 描述 |
|---|---|---|---|
field_id_in |
input | 1 | (可选)奇偶场标识,隔行视频中使能field id时生效 |
hsync_in |
input | 1 | 行同步 |
hblank_in |
input | 1 | 行消隐 |
vsync_in |
input | 1 | 场同步 |
vblank_in |
input | 1 | 场消隐 |
active_video_in |
input | 1 | 视频有效 |
active_chrome_in |
input | 1 | (可选)对应VIDEO_FORMAT和CHROMA_PARITY位,极性自适应。如果不连接相应信号,则必须取消相应选项。 |
时序生成接口(视频时序输出接口)
| 信号名称 | 方向 | 位宽 | 描述 |
|---|---|---|---|
field_id_out |
output | 1 | (可选)隔行信号场id,极性在Generator Polarity Register(0x006C)中设置。仅在支持隔行视频且使能field id生成时有效。 |
hsync_out |
output | 1 | 行同步,在GENERATOR HSYNC寄存器中设置起始和结束周期。 |
hblank_out |
output | 1 | 行消隐,在GENERATOR HSIZE寄存器中设置起始和结束周期。 |
vsync_out |
output | 1 | 场同步,在GENERATOR F#_VSYNC_V寄存器中设置起始和结束行。 |
vblank_out |
output | 1 | 场消隐,在GENERATOR VSIZE寄存器中设置起始和结束行 |
active_video_out |
output | 1 | 非消隐行第一个时钟生效,GENERATOR ACTIVE_SIZE中设置结束周期。 |
active_chroma_out |
output | 1 | 表示哪些行包含有效色度采样(用于YUV420),非消隐行生效,在GENERATOR Encoding寄存器中配置VIDEO_FORMAT以及CHROMA_PARITY位。 |
帧同步信号
| 信号名称 | 方向 | 位宽 | 描述 |
|---|---|---|---|
sync_out |
output | FrameSyncs | 帧同步输出,延迟可设,最大16路。 |
fsync_in |
input | 1 | 帧同步输入,高有效。使能时,时序生成会与此信号同步。 |
sof_state |
input | 1 | AXI4-S帧起始信号,当与AXI4视频输出IP一起使用时连接VTC。 |
2.3 寄存器配置介绍
寄存器列表如下,具体的寄存器含义建议直接查阅官方文档PG016.
| 偏移地址 | 名称 | 访问类型 | 双缓冲 | 默认值 | 描述 |
|---|---|---|---|---|---|
| 0x0000 | CONTROL | R/W | Y | 0 | 通用控制 |
| 0x0004 | STATUS | R/WC | N | 0 | 状态寄存器,写1清除 |
| 0x0008 | ERROR | R/WC | N | 0 | 附加状态核错误寄存器,写1清除 |
| 0x000C | IRQ_ENABLE | R/W | N | 0 | 中断使能/失能 |
| 0x0010 | VERSION | R | N/A | 0X06010001 | IP核版本信息 |
| 0x0014 | ADAPTIVE_SYNC_CTRL | R/W | N/A | 0 | 自适应同步控制 |
| 0x0018 | Stretch Limit | R/W | N/A | 0 | 自适应同步时最大Front porch |
| 0x0020 | DETECTOR ACTIVE_SIZE | R | N/A | 0 | 有效行场尺寸(不含消隐) |
| 0x0024 | DETECTOR TIMING_STATUS | R | N/A | 0 | 时序检测状态 |
| 0x0028 | DETECTOR ENCODING | R | N/A | 0 | 帧编码 |
| 0x002C | DETECTOR POLARITY | R | N/A | 0 | 消隐同步信号极性 |
| 0x0030 | DETECTOR HSIZE | R | N/A | 0 | 水平宽度(含消隐) |
| 0x0034 | DETECTOR VSIZE | R | N/A | 0 | 垂直高度(含消隐) |
| 0x0038 | DETECTOR HSYNC | R | N/A | 0 | 水平同步信号起止时钟 |
| 0x003C | DETECTOR F0_VBLANK_H | R | N/A | 0 | 场0垂直消隐起止时钟 |
| 0x0040 | DETECTOR F0_VSYNC_V | R | N/A | 0 | 场0垂直同步起止行 |
| 0x0044 | DETECTOR F0_VSYNC_H | R | N/A | 0 | 场0垂直同步起止时钟 |
| 0x0048 | DETECTOR F1_VBLANK_H | R | N/A | 0 | 场1垂直消隐起止时钟 |
| 0x004C | DETECTOR F1_VSYNC_V | R | N/A | 0 | 场1垂直同步起止行 |
| 0x0050 | DETECTOR F1_VSYNC_H | R | N/A | 0 | 场1垂直同步起止时钟 |
| 0x0060 | GENERATOR ACTIVE_SIZE | R/W | Y | GUI设置 | 场0行场尺寸 |
| 0x0064 | GENERATOR TIMING_STATUS | R | N | GUI设置 | 时序检测状态 |
| 0x0068 | GENERATOR ENCODING | R/W | Y | GUI设置 | 帧编码 |
| 0x006C | GENERATOR POLARITY | R/W | Y | GUI设置 | 消隐同步信号极性 |
| 0x0070 | GENERATOR HSIZE | R/W | Y | GUI设置 | 水平宽度(含消隐) |
| 0x0074 | GENERATOR VSIZE | R/W | Y | GUI设置 | 垂直高度(含消隐) |
| 0x0078 | GENERATOR HSYNC | R/W | Y | GUI设置 | 水平同步信号起止时钟 |
| 0x007C | GENERATOR F0_VBLANK_H | R/W | Y | GUI设置 | 场0的垂直消隐起止时钟 |
| 0x0080 | GENERATOR F0_VSYNC_V | R/W | Y | GUI设置 | 场0的垂直同步起止行 |
| 0x0084 | GENERATOR F0_VSYNC_H | R/W | Y | GUI设置 | 场0的垂直同步起止时钟 |
| 0x0088 | GENERATOR F1_VBLANK_H | R/W | Y | GUI设置 | 场1的垂直消隐起止时钟 |
| 0x008C | GENERATOR F1_VSYNC_V | R/W | Y | GUI设置 | 场1的垂直同步起止行 |
| 0x0090 | GENERATOR F1_VSYNC_H | R/W | Y | GUI设置 | 场1的垂直同步起止时钟 |
| 0x0094 | GENERATOR ACTIVE_SIZE | R/W | Y | GUI设置 | 场1的行场尺寸 |
| 0x0100 ~ 0x013C | FRAME SYNC 0 - 15 CONFIG | R/W | Y | 0 | 帧同步输出的起始时钟和起始行 |
| 0x0140 | GENERATOR GLOBAL DELAY | R/W | Y | 0 | 生成延时 |
3.AXI4-Stream to Video Out IP
3.1 IP概览
AXI4-Stream to Video Out(AXIS-Stream到视频输出)是一种IP核,用于将AXI4-Stream格式的视频数据转换为标准的视频输出格式。它主要用于视频处理系统中,能够接收来自不同源(如摄像头或视频处理单元)的数据流,并将其输出为可显示的图像或视频信号。
该IP的基础配置界面如下图所示:

其中我们可以配置输入输出信号的位宽与中间缓存区FIFO的深度。
Clock Mode用于时钟域划分,Common时AXI与VGA共用同一个时钟,Independent则分两个时钟。Timing Mode可将其配置为主机/从机模式。Hysteresis Level则可以设置滞后级别。
在配置时需要注意以下关键点:
-
输出的视频(或者说是图像)的速率是由视频相关的标准规定的,比如你 RGB888 1080p 60Hz 的分辨率,其实是可以计算出你需要的带宽的,所以在输出端的带宽是可以计算出来的,并且一定是遵循了视频标准的;
-
输入的 AXI4-Stream 数据速率没必要和输出的视频速率匹配(因为是可以支持到异步 FIFO),但是为了视频输出正常,最好是输入速率不能够太低,否则无法满足正常的视频帧的输出;
-
输入的 AXI4-Stream 速率可以比像素时钟稍微小一些,因为随着像素时钟输出的视频数据,存在消隐区,也就是说,随着像素时钟输出的并不是 100% 的显示数据,但是随着 AXI4-Stream 输入的数据,是 100% 的有效显示数据;
-
为了满足正常显示并合理的数据率(比如 1080p 60Hz),输出端速度已定,输入端需要足够的带宽,所以 AXI4-Stream 的数据率不能够太低;
3.2 端口介绍
该IP的接口概述如下表所示,更详细的说明详见Xilinx官方文档。
| 信号名称 | 方向 | 位宽 | 描述 |
|---|---|---|---|
video_in |
input | interface | 视频数据输入 |
vtming_in |
input | interface | 视频时序信号输入 |
aclk |
input | 1 | AXI时钟信号 |
aclken |
input | 1 | AXI时钟使能信号 |
aresetn |
input | 1 | AXI复位信号 |
fid |
input | 1 | 帧指示信号:指示当前帧的奇偶性 |
vid_io_out_clk |
input | 1 | (可选)视频输出接口时钟信号 |
vid_id_out_ce |
input | 1 | (可选)视频输出接口时钟使能 |
vid_id_out_reset |
input | 1 | (可选)视频输出接口复位信号 |
vid_io_out |
output | interface | 视频数据输出 |
vtg_ce |
output | 1 | 视频时序生成器的时钟使能信号 |
locked |
output | 1 | 锁相信号,时钟稳定后拉低 |
overflow |
output | 1 | FIFO缓存区溢出信号 |
underflow |
output | 1 | FIFO缓存区欠流信号 |
fifo_read_level |
output | log2(FIFO_DEPTH) | FIFO缓冲区读取级别信号 |
status |
output | 32 | 提供IP核状态 |