黑金HDMI显示通路搭建(续

DDR读取图像数据传输给video out输出图像成功

VDMA模块配置

在这里插入图片描述
在这里插入图片描述

​ VMDA通过AXI_LITE总线控制vdma模块的初始化,和参数配置,主要在SDK里面实现,目前VDMA只开启了DDR->VDMA->VIDEO_OUT->HDMI数据量,故只打开读通道。

按我的理解解释一下,有错请指正

  • Memory Map Data Width 数据带宽,一次输出来的数据宽度,ACU3EG核心板上配有5片Micron(美光)的1GB的DDR4芯片,型号为MT40A512M16LY-062E, 其中PS端挂载4片DDR4,组成64位数据总线带宽和4GB的容量。故选择64宽度
  • Read Burst Size 一次突发传输的数据个数,我一直以为这个8是 2^8 ,但其实就只是8,太搞笑了
  • Stream Data width 流接口数据带宽,黑白图像故是8位
  • Line Buffer Depth 缓冲空间
VTC

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这是我的配置,720P 60Hz。输入时钟为74.25Mhz

Video OUT

在这里插入图片描述

在这里插入图片描述

  • **video in ** 接入VDMA输出的流信号
  • vtiming in 接入VTC的时序控制信号
  • video Format 灰度格式
  • Hysteresis Level 好像是滞后时序,滞后了12拍?还没经过验证
Top.v

接入了HMDI硬件代码,提供时钟和视频信号接口就行,将之前的BD进行模块化,生成HDL代码。

`timescale 1ns / 1ps
//
// Company: 
// Engineer: 
// 
// Create Date: 2024/09/07 10:15:13
// Design Name: 
// Module Name: top
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//


module top(
input                    sys_clk_p,	
input                    sys_clk_n,

output                   hdmi_clk ,
output  [23:0]           hdmi_data,
output                   hdmi_de  ,
output                   hdmi_hs  ,
output                   hdmi_vs  ,
output					 hdmi_rstn,

output					 led	  ,

inout                    hdmi_scl,
inout                    hdmi_sda 
);
	
wire                     sys_clk		;	
(*mark_debug="true"*)wire					  rst_n			;	
(*mark_debug="true"*)wire                     clk_100M		;
(*mark_debug="true"*)wire   [9:0]             lut_index	    ;                  
(*mark_debug="true"*)wire   [31:0]            lut_data	    ;    



	
IBUFDS IBUFDS_inst (
      .O(sys_clk),   // 1-bit output: Buffer output
	  
	  
      .I(sys_clk_p),   // 1-bit input: Diff_p buffer input (connect directly to top-level port)
      .IB(sys_clk_n)  // 1-bit input: Diff_n buffer input (connect directly to top-level port)
   );	


clk_wiz_0 instance_name
 (
  // Clock out ports
  .clk_out1(clk_100M),     // output clk_out1
  // Status and control signals
  .locked(rst_n),       // output locked
 // Clock in ports
  .clk_in1(sys_clk));      // input clk_in1	


assign hdmi_rstn = rst_n;

	
lut_si9134 lut1(
	.lut_index		(lut_index	), // Look-up table index address
	.lut_data 		(lut_data	)  // I2C device address register address register data
);	
	
i2c_config i2c1(
	.rst					(~rst_n		),
	.clk					(clk_100M	),
	.clk_div_cnt			(16'd499    ),
	.i2c_addr_2byte		    (1'b0		),
	.lut_index              (lut_index                ),
	.lut_dev_addr           (lut_data[31:24]          ),
	.lut_reg_addr           (lut_data[23:8]           ),
	.lut_reg_data           (lut_data[7:0]            ),
	.error                  (                         ),
	.done                   (                         ),
	.i2c_scl                (hdmi_scl                 ),
	.i2c_sda                (hdmi_sda                 )
);
	
design_1_wrapper design1
   (
.clk_100M				(clk_100M   ),
.led					(led		),
.rst_n					(rst_n		),
.video_clk				(hdmi_clk   ),
.video_data				(hdmi_data  ),
.video_de				(hdmi_de    ),
.video_hs				(hdmi_hs    ),
.video_vs				(hdmi_vs    )
);

endmodule

  • 之前调试总不出波形,不知道是哪里的问题,后来发现lut_index信号已经变为2,这是已经连接上,说明是视频信号没有输出,VDMA没有正常启动,调了后就好了。
SDK设计
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "xil_types.h"
#include "xil_cache.h"
#include "xparameters.h"

#include "vdma.h"
//宏定义
#define BYTES_PIXEL        1                          //像素字节数,RGB888占3个字节
#define VDMA_ID            XPAR_AXIVDMA_0_DEVICE_ID   //VDMA器件ID

//函数声明
void graybar(u8 *frame, u32 width, u32 height, u32 stride);
//全局变量
XAxiVdma     vdma;
//frame buffer的起始地址
unsigned int const frame_buffer_addr = (XPAR_PSU_DDR_0_S_AXI_BASEADDR + 0x1000000);

int main(void)
{

	Xil_DCacheDisable();
	Xil_ICacheDisable();

	xil_printf("HDMI Display 1280*720 \r\n");

	//配置VDMA
	vdma_read_init(VDMA_ID,1280,720,1280,frame_buffer_addr);

	//写彩条
	graybar((u8*)frame_buffer_addr, 1280, 720, 1280);
    return 0;
}

//写彩条函数(彩虹色)
void graybar(u8 *frame, u32 width, u32 height, u32 stride)
{
	u32 x_pos, y_pos;
	u32 y_stride = 0;

	for (y_pos = 0; y_pos < height; y_pos++) {
		for (x_pos = 0; x_pos < (width * BYTES_PIXEL); x_pos += BYTES_PIXEL) {
			frame[x_pos + y_stride] = x_pos % 256;
		}
		y_stride += stride;
	}
	Xil_DCacheFlush();     //刷新Cache,数据更新至DDR3中
	xil_printf("show color bar\r\n");
}

#include "xil_printf.h"
#include "vdma.h"

u32 vdma_version(XAxiVdma *Vdma) {
	return XAxiVdma_GetVersion(Vdma);
}

int vdma_read_start(XAxiVdma *Vdma) {
	int Status;

	// MM2S Startup
	Status = XAxiVdma_DmaStart(Vdma, XAXIVDMA_READ);
	if (Status != XST_SUCCESS)
	{
	   xil_printf("Start read transfer failed %d\n\r", Status);
	   return XST_FAILURE;
	}

	return XST_SUCCESS;
}


int vdma_read_stop(XAxiVdma *Vdma) {
	XAxiVdma_DmaStop(Vdma, XAXIVDMA_READ);
	return XST_SUCCESS;
}


int vdma_read_init(short DeviceID,short HoriSizeInput,short VertSizeInput,short Stride,unsigned int FrameStoreStartAddr)
{
	XAxiVdma Vdma;
	XAxiVdma_Config *Config;
	XAxiVdma_DmaSetup ReadCfg;
	int Status;


	Config = XAxiVdma_LookupConfig(DeviceID);
	if (NULL == Config) {
		xil_printf("XAxiVdma_LookupConfig failure\r\n");
		return XST_FAILURE;
	}

	Status = XAxiVdma_CfgInitialize(&Vdma, Config, Config->BaseAddress);
	if (Status != XST_SUCCESS) {
		xil_printf("XAxiVdma_CfgInitialize failure\r\n");
		return XST_FAILURE;
	}

	

	ReadCfg.EnableCircularBuf = 1;
	ReadCfg.EnableFrameCounter = 0;
	ReadCfg.FixedFrameStoreAddr = 0;

	ReadCfg.EnableSync = 1;
	ReadCfg.PointNum = 1;

	ReadCfg.FrameDelay = 0;

	ReadCfg.VertSizeInput = VertSizeInput;
	ReadCfg.HoriSizeInput = HoriSizeInput;
	ReadCfg.Stride = Stride;

	Status = XAxiVdma_DmaConfig(&Vdma, XAXIVDMA_READ, &ReadCfg);
	if (Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,
				"Read channel config failed %d\r\n", Status);

			return XST_FAILURE;
	}


	ReadCfg.FrameStoreStartAddr[0] = FrameStoreStartAddr;

	Status = XAxiVdma_DmaSetBufferAddr(&Vdma, XAXIVDMA_READ, ReadCfg.FrameStoreStartAddr);
	if (Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,"Read channel set buffer address failed %d\r\n", Status);
			return XST_FAILURE;
	}


	Status = vdma_read_start(&Vdma);
	if (Status != XST_SUCCESS) {
		   xil_printf("error starting VDMA..!");
		   return Status;
	}
	return XST_SUCCESS;

}


int vdma_write_start(XAxiVdma *Vdma) {
	int Status;

	// MM2S Startup
	Status = XAxiVdma_DmaStart(Vdma, XAXIVDMA_WRITE);
	if (Status != XST_SUCCESS)
	{
	   xil_printf("Start write transfer failed %d\n\r", Status);
	   return XST_FAILURE;
	}

	return XST_SUCCESS;
}


int vdma_write_stop(XAxiVdma *Vdma) {
	XAxiVdma_DmaStop(Vdma, XAXIVDMA_WRITE);
	return XST_SUCCESS;
}


int vdma_write_init(short DeviceID,short HoriSizeInput,short VertSizeInput,short Stride,unsigned int FrameStoreStartAddr)
{
	XAxiVdma Vdma;
	XAxiVdma_Config *Config;
	XAxiVdma_DmaSetup WriteCfg;
	int Status;


	Config = XAxiVdma_LookupConfig(DeviceID);
	if (NULL == Config) {
		xil_printf("XAxiVdma_LookupConfig failure\r\n");
		return XST_FAILURE;
	}

	Status = XAxiVdma_CfgInitialize(&Vdma, Config, Config->BaseAddress);
	if (Status != XST_SUCCESS) {
		xil_printf("XAxiVdma_CfgInitialize failure\r\n");
		return XST_FAILURE;
	}

	

	WriteCfg.EnableCircularBuf = 0;
	WriteCfg.EnableFrameCounter = 0;
	WriteCfg.FixedFrameStoreAddr = 0;

	WriteCfg.EnableSync = 1;
	WriteCfg.PointNum = 1;

	WriteCfg.FrameDelay = 0;

	WriteCfg.VertSizeInput = VertSizeInput;
	WriteCfg.HoriSizeInput = HoriSizeInput;
	WriteCfg.Stride = Stride;

	Status = XAxiVdma_DmaConfig(&Vdma, XAXIVDMA_WRITE, &WriteCfg);
	if (Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,
				"Read channel config failed %d\r\n", Status);

			return XST_FAILURE;
	}


	WriteCfg.FrameStoreStartAddr[0] = FrameStoreStartAddr;

	Status = XAxiVdma_DmaSetBufferAddr(&Vdma, XAXIVDMA_WRITE, WriteCfg.FrameStoreStartAddr);
	if (Status != XST_SUCCESS) {
			xdbg_printf(XDBG_DEBUG_ERROR,"Write channel set buffer address failed %d\r\n", Status);
			return XST_FAILURE;
	}


	Status = vdma_write_start(&Vdma);
	if (Status != XST_SUCCESS) {
		   xil_printf("error starting VDMA..!");
		   return Status;
	}
	return XST_SUCCESS;

}


#ifndef VDMA_H_
#define VDMA_H_

#include "xaxivdma.h"


int vdma_read_init(short DeviceID,short HoriSizeInput,short VertSizeInput,short Stride,unsigned int FrameStoreStartAddr);
int vdma_write_init(short DeviceID,short HoriSizeInput,short VertSizeInput,short Stride,unsigned int FrameStoreStartAddr);
u32 vdma_version();

#endif /* VDMA_H_ */

中秋急着跑出去玩误工了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值