ZYNQ AXI4总线访问DDR3实现图像数据乒乓存储与显示

这篇具有很好参考价值的文章主要介绍了ZYNQ AXI4总线访问DDR3实现图像数据乒乓存储与显示。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

前言

一、添加端口

二、添加局部变量

三、例化读写FIFO

四、内部变量修改,设置一次读写进行多少次突发操作

五、写地址

六、读地址

七、状态机

1.写状态机

2.读状态机

总结



前言

在Altera FPGA进行图像处理时,我们采用的存储芯片为SDRAM,当时参照正点原子的例程是封装SDRAM控制器,然后像操作FIFO一样去控制SDRAM。现在换了ZYNQ的板子后,由于DDR3是挂载在PS端的,Xilinx官方提供了视频接口的IP,但是IP这东西像个小黑盒子一样,在开发过程中遇到了问题,极其不易排查,所以我就在官方的AXI4—FULL接口代码上稍做修改,实现像以前一样像操作FIFO一样去操作PS端的DDR3。


一、添加端口

// Users to add ports here
//图像数据写端口
input	wire			wr_clk,		//输入像素时钟
input	wire			wr_en,		//数据有效信号
input	wire	[15:0]	wr_data,	//像素数据
	
//图像数据读端口
input	wire			rd_clk,		//输入hdmi驱动时钟
input	wire			rd_en,		//读请求
output	wire	[15:0]	rd_data,	//像素数据

二、添加局部变量

触发一次读写DDR3的FIFO中的数据量设置为256,当写FIFO中的数据量大于THRESHOLD进行一次写操作的触发,当读FIFO中的数据量小于THRESHOLD时进行一次读操作的触发。一帧图像的最大存储地址为FIRST_FRAME

// I/O Connections assignments
localparam THRESHOLD 	= 256 			;	//触发写FIFO读数据个数
localparam FIRST_FRAME 	= (640*480)*4 	;	//存储最大值

三、例化读写FIFO

用作数据缓存

