开发板环境: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文件
硬件连接
显示效果(手机不行只能拍出这种效果了)