Vitis项目:基于 ZYNQ 的 IMX2221 摄像头实时视频流采集传输 (六)写DMA

项目:基于 ZYNQ 的 IMX2221 摄像头实时视频流采集传输

章节:写DMA

本章目的:添加写DMA,将Bayer2rgb模块出来的每帧1920 * 1080个像素存入内存中,中间使用一个fifo进行缓冲

本章需要一些前置知识

  1. AXI4总线的工作原理
    https://blog.youkuaiyun.com/qq_44406549/article/details/125623786
  2. 如何生成DMA IP
    https://blog.youkuaiyun.com/qq_44406549/article/details/125623900
  3. 如何编写属于自己的DMA
    https://blog.youkuaiyun.com/qq_44406549/article/details/125624097

下面正式开始本章内容

1. 创建DMA IP 并且修改 burst len = 256 , axi data width = 64 ,base address = 0x2000000

这部分见上面的博客,就不再重复

2. DMA时序绘制

在这里插入图片描述
介绍几个关键的信号

  1. bayer2rgb_rst :这个是上一章中bayer2rgb模块的复位信号,只有当这个信号出现下降沿我们的系统才开始真正采集数据,所以这个信号的下降沿作为了工作开始的标志
  2. work_on_flag:工作开始信号,当接收到ayer2rgb_rst下降沿之后一直拉高
  3. detect_fv:作为检测一帧开始的标志,因为如果我们直接检测hv有效就写入内存,那么绝对会造成存入内存的并不是一帧图片,所以设置这个信号保证开始存入的第一个像素就是一帧开始的第一个像素
  4. axi_busy:axi busy信号 信号在burst_start == 1 && axi_busy == 0的情况下拉高,在axi_wlast == 1 && axi_wvalid == 1 && axi_wready == 1 的情况下拉低
  5. burst_start :开始突发信号,在axi_busy == 0 && rd_data_count >=254拉高,在axi_busy == 1 拉低,在图中是INIT_AXI_TXN信号,把它换成burst_start
  6. 其他自己写吧

2. ila抓的结果

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

3. 最终结果居然出现了奇奇怪怪的错误

fifo的读信号拉高了,并且读出来了数据,但是居然count读计数器还在增加,按理说读时钟我们给的200M,写时钟才74.25,写数据32bit,读数据64bit,怎么算同时读写都应该读计数器减少,有哪位知道告诉我一下
在这里插入图片描述
但是最后莫名其妙的又好了,我傻了,我啥也没干,就搞了一天,实在太累了出去健了个身,回来好了。欢迎大家讨论这个问题

4. 最后最后给出代码

//--------------------------------------------------------------//
//----------------------parameter define------------------------//
//--------------------------------------------------------------//
	reg [7:0]	burst_cnt;
	reg 		work_on_flag;
	reg 		detect_fv;
	wire 		fifo_wr_en;
	wire [31:0]	fifo_wr_data;
	wire [10:0] rd_data_count;
	wire 		full,empty;
	reg 		burst_start;
	wire 		fifo_rd_en;
	wire [63:0]	fifo_rd_data;
	reg 		axi_busy;
//--------------------------------------------------------------//
//----------------------parameter define------------------------//
//--------------------------------------------------------------//