// Add user logic here
    //写数据补位
    assign din_wr_fifo = {16'd0,wr_data};
    assign wr_en_wr_fifo = wr_en;
    assign rd_en_wr = wnext;
    //写FIFO
    wr_fifo inst_fifo (
 	.wr_clk(wr_clk),                			// input wire wr_clk
 	.rd_clk(M_AXI_ACLK),                		// input wire rd_clk
 	.din(din_wr_fifo),                  		// input wire [31 : 0] din
 	.wr_en(wr_en_wr_fifo),              		// input wire wr_en
 	.rd_en(rd_en_wr),                  			// input wire rd_en
 	.dout(dout_wr_fifo),                    	// output wire [31 : 0] dout
 	.full(full_wr_fifo),                    	// output wire full
 	.empty(empty_wr_fifo),                  	// output wire empty
 	.rd_data_count(rd_data_count_wr_fifo)  		// output wire [11 : 0] rd_data_count
    );
	
	assign rd_data = dout_rd_fifo[15:0];
	assign wr_en_rd_fifo = rnext;
	//读FIFO
	rd_fifo inst_rd_fifo (
  	.wr_clk(M_AXI_ACLK),            // input wire wr_clk
  	.rd_clk(rd_clk),              // input wire rd_clk
  	.din(M_AXI_RDATA),              // input wire [63 : 0] din
  	.wr_en(wr_en_rd_fifo),                  // input wire wr_en
  	.rd_en(rd_en),                  // input wire rd_en
  	.dout(dout_rd_fifo),                    // output wire [31 : 0] dout
  	.full(full_rd_fifo),                    // output wire full
  	.empty(empty_rd_fifo),                  // output wire empty
  	.rd_data_count(rd_data_count_rd_fifo),  // output wire [11 : 0] rd_data_count
    .wr_data_count(wr_data_count_rd_fifo)   // output wire [10 : 0] wr_data_count
	);

四、内部变量修改,设置一次读写进行多少次突发操作

将原本代码里面C_MASTER_LENGTH 的数值12更改为10,原本的12表示一次读写操作进行64次突发操作,由于一次突发的数据量为16个32位的数据,所以64*16=1024个数据,与AXI4读写DDR3的实验现象一致,更改位10的原因为让其一次读写的数据量保持跟设置的THRESHOLD 一致都为256,避免数据冲突。

五、写地址

由于DDR3可以自由设置数据存储的地址,所以我们在代码内部自己划分读写bank,从而可以实现乒乓操作。

always @(posedge M_AXI_ACLK)begin
	if(M_AXI_ARESETN == 0)begin
		bank_1 <= 2'b00;
	end
	else if((axi_awaddr[21:0] == FIRST_FRAME) && writes_done && bank_1 == 2'b00)begin
			bank_1 <= 2'b01;
	end
	else if((axi_awaddr[21:0] == FIRST_FRAME) && writes_done && bank_1 == 2'b01)begin
			bank_1 <= 2'b00;
	end
	else
		bank_1 <= bank_1;
end


  always @(posedge M_AXI_ACLK)                                         
	  begin                                                                
	    if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                            
	      begin                                                            
	        axi_awaddr <= 'b0;
	        sw_bank_en <= 1'b0;
            rw_bank_flag <= 1'b0;                                             
	      end                                                              
	    else if (M_AXI_AWREADY && axi_awvalid)                             
	      begin
	           //bank0的剩余地址满足一次突发长度
	           if(axi_awaddr[21:0] < FIRST_FRAME - burst_size_bytes)begin
	               axi_awaddr <= axi_awaddr + burst_size_bytes;
	           end
			   //不满足切换BANK
	           else begin
	               axi_awaddr <= {8'b0000_0000,bank_1,22'd0};
	           end               
	      end                                                            
	    else                                                               
	      axi_awaddr <= axi_awaddr;                                        
	    end

六、读地址

读地址操作与写地址类似。

七、状态机

1.写状态机

在原本官方状态机上删除读状态与读写错误判断状态。

  always @ ( posedge M_AXI_ACLK)                                                                            
	  begin                                                                                                     
	    if (M_AXI_ARESETN == 1'b0 )                                                                             
	      begin                                                                                                 
	        // reset condition                                                                                  
	        // All the signals are assigned default values under reset condition                                
	        mst_exec_state      <= IDLE;                                                                
	        start_single_burst_write <= 1'b0;                                                                                                                                  
	        compare_done      <= 1'b0;                                                                          
	        ERROR <= 1'b0;   
	      end                                                                                                   
	    else                                                                                                    
	      begin                                                                                                 
	                                                                                                            
	        // state transition                                                                                 
	        case (mst_exec_state)                                                                               
	                                                                                                            
	          IDLE:                                                                                     
	            // This state is responsible to wait for user defined C_M_START_COUNT                           
	            // number of clock cycles.                                                                      
				if ( init_txn_pulse == 1'b1 || rd_data_count_wr_fifo >= THRESHOLD)                                                      
	              begin                                                                                         
	                mst_exec_state  <= INIT_WRITE;
	                start_single_burst_write <= 1'b0;                                                                                                                                
	                ERROR <= 1'b0;
	                compare_done <= 1'b0;
	              end
	            else                                                                                            
	              begin                                                                                         
	                mst_exec_state  <= IDLE;                                                            
	              end                                                                                           
	                                                                                                            
	          INIT_WRITE:                                                                                       
	            // This state is responsible to issue start_single_write pulse to                               
	            // initiate a write transaction. Write transactions will be                                     
	            // issued until burst_write_active signal is asserted.                                          
	            // write controller                                                                             
	            if (writes_done)                                                                                
	              begin                                                                                         
	                mst_exec_state <= IDLE;//
	                start_single_burst_write <= 1'b0;                                                                                                                             
	              end                                                                                           
	            else                                                                                            
	              begin                                                                                         
	                mst_exec_state  <= INIT_WRITE;                                                              
	                                                                                                            
	                if (~axi_awvalid && ~start_single_burst_write && ~burst_write_active)                       
	                  begin                                                                                     
	                    start_single_burst_write <= 1'b1;                                                       
	                  end                                                                                       
	                else                                                                                        
	                  begin                                                                                     
	                    start_single_burst_write <= 1'b0; //Negate to generate a pulse                          
	                  end                                                                                       
	              end                                                                                                                                                                  
	          default :                                                                                         
	            begin                                                                                           
	              mst_exec_state  <= IDLE;                                                              
	            end                                                                                             
	        endcase                                                                                             
	      end                                                                                                   
	  end 

2.读状态机

与写状态机类似,照着来就行

always @(posedge M_AXI_ACLK)begin
		if(M_AXI_ARESETN == 1'b0)begin
			curr_state      <= IDLE;                                                                                                                               
	        start_single_burst_read  <= 1'b0;
		end
		else begin
			case(curr_state)
				IDLE:	
					if(wr_data_count_rd_fifo < 2048-THRESHOLD)begin
						curr_state 		<= INIT_READ;                                                                 
						start_single_burst_read  <= 1'b0;
					end
					else begin
						curr_state		<= IDLE;
					end
				INIT_READ:
					if(reads_done)begin
						curr_state 		<= IDLE;                                                                
						start_single_burst_read  <= 1'b0;
					end
					else begin
						curr_state 		<= INIT_READ;
						if(~axi_arvalid && ~burst_read_active && ~start_single_burst_read)begin
							start_single_burst_read <= 1'b1;
						end
						else begin
							start_single_burst_read <= 1'b0;
						end
					end
				default :                                                                                         
					begin                                                                                           
						curr_state  <= IDLE;                                                              
					end
			endcase
		end
	end

总结

一开始拿到AXI4总线我也是一头雾水,但认真看完总线介绍还是比较简单的文章来源地址https://www.toymoban.com/news/detail-787489.html

到了这里,关于ZYNQ AXI4总线访问DDR3实现图像数据乒乓存储与显示的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • DDR3 控制器 MIG IP 详解完整版 (AXI4&VIVADO&Verilog)

    DDR系列文章分类地址: (1)DDR3 基础知识分享 (2)DDR3 控制器 MIG IP 详解完整版 (AXI4VivadoVerilog) (3)DDR3 控制器 MIG IP 详解完整版 (nativeVivadoVerilog) (4)基于 DDR3 的串口传图帧缓存系统设计实现 (5)基于 DDR3 的native接口串口局部传图缓存系统设计实现 (6)基于 DDR3 的

    2024年02月11日
    浏览(51)
  • ZYNQ通过AXI DMA实现PL发送连续大量数据到PS DDR

    硬件:ZYNQ7100 软件:Vivado 2017.4、Xilinx SDK 2017.4   ZYNQ PL 和 PS 的通信方式有 AXI GPIO、BRAM、DDR等。对于数据量较少、地址不连续、长度规则的情况,BRAM 比较适用。而对于传输速度要求高、数据量大、地址连续的情况,比如 ADC,可以通过 AXI DMA 来完成。 1、硬件设计 1.1 ZYNQ7

    2024年02月04日
    浏览(44)
  • 带你快速入门AXI4总线--AXI4-Full篇(1)----AXI4-Full总线

    目录 1、什么是AXI4-Full? 2、通道(Channel) 2.1、AXI 读取传输事务 2.2、AXI 写入传输事务

    2024年02月01日
    浏览(51)
  • 基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制

    基于fpga的ddr3读写控制,纯verilog实现,能实现多通道图像数据读写控制,模块接口清晰,可移植性高. 基于FPGA的DDR3读写控制是一项重要的技术,它为多通道图像数据的读写提供了高效的解决方案。本文将介绍一种纯Verilog实现的DDR3读写控制模块,旨在实现模块接口清晰、可移

    2024年04月12日
    浏览(57)
  • AXI4总线学习心得(一)

    AXI4:(For high-performance memory-mapped requirements.)主要面向高性能地址映射通信的需求,是面向地址映射的接口,允许最大 256 轮的数据突发传输; AXI4-Lite:(For simple, low-throughput memory-mapped communication )是一个轻量级的地址映射单次传输接口,占用很少的逻辑单元。 AXI4-Stream:

    2024年02月12日
    浏览(42)
  • FPGA——AXI4总线详解

    目录 AXI4总线 1、什么是AXI 2、AXI4协议的优势 AXI4的工作模式 AXI4读操作: AXI4写操作 AXI4和AXI4-Lite、AXI4-Stream接口信号 握手信号 AXI相关术语     AXI(Advanced eXtensible Interface高级可扩展总线)是一种总线协议     AXI4包含3种类型的接口: 1)AXI4:主要面向高性能地址映射通信的

    2024年02月02日
    浏览(56)
  • 使用VIVADO中的MIG控制DDR3(AXI接口)一——AXI简介

            最近,因为需要,学习了AXI总线协议和DDR3相关的知识,花了很多的时间去找各种相关的资料,深刻明白查资料的不容易,这里将所学到的东西做一个总结,同时给需要的人提供一些便利,有问题的欢迎一起讨论学习、共同进步。          首先来说一下有关AXI总

    2024年02月08日
    浏览(50)
  • FPGA AXI4总线信号介绍篇

    AXI是一种总线协议,可以挂在多个master和slave:         (1)AXI4:主要面向高性能地址映射通信的需求;(突发数据)(地址映射模式)         (2)AXI4-Lite:是一个轻量级的,适用于吞吐量较小的地址映射通信总线;(无突发)(地址映射模式)         (3)AXI4-

    2024年04月11日
    浏览(59)
  • DDR3(AXI接口例程)知识点笔记

    本文以7035开发板中的DDR3master例程对DDR3中所涉及的知识点梳理下笔记。 ① DDR支持的突发长度是2,4,8 。即如果芯片的数据位宽是16bit的话那么接口数据位宽是32bit,64bit以及128bit。因为 L-Bank一次就存取两倍于芯片位宽的数据,所以芯片至少也要进行两次传输才可以。我认为芯片

    2024年02月13日
    浏览(47)
  • 【FPGA】AXI4-Lite总线读写BRAM

    AXI协议基础知识 。这篇博客比较详细地介绍了AXI总线,并且罗列了所有的通道和端口,写代码的时候可以方便地进行查表。 AXI总线,AXI_BRAM读写仿真测试 。 这篇文章为代码的书写提供大致的思路,比如状态机和时序的控制问题,可以参考。 双向握手机制的实质是: 数据接

    2024年02月15日
    浏览(75)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包