第二十一章 使用VDMA驱动HDMI显示
第二十一章 使用VDMA驱动HDMI显示
PL开发
在基础的工程上开发,可以将原来的工程拷贝重新命名。
另一种方式是将block design导出之后,会得到一个tcl脚本,可以改下设计名再重新导入。
-
使能I2C0,选择EMIO,用于配置HDMI芯片(PL侧连接的编码芯片),这里相当于将PS的I2C连接到了HDMI芯片,后面也是通过PS去配置。
-
配置时钟,FCLK_CLK0配置为100Mhz,FCLK_CLK1配置为150Mhz。150Mhz时钟用于VDMA读取数据。这是由于1080p 60帧的频率为148.5MHz,但包含同步和消隐时间,而VDMA传输的都是有效数据,因此设置为150MHz就可以满足要求。
3. 配置中断,使能IRQ_F2P,接收PL端的中断。
- 使能HP0接口,用于VDMA快速读取ddr。
5. 添加VDMA IP和配置。
配置项 | 配置 | 备注 |
---|---|---|
Address Width(32-64) | 64 | |
Frame Buffers | 1 | 帧缓存数 |
Memory Map Data Width | 64 | Memory Map接口,采用AXI4接口,与ZYNQ HP口进行数据交互,读取PS端DDR中的图像数据。 ZYNQ HP接口为64位接口。 |
Stream Data Width | 24 | AXI4 stream流接口,用来传输图像数据到HDMI接口。 由于RGB数据是24位的,设置成 24。 |
Line Buffer Depth | 4096 | 类似于fifo缓存,以Stream Data Width为单位,设置大些,可以缓存的数据越多。 |
Allow Unaligned Transfers | 使能 | 如果不使能,在软件中就要对数据按照Memory Map Data Width对齐,比如我们设置的是64,也就是要64位对齐。 但这里使能了,就可以进行不对齐的数据传输。 |
GenLock | 避免读和写通道同时访问同一个frame,而使图像显示不正常。 |
6. 添加视频时序控制器,此模块主要是用来产生图像的时序。 Enable Generation是产生输出时序的使能,选择之后会出现vtiming_out 总线信号。Enable Detetion 是用于检测输入时序信号的使能,如果使能,会出现vtiming_in总线,由于本实验为图像输出,因此不使能。
- 添加AXI流转视频输出控制器。
配置项 | 配置 | 备注 |
---|---|---|
Clock Mode | Independent | AXI4-Stream和Video 的时钟是独立的,异步的,common是同步的。 |
Timing Mode | Slave mode | VTC 是时序的Slave,由Video Out 模块通过clock enable控制时序的输出。 Master Mode指VTC是时序的master,不由Video Out控制。 |
8. 添加一个动态时钟控制器IP(来自开源软件),主要功能是根据不同的分辨率配置出不同的时钟输出,本
质上是调用了锁相环。
9. 连接。
10. 端口导出,并将端口改为合适的名字。
端口 | 说明 | 备注 |
---|---|---|
vid_io_out | vid_active_video vid_data[23,0] vid_hsync vid_vsync | |
IIC_0 | ||
视频时钟端口 | PXL_CLK_O |
- 保存设计后按F6 检查设计,没有问题后创建HDL文件 。
- 添加HDMI输出的xdc文件,约束管脚 。
- 编译生成bit文件,导出硬件。
地址映射
默认生成的ip核映射地址,可以进行更改。
PS开发
使用Vitis再导出硬件平台的基础上(xsa文件)创建应用程序,运行调试。
程序运行后HDMI输出pic_800_600.h头文件里定义的一张图片。
AXI VDMA 配置参数分析
基本配置信息
- 实例和设备标识
#define XPAR_XAXIVDMA_NUM_INSTANCES 1U // 系统中有1个VDMA实例
#define XPAR_AXI_VDMA_0_DEVICE_ID 0U // 设备ID为0
#define XPAR_AXI_VDMA_0_BASEADDR 0x80010000U // 基地址: 0x80010000
#define XPAR_AXI_VDMA_0_HIGHADDR 0x8001FFFFU // 高端地址: 0x8001FFFF (64KB地址空间)
- 通道配置
#define XPAR_AXI_VDMA_0_INCLUDE_MM2S 1U // ✅ 包含 Memory-to-Stream 通道
#define XPAR_AXI_VDMA_0_INCLUDE_S2MM 0U // ❌ 不包含 Stream-to-Memory 通道
含义: 这个VDMA只支持从内存读取数据发送到显示设备,不支持从摄像头等设备接收数据。
- 数据宽度配置
#define XPAR_AXI_VDMA_0_M_AXI_MM2S_DATA_WIDTH 64U // AXI内存接口: 64位
#define XPAR_AXI_VDMA_0_M_AXIS_MM2S_TDATA_WIDTH 24U // AXI Stream输出: 24位
含义:
-
从DDR内存读取时使用64位总线
-
输出到显示设备时使用24位RGB888格式
- 帧缓冲区配置
#define XPAR_AXI_VDMA_0_NUM_FSTORES 1U // 帧存储数量: 1个
#define XPAR_AXI_VDMA_0_MM2S_LINEBUFFER_DEPTH 4096U // 行缓冲区深度: 4096
含义: 只支持单帧缓冲,行缓冲区较大适合高分辨率显示。
高级功能配置
- 同步和时序控制
#define XPAR_AXI_VDMA_0_USE_FSYNC 1U // ✅ 使用帧同步信号
#define XPAR_AXI_VDMA_0_FLUSH_ON_FSYNC 1U // ✅ 帧同步时刷新缓冲区
#define XPAR_AXI_VDMA_0_ENABLE_VIDPRMTR_READS 1U // ✅ 允许视频参数读取
含义: VDMA与VTC时序控制器配合工作,基于VSYNC信号同步。
- 数据实时引擎 (DRE)
#define XPAR_AXI_VDMA_0_INCLUDE_MM2S_DRE 1U // ✅ MM2S通道包含DRE
#define XPAR_AXI_VDMA_0_INCLUDE_S2MM_DRE 0U // ❌ S2MM通道不包含DRE
含义: DRE可以在数据宽度不匹配时自动进行数据打包/解包。
- 生成锁 (GenLock) 配置
#define XPAR_AXI_VDMA_0_MM2S_GENLOCK_MODE 1U // MM2S主模式
#define XPAR_AXI_VDMA_0_MM2S_GENLOCK_NUM_MASTERS 1U // 1个主设备
#define XPAR_AXI_VDMA_0_INCLUDE_INTERNAL_GENLOCK 1U // 包含内部GenLock
含义: 用于多VDMA同步,这里配置为主模式。
- 散射聚集 (Scatter Gather)
#define XPAR_AXI_VDMA_0_INCLUDE_SG 0U // ❌ 不包含散射聚集功能
含义: 使用简单DMA模式,不支持复杂的分散内存传输。
调试配置
#define XPAR_AXI_VDMA_0_ENABLE_DEBUG_INFO_6 1U // 启用调试信息6
#define XPAR_AXI_VDMA_0_ENABLE_DEBUG_INFO_7 1U // 启用调试信息7
#define XPAR_AXI_VDMA_0_ENABLE_DEBUG_INFO_14 1U // 启用调试信息14
#define XPAR_AXI_VDMA_0_ENABLE_DEBUG_INFO_15 1U // 启用调试信息15
#define XPAR_AXI_VDMA_0_ENABLE_DEBUG_ALL 0U // ❌ 不启用所有调试
其他配置
#define XPAR_AXI_VDMA_0_ADDR_WIDTH 64U // 地址宽度: 64位
#define XPAR_AXI_VDMA_0_ENABLE_VERT_FLIP 0U // ❌ 不启用垂直翻转
DYNCLK配置参数分析
/* Peripheral Definitions for peripheral AXI_DYNCLK_0 */
#define XPAR_AXI_DYNCLK_0_BASEADDR 0x80000000 // 基地址
#define XPAR_AXI_DYNCLK_0_HIGHADDR 0x8000FFFF
VTC (Video Timing Controller) 配置参数分析
基本配置信息
- 设备标识和地址范围
#define XPAR_VTC_0_DEVICE_ID XPAR_V_TC_0_DEVICE_ID // 设备ID映射
#define XPAR_VTC_0_BASEADDR 0x80020000 // 基地址: 0x80020000
#define XPAR_VTC_0_HIGHADDR 0x8002FFFF // 高端地址: 0x8002FFFF (64KB地址空间)
含义: VTC核心位于地址 0x80020000-0x8002FFFF,共64KB地址空间。
- 工作模式配置
#define XPAR_VTC_0_GENERATE_EN 1 // ✅ 启用时序生成功能
#define XPAR_VTC_0_DETECT_EN 0 // ❌ 禁用时序检测功能
含义:
-
生成模式: 主动产生视频时序信号 (VSYNC, HSYNC, 空白信号等)
-
检测模式: 分析输入视频流的时序参数(当前禁用)
- 检测器配置(虽然检测模式禁用,但配置仍然存在)
#define XPAR_VTC_0_DET_HSYNC_EN 1 // ✅ 启用水平同步检测
#define XPAR_VTC_0_DET_VSYNC_EN 1 // ✅ 启用垂直同步检测
#define XPAR_VTC_0_DET_HBLANK_EN 1 // ✅ 启用水平空白检测
#define XPAR_VTC_0_DET_VBLANK_EN 1 // ✅ 启用垂直空白检测
#define XPAR_VTC_0_DET_AVIDEO_EN 1 // ✅ 启用活动视频检测
#define XPAR_VTC_0_DET_ACHROMA_EN 0 // ❌ 禁用活动色度检测
含义: 这些配置在检测模式下使用,但由于 DETECT_EN=0,当前不会生效。
代码分析
功能分析
先来分析下平台硬件和功能。
硬件 | 功能 | 备注 |
---|---|---|
I2C | 用于配置HDMI解码芯片 | |
VDMA | 从PS DDR里面读取数据然后转换为流模式(Stream) | |
AXI4-Stream to Video Out | 将流模式转换成HDMI解码芯片需要的视频模式 | |
Dynamic Clock Generator | 动态时钟配置模块,提供不同频率的时钟, 这个时钟提供给AXI4-Stream to Video Out,也提供给解码芯片 | |
Video Timing Controller | 通过VDMA可以获取到需要的数据,但是视频还需要其它的行场信号控制,就需要由该模块生成 | |
解码芯片 | 需要根据芯片手册I2C进行配置 |
功能流程
- I2C初始化
- vdma初始化
- 显示初始化(这里也设置了VDMA循环模式,能够使vdma循环输出)
- 显示开始(根据时序配置时钟、vtc,配置vdma开始传输)
- 设置显示图像
- 配置编码芯片和检测热插拔
重构后代码
github代码仓库