2.VDMA视频流显示通路搭建

本文详细描述了如何使用ZYNQ7020搭建一个视频流接收、转换和显示的系统,包括img_gen模块的像素生成,以及VDMA、AXI接口的使用,最终实现1080P黑白渐变图像的实时显示。
摘要由CSDN通过智能技术生成

1.简介

  本节主要讲解如何基于ZYNQ7020搭建一个视频流接收以及显示的数据通路。为后续的算法图像验证提供基础。

2.项目框架

在这里插入图片描述
  整个项目简略框架如图,img_gen负责产生图像像素点,给到video in to AXI_Stream模块后转化为AXI_Stream数据流给到VDMA,VDMA采用三帧缓存的方式向ARM控制的DDR3写入像数据据并读出像素数据,读出的数据给到AXI4_Stream to Video Out模块,AXI4_Stream to Video Out同时接收Vide Time Controller模块产生的VGA时序,并将VGA时序与像素点信息全部给到VGA to DVI模块,然后交由HDMI显示屏显示。项目完成后的详细信息如下:
在这里插入图片描述
在这里插入图片描述

3.部分源码

3.1 img_gen

  其中img_gen用于产生像素信息,这里我们采用黑白渐变像素。源码如下

`timescale 1ns / 1ps

module img_gen 
#(
 	parameter ACTIVE_IW 	= 	800 	,
 	parameter ACTIVE_IH 	= 	480 	,
 	parameter TOTAL_IW 		= 	1057 	,
 	parameter TOTAL_IH 		= 	506 	,
 	parameter H_START 		= 	216 	,
 	parameter V_START  		= 	24 
)
( 
	input 				clk		,
	input 				rst_n	, 
	output reg 			vs		, 
	output reg 			de		,
	output reg [7:0]	data	
);

reg  [7:0] raw_array [ACTIVE_IW*ACTIVE_IH-1:0];

integer i;
 
initial begin

	for (i=0; i<ACTIVE_IW*ACTIVE_IH; i=i+1) 
		raw_array[i] = 0;
		
end

/* initial begin
	$readmemh("F:/lesson/lesson1/data/pre.txt",raw_array);
end */

reg	[31:0]	cnt_delay	;

reg [15:0] 	hcnt		;
reg [15:0] 	vcnt		;

reg			h_de		;
reg			v_de		;

reg			index_de	;	
reg	[7:0]	index       ;

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		cnt_delay <= 'd0;
	else if(cnt_delay==100000000*5-1)
		cnt_delay <= cnt_delay;
	else
		cnt_delay <= cnt_delay + 1'b1;

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		hcnt <= 'd0;
	else if(hcnt==TOTAL_IW-1)
		hcnt <= 'd0;
	else if(cnt_delay==100000000*5-1)
		hcnt <= hcnt + 1'b1;
	else
		hcnt <= hcnt;
		
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		vcnt <= 'd0;
	else if(hcnt==TOTAL_IW-1&&vcnt==TOTAL_IH-1)
		vcnt <= 'd0;
	else if(hcnt==TOTAL_IW-1)
		vcnt <= vcnt + 1'b1;
	else
		vcnt <= vcnt;
					
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		vs <= 1'b0;
	else if(vcnt>=2)
		vs <= 1'b1;
	else
		vs <= 1'b0;

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		h_de <= 1'b0;
	else if(hcnt>=H_START&&hcnt<H_START+ACTIVE_IW)
		h_de <= 1'b1;
	else
		h_de <= 1'b0;
	
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		v_de <= 1'b0;
	else if(vcnt>=V_START&&vcnt<V_START+ACTIVE_IH)
		v_de <= 1'b1;
	else
		v_de <= 1'b0;

always@(posedge clk or negedge rst_n)
	if(!rst_n)
		index_de <= 1'b0;
	else if(h_de==1'b1&&v_de==1'b1)
		index_de <= 1'b1;
	else
		index_de <= 1'b0;
		
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		index <= 'd0;
	else if(index_de==1'b1)
		index <= index + 1'b1;
	else
		index <= 'd0;
		
always@(posedge clk or negedge rst_n)
	if(!rst_n)
		de <= 1'b0;
	else
		de <= index_de;
		
always@(posedge clk)
	if(index_de==1'b1)
		data <= index;
	else
		data <= 0;
endmodule 

3.2 top

  顶层模块负责连接block design与一些外部模块

`timescale 1ns / 1ps

module top(
	input 	wire 		 	sys_clk				,	
	
	inout  	wire 	[14:0]	DDR_addr			,
	inout  	wire 	[2:0]	DDR_ba				,
	inout	wire			DDR_cas_n			,
	inout	wire			DDR_ck_n			,
	inout	wire			DDR_ck_p			,
	inout	wire			DDR_cke				,
	inout	wire			DDR_cs_n			,
	inout  	wire 	[3:0]	DDR_dm				,
	inout  	wire	[31:0]	DDR_dq				,
	inout  	wire	[3:0]	DDR_dqs_n			,
	inout  	wire	[3:0]	DDR_dqs_p			,
	inout 	wire			DDR_odt				,
	inout 	wire			DDR_ras_n			,
	inout 	wire			DDR_reset_n			,
	inout 	wire			DDR_we_n			,
	inout 	wire			FIXED_IO_ddr_vrn	,
	inout 	wire			FIXED_IO_ddr_vrp	,
	inout  	wire	[53:0]	FIXED_IO_mio		,
	inout 	wire			FIXED_IO_ps_clk		,
	inout 	wire			FIXED_IO_ps_porb	,
	inout 	wire			FIXED_IO_ps_srstb	,
	
	output	wire 	 		tmds_clk_p 	 		,
	output	wire 	 		tmds_clk_n 	 		,
	output	wire 	[ 2:0] 	tmds_data_p  		,	
	output	wire 	[ 2:0] 	tmds_data_n 	
);