//--------------------------------------------------------------//
//--------------------------logic RTL---------------------------//
//--------------------------------------------------------------//
	always @(posedge pixel_clk) begin
	  if(M_AXI_ARESETN == 1'b0) begin
	      work_on_flag <= 1'b0;
	  end
	  else if (init_txn_pulse == 1'b1) begin
	      work_on_flag <= 1'b1;
	  end
	end

	always @(posedge pixel_clk) begin
	  if(M_AXI_ARESETN == 1'b0) begin
	      detect_fv <= 1'b0;
	  end
	  else if (work_on_flag == 1'b1 && fv == 1'b1) begin
	      detect_fv <= 1'b1;
	  end
	end

	assign fifo_wr_data = {8'd0,pixel_rgb};
	assign fifo_wr_en = detect_fv & hv;

	//fifo 2 clock domain switch
	asfifo_w32x4096_r64x2048 frame_buffer (
  .wr_clk(pixel_clk),                // input wire wr_clk
  .rd_clk(M_AXI_ACLK),                // input wire rd_clk
  .din(fifo_wr_data),                      // input wire [31 : 0] din
  .wr_en(fifo_wr_en),                  // input wire wr_en
  .rd_en(fifo_rd_en),                  // input wire rd_en
  .dout(fifo_rd_data),                    // output wire [63 : 0] dout
  .full(full),                    // output wire full
  .empty(empty),                  // output wire empty
  .rd_data_count(rd_data_count)  // output wire [10 : 0] rd_data_count
);
	//dma write channel 
	assign fifo_rd_en = axi_wvalid & M_AXI_WREADY;

	always @(posedge M_AXI_ACLK) begin
	  if(M_AXI_ARESETN == 1'b0) begin
	      burst_start <= 1'b0;
	  end
	  else if (rd_data_count >='d254 && axi_busy == 1'b0) begin
	      burst_start <= 1'b1;
	  end
	  else begin
	  	  burst_start <= 1'b0;
	  end

	end

	always @(posedge M_AXI_ACLK) begin
		if(M_AXI_ARESETN == 1'b0) begin
			axi_awvalid <= 1'b0;
		end
		else if (axi_awvalid == 1'b1 && M_AXI_AWREADY == 1'b1) begin
			axi_awvalid <= 1'b0;
		end
		else if (burst_start == 1'b1 && axi_busy == 1'b0) begin
			axi_awvalid <= 1'b1;
		end
	end

	always @(posedge M_AXI_ACLK) begin
	  if(M_AXI_ARESETN == 1'b0) begin
	    	axi_awaddr <= 'd0;
	  end
	  else if (M_AXI_AWREADY == 1'b1 && axi_awvalid == 1'b1 && axi_awaddr == 'd8292352) begin
	  		axi_awaddr <= 'd0;
	  end
	  else if (M_AXI_AWREADY == 1'b1 && axi_awvalid == 1'b1) begin
	    	axi_awaddr <= axi_awaddr + 'd2048;
	  end
	end

	always @(posedge M_AXI_ACLK) begin
		if (M_AXI_ARESETN == 0)
			axi_busy <= 1'b0;
		else if(axi_wlast == 1'b1 && axi_wvalid == 1'b1 && M_AXI_WREADY == 1'b1)
			axi_busy <= 1'b0;
		else if(burst_start == 1'b1 && axi_busy == 1'b0)
			axi_busy <= 1'b1;
	end

	always @(posedge M_AXI_ACLK) begin
	  if(M_AXI_ARESETN == 1'b0) begin
	    	axi_wvalid <= 1'b0;
	  end
	  else if (M_AXI_WREADY == 1'b1 && axi_wvalid == 1'b1 && burst_cnt == 'd255) begin //burst end
	  		axi_wvalid <= 1'b0;
	  end
	  else if (M_AXI_AWREADY == 1'b1 && axi_awvalid == 1'b1) begin
	    	axi_wvalid <= 1'b1;
	  end
	end

	always @(posedge M_AXI_ACLK) begin
	  if(M_AXI_ARESETN == 1'b0) begin
	      burst_cnt <='d0;
	  end
	  else if (M_AXI_WREADY == 1'b1 && axi_wvalid == 1'b1 && burst_cnt == 'd255) begin
	  	  burst_cnt <= 'd0;
	  end
	  else if (M_AXI_WREADY == 1'b1 && axi_wvalid == 1'b1) begin
	      burst_cnt <= burst_cnt + 1'b1;
	  end
	end

	always @* begin
		if(M_AXI_WREADY == 1'b1 && axi_wvalid == 1'b1 && burst_cnt == 'd255) begin
			axi_wlast <= 1'b1;
		end
		else begin
			axi_wlast <= 1'b0;
		end
	end

	always @* begin
	  	axi_wdata = fifo_rd_data;
	end

	always @(posedge M_AXI_ACLK) begin
	  if(M_AXI_ARESETN == 1'b0) begin
	      axi_bready <= 1'b0;
	  end
	  else begin
	  	  axi_bready <= 1'b1;
	  end
	end
wire [255:0] probe0;
assign probe0 = {
	INIT_AXI_TXN,
	work_on_flag,
	detect_fv,
	fv,hv,
	axi_wdata,
	axi_wvalid,
	axi_awvalid,
	M_AXI_AWREADY,
	M_AXI_WREADY,
	axi_awaddr,
	burst_cnt,
	full,
	fifo_rd_en,
	fifo_wr_en,
	rd_data_count
};
ila_0 ila_inst (
	.clk(M_AXI_ACLK), // input wire clk


	.probe0(probe0) // input wire [255:0] probe0
);

	// User logic ends
//--------------------------------------------------------------//
//--------------------------logic RTL---------------------------//
//--------------------------------------------------------------//
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值