uisrc 发表于 2023-12-30 14:04:43

3-1-04 FPGA使用fdma读写DDR

软件版本:vitis2021.1(vivado2021.1)操作系统:WIN10 64bit硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!4.1概述    在前文的实验中我们详细介绍了FDMA的使用方法, 前面一节课演示了FDMA读写AXI-BRAM,本文我们继续使用FDMA实现对AXI-MIG的读写,以此读写DDR。由于FDMA的读写操作都是基于AXI总线,所以用户代码部分一致性也非常好,我们的状态机都不需要做修改,基本上只要把前文的BRAM IP换成MIG IP即可。本文实验目的:1:利用uiFDMA3.2提供的接口,编写DDR测试程序2:对MIG接口读写仿真和测试本系统中先将测试数据通过AXI-DMA写入DDR,再通过AXI-DMA将DDR3中数据读出。将读写数据进行对比。通过在线逻辑分析仪抓取读写数据测试读写正确性。4.3基于图形化逻辑设计搭建过程我们不再详细描述,不清楚的可以参考前"使用FDMA读写AXI-BRAM",搭建好的工程如下我们主要看下MIG的配置1:MIG配置
继续该页面设置

继续NEXT,知道下页2:编写FDMA的DDR测试代码以下程序中是fdma读写操作的具体实现,先写入一定数据到DDR中,然后再读出,对比是否有错误,几个关键参数:TEST_MEM_SIZE:定义了测试内从空间的大小,以byte为单位,是整数倍的FDMA_BURST_LEN *(fdma_wdata/8)。FDMA_BURST_LEN:定义每次FDMA传输的长度,这个长度是整数倍的fdma_wdata或者fdma_rdata。ADDR_MEM_OFFSET:代码了内从访问的起始地址。

