[X]关闭
8

09使用fdma读写DDR(AXI4总线实战)

摘要: 在前文的实验中我们详细介绍了FDMA的使用方法,以及使用了AXI-BRAM演示了FDMA的使用,现在我们已经掌握了FDMA的使用,本文我们继续使用FDMA实现对AXI-MIG的读写,以此读写DDR。由于FDMA的读写操作都是基于AXI总线, ...

软件版本:vitis2020.2(vivado2020.2)

操作系统:WIN10 64bit

硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA(米联客(milianke)MZU07A-EG硬件开发平台)

登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!

9.1概述    

在前文的实验中我们详细介绍了FDMA的使用方法,以及使用了AXI-BRAM演示了FDMA的使用,现在我们已经掌握了FDMA的使用,本文我们继续使用FDMA实现对AXI-MIG的读写,以此读写DDR。由于FDMA的读写操作都是基于AXI总线,所以用户代码部分一致性也非常好,我们的状态机都不需要做修改,基本上只要把前文的BRAM IP换成MIG IP即可。

本文实验目的:

1:利用uiFDMA2.0/3.0提供的接口,编写DDR测试程序

2:对MIG接口读写仿真和测试

9.2PL图形化设计

搭建过程我们不再详细描述,不清楚的可以参考前"01使用FDMA读写AXI-BRAM",搭建好的工程如下

我们主要看下MIG的配置

9.3编写FDMA的DDR测试代码

以下代码除来DDR的引脚定义,以及增加来1按键输入复位,其他内容都和"01使用FDMA读写AXI-BRAM"一样。读写状态机完全一样,对PL DDR整个内存地址空间进行测试。

 

