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通道
    截图 2025-11-21 23-01-50
    截图 2025-11-21 23-02-35

公共信号

信号 描述
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被复位,此时主机会死锁
posted @ 2025-11-21 18:26  刘朝锋  阅读(88)  评论(0)    收藏  举报