一.什么是AXI通信协议
AXI是ARM 1996年提出的微控制器总线家族AMBA中的一部分。AXI的第一个版本出现在AMBA3.0,发布于2003年。当前的最新的版本发布于2010年。AXI 4总线和别的总线一样,都用来传输bits信息 (包含了数据或者地址) 。AXI4总线有三种类型,分别是AXI4、AXI4-Lite、AXI4-Stream
AXI4:主要面向高性能地址映射通信的需求,支持突发传输;
AXI4-Lite:是一个简单地吞吐量地址映射性通信总线,不支持突发传输;
AXI4-Stream:不包含地址,面向高速流数据传输;
AXI4 是一种高性能memory-mapped总线,分为主、从两端,两者间可以连续的进行通信。AXI4及AXI4Lite有地址,AX14能够实现burst传输,可以在一个地址后传输多个数据,最多可以达256 字节。AXI4-Lite不支持burst传输。AXI4-Stream 只有一个通道,不需要地址,可以burst 传输无限的数据。假设有master A,和 slave B,A与B通过AXI4或者AXI4Lite连接通讯,A可以把B这个外设看作A上的某个地址。当A向B传输数据时,就等同于A向这个地址传数。
AXI4 和 AXI4-Lite接口包含5个不同的通道:两个读通道和三个写通道。
两个读通道:读地址通道(read addresschannel)、读数据通道(read data channel):
三个写通道: 写地址通道(write addresschannel)、写数据通道(write data channel)、写响应通道(write response channel);
相比于 AXI4,AXI4-Stream 不涉及地址。AXI4-Stream传输的数据流包含三种类型: data type、position type、 null type 。data type是最有意义的数据; position type作为占位符使用,可以用来表征date type 的相对位置,null type不包含任何有用的信息。
数据流的结构可以有很多种,例如: 可以只传数据,也即都是data type,不包含position type和null type; 也可以将data type 和 null type 混着传输;还可以将position type 和 data type混着传输。当然,三者混着传输也没有问题。
二.信号描述
AXI与AXI-lite信号描述如下所示,由于AXI-lite不支持突发,所以与突发相关的管教都不具备。
//全局信号
.M_AXI_ACLK(m00_axi_aclk),//时钟
.M_AXI_ARESETN(m00_axi_aresetn),//全局复位
//写地址通道信号
.M_AXI_AWID(m00_axi_awid),//AXI4-LITE不支持 写地址ID。这个信号用于写地址信号组的标记,用来标识数据传输顺序。详见协议定义。
.M_AXI_AWADDR(m00_axi_awaddr),//写地址。写地址给出突发数据传输的第一个传输地址。
.M_AXI_AWLEN(m00_axi_awlen),//AXI4-LITE不支持 突发长度。给出突发传输中准确的传输个数。支持INCR和WRAP传输模式。(长度)突发长度=awlen+1
.M_AXI_AWSIZE(m00_axi_awsize),//AXI4-LITE不支持 突发大小。这个信号用于确定突发传输中每个传输的大小。(宽度)总线位宽=2^size Betyes
.M_AXI_AWBURST(m00_axi_awburst),//AXI4-LITE不支持 突发类型。该信息与突发大小信息一起,表示在突发过程中,地址如何应用于每个传输。支持INCR和WRAP传输模式。
.M_AXI_AWLOCK(m00_axi_awlock),//AXI4-LITE不支持 锁类型。该信号提供了关于传输原子特性的额外信息(普通或互斥访问)。AXI3支持,AXI4不支持
.M_AXI_AWCACHE(m00_axi_awcache),//缓存类型,建议值为0011。
.M_AXI_AWPROT(m00_axi_awprot),//保护类型,访问权限,建议值为000。
.M_AXI_AWQOS(m00_axi_awqos),//QoS标识符,xilinx AXI4不支持
.M_AXI_AWUSER(m00_axi_awuser),//xilinx AXI4不支持
.M_AXI_AWVALID(m00_axi_awvalid),//写地址有效信号。为高指示地址有效。
.M_AXI_AWREADY(m00_axi_awready),//写地址准备信号。为高表示从设备空闲,准备接收地址;为低表示从设备忙。
//写数据通道信号
.M_AXI_WDATA(m00_axi_wdata),//写数据,AXI-LITE仅支持32bit,AXI支持32bit-1024bit
.M_AXI_WSTRB(m00_axi_wstrb),//写字节选通,用于表示更新存储器的字节通道,对于数据总线的每8位数据有一位写选通信号
.M_AXI_WLAST(m00_axi_wlast),//AXI-LITE不支持 写最后一个数据指示信号。表示突发传输中的最后一个数据。
.M_AXI_WUSER(m00_axi_wuser),//xilinx AXI4不支持。
.M_AXI_WVALID(m00_axi_wvalid),//写有效。为高指示数据有效。
.M_AXI_WREADY(m00_axi_wready),//写准备。为高表示从设备空闲,准备接收数据;为低表示从设备忙。
//写响应通道
.M_AXI_BID(m00_axi_bid),//AXI-LITE不支持 响应ID。写响应识别标记,BID值必须匹配AWID值。
.M_AXI_BRESP(m00_axi_bresp),//写响应。该信号表示写状态,0时候表示没有错误,
.M_AXI_BUSER(m00_axi_buser),//xilinx AXI4不支持。
.M_AXI_BVALID(m00_axi_bvalid),//写响应有效。为高指示响应数据有效
.M_AXI_BREADY(m00_axi_bready),//写响应准备。为高表示主设备空闲,准备接收写响应;为低表示主设备忙。
//读地址通道
.M_AXI_ARID(m00_axi_arid),//AXI-LITE不支持 读地址ID。这个信号用于读地址信号组的标记。
.M_AXI_ARADDR(m00_axi_araddr),//读地址。读地址给出突发数据传输的第一个传输地址。
.M_AXI_ARLEN(m00_axi_arlen),//AXI-LITE不支持 突发长度。给出突发传输中准确的传输个数。支持INCR和WRAP传输模式。
.M_AXI_ARSIZE(m00_axi_arsize),//AXI-LITE不支持 突发大小。这个信号用于确定突发传输中每个传输的大小。
.M_AXI_ARBURST(m00_axi_arburst),//AXI-LITE不支持 突发类型。该信息与突发大小信息一起,表示在突发过程中,地址如何应用于每个传输。支持INCR和WRAP传输模式
.M_AXI_ARLOCK(m00_axi_arlock),//锁类型。该信号提供了关于传输原子特性的额外信息(普通或互斥访问)
.M_AXI_ARCACHE(m00_axi_arcache),//缓存类型,建议值为0011。
.M_AXI_ARPROT(m00_axi_arprot),//保护类型,建议值为000。
.M_AXI_ARQOS(m00_axi_arqos),//QoS标识符,xilinx AXI4不支持。
.M_AXI_ARUSER(m00_axi_aruser),//xilinx AXI4不支持
.M_AXI_ARVALID(m00_axi_arvalid),// 读地址有效信号。为高指示地址有效
.M_AXI_ARREADY(m00_axi_arready),//读地址准备信号。为高表示从设备空闲,准备接收地址;为低表示从设备忙
//读数据通道
.M_AXI_RID(m00_axi_rid),//AXI-LITE不支持 读ID标记,该信号是读数据信号组标记,由从设备产生RID,RID必须和读交易中的ARID匹配
.M_AXI_RDATA(m00_axi_rdata),//读数据。32位到1024位宽 AXI-LITE只支持32位宽
.M_AXI_RRESP(m00_axi_rresp),//读响应。该信号表示读状态,可允许相应的表示为
.M_AXI_RLAST(m00_axi_rlast),//AXI-LITE不支持 读最后一个数据指示信号。表示突发传输中的最后一个数据
.M_AXI_RUSER(m00_axi_ruser),//xilinx AXI4不支持。
.M_AXI_RVALID(m00_axi_rvalid),//读有效。为高指示数据有效
.M_AXI_RREADY(m00_axi_rready)//读准备。为高表示主设备空闲,准备接收数据;为低表示主设备忙。
AXI-stream信号描述如下所示,
.M_AXIS_ACLK(m00_axis_aclk),//时钟
.M_AXIS_ARESETN(m00_axis_aresetn),//复位
.M_AXIS_TVALID(m00_axis_tvalid),//Stream读写数据有效。为高指示数据有效。
.M_AXIS_TDATA(m00_axis_tdata),//Stream读写数据,8到4096位宽。
.M_AXIS_TSTRB(m00_axis_tstrb),//字节选通信号。用于表示更新存储器的字节通道,对于数据总线的每8位数据有一位选通信号。
.M_AXIS_TLAST(m00_axis_tlast),//表明包的边界,1代表最后数据
.M_AXIS_TREADY(m00_axis_tready)//Stream读写读准备。为高表示对端设备空闲,准备接收数据;为低表示对端设备忙。
三.工作时序图
AXI4协议主从设备间的读操作使用独立的读地址和读数据通道,只需要一个地址就可以执行最大为256的突发长度的读操作。
读时序如下所示。
(1)首先Master判断arready的信号是否为高电平,若该信号为高电平时,代表slave已经准备好接收新的地址信息,否则Master不能给Slave发送地址信息。
(2)当判断完成后,Master给Slave发送地址信息,即发送araddr;在进行地址发送时,arvalid为高电平,arvalid为高电平,发送araddr。
(3)当地址发送结束之后,slave就会通过read_data通道返回数据,master必须在rready和rvalid信号同时为高时,将数据读取,否则不能读取数据;当最后一个数据发送时,slave会将rlast信号同时拉高,代表最后一个数据发送完成。
写时序如下所示。
AXI写事务是在3个写通道上完成多次数据传输(transfers)
(1)MASTER将写地址及相应的控制信息通过写地址通道发送给SLAVE
(2)MASTER将需要写入该地址的数据通过写输入通道发送给SLAVE
(3)SLAVE将写结果通过写反馈通道发送给MASTER,表明写入是否成功
四.时序代码实现
读事务握手信号的关系:
单箭头指向 可以在前一个信号(本信号)断言之前或之后断言的信号(指向的信号)。
双箭头指向 只有在前一个信号(本信号)断言之后才可以断言的信号(指向的信号)。
所以slave 在断言读取的数据有效信号RVALID之前,必须等到ARVALID与ARREADY断言后。
//----------------------------
//Read Address Channel
//----------------------------
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )
begin
axi_arvalid <= 1'b0;
end
// If previously not valid , start next transaction
else if (~axi_arvalid && start_single_burst_read)
begin
axi_arvalid <= 1'b1;
end
else if (M_AXI_ARREADY && axi_arvalid)
begin
axi_arvalid <= 1'b0;
end
else
axi_arvalid <= axi_arvalid;
end
// Next address after ARREADY indicates previous address acceptance
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
begin
axi_araddr <= 'b0;
end
else if (M_AXI_ARREADY && axi_arvalid)
begin
axi_araddr <= axi_araddr + burst_size_bytes;
end
else
axi_araddr <= axi_araddr;
end
//--------------------------------
//Read Data (and Response) Channel
//--------------------------------
// Forward movement occurs when the channel is valid and ready
assign rnext = M_AXI_RVALID && axi_rready;
// Burst length counter. Uses extra counter register bit to indicate
// terminal count to reduce decode logic
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 || start_single_burst_read)
begin
read_index <= 0;
end
else if (rnext && (read_index != C_M_AXI_BURST_LEN-1))
begin
read_index <= read_index + 1;
end
else
read_index <= read_index;
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )
begin
axi_rready <= 1'b0;
end
// accept/acknowledge rdata/rresp with axi_rready by the master
// when M_AXI_RVALID is asserted by slave
else if (M_AXI_RVALID)
begin
if (M_AXI_RLAST && axi_rready)
begin
axi_rready <= 1'b0;
end
else
begin
axi_rready <= 1'b1;
end
end
// retain the previous value
end
写事务握手信号的关系:
单箭头指向 可以在前一个信号(本信号)断言之前或之后断言的信号(指向的信号)。
双箭头指向 只有在前一个信号(本信号)断言之后才可以断言的信号(指向的信号)。文章来源:https://www.toymoban.com/news/detail-861067.html
//--------------------
//Write Data Channel
//--------------------
assign wnext = M_AXI_WREADY & axi_wvalid;
// WVALID logic, similar to the axi_awvalid always block above
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )
begin
axi_wvalid <= 1'b0;
end
// If previously not valid, start next transaction
else if (~axi_wvalid && start_single_burst_write)
begin
axi_wvalid <= 1'b1;
end
/* If WREADY and too many writes, throttle WVALID
Once asserted, VALIDs cannot be deasserted, so WVALID
must wait until burst is complete with WLAST */
else if (wnext && axi_wlast)
axi_wvalid <= 1'b0;
else
axi_wvalid <= axi_wvalid;
end
//WLAST generation on the MSB of a counter underflow
// WVALID logic, similar to the axi_awvalid always block above
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )
begin
axi_wlast <= 1'b0;
end
else if (((write_index == C_M_AXI_BURST_LEN-2 && C_M_AXI_BURST_LEN >= 2) && wnext) || (C_M_AXI_BURST_LEN == 1 ))
begin
axi_wlast <= 1'b1;
end
else if (wnext)
axi_wlast <= 1'b0;
else if (axi_wlast && C_M_AXI_BURST_LEN == 1)
axi_wlast <= 1'b0;
else
axi_wlast <= axi_wlast;
end
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 || start_single_burst_write == 1'b1)
begin
write_index <= 0;
end
else if (wnext && (write_index != C_M_AXI_BURST_LEN-1))
begin
write_index <= write_index + 1;
end
else
write_index <= write_index;
end
/* Write Data Generator
Data pattern is only a simple incrementing count from 0 for each burst */
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
axi_wdata <= 'b1;
//else if (wnext && axi_wlast)
// axi_wdata <= 'b0;
else if (wnext)
axi_wdata <= axi_wdata + 1;
else
axi_wdata <= axi_wdata;
end
//----------------------------
//Write Response (B) Channel
//----------------------------
always @(posedge M_AXI_ACLK)
begin
if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )
begin
axi_bready <= 1'b0;
end
// accept/acknowledge bresp with axi_bready by the master
// when M_AXI_BVALID is asserted by slave
else if (M_AXI_BVALID && ~axi_bready)
begin
axi_bready <= 1'b1;
end
// deassert after one clock cycle
else if (axi_bready)
begin
axi_bready <= 1'b0;
end
// retain the previous value
else
axi_bready <= axi_bready;
end
//Flag any write response errors
assign write_resp_error = axi_bready & M_AXI_BVALID & M_AXI_BRESP[1];
五.总结
vivado中许多IP核都采用AXI通信协议,理解AXI协议有助于后续开发工作,详细信息推荐官方文件ug1037以及ihi0022c文章来源地址https://www.toymoban.com/news/detail-861067.html
到了这里,关于【FPGA】 xilinx vivado中AXI4通信协议详解的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!