`timescale 1ns / 1ps/*******************************MILIANKE********************************Company : MiLianKe Electronic Technology Co., Ltd.*WebSite:https://www.milianke.com*TechWeb:https://www.uisrc.com*tmall-shop:https://milianke.tmall.com*jd-shop:https://milianke.jd.com*taobao-shop1: https://milianke.taobao.com*Create Date: 2021/10/15*Module Name:*File Name:*Description:*config sensor resgister*The reference demo provided by Milianke is only used for learning.*We cannot ensure that the demo itself is free of bugs, so users*should be responsible for the technical problems and consequences*caused by the use of their own products.*Copyright: Copyright (c) MiLianKe*All rights reserved.*Revision: 1.0*Signal description*1) I_ input*2) O_ output*3) IO_ input output*4) S_ system internal signal*5) _n activ low*6) _dg debug signal*7) _r delay or register*8) _s state mechine*********************************************************************/module fdma_ddr_test(output DDR3_0_addr,output DDR3_0_ba,output DDR3_0_cas_n,output DDR3_0_ck_n,output DDR3_0_ck_p,output DDR3_0_cke,output DDR3_0_cs_n,output DDR3_0_dm,inoutDDR3_0_dq,inoutDDR3_0_dqs_n,inoutDDR3_0_dqs_p,output DDR3_0_odt,output DDR3_0_ras_n,output DDR3_0_reset_n,output DDR3_0_we_n,input sysclk);
wire    fdma_raddr;reg         fdma_rareq;wire          fdma_rbusy;wire fdma_rdata;wire    fdma_rsize;wire          fdma_rvalid;wire    fdma_waddr;reg         fdma_wareq;wire          fdma_wbusy;wire fdma_wdata;wire    fdma_wsize;wire          fdma_wvalid;wire     fdma_rstn;wire          ui_clk;
parameter TEST_MEM_SIZE   = 32'd1024*1024*256;parameter FDMA_BURST_LEN= 16'd512;parameter ADDR_MEM_OFFSET = 0;parameter ADDR_INC = FDMA_BURST_LEN * 16;
parameter WRITE1 = 0;parameter WRITE2 = 1;parameter WAIT   = 2;parameter READ1= 3;parameter READ2= 4;
reg t_data;reg fdma_waddr_r;reg T_S = 0;
assign fdma_waddr = fdma_waddr_r + ADDR_MEM_OFFSET;assign fdma_raddr = fdma_waddr;
assign fdma_wsize = FDMA_BURST_LEN;assign fdma_rsize = FDMA_BURST_LEN;assign fdma_wdata ={t_data,t_data,t_data,t_data};
reg rst_cnt = 0;
always @(posedge ui_clk)    if(~fdma_rstn)begin      rst_cnt <=0;    end    else begin      if(rst_cnt == 1'b0)            rst_cnt <= rst_cnt + 1'b1;      else            rst_cnt <= rst_cnt;    end
always @(posedge ui_clk)begin    if(rst_cnt == 1'b0)begin      T_S <=0;      fdma_wareq<= 1'b0;      fdma_rareq<= 1'b0;      t_data<=0;      fdma_waddr_r <=0;          end    else begin      case(T_S)            WRITE1:begin            if(fdma_waddr_r==TEST_MEM_SIZE) fdma_waddr_r<=0;                if(!fdma_wbusy)begin                  fdma_wareq<= 1'b1;                  t_data<= 0;                end                if(fdma_wareq&&fdma_wbusy)begin                  fdma_wareq<= 1'b0;                  T_S         <= WRITE2;                end      end      WRITE2:begin            if(!fdma_wbusy) begin               T_S <= WAIT;               t_data<= 32'd0;            end            else if(fdma_wvalid) begin                t_data <= t_data + 1'b1;            end      end      WAIT:begin//not needed            T_S <= READ1;      end      READ1:begin            if(!fdma_rbusy)begin                fdma_rareq<= 1'b1;                t_data   <= 0;            end            if(fdma_rareq&&fdma_rbusy)begin               fdma_rareq<= 1'b0;               T_S         <= READ2;            end      end      READ2:begin            if(!fdma_rbusy) begin               T_S <= WRITE1;               t_data<= 32'd0;               fdma_waddr_r<= fdma_waddr_r + ADDR_INC;//128/8=16            end            else if(fdma_rvalid) begin                t_data <= t_data + 1'b1;            end      end      default:            T_S <= WRITE1;          endcase    endend
reg test_error;
always @(posedge ui_clk)begin    test_error <= (fdma_rvalid && (t_data != fdma_rdata));end
ila_0 ila_dbg (    .clk(ui_clk),    .probe0({fdma_wdata,fdma_wareq,fdma_wvalid,fdma_wbusy}),    .probe1({fdma_rdata,t_data,fdma_rvalid,fdma_rbusy,T_S,test_error}));
system system_i       (.DDR3_0_addr(DDR3_0_addr),      .DDR3_0_ba(DDR3_0_ba),      .DDR3_0_cas_n(DDR3_0_cas_n),      .DDR3_0_ck_n(DDR3_0_ck_n),      .DDR3_0_ck_p(DDR3_0_ck_p),      .DDR3_0_cke(DDR3_0_cke),      .DDR3_0_cs_n(DDR3_0_cs_n),      .DDR3_0_dm(DDR3_0_dm),      .DDR3_0_dq(DDR3_0_dq),      .DDR3_0_dqs_n(DDR3_0_dqs_n),      .DDR3_0_dqs_p(DDR3_0_dqs_p),      .DDR3_0_odt(DDR3_0_odt),      .DDR3_0_ras_n(DDR3_0_ras_n),      .DDR3_0_reset_n(DDR3_0_reset_n),      .DDR3_0_we_n(DDR3_0_we_n),      .FDMA_S_0_i_fdma_raddr(fdma_raddr),      .FDMA_S_0_i_fdma_rareq(fdma_rareq),      .FDMA_S_0_o_fdma_rbusy(fdma_rbusy),      .FDMA_S_0_o_fdma_rdata(fdma_rdata),      .FDMA_S_0_i_fdma_rready(1'b1),      .FDMA_S_0_i_fdma_rsize(fdma_rsize),      .FDMA_S_0_o_fdma_rvalid(fdma_rvalid),      .FDMA_S_0_i_fdma_waddr(fdma_waddr),      .FDMA_S_0_i_fdma_wareq(fdma_wareq),      .FDMA_S_0_o_fdma_wbusy(fdma_wbusy),      .FDMA_S_0_i_fdma_wdata(fdma_wdata),      .FDMA_S_0_i_fdma_wready(1'b1),      .FDMA_S_0_i_fdma_wsize(fdma_wsize),      .FDMA_S_0_o_fdma_wvalid(fdma_wvalid),      .fdma_rstn(fdma_rstn),      .sysclk(sysclk),      .ui_clk(ui_clk));
endmodule


3:程序分析3-1:总流程图如下图所示,本文的程序工作流程如下,包括请求写数据、FDMA收到写数据请求、写数据完成、请求读数据、FDMA收到读数据请求和读数据完成、校验。以下是fdma_test.v中读写fdma ip接口的状态机,由于读写代码对称,对fdma的读写操作可以分为2步完成,分别是:1:发送读/写请求 2:读/写有效数据。
3-2:FDMA的写时序fdma_wready设置为1,当fdma_wbusy=0的时候代表FDMA的总线非忙,可以进行一次新的FDMA传输,这个时候可以设置fdma_wreq=1,同时设置fdma burst的起始地址和fdma_wsize本次需要传输的数据大小(以bytes为单位)。当fdma_wvalid=1的时候需要给出有效的数据,写入AXI总线。当最后一个数写完后,fdma_wvalid和fdma_wbusy变为0。AXI4总线最大的burst lenth是256,而经过封装后,用户接口的fdma_size可以任意大小的,fdma ip内部代码控制每次AXI4总线的Burst长度,这样极大简化了AXI4总线协议的使用。3-3:FDMA的读时序fdma_rready设置为1,当fdma_rbusy=0的时候代表FDMA的总线非忙,可以进行一次新的FDMA传输,这个时候可以设置fdma_rreq=1,同时设置fdma burst的起始地址和fdma_rsize本次需要传输的数据大小(以bytes为单位)。当fdma_rvalid=1的时候需要给出有效的数据,写入AXI总线。当最后一个数写完后,fdma_rvalid和fdma_rbusy变为0。同样对于AXI4总线的读操作,AXI4总线最大的burst lenth是256,而经过封装后,用户接口的fdma_size可以任意大小的,fdma ip内部代码控制每次AXI4总线的Burst长度,这样极大简化了AXI4总线协议的使用。4:地址空间分配配置完成后需要注意地址空间分配,FDMA IP的内存起始地址从0开始4.4RTL仿真1:仿真tb文件DDR3的仿真文件在对应的FPGA工程路径uisrc/02_sim路径下,把仿真文件添加进来2:仿真测试4.5上板验证添加fpga_pin.xdc文件,不同的开发板IO的约束定义一样,下图仅仅提供演示,具体以自己拿到的配套资料工程路径下的uisrc/04_pin/fpga_pin.xdc为准。当然读者也可以根据原理图自己定义约束。通过ila在线逻辑分析仪IP-CORE,在线观察波形通过在线逻辑分析仪查看结果,可以看到test_error信号一直低电平
页: [1]
查看完整版本: 3-1-04 FPGA使用fdma读写DDR