3-1-02 AXI4-FULL-uiFDMA IP仿真验证
软件版本:vitis2021.1(vivado2021.1)操作系统:WIN10 64bit硬件平台:适用XILINX A7/K7/Z7/ZU/KU系列FPGA登录"米联客"FPGA社区-www.uisrc.com视频课程、答疑解惑!2.1概述本文试验中对前面编写的FDMA IP进行仿真验证。2.2saxi_full_mem IP介绍这个IP的源码可以基于XILINX提供的axi-full-slave的模板简单修改就可以实现,如果读者想要更加详细的学习AXI总线想内容,可以阅读或者观看米联客"米联客2022版AXI4总线专题篇"相关课程内容。本文实验使用我们已经修改好的代码来完成验证。这个IP后面可以用于AXI4总线的仿真验证2.3创建FPGA逻辑工程设置IP路径添加已经创建好的IP输入关键词fdma,在最后可以看到,双击添加Ip可以看到本文的FDMA版本升级到3.2版完成连线继续添加剩余IP设置IP参数完成连线设置地址分配:2.4添加FDMA接口控制代码
添加完成后如下图:fdma_axi_slave_test.v源码如下
/*******************************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/04/25*Module Name:fdma_axi_slave_test*File Name:fdma_axi_slave_test.v*Description:*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*********************************************************************/`timescale 1ns / 1psmodule fdma_axi_slave_test(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 ui_clk;
parameter TEST_MEM_SIZE = 32'd20000; //测试内存的地址范围parameter FDMA_BURST_LEN= 16'd500; //测试一次的长度parameter ADDR_MEM_OFFSET = 0; //地址偏移量parameter ADDR_INC = FDMA_BURST_LEN*4; //下一次FDMA burst的地址增加
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; //设置FDMA控制器一次写burst的数据长度assign fdma_rsize = FDMA_BURST_LEN; //设置FDMA控制器一次读burst的数据长度assign fdma_wdata ={t_data,t_data,t_data,t_data};
////延迟复位reg rst_cnt = 0;always @(posedge ui_clk) if(rst_cnt == 1'b0) rst_cnt <= rst_cnt + 1'b1; else rst_cnt <= rst_cnt;
//FDMA 读写控制器,每次先写后读,读出后对比数据正确性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进入空闲,fdma_wbusy=0,请求写 fdma_wareq<= 1'b1; //设置写请求 t_data<= 0; //设置初值 end if(fdma_wareq&&fdma_wbusy)begin//当fdma响应请求后,fdma_wbusy=1,进入下一个状态 fdma_wareq<= 1'b0; T_S <= WRITE2; end end WRITE2:begin if(!fdma_wbusy) begin//当fdma完成请求后,fdma_wbusy=0,进入下一个状态 T_S <= WAIT; t_data<= 32'd0; end else if(fdma_wvalid) begin//当fdma_wvalid有效期间必须写入有效数据 t_data <= t_data + 1'b1; end end WAIT:begin//not needed T_S <= READ1; end READ1:begin if(!fdma_rbusy)begin//当fdma进入空闲,fdma_rbusy=0,请求读 fdma_rareq<= 1'b1; //设置读请求 t_data <= 0; //设置初值 end if(fdma_rareq&&fdma_rbusy)begin//当fdma响应请求后,fdma_rbusy=1,进入下一个状态 fdma_rareq<= 1'b0; //清除读请求 T_S <= READ2; end end READ2:begin if(!fdma_rbusy) begin//当fdma完成请求后,fdma_rbusy=0,进入下一个状态 T_S <= WRITE1; t_data<= 32'd0; fdma_waddr_r<= fdma_waddr_r + ADDR_INC; //当本次读写周期完成增加地址,地址以BYTE计算 end else if(fdma_rvalid) begin//当fdma_rvalid有效期间读出的数据有效 t_data <= t_data + 1'b1; end end default: T_S <= WRITE1; endcase endend //对比是否有错误数据wire test_error = (fdma_rvalid && (t_data != fdma_rdata));
//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 (.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), .sysclk(sysclk), .ui_clk(ui_clk) );
endmodule
以上代码中调用的system.bd的图形代码接口。在状态机中,每次写500个长度32bit的数据,再读出来判断数据是否正确,因此传输20000字节的数据需要传输10次,每次FDMA传输的地址递增2000。2.5仿真文件添加仿真文件以下文件路径以实际工程的路径为准添加完成后:仿真文件非常简单,只要提供时钟激励就可以。
`timescale 1ns / 1psmodule fdma_axi_slave_test_tb(); reg sysclk; fdma_axi_slave_test fdma_axi_slave_test_inst( .sysclk(sysclk) );initial begin sysclk= 0; #100;end always #10 sysclk = ~sysclk;endmodule
2.6实验结果下图中红色框内分别代表了FDMA一次burst的写操作和一次burst的读操作。FDMA 控制器会根据用户代码设置的fdma_wsize和fdma_rsize以及设置的FDMA IP参数中,AXI4总线支持的最大burst 长度,来决定进行多少次的AXI4 burst。本次写传输中,wburst_len_req自动发起计算AXI4总线需要发起的传输长度,本次传输中,FDMA的用户代码每次发起传输长度为500,因此FDMA部分会自动控制AXI部分的传输长度,第一次axi burst长度为256,第二次axi burst长度为244。一次FDMA写传输的起始时序连续burst,自动管理burst长度,以及一次FDMA写传输结束时序本次读传输中,rburst_len_req自动发起计算AXI4总线需要发起的传输长度,本次传输中,FDMA的用户代码每次发起传输长度为500,因此FDMA部分会自动控制AXI部分的传输长度,第一次axi burst长度为256,第二次axi burst长度为244。一次FDMA读传输的起始时序连续burst,自动管理burst长度,以及一次FDMA读传输结束时序
页:
[1]