wire			clk_200M	;
wire			rst_n		;

wire			pre_vs		;		
wire			pre_de		;	
wire	[7:0]	pre_data	;	

wire            video_clk 	;   
wire            video_clk5  ;  
wire            video_vs 	;   
wire            video_hs    ;	
wire            video_de    ;	
wire    [23:0]  video_data  ;	

clk_global u1_clk_global (
	.clk_in1		(sys_clk	),
	.clk_200M		(clk_200M	), 
	.locked			(rst_n		) 
); 

//1920*1080 60fps

img_gen 
#(
	.ACTIVE_IW  (1920),
	.ACTIVE_IH  (1080),
	.TOTAL_IW   (2200),
	.TOTAL_IH   (1111),
	.H_START    (5	 ), 
	.V_START    (5   )  
)
u1_img_gen
( 
	.clk		(clk_200M	),
	.rst_n		(rst_n		), 
	.vs			(pre_vs		), 
	.de			(pre_de		),
	.data	    (pre_data	)
);

cpu_wrapper u1_cpu_wrapper (
    .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	),
	
	.clk_200M				(clk_200M			),
	.rst_n					(rst_n				),
	
    .pre_clk				(clk_200M			),
	.pre_vs					(pre_vs				),
	.pre_de					(pre_de				),
    .pre_data				(pre_data			),
    
	.video_clk              (video_clk 	        ),
	.video_clk5             (video_clk5         ),
	.video_vs               (video_vs 	        ),
	.video_hs				(video_hs    		),
	.video_de				(video_de  			),
    .video_data				(video_data  		)
);

DVI_Transmitter u_DVI_Transmitter (
	.pclk 			(video_clk 		),
	.pclk_x5 		(video_clk5 	),
	.reset_n 		(rst_n   		),
	.video_din 		(video_data 	),
	.video_hsync 	(video_hs 	 	),
	.video_vsync 	(video_vs   	),
	.video_de 		(video_de 		),
	.tmds_clk_p 	(tmds_clk_p 	),
	.tmds_clk_n 	(tmds_clk_n 	),
	.tmds_data_p 	(tmds_data_p 	),
	.tmds_data_n 	(tmds_data_n 	),
	.tmds_oen 		( 		 		) 
);
wire 	[99:0] 	probe0;
assign 	probe0 = {
	video_vs,
	video_hs,
	video_de,
	video_data
};

ila_vga u1_ila_vga(
	.clk 		(video_clk 	), 
	.probe0 	(probe0 	) 
);

endmodule

main.c

  main.c主要负责配置vdma模块

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include "xil_printf.h"
#include "xil_io.h"


#define VDMA_BASEADDR	XPAR_AXI_VDMA_0_BASEADDR
//三帧缓存中每一帧的首地址
#define VIDEO_BASEADDR0 0x01000000
#define VIDEO_BASEADDR1 0x02000000
#define VIDEO_BASEADDR2 0x03000000

#define H_ACTIVE	1920
#define V_ACTIVE	1080
#define H_STRIDE	1920

int main()
{
	Xil_Out32((VDMA_BASEADDR + 0x030), 0x108B); 			// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x0AC), VIDEO_BASEADDR0);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0B0), VIDEO_BASEADDR1);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0B4), VIDEO_BASEADDR2);	// start address
	Xil_Out32((VDMA_BASEADDR + 0x0A8), (H_STRIDE*1));		// h offset 1280 bytes
	Xil_Out32((VDMA_BASEADDR + 0x0A4), (H_ACTIVE*1));		// h size 1280 bytes
	Xil_Out32((VDMA_BASEADDR + 0x0A0), V_ACTIVE);			// v size 1024
	/*****************从DDR读数据设置**********************/
	Xil_Out32((VDMA_BASEADDR + 0x000), 0x8B); 		 		// enable circular mode
	Xil_Out32((VDMA_BASEADDR + 0x05c), VIDEO_BASEADDR0); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x060), VIDEO_BASEADDR1); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x064), VIDEO_BASEADDR2); 	// start address
	Xil_Out32((VDMA_BASEADDR + 0x058), (H_STRIDE*1)); 		// h offset 1280 bytes
	Xil_Out32((VDMA_BASEADDR + 0x054), (H_ACTIVE*1)); 		// h size 1280 bytes
	Xil_Out32((VDMA_BASEADDR + 0x050), V_ACTIVE); 			// v size 1024

	while (1) ;

	return 0;

}

4.现象

  本次的图像为1080P,考虑到资源问题,本次的像素信息实时生成,最终上板测试的图像为黑白渐变条纹。在1080P显示屏上显示如下图。
在这里插入图片描述

  • 9
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值