`timescale 1ns / 1ps

//////////////////////////////////////////////////////////////////////////////////

/*

Company : Liyang Milian Electronic Technology Co., Ltd.

Brand: milianke

Technical forum:uisrc.com

taobao: https://milianke.taobao.com https://osrc.taobao.com

jd:https://milianke.jd.com

Create Date: 2021/04/26

Module Name: fdma_ddr_test

Description:

Copyright: Copyright (c) milianke

Revision: 1.0

Signal description:

1) _i input

2) _o output

3) _n activ lowpai

4) _dg debug signal

5) _r delay or register

6) _s state mechine

*/

//////////////////////////////////////////////////////////////////////////////////

module fdma_ddr_test(

output C0_DDR4_act_n,

output [16:0]C0_DDR4_adr,

output [1 :0]C0_DDR4_ba,

output [0 :0]C0_DDR4_bg,

output [0 :0]C0_DDR4_ck_c,

output [0 :0]C0_DDR4_ck_t,

output [0 :0]C0_DDR4_cke,

output [0 :0]C0_DDR4_cs_n,

inout [7 :0]C0_DDR4_dm_n,

inout [63:0]C0_DDR4_dq,

inout [7 :0]C0_DDR4_dqs_c,

inout [7 :0]C0_DDR4_dqs_t,

output [0 :0]C0_DDR4_odt,

output C0_DDR4_reset_n,

output C0_init_calib_complete,

input key_i,

input sysclk_p,

input sysclk_n

);

wire ddr_rst = ~key_i;

wire [31:0] fdma_raddr;

reg fdma_rareq;

wire fdma_rbusy;

wire [127:0] fdma_rdata;

wire [15:0] fdma_rsize;

wire fdma_rvalid;

wire [31:0] fdma_waddr;

reg fdma_wareq;

wire fdma_wbusy;

wire [127:0] fdma_wdata;

wire [15:0] fdma_wsize;

wire fdma_wvalid;

wire [0:0] fdma_rstn;

wire ui_clk;

 

 

parameter TEST_MEM_SIZE = 32'd1024*1024*1024;//4GB

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 [31: 0] t_data;

reg [31: 0] fdma_waddr_r;

reg [2 :0] 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 [8:0] rst_cnt = 0;

 

always @(posedge ui_clk)

if((fdma_rstn & C0_init_calib_complete)==1'b0)begin

rst_cnt <=0;

end

else begin

if(rst_cnt[8] == 1'b0)

rst_cnt <= rst_cnt + 1'b1;

else

rst_cnt <= rst_cnt;

end

 

always @(posedge ui_clk)begin

if(rst_cnt[8] == 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

end

end

 

wire test_error = (fdma_rvalid && (t_data[15:0] != fdma_rdata[15:0]));

 

ila_0 ila_dbg (

    .clk(ui_clk),

    .probe0({fdma_wdata[15:0],fdma_wareq,fdma_wvalid,fdma_wbusy}),

    .probe1({fdma_rdata[15:0],t_data[15:0],fdma_rvalid,fdma_rbusy,T_S,test_error})

);

 

system system_i

(.C0_DDR4_act_n(C0_DDR4_act_n),

.C0_DDR4_adr(C0_DDR4_adr),

.C0_DDR4_ba(C0_DDR4_ba),

.C0_DDR4_bg(C0_DDR4_bg),

.C0_DDR4_ck_c(C0_DDR4_ck_c),

.C0_DDR4_ck_t(C0_DDR4_ck_t),

.C0_DDR4_cke(C0_DDR4_cke),

.C0_DDR4_cs_n(C0_DDR4_cs_n),

.C0_DDR4_dm_n(C0_DDR4_dm_n),

.C0_DDR4_dq(C0_DDR4_dq),

.C0_DDR4_dqs_c(C0_DDR4_dqs_c),

.C0_DDR4_dqs_t(C0_DDR4_dqs_t),

.C0_DDR4_odt(C0_DDR4_odt),

.C0_DDR4_reset_n(C0_DDR4_reset_n),

.FDMA_S_0_fdma_raddr(fdma_raddr),

.FDMA_S_0_fdma_rareq(fdma_rareq),

.FDMA_S_0_fdma_rbusy(fdma_rbusy),

.FDMA_S_0_fdma_rdata(fdma_rdata),

.FDMA_S_0_fdma_rready(1'b1),

.FDMA_S_0_fdma_rsize(fdma_rsize),

.FDMA_S_0_fdma_rvalid(fdma_rvalid),

.FDMA_S_0_fdma_waddr(fdma_waddr),

.FDMA_S_0_fdma_wareq(fdma_wareq),

.FDMA_S_0_fdma_wbusy(fdma_wbusy),

.FDMA_S_0_fdma_wdata(fdma_wdata),

.FDMA_S_0_fdma_wready(1'b1),

.FDMA_S_0_fdma_wsize(fdma_wsize),

.FDMA_S_0_fdma_wvalid(fdma_wvalid),

.C0_init_calib_complete(C0_init_calib_complete),

.ddr_rst(ddr_rst),

.fdma_rstn(fdma_rstn),

.sysclk_clk_p(sysclk_p),

.sysclk_clk_n(sysclk_n),

 

.ui_clk(ui_clk));

endmodule 

9.4程序分析

以下关于程序的分析和"01使用FDMA读写AXI-BRAM"一样,重复是为了读者不会因此遗漏这部分重要信息。

9.4.1FDMA的写时序

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。

9.4.2FDMA的读时序

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。

9.4.3读写状态机

 

 

9.5实验结果

9.5.1仿真结果

1:仿真tb文件

DDR4的仿真文件在对应的FPGA工程路径uisrc/02_sim路径下,把仿真文件添加进来

2:仿真测试

可以看到DDR4的仿真速度还是很快,在6us左右就可以得到仿真结果了,可以看到test_error信号一直是低电平。

9.5.2板级测试

添加fpga_pin.xdc文件,不同的开发板IO的约束定义一样,下图仅仅提供演示,具体以自己拿到的配套资料工程路径下的uisrc/04_pin/fpga_pin.xdc为准。当然读者也可以根据原理图自己定义约束。

通过ila在线逻辑分析仪IP-CORE,在线观察波形

通过在线逻辑分析仪查看结果,可以看到test_error信号一直低电平


路过

雷人

握手

鲜花

鸡蛋
发表评论

最新评论

引用 qq_Z4Y3U 2024-3-8 18:28
请问“同时设置fdma burst的起始地址和fdma_wsize本次需要传输的数据大小(以bytes为单位)”这里。fdma_wsize看起来就是burst的次数,为什么这里说是以byte为单位呢
引用 大脸猫不爱吃鱼 2022-7-12 10:32
你好老师,我想问下DDR3支持同时读同时写吗
引用 郭_C4CC2 2022-6-18 10:49
请问 我只用一个通道 可不可以不用axi_interconnect 直接把FDMA接到MIG上呢?
我试了一下 好像不能正常工作 不知道哪里出问题了  望指教
引用 曾经的你 2022-3-7 22:00
为什么我仿真了一下午也没出来结果???
引用 放空 2021-12-15 11:08
支持多通道的,多挂几个FDMA这个做法有参考工程么。
引用 uisrc 2021-8-18 20:43
配套源码下载链接:https://pan.baidu.com/s/1TvjOdZvCyDQpS4a7jYivRQ 提取码:1111
引用 uisrc 2021-8-17 17:53
支持多通道的,可以多挂几个FDMA都可以,目前测试过挂4路FDMA 让,axi-interconnect 做仲裁
引用 rluxezmn 2021-8-16 18:11
能做到多通道读写仲裁就更好了

查看全部评论(8)

本文作者
2021-8-15 23:39
  • 7
    粉丝
  • 8920
    阅读
  • 8
    回复
  • 1
  • 2
  • 3
热门评论
排行榜