AXI VDMAでHDMI出力

概要

AXI VDMAの使い方についてのメモです。
ArtyZ7でHDMI出力をしてみたいと思います。
回路構成はArty-Z7のHDMI OUTのサンプルデザインを参考にデザインを一から作り直して調べていこうと思います。
この記事は、調べながら順に更新をしていこうと思います。

必要なもの

・ArtyZ7 (HDMI出力があるボード)
・Vivado 2017.3
DigilentのIPコア

Vivadoプロジェクトの作成

全体図

ZYNQ、VDMA、VTC、AXI4-Stream to Video Out、RGB2DVIなどを接続していきます。
(後日更新予定)

VDMAの設定

(後日更新予定)

VTCの設定

1080pで設定していきます。
画像2枚目の1080pの設定はVivado2017.1以降から追加されているようです。(たぶん…)


AXI4-Stream to Video Out

(後日更新予定)

RGB2DVI

Reset active high Disable
Generate SerialClk internally from pixel clock Disable
MMCM/PLL どっちでもいい?
TMDS clocking range >=120 MHz (1080p)
Invert TMDS lanes チェックなし

SDKプロジェクトの作成

ソースコード

ソースコード全体はこのようになりました。
必要最低限の構成です。

#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xaxivdma.h"

XAxiVdma vdma;

u8 framebuf[3][1920*1080*4];
u8 *pFrames[3];

int main()
{
    int Status;
    XAxiVdma_Config *vdmaConfig;
    XAxiVdma_DmaSetup vdmaDmaSetup;

    init_platform();

    for (int i=0; i<3; i++){
    	pFrames[i] = framebuf[i];
    }

    vdmaConfig = XAxiVdma_LookupConfig(XPAR_AXI_VDMA_0_DEVICE_ID);
    if (!vdmaConfig) return XST_FAILURE;

    Status = XAxiVdma_CfgInitialize(&vdma, vdmaConfig, vdmaConfig->BaseAddress);
    if(Status != XST_SUCCESS) return XST_FAILURE;

    // VDMAの設定
    vdmaDmaSetup.FrameDelay = 0;
    vdmaDmaSetup.EnableCircularBuf = 1;
    vdmaDmaSetup.EnableSync = 0;
    vdmaDmaSetup.PointNum = 0;
    vdmaDmaSetup.EnableFrameCounter = 0;
    vdmaDmaSetup.VertSizeInput = 1080;
    vdmaDmaSetup.HoriSizeInput = 1920 * 3;
    vdmaDmaSetup.FixedFrameStoreAddr = 0;
    vdmaDmaSetup.Stride = 1920 * 4;
    vdmaDmaSetup.FrameStoreStartAddr[0] = (u32)pFrames[0];
    vdmaDmaSetup.FrameStoreStartAddr[1] = (u32)pFrames[1];
    vdmaDmaSetup.FrameStoreStartAddr[2] = (u32)pFrames[2];

    Status = XAxiVdma_DmaConfig(&vdma, XAXIVDMA_READ, &vdmaDmaSetup);
    if(Status != XST_SUCCESS) return XST_FAILURE;

    Status = XAxiVdma_DmaSetBufferAddr(&vdma, XAXIVDMA_READ, vdmaDmaSetup.FrameStoreStartAddr);
    if(Status != XST_SUCCESS) return XST_FAILURE;

    Status = XAxiVdma_DmaStart(&vdma, XAXIVDMA_READ);
    if(Status != XST_SUCCESS) return XST_FAILURE;

    Status = XAxiVdma_StartParking(&vdma, 0, XAXIVDMA_READ);
    if(Status != XST_SUCCESS) return XST_FAILURE;

    for(int i=0; i<1920*1080*4; i++){
    	framebuf[0][i] = 0xff;
    }

    while(1);

    cleanup_platform();
    return 0;
}

VDMAの初期化

(後日更新予定)