MYIR-ZYNQ7000系列-zturn教程(24):用vdma搭建hdmi显示通路

开发板环境:vivado 2017.4 ,开发板型号xc7z010clg400-1,这个工程主要用vdma核搭建hdmi显示工程

链接:https://pan.baidu.com/s/1FoqtKnNewxFusP4v-DnPoQ    提取码:pvim 

Step1 新建工程,调用一个zynq核并配置

这里配置项比较多所以没有例具体配置了哪些,这里我直接导入之前已经配置好tcl文件

配置完成后如下图所示

Step2  调用IP核并配置

调用vid_out

配置vid_out

调用inter

调用subset(这个IP核主要将VDMA输出的32位数据转换为24位数据)

调用V_TC

这里选择1080p,这个可以根据自己的分辨率进行选择,然后点击OK

调用vector

调用vdma

调用constant(直接使用默认参数)

调用clk

调用两个reset

调用一个inter

调用所有的IP如下图所示

按照下面截图中的进行连接

分配地址空间大小

Step3  综合、生成顶层文件、生成bit文件,配置xdc

综合

生成顶层文件

这里的顶层进行部分更改可以复制这个顶层文件

//Copyright 1986-2017 Xilinx, Inc. All Rights Reserved.
//--------------------------------------------------------------------------------
//Tool Version: Vivado v.2017.4 (win64) Build 2086221 Fri Dec 15 20:55:39 MST 2017
//Date        : Wed Mar 13 13:45:47 2019
//Host        : taowei running 64-bit Service Pack 1  (build 7601)
//Command     : generate_target design_1_wrapper.bd
//Design      : design_1_wrapper
//Purpose     : IP block netlist
//--------------------------------------------------------------------------------
`timescale 1 ps / 1 ps

module design_1_wrapper
   (DDR_addr,
    DDR_ba,
    DDR_cas_n,
    DDR_ck_n,
    DDR_ck_p,
    DDR_cke,
    DDR_cs_n,
    DDR_dm,
    DDR_dq,
    DDR_dqs_n,
    DDR_dqs_p,
    DDR_odt,
    DDR_ras_n,
    DDR_reset_n,
    DDR_we_n,
    FIXED_IO_ddr_vrn,
    FIXED_IO_ddr_vrp,
    FIXED_IO_mio,
    FIXED_IO_ps_clk,
    FIXED_IO_ps_porb,
    FIXED_IO_ps_srstb,
    IIC_0_0_scl_io,
    IIC_0_0_sda_io,
    hdmi_clk,
    hdmi_data,
    hdmi_de,
    hdmi_hs,
    hdmi_vs
    );
  inout [14:0]DDR_addr;
  inout [2:0]DDR_ba;
  inout DDR_cas_n;
  inout DDR_ck_n;
  inout DDR_ck_p;
  inout DDR_cke;
  inout DDR_cs_n;
  inout [3:0]DDR_dm;
  inout [31:0]DDR_dq;
  inout [3:0]DDR_dqs_n;
  inout [3:0]DDR_dqs_p;
  inout DDR_odt;
  inout DDR_ras_n;
  inout DDR_reset_n;
  inout DDR_we_n;
  inout FIXED_IO_ddr_vrn;
  inout FIXED_IO_ddr_vrp;
  inout [53:0]FIXED_IO_mio;
  inout FIXED_IO_ps_clk;
  inout FIXED_IO_ps_porb;
  inout FIXED_IO_ps_srstb;
  inout IIC_0_0_scl_io;
  inout IIC_0_0_sda_io;
  output hdmi_clk;
  output [15:0]hdmi_data;
  output hdmi_de;
  output hdmi_hs;
  output hdmi_vs;

  wire [14:0]DDR_addr;
  wire [2:0]DDR_ba;
  wire DDR_cas_n;
  wire DDR_ck_n;
  wire DDR_ck_p;
  wire DDR_cke;
  wire DDR_cs_n;
  wire [3:0]DDR_dm;
  wire [31:0]DDR_dq;
  wire [3:0]DDR_dqs_n;
  wire [3:0]DDR_dqs_p;
  wire DDR_odt;
  wire DDR_ras_n;
  wire DDR_reset_n;
  wire DDR_we_n;
  wire FIXED_IO_ddr_vrn;
  wire FIXED_IO_ddr_vrp;
  wire [53:0]FIXED_IO_mio;
  wire FIXED_IO_ps_clk;
  wire FIXED_IO_ps_porb;
  wire FIXED_IO_ps_srstb;
  wire IIC_0_0_scl_i;
  wire IIC_0_0_scl_io;
  wire IIC_0_0_scl_o;
  wire IIC_0_0_scl_t;
  wire IIC_0_0_sda_i;
  wire IIC_0_0_sda_io;
  wire IIC_0_0_sda_o;
  wire IIC_0_0_sda_t;
  wire vid_clk;
  wire [23:0]vid_data;
  wire vid_de;
  wire vid_hs;
  wire vid_vs;
  wire hdmi_clk;
  wire [15:0]hdmi_data;
  wire hdmi_de;
  wire hdmi_hs;
  wire hdmi_vs;
  
  assign    hdmi_data   =   {vid_data[23:19],vid_data[15:10],vid_data[7:3]};
  assign    hdmi_clk    =   vid_clk;
  assign    hdmi_de     =   vid_de;
  assign    hdmi_hs     =   vid_hs;
  assign    hdmi_vs     =   vid_vs;
  

  IOBUF IIC_0_0_scl_iobuf
       (.I(IIC_0_0_scl_o),
        .IO(IIC_0_0_scl_io),
        .O(IIC_0_0_scl_i),
        .T(IIC_0_0_scl_t));
  IOBUF IIC_0_0_sda_iobuf
       (.I(IIC_0_0_sda_o),
        .IO(IIC_0_0_sda_io),
        .O(IIC_0_0_sda_i),
        .T(IIC_0_0_sda_t));
  design_1 design_1_i
       (.DDR_addr(DDR_addr),
        .DDR_ba(DDR_ba),
        .DDR_cas_n(DDR_cas_n),
        .DDR_ck_n(DDR_ck_n),
        .DDR_ck_p(DDR_ck_p),
        .DDR_cke(DDR_cke),
        .DDR_cs_n(DDR_cs_n),
        .DDR_dm(DDR_dm),
        .DDR_dq(DDR_dq),
        .DDR_dqs_n(DDR_dqs_n),
        .DDR_dqs_p(DDR_dqs_p),
        .DDR_odt(DDR_odt),
        .DDR_ras_n(DDR_ras_n),
        .DDR_reset_n(DDR_reset_n),
        .DDR_we_n(DDR_we_n),
        .FIXED_IO_ddr_vrn(FIXED_IO_ddr_vrn),
        .FIXED_IO_ddr_vrp(FIXED_IO_ddr_vrp),
        .FIXED_IO_mio(FIXED_IO_mio),
        .FIXED_IO_ps_clk(FIXED_IO_ps_clk),
        .FIXED_IO_ps_porb(FIXED_IO_ps_porb),
        .FIXED_IO_ps_srstb(FIXED_IO_ps_srstb),
        .IIC_0_0_scl_i(IIC_0_0_scl_i),
        .IIC_0_0_scl_o(IIC_0_0_scl_o),
        .IIC_0_0_scl_t(IIC_0_0_scl_t),
        .IIC_0_0_sda_i(IIC_0_0_sda_i),
        .IIC_0_0_sda_o(IIC_0_0_sda_o),
        .IIC_0_0_sda_t(IIC_0_0_sda_t),
        .vid_clk(vid_clk),
        .vid_data(vid_data),
        .vid_de(vid_de),
        .vid_hs(vid_hs),
        .vid_vs(vid_vs));
endmodule

不同的开发板xdc有差异可以自己分配管脚

create_clock -period 5.000 -name hdmi_clk_OBUF -waveform {0.000 2.500} [get_nets hdmi_clk_OBUF]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -min  -2 [get_ports {hdmi_data[*]}]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -max  0 [get_ports {hdmi_data[*]}]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -min  -2 [get_ports hdmi_de]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -max  0 [get_ports hdmi_de]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -min  -2 [get_ports hdmi_hs]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -max  0 [get_ports hdmi_hs]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -min  -2 [get_ports hdmi_vs]
set_output_delay -clock [get_clocks hdmi_clk_OBUF] -max  0 [get_ports hdmi_vs]


set_property PACKAGE_PIN T16 [get_ports {hdmi_data[0]}]
set_property PACKAGE_PIN U17 [get_ports {hdmi_data[1]}]
set_property PACKAGE_PIN V15 [get_ports {hdmi_data[2]}]
set_property PACKAGE_PIN W15 [get_ports {hdmi_data[3]}]
set_property PACKAGE_PIN U18 [get_ports {hdmi_data[4]}]
set_property PACKAGE_PIN U19 [get_ports {hdmi_data[5]}]
set_property PACKAGE_PIN N18 [get_ports {hdmi_data[6]}]
set_property PACKAGE_PIN P19 [get_ports {hdmi_data[7]}]
set_property PACKAGE_PIN N20 [get_ports {hdmi_data[8]}]
set_property PACKAGE_PIN P20 [get_ports {hdmi_data[9]}]
set_property PACKAGE_PIN T20 [get_ports {hdmi_data[10]}]
set_property PACKAGE_PIN U20 [get_ports {hdmi_data[11]}]
set_property PACKAGE_PIN V20 [get_ports {hdmi_data[12]}]
set_property PACKAGE_PIN W20 [get_ports {hdmi_data[13]}]
set_property PACKAGE_PIN Y18 [get_ports {hdmi_data[14]}]
set_property PACKAGE_PIN Y19 [get_ports {hdmi_data[15]}]

set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[15]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[14]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[13]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[12]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[11]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[10]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[9]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[8]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {hdmi_data[0]}]

set_property PACKAGE_PIN V16 [get_ports hdmi_vs]
set_property PACKAGE_PIN W16 [get_ports hdmi_hs]
set_property PACKAGE_PIN R16 [get_ports hdmi_de]
set_property PACKAGE_PIN R17 [get_ports hdmi_clk]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_clk]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_hs]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_de]
set_property IOSTANDARD LVCMOS33 [get_ports hdmi_vs]

set_property PACKAGE_PIN P15 [get_ports IIC_0_0_sda_io]
set_property PACKAGE_PIN P16 [get_ports IIC_0_0_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC_0_0_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports IIC_0_0_scl_io]
set_property PULLUP true [get_ports IIC_0_0_sda_io]
set_property PULLUP true [get_ports IIC_0_0_scl_io]


生成bit文件

Step4  导出硬件配置、打开sdk、新建工程

导出硬件配置

打开SDK

新建fsbl

点击完成

新建hdmi工程

点击完成

新建完成后如下图所示

然后将我提供的工程的这三个文件覆盖新建的这个hdmi里的文件

主程序如下图所示

/*
 * Copyright (c) 2009-2012 Xilinx, Inc.  All rights reserved.
 *
 * Xilinx, Inc.
 * XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION "AS IS" AS A
 * COURTESY TO YOU.  BY PROVIDING THIS DESIGN, CODE, OR INFORMATION AS
 * ONE POSSIBLE   IMPLEMENTATION OF THIS FEATURE, APPLICATION OR
 * STANDARD, XILINX IS MAKING NO REPRESENTATION THAT THIS IMPLEMENTATION
 * IS FREE FROM ANY CLAIMS OF INFRINGEMENT, AND YOU ARE RESPONSIBLE
 * FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE FOR YOUR IMPLEMENTATION.
 * XILINX EXPRESSLY DISCLAIMS ANY WARRANTY WHATSOEVER WITH RESPECT TO
 * THE ADEQUACY OF THE IMPLEMENTATION, INCLUDING BUT NOT LIMITED TO
 * ANY WARRANTIES OR REPRESENTATIONS THAT THIS IMPLEMENTATION IS FREE
 * FROM CLAIMS OF INFRINGEMENT, IMPLIED WARRANTIES OF MERCHANTABILITY
 * AND FITNESS FOR A PARTICULAR PURPOSE.
 *
 */

/*
 * helloworld.c: simple test application
 *
 * This application configures UART 16550 to baud rate 9600.
 * PS7 UART (Zynq) is not initialized by this application, since
 * bootrom/bsp configures it to baud rate 115200
 *
 * ------------------------------------------------
 * | UART TYPE   BAUD RATE                        |
 * ------------------------------------------------
 *   uartns550   9600
 *   uartlite    Configurable only in HW design
 *   ps7_uart    115200 (configured by bootrom/bsp)
 */

#include <stdio.h>
#include "platform.h"
#include "xparameters.h"
#include "xil_io.h"
#include "sleep.h"



#define DDR_BASEADDR        0x00000000

#define VDMA_BASEADDR       XPAR_AXI_VDMA_0_BASEADDR
#define H_STRIDE            1920
#define H_ACTIVE            1920
#define V_ACTIVE            1080


#define VIDEO_LENGTH  (H_STRIDE*V_ACTIVE)
#define VIDEO_BASEADDR0 DDR_BASEADDR + 0x2000000
#define VIDEO_BASEADDR1 DDR_BASEADDR + 0x3000000
#define VIDEO_BASEADDR2 DDR_BASEADDR + 0x4000000

//函数声明
void Xil_DCacheFlush(void);


extern const unsigned char gImage_beijing[8294400];

void show_img(u32 x, u32 y, u32 disp_base_addr, const unsigned char * addr, u32 size_x, u32 size_y)
{
	//计算图片 左上角坐标
	u32 i=0;
	u32 j=0;
	u32 r,g,b;
	u32 start_addr=disp_base_addr;
	start_addr = disp_base_addr + 4*x + y*4*H_STRIDE;
	for(j=0;j<size_y;j++)
	{
		for(i=0;i<size_x;i++)
		{
			b = *(addr+(i+j*size_x)*4+1);
			g = *(addr+(i+j*size_x)*4+2);
			r = *(addr+(i+j*size_x)*4+3);
			Xil_Out32((start_addr+(i+j*H_STRIDE)*4),((r<<24)|(g<<16)|(b<<8)|0x0));
		}
	}
	Xil_DCacheFlush();
}

int main()
{

    sii9022_init();

	//各种显示 相关的参数
	Xil_Out32((VDMA_BASEADDR + 0x000), 0x00000003); 		// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*4)); 		// h offset (1920 * 4) bytes
	Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*4)); 		// h size (1920 * 4) bytes
	Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); 			// v size (1080)


	while(1)
	{
		show_img(0,0,VIDEO_BASEADDR0,&gImage_beijing[0],1920,1080);
	}


}

show_img程序说明:下面这一段是需要读出的数据,网上的图片多数是24位的,通过软件转换为

32数据时,会强行将低位添0x00

const unsigned char gImage_beijing[8294400] = {
 0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A
,0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A
,0x00,0x9F,0x69,0x0B,0x00,0x9F,0x69,0x0B,0x00,0x9F,0x69,0x0B,0x00,0x9F,0x69,0x0B
,0x00,0x9F,0x69,0x0B,0x00,0x9F,0x69,0x0B,0x00,0xA0,0x6A,0x0C,0x00,0xA1,0x6B,0x0D
,0x00,0xA1,0x6B,0x0C,0x00,0xA1,0x6B,0x0C,0x00,0xA1,0x6B,0x0C,0x00,0xA1,0x6B,0x0C
,0x00,0xA1,0x6B,0x0C,0x00,0xA1,0x6B,0x0C,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B
,0x00,0xA1,0x6B,0x0C,0x00,0x9F,0x69,0x0A,0x00,0x9E,0x68,0x09,0x00,0x9E,0x68,0x09
,0x00,0xA0,0x6A,0x0B,0x00,0xA1,0x6B,0x0C,0x00,0xA0,0x6A,0x0B,0x00,0x9F,0x69,0x0A
,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B
,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B
,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B
,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B,0x00,0xA0,0x6A,0x0B
,0x00,0x9D,0x6A,0x0A,0x00,0x9E,0x6B,0x0B,0x00,0x9F,0x6C,0x0C,0x00,0x9F,0x6C,0x0C

从上图可以看到0x00,0x9E,0x68,0x0A,这四个八位构成一个32位数据最低位为0x00, 0x00,0x9E,0x68,0x0A这四个八位构成

的32位数据也是低位为0x00,按照图片生成的规则可以看到,按照0,1,2,3这样的数,1位为b,2为g,3为r

const unsigned char gImage_beijing[8294400] = {
 0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A,0x00,0x9E,0x68,0x0A
        b    g    r        b    g    r          b    g    r        b    g    r

要输出rgb就可以按照下面的代码来实现,低位直接0x0,其它的直接取b,g,r 数据

		for(i=0;i<size_x;i++)
		{
			b = *(addr+(i+j*size_x)*4+1);
			g = *(addr+(i+j*size_x)*4+2);
			r = *(addr+(i+j*size_x)*4+3);
			Xil_Out32((start_addr+(i+j*H_STRIDE)*4),((r<<24)|(g<<16)|(b<<8)|0x0));
		}

生成BOOT.bin文件

硬件连接

显示效果(手机不行只能拍出这种效果了)

  • 6
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值