一、AXI4协议介绍

AXI4 相对复杂,但 SOC 开发者必须掌握。AXI 协议的具体内容可参考 Xilinx UG761 AXI Reference Guide。

在这里我们简单了解一下。

AXI4 所采用的是一种 READY,VALID 握手通信机制,即主从模块进行数据通信前,先根

据操作对各所用到的数据、地址通道进行握手。主要操作包括传输发送者 A 等到传输接受者 B

的 READY 信号后,A 将数据与 VALID 信号同时发送给 B,这是一种典型的握手机制。

AXI 总线分为五个通道:

 读地址通道,包含 ARVALID, ARADDR, ARREADY 信号;

 写地址通道,包含 AWVALID,AWADDR, AWREADY 信号;

 读数据通道,包含 RVALID, RDATA, RREADY, RRESP 信号;

 写数据通道,包含 WVALID, WDATA,WSTRB, WREADY 信号;

 写应答通道,包含 BVALID, BRESP, BREADY 信号;

 系统通道,包含:ACLK,ARESETN 信号;

其中 ACLK 为 axi 总线时钟,ARESETN 是 axi 总线复位信号,低电平有效;读写数据与读

写地址类信号宽度都为 32bit;READY 与 VALID 是对应的通道握手信号;WSTRB 信号为 1 的

bit 对应 WDATA 有效数据字节,WSTRB 宽度是 32bit/8=4bit;BRESP 与 RRESP 分别为写回

应信号,读回应信号,宽度都为 2bit,‘h0 代表成功,其他为错误。

读操作顺序为主与从进行读地址通道握手并传输地址内容,然后在读数据通道握手并传输

所读内容以及读取操作的回应,时钟上升沿有效。如图所示:

写操作顺序为主与从进行写地址通道握手并传输地址内容,然后在写数据通道握手并传输

所读内容,最后再写回应通道握手,并传输写回应数据,时钟上升沿有效。如图所示:

二、axi协议应用举例

在我们不擅长写 FPGA 的一些代码时我们往往要借鉴别人的代码或者使用 IP core。在这里

笔者从 github 上找到一个 AXI master 的代码,地址是

https://github.com/aquaxis/IPCORE/tree/master/aq_axi_vdma。这个工程是一个自己写的

VDMA,里面包含了大量可参考的代码。笔者这里主要使用了 aq_axi_master.v 这个代码用于

AXI master 读写操作。借鉴别人代码有时会节省很多时间,但如果不能理解的去借鉴,出现问

题了很难解决。aq_axi_master.v 代码如下,有部分修改。

