文章目录
- [1 实验任务](#1 实验任务)
- [2 系统框图](#2 系统框图)
- [3 硬件设计](#3 硬件设计)
-
- [3.1 IP核配置](#3.1 IP核配置)
- [3.2 注意事项](#3.2 注意事项)
- [4 软件设计](#4 软件设计)
-
- [4.1 注意事项](#4.1 注意事项)
- [4.2 工程源码](#4.2 工程源码)
-
- [4.2.1 main.c文件](#4.2.1 main.c文件)
1 实验任务
基于14.1,使用Xilinx TPG(Test Pattern Generator) IP提供视频源,将视频数据通过VDMA写入PS侧内存,然后再通过VDMA将视频数据从PS侧内存读出来,最后通过HDMI接口发送出去,即实现视频转发的功能。
2 系统框图
基于14.1,添加TPG IP核作为视频源,连接到VDMA的写通道,如下图所示:
3 硬件设计
3.1 IP核配置
- 配置VDMA IP核
- (1)Basic页面
- 1)Frame Buffers:选择默认值3,即缓存3帧图像数据
- 2)Enable Write Channel:勾选,使能写通道
- 3)Write Burst Size:选择256,最大化传输效率
- 4)Line Buffer Depth:选择2048,图像分辨率为1920x1080,能够缓存一行像素数据
- (2)Advanced页面
- 1)保持默认值,采用动态同步锁相模式,写通道为主,读通道为从
- 1)保持默认值,采用动态同步锁相模式,写通道为主,读通道为从
- (1)Basic页面
- 配置TGP IP核
- (1)全部保持默认即可
- (1)全部保持默认即可
3.2 注意事项
为各个接口自动连线:必须手动指定主从接口和互联模块的时钟
- 为VDMA的M_AXI_S2MM接口连线:从接口是PS的S_AXI_HP0接口
- 为TPG的s_axi_CTRL接口连线:主接口是PS的M_AXI_GP0接口,注意
- (1)TPG只有一个时钟接口ap_clk,该时钟是AXI4-Stream data interface和AXI4-Lite control interface共用,所以时钟源选择的是Clocking Wizard输出的clk_out1时钟,即视频时钟,使输入视频和输出视频同步
- (1)TPG只有一个时钟接口ap_clk,该时钟是AXI4-Stream data interface和AXI4-Lite control interface共用,所以时钟源选择的是Clocking Wizard输出的clk_out1时钟,即视频时钟,使输入视频和输出视频同步
- 将TPG和VDMA连接起来,为VDMA的s_axis_s2mm_aclk连线,自动识别为Clocking Wizard输出的clk_out1时钟,即视频时钟
4 软件设计
4.1 注意事项
- TPG IP核生成一个背景为纯白,叠加一个黑色移动小方块的视频
- 当VDMA写通道停止时
- (1)VDMA写通道暂停接收视频数据,TPG暂停产生视频数据
- (2)VDMA读通道依然在发送数据
- 1)显示器上小方块停止移动
- 2)说明VDMA读通道在重复发送同一帧视频数据,该帧视频数据是VDMA写通道在停止前写入的最后一帧
- 3)符合动态同步锁相模式的工作机制,即读通道(Dynamic Genlock Slave)会操作写通道(Dynamic Genlock Master)上一个周期操作的帧
- 当VDMA写通道重启时
- (1)TPG恢复产生视频数据
- (2)显示器上小方块继续从停止的位置开始移动
4.2 工程源码
4.2.1 main.c文件
c
/********************************************************************/
#include "vdma/vdma_api.h"
#include "xparameters.h"
#include "stdio.h"
#include "sleep.h"
#include "xv_tpg.h"
/********************************************************************/
#define TPG_DEVICE_ID XPAR_V_TPG_0_DEVICE_ID
#define VDMA_DEVICE_ID XPAR_AXIVDMA_0_DEVICE_ID
#define MEMORY_BASEADDR XPAR_PS7_DDR_0_S_AXI_BASEADDR
#define IMAGE_WIDTH 1920
#define IMAGE_HEIGHT 1080
/********************************************************************/
/********************************************************************/
XV_tpg TpgInst;
XAxiVdma VdmaInst;
int FrameBufferAddr = (MEMORY_BASEADDR + 0x02000000);
/********************************************************************/
int main()
{
//
int Status;
u32 BackGndPatternId;
u32 ForeGndPatternId;
u32 BoxSize;
u32 BoxColorRed;
u32 BoxColorGreen;
u32 BoxColorBlue;
u32 MotionSpeed;
//
printf("Vdma Video Forward Test.\n");
//
Status = XV_tpg_Initialize(&TpgInst, TPG_DEVICE_ID);
if (Status == XST_FAILURE) {
printf("Error : video test pattern generator initialization failed.\n");
return XST_FAILURE;
}
//
BackGndPatternId = 0x8;
ForeGndPatternId = 0x1;
BoxSize = 0x20;
BoxColorRed = 0x00;
BoxColorGreen = 0x00;
BoxColorBlue = 0x00;
MotionSpeed = 0x2;
XV_tpg_Set_width(&TpgInst, IMAGE_WIDTH);
XV_tpg_Set_height(&TpgInst, IMAGE_HEIGHT);
XV_tpg_Set_bckgndId(&TpgInst, BackGndPatternId);
XV_tpg_Set_boxSize(&TpgInst, BoxSize);
XV_tpg_Set_boxColorR(&TpgInst, BoxColorRed);
XV_tpg_Set_boxColorG(&TpgInst, BoxColorGreen);
XV_tpg_Set_boxColorB(&TpgInst, BoxColorBlue);
XV_tpg_Set_motionSpeed(&TpgInst, MotionSpeed);
XV_tpg_Set_ovrlayId(&TpgInst, ForeGndPatternId);
XV_tpg_Start(&TpgInst);
XV_tpg_EnableAutoRestart(&TpgInst);
// 启动VDMA读写操作
Status = run_vdma_frame_buffer(&VdmaInst, VDMA_DEVICE_ID, IMAGE_WIDTH, IMAGE_HEIGHT, FrameBufferAddr, 0, 0, BOTH);
if (Status == XST_FAILURE) {
printf("Error : run vdma frame buffer failed.\n");
return XST_FAILURE;
}
//
while (1) {
//
sleep(10);
printf("Stop vdma channel.\n");
// XAxiVdma_DmaStop(&VdmaInst, XAXIVDMA_READ);
XAxiVdma_DmaStop(&VdmaInst, XAXIVDMA_WRITE);
//
sleep(5);
printf("Start vdma channel.\n");
// XAxiVdma_DmaStart(&VdmaInst, XAXIVDMA_READ);
XAxiVdma_DmaStart(&VdmaInst, XAXIVDMA_WRITE);
}
//
return XST_SUCCESS;
}
/*****************************************************************************/
/*****************************************************************************/