AXI协议简介
版本历史
| Issue / 商用名 | 发布年 | 所属 AMBA 代 | 文档里程碑 |
|---|---|---|---|
| AXI3 | 2003 | AMBA 3 | 首代 AXI,引入分离通道、multiple outstanding、乱序完成 |
| AXI4 | 2010 | AMBA 4 | 新增 QoS、long burst(256)、byte strobes、AXI4-Lite 子集 |
| AXI4-Stream | 2010 | AMBA 4 | 去地址通道,仅单向数据流,用于视频/数据包 |
| ACE / ACE-Lite | 2011 | AMBA 4 | 在 AXI4 上加缓存一致性(snoop 通道),支持多核 CCI |
| AXI5 / AXI5-Lite | 2019 | AMBA 5 | 原子操作、奇偶校验、数据检查、TraceTag、AXI-J 简化文档 |
| ACE5 系列 | 2019 | AMBA 5 | 对应 AXI5 的一致性扩展,含 ACE5-Lite、ACE5-LiteDVM |
AXI信号列表
- AXI的信号被分成5个通道,每组通道相对 独立
-- AR:read address通道
-- R:read data通道
-- AW:write address通道
-- W:write data 通道
-- B:write response通道
-- Snoop request通道
-- Snoop response通道


公共信号
| 信号 | 描述 |
|---|---|
| ACLK | 全局时钟 |
| ARESETn | 异步复位(低有效) |
| AWAKEUP / ARWAKEUP | 低功耗唤醒(可选) |
AW通道
| 信号 | 位宽 | 方向 | AXI5 描述 |
|---|---|---|---|
| AWID | ID_W | M→S | 事务标识 |
| AWADDR | ADDR_W | M→S | 起始字节地址 |
| AWLEN | 8 | M→S | burst 长度 (beats-1) |
| AWSIZE | 3 | M→S | 每 beat 字节数 (2^N) |
| AWBURST | 2 | M→S | burst 类型 (FIXED/INCR/WRAP) |
| AWLOCK | 1 | M→S | 原子属性 (0/1) |
| AWCACHE | 4 | M→S | 缓存策略 (直写/回写/分配等) |
| AWPROT | 3 | M→S | 保护级别 (priv/secure/inst) |
| AWQOS | 4 | M→S | QoS 优先级 |
| AWREGION | 4 | M→S | 区域标识 |
| AWUSER | USER_W | M→S | 用户自定义 |
| AWATOP | 6 | M→S | AXI5 原子操作类型 (AtomicStore/AtomicLoad/...) |
| AWTRACE | 1 | M→S | 跟踪使能 |
| AWLOOP | LOOP_W | M→S | 环回测试标识 |
| AWMMUSECSID | 1 | M→S | MMU 安全 ID 有效 |
| AWMMUSID | SID_W | M→S | MMU 流 ID |
| AWMMUSSIDV | 1 | M→S | MMU 子流 ID 有效 |
| AWMMUSSID | SSID_W | M→S | MMU 子流 ID |
| AWMMUATST | 1 | M→S | MMU 访问状态 |
| AWNSAID | 4 | M→S | 非安全访问 ID |
| AWIDUNQ | 1 | M→S | ID 唯一性指示 |
| AWVALID | 1 | M→S | 通道有效 |
| AWREADY | 1 | S→M | 通道就绪 |
W通道
| 信号 | 位宽 | 方向 | 描述 |
|---|---|---|---|
| WDATA | DATA_W | M→S | 写数据 |
| WSTRB | DATA_W/8 | M→S | 字节使能 |
| WLAST | 1 | M→S | 最后一 beat 标志 |
| WUSER | USER_W | M→S | 用户自定义 |
| WDATACHK | DATA_W/64 | M→S | 每 64-bit 数据奇偶校验 |
| WPOISON | DATA_W/64 | M→S | 数据污染位 (64-bit 粒度) |
| WTRACE | 1 | M→S | 跟踪使能 |
| WVALID | 1 | M→S | 通道有效 |
| WREADY | 1 | S→M | 通道就绪 |
B通道
| 信号 | 位宽 | 方向 | 描述 |
|---|---|---|---|
| BID | ID_W | S→M | 响应 ID |
| BRESP | 2 | S→M | 写结果 (OK/EXOK/SLVERR/DECERR) |
| BUSER | USER_W | S→M | 用户自定义 |
| BTRACE | 1 | S→M | 跟踪使能 |
| BLOOP | LOOP_W | S→M | 环回标识 |
| BIDUNQ | 1 | S→M | ID 唯一性指示 |
| BVALID | 1 | S→M | 通道有效 |
| BREADY | 1 | M→S | 通道就绪 |
AR通道
| 信号 | 位宽 | 方向 | 描述 |
|---|---|---|---|
| ARID / ARADDR / ARLEN / ARSIZE / ARBURST / ARLOCK / ARCACHE / ARPROT / ARQOS / ARREGION / ARUSER | 同 AW | M→S | 与写地址通道对应 |
| ARATOP | 6 | M→S | 读原子操作码 (AXI5) |
| ARTRACE / ARLOOP / ARMMUSECSID / ARMMUSID / ARMMUSSIDV / ARMMUSSID / ARMMUATST / ARNSAID / ARIDUNQ | 同 AW | M→S | 与 AW 通道新增信号一一对应 |
| ARVALID | 1 | M→S | 通道有效 |
| ARREADY | 1 | S→M | 通道就绪 |
R通道
| 信号 | 位宽 | 方向 | 描述 |
|---|---|---|---|
| RID / RDATA / RRESP / RLAST / RUSER | 标准 | S→M | 同 AXI4 |
| RDATACHK | DATA_W/64 | S→M | 读数据奇偶校验 |
| RPOISON | DATA_W/64 | S→M | 读数据污染位 |
| RTRACE / RLOOP / RIDUNQ | 同 B | S→M | 同写响应通道新增信号 |
| RVALID | 1 | S→M | 通道有效 |
| RREADY | 1 | M→S | 通道就绪 |
Snoop通道(ACE扩展,仅一致性系统)
| 通道 | 信号 | 位宽 | 方向 | 描述 |
|---|---|---|---|---|
| AC | ACADDR | ADDR_W | I→M | 监听物理地址 |
| ACSNOOP | SNOOP_W | I→M | 监听命令码(Clean/Invalidate/ReadClean 等) | |
| ACPROT | 3 | I→M | 监听事务保护属性 | |
| ACVMIDEXT | VMID_W | I→M | 虚拟机 ID 扩展 | |
| ACTRACE | 1 | I→M | 跟踪使能 | |
| ACVALID / ACREADY | 1 | I↔M | 握手 | |
| CR | CRRESP | RESP_W | M→I | 监听响应(Hit/Miss/Dirty/PassDirty 等) |
| CRTRACE | 1 | M→I | 跟踪 | |
| CRVALID / CRREADY | 1 | M↔I | 握手 | |
| CD | CDDATA | DATA_W | M↔I | 监听数据(Cache Line) |
| CDLAST | 1 | M↔I | 最后一 beat | |
| CDVALID / CDREADY | 1 | M↔I | 握手 |
AxSIZE[2:0]
- 一次burst中的每个beat传输有多少byte
| AxSIZE[2:0] | 字节数 | 典型宽度举例 |
|---|---|---|
| 000 | 1 Byte | 8-bit |
| 001 | 2 B | 16-bit |
| 010 | 4 B | 32-bit |
| 011 | 8 B | 64-bit |
| 100 | 16 B | 128-bit |
| 101 | 32 B | 256-bit |
| 110 | 64 B | 512-bit |
| 111 | 128 B | 1024-bit |
AxLEN[7:0]
- 一次burst传输有多少个beat
| AxLEN[7:0] | 实际 beat 数 | 举例(16 B beat) |
|---|---|---|
| 0x00 | 1 | 16 B 总量 |
| 0x01 | 2 | 32 B |
| … | … | … |
| 0xFF | 256 | 4 KB |
AxBURST[1:0]
- burst的类型
- WRAP通常用于从main memory读取cache line
| AxBURST[1:0] | 类型 | 地址变化规则 | 典型用途 |
|---|---|---|---|
| 00 | FIXED | 所有 beat 地址保持不变 | FIFO、外设寄存器 |
| 01 | INCR | 每拍地址按 beat 大小递增 | 普通内存顺序访问 |
| 10 | WRAP | 递增到对齐边界后回绕 | Cache line fill |
Axaddr
- master发起请求对应的address
- 对齐规则
-- INCR类型可以起始于任意地址(允许非对齐)
-- WRAP首地址必须对齐到burst总长度(= beat 数 × beat 大小) - 跨4K约束
-- INCR可以跨4K
-- WRAP不允许跨4K
BRESP(AXI4)
| BRESP[1:0] | 含义 | 何时使用 |
|---|---|---|
| 00 | OKAY | 普通成功写完成(最常见) |
| 01 | EXOKAY | 独占写成功(仅用于 AXI exclusive 访问) |
| 10 | SLVERR | 从机收到事务,但内部出错(ECC、越界、权限等) |
| 11 | DECERR | 解码错误——地址路由不到任何从机(interconnect 返回) |
RRESP(AXI4)
| RRESP[2:0] | 含义 | 适用场景 |
|---|---|---|
| 000 | OKAY | 普通读成功(最常见) |
| 001 | EXOKAY | 独占读成功(返回有效数据) |
| 010 | SLVERR | 从机收到事务,但内部出错(ECC、权限、越界等) |
| 011 | DECERR | 解码错误——地址未映射到任何从机 |
| 100 | OKAY | 独占读失败(数据无效,仅用于 独占读) |
Transfer
Narrow transfers
- 每一 beat 的实际数据宽度(由 AxSIZE 指示)小于物理数据总线宽度
- 由于总线位宽“富余”,主设备必须告诉从机 “哪些字节通道有效”——这通过 WSTRB(写)或 RSTRB(读,可选)实现
- INCR / WRAP burst
-- 每一 beat 可以使用不同的字节通道(地址递增后,有效字节 lane 随地址偏移而滑动)。
-- 起始地址不必对齐到总线宽度,但 必须对齐到 AxSIZE - FIXED burst
-- 每一 beat 使用相同的字节通道(地址固定,WSTRB 每拍不变)。
-- 常用于 FIFO/寄存器文件——多次读/写同一个地址,但每次只更新部分字节
Unaligned transfers
- 起始地址 AxADDR 不是 AxSIZE 所指示字节数的整数倍
- 主设备 必须 在首拍把 WSTRB/RSTRB 对应位拉低,屏蔽无效字节 lane
- 唯一例外是 WRAP burst——起始地址必须对齐到“burst 总长度
高频问题
问题1: AXI与AHB核心区别
- AXI分离读写通道+支持乱序/outstanding;AHB单通道、顺序
问题2: AXI4与AXI3的5点区别
- 增加到256beat
- 去掉WID
- 去掉lock
- 增加WoS
- 去掉写交织
问题3: AXI4-lite砍掉哪些信号
- 去掉burst所有信号(AxLEN/BURST/ID等),近支持SINGLE
问题4: AXI通道列表
- 基础:AW/W/B/AR/R;ACE增加:AC/CR/CD
问题5: VALID/READY握手原则
- 双向独立,不允许依赖组合路径,防止死锁
问题6: AxCACHE 4bit含义
- Bufferable(0)、Cacheable(1)、Read-Allocate(2)、Write-Allocate(3)
问题7: AxPROT3bit含义
- Privilege(0)、Secure(1)、Instruction(2)
问题8: 4KB边界限制谁遵守
- WRAP必须对齐且不得跨4KB;INCR允许跨越4KB
问题9: INCR/WRAP/FIXED地址计算差异?
- FIXED不动;INCR直线增加;WRAP到边界回绕
问题10: WRAP起始地址对齐公式
- addr%((AxLEN=1)*2^AxSIZE)==0
问题11: WRAP场景
- WRAP常用于从main memory读取cache line
- 因为master对cache的访问通常是cache line中的某些bytes,但当发生cache miss时,从memory读回来的是整个cache line。而此时master发送的地址却不一定是cache line的起始地址,而可能位于中间,因此递增到upper boundary时需要回卷到lower boundary,才能将该cache line读完。
问题12: 如何实现narrow transfer
- 数据总线宽度 > AxSIZE,使用WSTRB掩码指示有效字节
问题13: UNaligned首地址处理流程
- 首拍向下对齐到Axsize,WSTRB掩掉无效字节,后续自动对齐
问题14: OOO实现关键
- 不同ID可乱序;同ID必须保序
问题15: AXI4为何去掉interleaving
- 设计难度增大,使用场景不多
问题16: WLAST/RLAST能提前拉高吗
- 绝对不行,提前拉高是协议违反
问题17: AXI4的AxLEN上限
- AxLEN=255,上限256beat
问题18: OKAY vs EXOKAY 出现场景?
- 001:独占读成功/写成功;000:独占写失败/读失败;
问题19: 写响应必须每笔trans一个吗
- 是;每笔trans只允许回复一个BRESP(与beat数无关)
问题20: 读响应每beat都带RRESP?
- 是,每笔beta都必须带RRESP,RLAST那拍同样
问题21: 提前受到错误响应能终止Burst吗?
- 不能,协议不允许提前终止,必须收完固定长度
问题22: QoS能降低错误响应概率吗
- 不能,QoS只影响仲裁顺序
问题23: 手写Unaligned WRAP地址
- if(addr%((len+1)<<size) != 0) slverr=1;
- 或者先计算base_addr、再计算最大addr,判断当前addr是否超过最大addr
问题24: Outstanding太深会怎样
- 从机缓存爆炸+队头阻塞,需要credit反压
问题25: 4KB边界限制谁最受益
- 从机页表/保护单元
问题26: 为什么WRAP必须2/4/8/16beat
- 方便回绕地址用掩码计算,硬件只需移位
问题27: 手写AXI-lite接口的SRAM控制器
点击查看代码
// AXI-Lite SRAM Controller
// 1-clock read, 0-wait write, byte-write, 4 KB SRAM
// Usage: interview hand-write demo
//-----------------------------------------------------
module axi_lite_sram #(
parameter int ADDR_WIDTH = 32,
parameter int DATA_WIDTH = 32,
parameter int SRAM_DEPTH = 1024, // 1 k x 32-bit
parameter int SRAM_AW = $clog2(SRAM_DEPTH) // 10
)(
input wire aclk,
input wire aresetn,
// Write Address Channel
input wire [ADDR_WIDTH-1:0] awaddr,
input wire awvalid,
output logic awready,
// Write Data Channel
input wire [DATA_WIDTH-1:0] wdata,
input wire [DATA_WIDTH/8-1:0] wstrb,
input wire wvalid,
output logic wready,
// Write Response Channel
output logic [1:0] bresp,
output logic bvalid,
input wire bready,
// Read Address Channel
input wire [ADDR_WIDTH-1:0] araddr,
input wire arvalid,
output logic arready,
// Read Data Channel
output logic [DATA_WIDTH-1:0] rdata,
output logic [1:0] rresp,
output logic rvalid,
input wire rready
);
//-----------------------------------------------------
// SRAM storage
logic [DATA_WIDTH-1:0] mem [0:SRAM_DEPTH-1];
// word address & byte-write enable
logic [SRAM_AW-1:0] addr;
logic [DATA_WIDTH/8-1:0] we;
assign addr = (awvalid & awready) ? awaddr[SRAM_AW+2-1:2] :
(arvalid & arready) ? araddr[SRAM_AW+2-1:2] :
'0;
assign we = (awvalid & awready) ? wstrb : '0;
//-----------------------------------------------------
// Write path: 0 wait
assign awready = 1'b1;
assign wready = 1'b1;
always_ff @(posedge aclk or negedge aresetn) begin
if (!aresetn) begin
bvalid <= 0;
bresp <= 2'b00;
end else begin
bvalid <= awvalid & wvalid; // accept & respond
bresp <= 2'b00; // OKAY
end
end
//-----------------------------------------------------
// Read path: 1 clock latency
assign arready = 1'b1;
always_ff @(posedge aclk or negedge aresetn) begin
if (!aresetn) begin
rvalid <= 0;
rdata <= '0;
rresp <= 2'b00;
end else begin
rvalid <= arvalid;
rdata <= mem[addr];
rresp <= 2'b00; // OKAY
end
end
//-----------------------------------------------------
// Byte-write SRAM
genvar i;
generate
for (i = 0; i < DATA_WIDTH/8; i = i + 1) begin : g_we
always_ff @(posedge aclk) begin
if (we[i])
mem[addr][8*i +: 8] <= wdata[8*i +: 8];
end
end
endgenerate
//-----------------------------------------------------
// Simple assertions (bonus)
assert property (@(posedge aclk) disable iff (!aresetn)
awvalid & wvalid |-> bvalid ##1 bready);
assert property (@(posedge aclk) disable iff (!aresetn)
arvalid |-> rvalid ##1 rready);
endmodule
问题28: 手写 AXI4 1-to-N 互联仲裁
点击查看代码
//-----------------------------------------
// AXI4 1-to-N Interconnect Arbiter
// Round-Robin + QoS Weighted Round-Robin
// 8 Masters → 1 Slave
//-----------------------------------------
module axi4_1toN_arb #(
parameter int M = 8, // 主端数量
parameter int ADDR_W = 32,
parameter int DATA_W = 64,
parameter int ID_W = 4,
parameter int USER_W = 1,
parameter int QoS_W = 4,
// 每主端权重(越大越优先)
parameter int WGT[M] = '{1,1,1,1,1,1,1,1} // 默认等权
)(
input logic aclk,
input logic aresetn,
//---------------- 主端接口 (M×) ----------------
input logic [M-1:0] awvalid_s,
output logic [M-1:0] awready_s,
input logic [M*ADDR_W-1:0] awaddr_s,
input logic [M*3-1:0] awprot_s,
input logic [M*QoS_W-1:0] awqos_s,
input logic [M*ID_W-1:0] awid_s,
input logic [M*USER_W-1:0] awuser_s,
input logic [M-1:0] wvalid_s,
output logic [M-1:0] wready_s,
input logic [M*DATA_W-1:0] wdata_s,
input logic [M*DATA_W/8-1:0] wstrb_s,
input logic [M-1:0] wlast_s,
output logic [M-1:0] bvalid_s,
input logic [M-1:0] bready_s,
output logic [M*2-1:0] bresp_s,
output logic [M*ID_W-1:0] bid_s,
input logic [M-1:0] arvalid_s,
output logic [M-1:0] arready_s,
input logic [M*ADDR_W-1:0] araddr_s,
input logic [M*3-1:0] arprot_s,
input logic [M*QoS_W-1:0] arqos_s,
input logic [M*ID_W-1:0] arid_s,
input logic [M*USER_W-1:0] aruser_s,
output logic [M-1:0] rvalid_s,
input logic [M-1:0] rready_s,
output logic [M*DATA_W-1:0] rdata_s,
output logic [M*2-1:0] rresp_s,
output logic [M-1:0] rlast_s,
output logic [M*ID_W-1:0] rid_s,
//---------------- 从端接口 (1×) ----------------
output logic awvalid_m,
input logic awready_m,
output logic [ADDR_W-1:0] awaddr_m,
output logic [2:0] awprot_m,
output logic [QoS_W-1:0] awqos_m,
output logic [ID_W-1:0] awid_m,
output logic [USER_W-1:0] awuser_m,
output logic wvalid_m,
input logic wready_m,
output logic [DATA_W-1:0] wdata_m,
output logic [DATA_W/8-1:0] wstrb_m,
output logic wlast_m,
input logic bvalid_m,
output logic bready_m,
input logic [1:0] bresp_m,
input logic [ID_W-1:0] bid_m,
output logic arvalid_m,
input logic arready_m,
output logic [ADDR_W-1:0] araddr_m,
output logic [2:0] arprot_m,
output logic [QoS_W-1:0] arqos_m,
output logic [ID_W-1:0] arid_m,
output logic [USER_W-1:0] aruser_m,
input logic rvalid_m,
output logic rready_m,
input logic [DATA_W-1:0] rdata_m,
input logic [1:0] rresp_m,
input logic rlast_m,
input logic [ID_W-1:0] rid_m
);
//-----------------------------------------
// 内部信号
logic [$clog2(M)-1:0] aw_grant, ar_grant;
logic aw_valid_m, w_valid_m, b_valid_m;
logic ar_valid_m, r_valid_m;
// 写通道合并
assign aw_valid_m = |awvalid_s;
assign w_valid_m = |wvalid_s;
assign b_valid_m = bvalid_m;
// 读通道合并
assign ar_valid_m = |arvalid_s;
assign r_valid_m = rvalid_m;
// 仲裁核心:WRR + Round-Robin
// 这里给出简化版:每周期选最高权重请求,权重递减,归零后轮转
logic [$clog2(M)-1:0] aw_sel, ar_sel;
logic [31:0] aw_weight [M];
logic [31:0] ar_weight [M];
// 初始化权重
generate
for (genvar i = 0; i < M; i++) begin
always_ff @(posedge aclk or negedge aresetn) begin
if (!aresetn) begin
aw_weight[i] <= WGT[i];
ar_weight[i] <= WGT[i];
end else begin
// 权重耗尽则恢复,否则递减
if (aw_grant == i && aw_valid_m && awready_m)
aw_weight[i] <= (aw_weight[i] == 0) ? WGT[i] : aw_weight[i] - 1;
if (ar_grant == i && ar_valid_m && arready_m)
ar_weight[i] <= (ar_weight[i] == 0) ? WGT[i] : ar_weight[i] - 1;
end
end
end
endgenerate
// 选择权重非零且 valid 的最高索引(简单优先级)
function automatic [$clog2(M)-1:0] pick_winner(input logic [M-1:0] valid,
input logic [31:0] weight [M]);
for (int i = M-1; i >= 0; i--) begin
if (valid[i] && weight[i] > 0)
return i[$clog2(M)-1:0];
end
return '0;
endfunction
assign aw_sel = pick_winner(awvalid_s, aw_weight);
assign ar_sel = pick_winner(arvalid_s, ar_weight);
// 授权寄存(保证同 ID 保序,这里简化:一拍授权)
always_ff @(posedge aclk or negedge aresetn) begin
if (!aresetn) begin
aw_grant <= '0;
ar_grant <= '0;
end else begin
if (aw_valid_m && awready_m) aw_grant <= aw_sel;
if (ar_valid_m && arready_m) ar_grant <= ar_sel;
end
end
// 主端握手信号生成
assign awready_s = '0;
assign awready_s[aw_grant] = awready_m;
assign wready_s = '0;
assign wready_s[aw_grant] = wready_m; // 写数据跟随写地址得主
assign arready_s = '0;
assign arready_s[ar_grant] = arready_m;
// 从端输出 = 当前授权主端值
function automatic [ADDR_W-1:0] sel_addr(input logic [M*ADDR_W-1:0] vec);
return vec[aw_grant*ADDR_W +: ADDR_W];
endfunction
// 写地址通道
assign awaddr_m = sel_addr(awaddr_s);
assign awprot_m = awprot_s[aw_grant*3 +: 3];
assign awqos_m = awqos_s[aw_grant*QoS_W +: QoS_W];
assign awid_m = awid_s[aw_grant*ID_W +: ID_W];
assign awuser_m = awuser_s[aw_grant*USER_W +: USER_W];
// 写数据通道
assign wdata_m = wdata_s[aw_grant*DATA_W +: DATA_W];
assign wstrb_m = wstrb_s[aw_grant*DATA_W/8 +: DATA_W/8];
assign wlast_m = wlast_s[aw_grant];
// 写响应广播
assign bvalid_s = {M{bvalid_m}};
assign bready_m = |bready_s; // 任一主端可收
assign bresp_s = {M{bresp_m}};
assign bid_s = {M{bid_m}};
// 读地址通道
assign araddr_m = araddr_s[ar_grant*ADDR_W +: ADDR_W];
assign arprot_m = arprot_s[ar_grant*3 +: 3];
assign arqos_m = arqos_s[ar_grant*QoS_W +: QoS_W];
assign arid_m = arid_s[ar_grant*ID_W +: ID_W];
assign aruser_m = aruser_s[ar_grant*USER_W +: USER_W];
// 读数据广播
assign rvalid_s = {M{rvalid_m}};
assign rready_m = |rready_s;
assign rdata_s = {M{rdata_m}};
assign rresp_s = {M{rresp_m}};
assign rlast_s = {M{rlast_m}};
assign rid_s = {M{rid_m}};
endmodule
手写 WLAST 生成代码
点击查看代码
module wlast_generator (
input clk,
input rst_n,
// 来自写地址通道
input awvalid,
input [7:0] awlen, // AWLEN 是 burst 长度 - 1
input awready,
// 写数据通道握手
input wvalid,
input wready,
// 输出
output reg wlast
);
// 内部计数器
reg [7:0] burst_cnt;
reg burst_active;
// 当 AW 握手成功时,锁存 burst 长度并启动计数
wire aw_fire = awvalid && awready;
always @(posedge clk or negedge rst_n) begin
if (!rst_n) begin
burst_cnt <= 8'd0;
burst_active <= 1'b0;
end else begin
if (aw_fire) begin
burst_cnt <= 8'd0; // 重置计数器
burst_active <= 1'b1; // 启动 burst
end else if (wvalid && wready && burst_active) begin
if (burst_cnt == awlen) begin
burst_active <= 1'b0; // 结束 burst
end else begin
burst_cnt <= burst_cnt + 1'b1;
end
end
end
end
// 生成 WLAST:当计数器等于 AWLEN 时拉高
always @(posedge clk or negedge rst_n) begin
if (!rst_n)
wlast <= 1'b0;
else
wlast <= (wvalid && wready && burst_active && (burst_cnt == awlen));
end
endmodule
问题29: AXI WRAP地址回绕计算
- MCU Cortex-M7 + 256-bit AXI —— TCM 回绕 DMA
- 项目背景
-- 车规 MCU(某 Tier-1 流片,2024 Q4)
-- 256 bit 总线 = 32 B per beat;Cache line 256 B → 8 beat
-- BootROM 用 DMA 把 256 B 固件搬到 ITCM,要求“首地址 0x41C 先到达 CPU” - AXI 参数
-- ARADDR = 0x0000_041C // 非对齐起始,但落在 0x0000_0400-0x0000_04FF line
-- ARLEN = 7 // 8 beat
-- ARSIZE = 5 // 32 B
-- ARBURST= 2 (WRAP) - 回绕边界
-- wrap_low = 0x0000_0400
-- wrap_high = 0x0000_0500
- 地址序列(逻辑分析仪截图)
-- 0x041C → 0x0440 → 0x0460 → 0x0480 → 0x04A0 → 0x04C0 → 0x04E0 → 0x0400
-- 第 8 beat 回到下界 0x0400,完成整条 line 搬运;CPU 在 beat0 即可开始取指, boot 时间缩短 12 %
问题30:AXI的outstanding深度如何计算:
outstanding是master在未收到完成响应之前,可以发出的trans的最大值,因为发出的trans都还没有完成,因此master必须将这些trans缓存起来,即需要准备N个缓冲资源。
通过outstand,类似于CPU中的流水线,可以将延迟隐藏掉,因此outstanding深度(类似流水线级数)也会影响总线带宽。
1:总线隐藏延迟需要outstanding深度
假设系统读写延迟为Tns,总线带宽为B GB/s,单笔burst数据量为burst_size=(burst_len+1)*beat_size
理论上把总线打满,完成流水起来,即第一笔trans发出之后,到收到resp之间,还需要再发送T*B/burst_size笔burst trans。
2:outstanding的能力还受master的缓存深度影响
master已经发出,但是还没有完成的数据量为:outstanding_depth(burst_len+1)beat_size;
对于读操作:master需要全部缓存,否则会出现反压导致死锁(比如outstanding能力为8,缓存深度小于8,乱序返回,就会死锁)
对于写操作:master可以只缓存AW/W通道
outstanding深度一般取1和2的最小值。
问题31:如何验证outstanding
验证要从功能、性能两反面考虑
单master outstanding功能:
- 基本收发
- 发满outstanding,不返回数据,再发数据,检查是否被反压
- 随机返回某个数据(第一笔、最后一笔、中间任意一笔),检查master可以再发trans,
- 读写之间outstanding的影响
多master的outstanding:比较复杂,主要考虑多master同时最大outstanding能力时功能正常、仲裁优先级、不同主机最同一地址的读写交叉、formal证明没有死锁、master不会饿死
性能:
- 检查延迟是否被有效的隐藏(不考虑其他master的抢占)
- 是否能达到理论带宽峰值
问题32: AXI为什么有4KB的约束
这涉及到虚拟地址和物理地址之间的转换,每个程序都有自己的虚拟地址空间,比如32位系统,每个程序可用程序空间都是4GB,这是虚拟空间,实际的物理地址空间也只有4GB,两个程序共享实际4GB,此时就需要通过页表、TLB进行虚拟地址到物理地址的映射,
一般页表大小都是4KB,如果跨4KB,可能就会访问到其他程序的地址空间了
AXI死锁
- 不当的复位可能会导致系统死锁;AXI组件发出的Outstanding会等待全部结束,如果结束前互联总线被复位、slave被复位,此时主机会死锁

浙公网安备 33010602011771号