/* * Copyright (C)2014-2015 AQUAXIS TECHNOLOGY. *  Don't remove this header.  * When you use this source, there is a need to inherit this header. * * License *  For no commercial - *   License:     The Open Software License 3.0 *   License URI: http://www.opensource.org/licenses/OSL-3.0 * *  For commmercial - *   License:     AQUAXIS License 1.0 *   License URI: http://www.aquaxis.com/licenses * * For further information please contact. *  URI:    http://www.aquaxis.com/ *  E-Mail: info(at)aquaxis.com */ //
// Company:
// Engineer:
//
// Create Date: 2016/11/17 10:27:06
// Design Name:
// Module Name: mem_test
// Project Name:
// Target Devices:
// Tool Versions:
// Description:
//
// Dependencies:
//
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
//  //
module aq_axi_master(
// Reset, Clock
input           ARESETN,
input           ACLK, // Master Write Address
output[0:0]  M_AXI_AWID,
output[31:0] M_AXI_AWADDR,
output[7:0]  M_AXI_AWLEN,// Burst Length: 0-255
output[2:0]  M_AXI_AWSIZE,// Burst Size: Fixed 2'b011
output[1:0]  M_AXI_AWBURST,// Burst Type: Fixed 2'b01(Incremental Burst)
output        M_AXI_AWLOCK,// Lock: Fixed 2'b00
output[3:0]  M_AXI_AWCACHE,// Cache: Fiex 2'b0011
output[2:0]  M_AXI_AWPROT,// Protect: Fixed 2'b000
output[3:0]  M_AXI_AWQOS,// QoS: Fixed 2'b0000
output[0:0]  M_AXI_AWUSER,// User: Fixed 32'd0
output        M_AXI_AWVALID,
input         M_AXI_AWREADY, // Master Write Data
output[63:0] M_AXI_WDATA,
output[7:0]  M_AXI_WSTRB,
output        M_AXI_WLAST,
output[0:0]  M_AXI_WUSER,
output        M_AXI_WVALID,
input         M_AXI_WREADY, // Master Write Response
input[0:0]   M_AXI_BID,
input[1:0]   M_AXI_BRESP,
input[0:0]   M_AXI_BUSER,
input         M_AXI_BVALID,
output        M_AXI_BREADY, // Master Read Address
output[0:0]  M_AXI_ARID,
output[31:0] M_AXI_ARADDR,
output[7:0]  M_AXI_ARLEN,
output[2:0]  M_AXI_ARSIZE,
output[1:0]  M_AXI_ARBURST,
output[1:0]  M_AXI_ARLOCK,
output[3:0]  M_AXI_ARCACHE,
output[2:0]  M_AXI_ARPROT,
output[3:0]  M_AXI_ARQOS,
output[0:0]  M_AXI_ARUSER,
output        M_AXI_ARVALID,
input         M_AXI_ARREADY, // Master Read Data
input[0:0]   M_AXI_RID,
input[63:0]  M_AXI_RDATA,
input[1:0]   M_AXI_RRESP,
input         M_AXI_RLAST,
input[0:0]   M_AXI_RUSER,
input         M_AXI_RVALID,
output        M_AXI_RREADY, // Local Bus
input         MASTER_RST, input         WR_START,
input[31:0]  WR_ADRS,
input[31:0]  WR_LEN,
output        WR_READY,
output        WR_FIFO_RE,
input         WR_FIFO_EMPTY,
input         WR_FIFO_AEMPTY,
input[63:0]  WR_FIFO_DATA,
output        WR_DONE, input         RD_START,
input[31:0]  RD_ADRS,
input[31:0]  RD_LEN,
output        RD_READY,
output        RD_FIFO_WE,
input         RD_FIFO_FULL,
input         RD_FIFO_AFULL,
output[63:0] RD_FIFO_DATA,
output        RD_DONE, output[31:0] DEBUG
); localparam S_WR_IDLE  =3'd0;
localparam S_WA_WAIT  =3'd1;
localparam S_WA_START =3'd2;
localparam S_WD_WAIT  =3'd3;
localparam S_WD_PROC  =3'd4;
localparam S_WR_WAIT  =3'd5;
localparam S_WR_DONE  =3'd6; reg[2:0]   wr_state;
reg[31:0]  reg_wr_adrs;
reg[31:0]  reg_wr_len;
reg         reg_awvalid, reg_wvalid, reg_w_last;
reg[7:0]   reg_w_len;
reg[7:0]   reg_w_stb;
reg[1:0]   reg_wr_status;
reg[3:0]   reg_w_count, reg_r_count; reg[7:0]   rd_chkdata, wr_chkdata;
reg[1:0]   resp;
reg rd_first_data;
reg rd_fifo_enable;
reg[31:0] rd_fifo_cnt;
assign WR_DONE =(wr_state == S_WR_DONE); assign WR_FIFO_RE         = rd_first_data |(reg_wvalid &~WR_FIFO_EMPTY &
M_AXI_WREADY & rd_fifo_enable);
//assign WR_FIFO_RE         = reg_wvalid & ~WR_FIFO_EMPTY & M_AXI_WREADY;
always@(posedge ACLK ornegedge ARESETN)
begin if(!ARESETN) rd_fifo_cnt <=32'd0; elseif(WR_FIFO_RE) rd_fifo_cnt <= rd_fifo_cnt +32'd1; elseif(wr_state == S_WR_IDLE) rd_fifo_cnt <=32'd0;
end always@(posedge ACLK ornegedge ARESETN)
begin if(!ARESETN) rd_fifo_enable <=1'b0; elseif(wr_state == S_WR_IDLE && WR_START) rd_fifo_enable <=1'b1; elseif(WR_FIFO_RE &&(rd_fifo_cnt == RD_LEN[31:3]-32'd1)) rd_fifo_enable <=1'b0;
end
// Write State
always@(posedge ACLK ornegedge ARESETN)begin
if(!ARESETN)begin wr_state            <= S_WR_IDLE; reg_wr_adrs[31:0]<=32'd0; reg_wr_len[31:0]<=32'd0; reg_awvalid         <=1'b0; reg_wvalid          <=1'b0; reg_w_last          <=1'b0; reg_w_len[7:0]<=8'd0; reg_w_stb[7:0]<=8'd0; reg_wr_status[1:0]<=2'd0; reg_w_count[3:0]<=4'd0; reg_r_count[3:0]<=4'd0; wr_chkdata          <=8'd0; rd_chkdata <=8'd0; resp <=2'd0; rd_first_data <=1'b0;
endelsebegin
if(MASTER_RST)begin wr_state <= S_WR_IDLE;
endelsebegin
case(wr_state) S_WR_IDLE:begin
if(WR_START)begin wr_state          <= S_WA_WAIT; reg_wr_adrs[31:0]<= WR_ADRS[31:0]; reg_wr_len[31:0]<= WR_LEN[31:0]-32'd1; rd_first_data <=1'b1;
end reg_awvalid         <=1'b0; reg_wvalid          <=1'b0; reg_w_last          <=1'b0; reg_w_len[7:0]<=8'd0; reg_w_stb[7:0]<=8'd0; reg_wr_status[1:0]<=2'd0;
end S_WA_WAIT:begin
if(!WR_FIFO_AEMPTY |(reg_wr_len[31:11]==21'd0))begin wr_state          <= S_WA_START;
end rd_first_data <=1'b0;
end S_WA_START:begin wr_state            <= S_WD_WAIT; reg_awvalid         <=1'b1; reg_wr_len[31:11]<= reg_wr_len[31:11]-21'd1;
if(reg_wr_len[31:11]!=21'd0)begin reg_w_len[7:0]<=8'hFF; reg_w_last      <=1'b0; reg_w_stb[7:0]<=8'hFF;
endelsebegin reg_w_len[7:0]<= reg_wr_len[10:3]; reg_w_last      <=1'b1; reg_w_stb[7:0]<=8'hFF;
/* case(reg_wr_len[2:0]) begin case 3'd0: reg_w_stb[7:0]  <= 8'b0000_0000; case 3'd1: reg_w_stb[7:0]  <= 8'b0000_0001; case 3'd2: reg_w_stb[7:0]  <= 8'b0000_0011; case 3'd3: reg_w_stb[7:0]  <= 8'b0000_0111; case 3'd4: reg_w_stb[7:0]  <= 8'b0000_1111; case 3'd5: reg_w_stb[7:0]  <= 8'b0001_1111; case 3'd6: reg_w_stb[7:0]  <= 8'b0011_1111; case 3'd7: reg_w_stb[7:0]  <= 8'b0111_1111; default:   reg_w_stb[7:0]  <= 8'b1111_1111; endcase
*/
end
end S_WD_WAIT:begin
if(M_AXI_AWREADY)begin wr_state        <= S_WD_PROC; reg_awvalid     <=1'b0; reg_wvalid      <=1'b1;
end
end S_WD_PROC:begin
if(M_AXI_WREADY &~WR_FIFO_EMPTY)begin
if(reg_w_len[7:0]==8'd0)begin wr_state        <= S_WR_WAIT; reg_wvalid      <=1'b0; reg_w_stb[7:0]<=8'h00;
endelsebegin reg_w_len[7:0]<= reg_w_len[7:0]-8'd1;
end
end
end S_WR_WAIT:begin
if(M_AXI_BVALID)begin reg_wr_status[1:0]<= reg_wr_status[1:0]| M_AXI_BRESP[1:0];
if(reg_w_last)begin wr_state          <= S_WR_DONE;
endelsebegin wr_state          <= S_WA_WAIT; reg_wr_adrs[31:0]<= reg_wr_adrs[31:0]+32'd2048;
end
end
end S_WR_DONE:begin wr_state <= S_WR_IDLE;
end
default:begin wr_state <= S_WR_IDLE;
end
endcase
/* if(WR_FIFO_RE) begin reg_w_count[3:0]  <= reg_w_count[3:0] + 4'd1; end if(RD_FIFO_WE)begin reg_r_count[3:0]  <= reg_r_count[3:0] + 4'd1; end if(M_AXI_AWREADY & M_AXI_AWVALID) begin wr_chkdata <= 8'hEE; end else if(M_AXI_WSTRB[7] & M_AXI_WVALID) begin wr_chkdata <= WR_FIFO_DATA[63:56]; end if(M_AXI_AWREADY & M_AXI_AWVALID) begin rd_chkdata <= 8'hDD; end else if(M_AXI_WSTRB[7] & M_AXI_WREADY) begin rd_chkdata <= WR_FIFO_DATA[63:56]; end if(M_AXI_BVALID & M_AXI_BREADY) begin resp <= M_AXI_BRESP; end
*/
end
end
end assign M_AXI_AWID         =1'b0;
assign M_AXI_AWADDR[31:0]= reg_wr_adrs[31:0];
assign M_AXI_AWLEN[7:0]= reg_w_len[7:0];
assign M_AXI_AWSIZE[2:0]=2'b011;
assign M_AXI_AWBURST[1:0]=2'b01;
assign M_AXI_AWLOCK       =1'b0;
assign M_AXI_AWCACHE[3:0]=4'b0011;
assign M_AXI_AWPROT[2:0]=3'b000;
assign M_AXI_AWQOS[3:0]=4'b0000;
assign M_AXI_AWUSER[0]=1'b1;
assign M_AXI_AWVALID      = reg_awvalid; assign M_AXI_WDATA[63:0]= WR_FIFO_DATA[63:0];
//  assign M_AXI_WSTRB[7:0]   = (reg_w_len[7:0] ==
8'd0)?reg_w_stb[7:0]:8'hFF;
//  assign M_AXI_WSTRB[7:0]   = (wr_state == S_WD_PROC)?8'hFF:8'h00;
assign M_AXI_WSTRB[7:0]=(reg_wvalid &~WR_FIFO_EMPTY)?8'hFF:8'h00;
assign M_AXI_WLAST        =(reg_w_len[7:0]==8'd0)?1'b1:1'b0;
assign M_AXI_WUSER        =1;
assign M_AXI_WVALID       = reg_wvalid &~WR_FIFO_EMPTY;
//  assign M_AXI_WVALID       = (wr_state == S_WD_PROC)?1'b1:1'b0; assign M_AXI_BREADY       = M_AXI_BVALID; assign WR_READY           =(wr_state == S_WR_IDLE)?1'b1:1'b0; //  assign WR_FIFO_RE         = (wr_state == S_WD_PROC)?M_AXI_WREADY:1'b0; localparam S_RD_IDLE  =3'd0;
localparam S_RA_WAIT  =3'd1;
localparam S_RA_START =3'd2;
localparam S_RD_WAIT  =3'd3;
localparam S_RD_PROC  =3'd4;
localparam S_RD_DONE  =3'd5; reg[2:0]   rd_state;
reg[31:0]  reg_rd_adrs;
reg[31:0]  reg_rd_len;
reg         reg_arvalid, reg_r_last;
reg[7:0]   reg_r_len;
assign RD_DONE =(rd_state == S_RD_DONE);
// Read State
always@(posedge ACLK ornegedge ARESETN)begin
if(!ARESETN)begin rd_state          <= S_RD_IDLE; reg_rd_adrs[31:0]<=32'd0; reg_rd_len[31:0]<=32'd0; reg_arvalid       <=1'b0; reg_r_len[7:0]<=8'd0;
endelsebegin
case(rd_state) S_RD_IDLE:begin
if(RD_START)begin rd_state          <= S_RA_WAIT; reg_rd_adrs[31:0]<= RD_ADRS[31:0]; reg_rd_len[31:0]<= RD_LEN[31:0]-32'd1;
end reg_arvalid     <=1'b0; reg_r_len[7:0]<=8'd0;
end S_RA_WAIT:begin
if(~RD_FIFO_AFULL)begin rd_state          <= S_RA_START;
end
end S_RA_START:begin rd_state          <= S_RD_WAIT; reg_arvalid       <=1'b1; reg_rd_len[31:11]<= reg_rd_len[31:11]-21'd1;
if(reg_rd_len[31:11]!=21'd0)begin reg_r_last      <=1'b0; reg_r_len[7:0]<=8'd255;
endelsebegin reg_r_last      <=1'b1; reg_r_len[7:0]<= reg_rd_len[10:3];
end
end S_RD_WAIT:begin
if(M_AXI_ARREADY)begin rd_state        <= S_RD_PROC; reg_arvalid     <=1'b0;
end
end S_RD_PROC:begin
if(M_AXI_RVALID)begin
if(M_AXI_RLAST)begin
if(reg_r_last)begin rd_state          <= S_RD_DONE;
endelsebegin rd_state          <= S_RA_WAIT; reg_rd_adrs[31:0]<= reg_rd_adrs[31:0]+32'd2048;
end
endelsebegin reg_r_len[7:0]<= reg_r_len[7:0]-8'd1;
end
end
end S_RD_DONE:begin rd_state          <= S_RD_IDLE; end endcase
end
end // Master Read Address
assign M_AXI_ARID         =1'b0;
assign M_AXI_ARADDR[31:0]= reg_rd_adrs[31:0];
assign M_AXI_ARLEN[7:0]= reg_r_len[7:0];
assign M_AXI_ARSIZE[2:0]=3'b011;
assign M_AXI_ARBURST[1:0]=2'b01;
assign M_AXI_ARLOCK       =1'b0;
assign M_AXI_ARCACHE[3:0]=4'b0011;
assign M_AXI_ARPROT[2:0]=3'b000;
assign M_AXI_ARQOS[3:0]=4'b0000;
assign M_AXI_ARUSER[0]=1'b1;
assign M_AXI_ARVALID      = reg_arvalid; assign M_AXI_RREADY       = M_AXI_RVALID &~RD_FIFO_FULL; assign RD_READY           =(rd_state == S_RD_IDLE)?1'b1:1'b0;
assign RD_FIFO_WE         = M_AXI_RVALID;
assign RD_FIFO_DATA[63:0]= M_AXI_RDATA[63:0]; assign DEBUG[31:0]={reg_wr_len[31:8],
1'd0, wr_state[2:0],1'd0, rd_state[2:0]}; endmodule 

三、工程下载

下面有一个关于 PL 读写 PS 端 DDR 数据的真实工程,本人已经完全验证过了,即包括了ZYNQ处理器的搭建,逻辑封装,又包括PS端SDK的测试代码。

PL 读写PS 端 DDR 数据

Xilinx AXI4 协议相关推荐

  1. AXI3和AXI4协议详细说明

    本文基于ARM官方文档<AMBA AXI and ACE Protocol Specification> 因为AXI3和AXI4协议大部分相同,小部分不同,在官方文档中也是一起介绍的,所以 ...

  2. Xilinx AXI4总线介绍

    1.什么是AXI AXI(Advanced eXtensible Interface)是一种总协议,该协议的第一个版本AXI3是ARM公司提出的AMBA(Advanced Microcontrolle ...

  3. 编写AXI4协议读写BRAM并仿真验证

    前篇博文我们试验了AXI4-Lite协议读写BRAM,这里我们试验一下完整的AXI4协议.流程跟AXI4-Lite是一样的.省略的部分请参考:编写AXI4-Lite协议读写BRAM并仿真验证 一. 建 ...

  4. UPP协议转AXI4协议的burst读写FPGA实现

    UPP协议转AXI4协议的burst读写FPGA实现 名字是按标准协议命名的,细节都在图里,有兴趣的朋友自己看下,或者私信我,欢迎批评指正! Burst 读和写 写数据 读数据

  5. AXI4协议详解(二)

    写在前面:上一篇文章我们介绍了AXI4协议各通道的信号构成与握手机制,之后我们将在解析读写过程的同时,手把手教你实现一个从机的读写过程.由于今天的篇幅所限,本篇文章将实现一个从机的写过程,作为协议解析 ...

  6. axi4协议的乱序_一篇文章读懂读透FPGA AXI4 总线协议

    新一代FPGA中采用的基本都是AXI4总线协议,例如与slaver侧的DMA或DDR等通信.这篇讲AXI4的文章感觉讲的很清楚. 0.绪论AXI是高级扩展接口,在AMBA3.0中提出,AMBA4.0将 ...

  7. AXI4协议学习:架构、信号定义、工作时序和握手机制

    目录 1 AXI是什么? 2 AXI怎么工作? 3 AXI协议 3.1 架构 3.1.1 通道定义 3.1.2 接口与互连(interconnect) 3.1.3 Register slices 3. ...

  8. AMBA总线-结合axi-vip对axi4协议的理解1

    一直想写一个axi-vip的理解,但是介于个人水平有限,一直没能做出很好的总结,这个系列的内容将对这方面内容做出一个阐述.另外,个人水平有限,仅参考,有什么问题希望大家能够批评指正,共同进步! 这个v ...

  9. AXI4协议与AXI3协议区别

    1.burst length AXI4对burst length进行了扩展.AXI3最大burst length是16 beats,而AXI4支持最大到256 beats,但是仅支持INCR burs ...

最新文章

  1. 2022-2028年中国TCO导电玻璃行业市场研究分析及前瞻规划报告
  2. 二分图 ---- 树的二分图性质 2020icpc 济南 J Tree Constructer(构造)
  3. HDU-5723 Abandoned country
  4. SQL中关联表并使用子表的COUNT和SUM函数作为扩展字段
  5. windows2000 日志
  6. assertpythonraise_使用assertRaise测试异常消息
  7. 老板思维:有支出必须有对应的收入
  8. web开发快餐式入门指南 0. 写在前面
  9. 能在市场上大概率赚钱的人类型
  10. T3500通过PXE克隆报“Unable to Control A20 Line XMS Driver not installed”
  11. C语言知识点总结(完美版)
  12. Visual Studio添加Numpy
  13. matlab中clear;close;clc的作用说明
  14. 玲珑杯Unity开发心得——进度条界面(异步加载游戏场景)
  15. 对称数c语言,中心对称数 - Developmer的个人空间 - OSCHINA - 中文开源技术交流社区...
  16. gta5 android ps4,gta5导演模式怎么玩好玩_gta5怎么进入导演模式怎么玩ps4导演模式怎么打开_攻略...
  17. python开发autocad_利用Python自动化操作AutoCAD的实现
  18. 【莫烦Python】Python 基础教程学习笔记与代码
  19. 网络信息安全之基于时间的安全模型(PDR和PPDR模型)
  20. 输入精度e,使用格雷戈里公式求π的近似值,精确到最后一项的绝对值小于e。要求定义和调用函数funpi(e)求π的近似值。

热门文章

  1. php laravel 忘记密码,Laravel重置密码实例详解
  2. 【SOA】程立谈支付宝大规模SOA系统(ZZ)
  3. SCARA 机器人概述
  4. 自动调节系统解析与PID整定 汽包液位控制-白志刚
  5. 飞瓜快数app之sign参数分析
  6. 练手小项目(2)-生活小助手--星座运势查询
  7. 如何理解dotplot
  8. 个性签名设计五十行Python轻松实现
  9. 【第50、51天】jQuery基本知识,LayUI动态表格的学习
  10. 1024*1024像素的图片 占多少内存