Skip to content
字数
10268 字
阅读时间
41 分钟

一、创建 axi4-full-master 总线接口 IP

创建一个 AXI4-Full 接口总线 IP 设置 IP 的名字为 maxi_full 选择 Full Master 模式 打开快速验证 maxi_full_0就是我们自定义的 IP slave_0 是用来验证 maxi_full_0 正确性 采用默认地址分配即可 路径 uisrc/03_ip/ maxi_full_1.0/hdl 路径下的 maxi_full_v1_0_M00_AXI.v 就是我们的源码。 另外一个 maxi_full_v1_0.v是软件产生了一个接口文件,如果我们自己定义 IP 可有可无。

二、程序分析

axi 总线信号的关键无非是地址和数据,而写地址的有效取决于 AXI_AWVALID 和AXI_AWREADY,写数据的有效取决于 S_AXI_WVALID 和 S_AXI_WREADY。同理,读地址的有效取决于 AXI_ARVALID 和 AXI_ARREADY,读数据的有效取决于 S_AXI_RVALID 和S_AXI_RREADY。所以以下代码的阅读分析注意也是围绕以上 4 个信号的有效时序。

1:产生初始化信号

同步打拍 + 边沿检测逻辑(核心是把外部的 INIT_AXI_TXN 信号同步到 AXI 时钟域,并生成一个单周期的 init_txn_pulse 启动脉冲),是跨时钟域 / 异步信号同步的典型设计)

  • 同步异步信号:通过两级寄存器打拍,将外部异步的 INIT_AXI_TXN 同步到 AXI 时钟域,避免亚稳态;
  • 生成单周期脉冲:配合边沿检测,将持续高电平的启动信号转为单周期的 init_txn_pulse
  • 触发状态机init_txn_pulse 作为状态机从 IDLE 启动的唯一触发信号,保证事务启动的精准性和唯一性

2:axi-full-master 的 axi_awvalid

当(~axi_awvalid && start_single_burst_write)== 1 条件满足,开始一次写传输,设置 axi_awvalid 有效。

写地址有效信号(axi_awvalid)的控制逻辑,核心遵循 AXI 协议中 “VALID 信号一旦置位就不能主动撤销,必须等待从机 READY 信号响应后才能清零” 的关键规则,专门用于管理写地址通道的握手流程

  • 复位 / 事务初始化(最高优先级) 当 AXI 异步复位信号 M_AXI_ARESETN 为低电平,或事务启动脉冲 init_txn_pulse 有效时,直接将 axi_awvalid 清零。这是安全兜底逻辑,保证复位 / 新事务启动时,写地址通道处于 “无有效请求” 的初始状态,避免残留的有效信号导致误发起写地址请求。
  • 发起写地址请求(次优先级) 仅当 “当前无有效写地址请求(~axi_awvalid)” 且 “触发了单次突发写(start_single_burst_write 有效)” 时,才将 axi_awvalid 置为高电平。这一条件确保:① 同一时间仅发起一个写地址请求,避免多个请求冲突;② 仅在外部触发写事务时才启动地址通道,符合 “按需发起” 的逻辑。
  • 撤销写地址请求(遵循协议规则) 代码内的注释明确了 AXI 协议的核心要求:VALID 信号一旦置位,不能主动撤销(即不能在从机未响应时清零)。因此仅当 “从机已就绪(M_AXI_AWREADY=1)且主机写地址有效(axi_awvalid=1)”—— 也就是写地址握手完成(从机已接收地址)时,才将 axi_awvalid 清零,这是完全符合 AXI 协议的 “握手完成后撤销” 规则,避免协议违规导致的总线错误。
  • 状态保持(兜底逻辑) 若以上条件都不满足(比如 axi_awvalid=1M_AXI_AWREADY=0),则保持 axi_awvalid 的当前值不变。这意味着:当主机发起写地址请求(axi_awvalid=1)但从机暂未就绪时,axi_awvalid 会持续保持高电平,直到从机响应(M_AXI_AWREADY=1),保证地址请求不会丢失,符合 AXI “VALID 需稳定到握手完成” 的要求。

3:axi-full-slave 的 axi_awaddr

写通道地址每当 M_AXI_AWREADY && axi_awvalid 地址加 1

AXI 主机写地址(axi_awaddr)的递增控制逻辑,核心作用是在每次写地址握手完成后,自动将写地址递增一个突发长度(burst_size_bytes),实现连续向从机 / DDR 的连续地址发起批量写事务,且严格遵循 AXI 协议的地址更新时机要求

  1. 复位 / 事务初始化(最高优先级) 当 AXI 异步复位信号 M_AXI_ARESETN 为低电平,或事务启动脉冲 init_txn_pulse 有效时,将写地址 axi_awaddr 清零('b0 表示全 0)。这一逻辑保证:每次复位或新事务启动时,写地址都会回到初始值(通常是你预设的 DDR 起始地址,可在外部将初始值改为 C_M_START_ADDR 而非全 0),避免残留的旧地址导致数据写入错误位置。
  2. 地址递增(核心逻辑,对应原注释) 原注释 “Next address after AWREADY indicates previous address acceptance” 直接点明核心规则:只有当从机确认接收了上一个地址(写地址握手完成),才更新下一个地址。具体触发条件是 M_AXI_AWREADY && axi_awvalid(写地址通道握手完成),此时将当前地址加上 burst_size_bytes(突发传输的字节数,比如 4 字节、8 字节,需与 AXI 数据位宽匹配),实现地址的连续递增。这一设计的关键优势: ① 地址更新时机严格滞后于 “地址被接收”,符合 AXI 协议 “地址需稳定到握手完成” 的要求,避免地址在传输过程中变化; ② 保证每次写入的地址都是连续的,适配批量写入 DDR 连续地址的场景 (比如从 0x80000000 → 0x80000004 → 0x80000008…)。
  3. 地址保持(兜底逻辑) 若以上条件都不满足(比如 axi_awvalid=1M_AXI_AWREADY=0,即主机发起了地址请求但从机暂未就绪),则保持 axi_awaddr 不变。这意味着:在写地址握手完成前,当前地址会一直稳定,确保从机最终接收的是正确的地址,不会因地址提前递增导致错误。

与整体 AXI 写事务的联动 这段地址递增逻辑是你之前写事务流程的核心配套逻辑,联动关系如下:

  • axi_awvalid 逻辑联动:axi_awvalid 置位发起地址请求,握手完成后 axi_awaddr 自动递增,为下一次写事务准备好新地址;
  • burst_size_bytes 联动:burst_size_bytes 是预设的突发长度(比如 32 位数据对应 4 字节,即 burst_size_bytes=4),地址递增步长与数据位宽匹配,保证地址按字节对齐(AXI 协议要求);
  • write_index 联动:地址递增次数与 write_index 的计数次数一致,最终实现 “写索引每 + 1,地址递增一个突发长度”,精准对应 “每写一次数据,地址往后挪一个数据位宽” 的批量写入需求。

4:axi-full-master 的 axi_wvalid

设置 axi_wvalid <= 1'b1 开始写数据。wnext 信号有效代码 axi_full_master 写数据有效。 AXI 主机写数据通道(W 通道)核心控制逻辑,包含写数据有效信号(axi_wvalid)和写数据握手判定(wnext),严格遵循 AXI 协议中 “WVALID 一旦置位不可主动撤销,需等到突发传输完成(WLAST 置位 + 握手完成)才能清零” 的规则,专门管理批量突发写事务中数据的发送流程

  1. 复位 / 事务初始化(最高优先级) 当 AXI 异步复位信号 M_AXI_ARESETN 为低电平,或事务启动脉冲 init_txn_pulse 有效时,直接将 axi_wvalid 清零。这是安全兜底逻辑:保证复位 / 新事务启动时,写数据通道处于 “无有效数据发送” 的初始状态,避免残留的 axi_wvalid=1 导致误发送数据,同时与写地址通道(AW 通道)的复位逻辑保持一致,确保读写通道同步初始化。
  2. 发起写数据请求(次优先级) 仅当 “当前无有效写数据请求(~axi_wvalid)” 且 “触发单次突发写(start_single_burst_write 有效)” 时,才将 axi_wvalid 置为高电平。这一条件的核心作用:
    • 保证同一时间仅发起一个写数据请求,避免多个数据帧冲突;
    • 与写地址通道的 axi_awvalid 触发条件对齐(均由 start_single_burst_write 触发),确保 “地址请求” 和 “数据请求” 同步发起,符合 AXI 写事务 “地址 + 数据配套传输” 的规则;
    • 仅在外部触发写事务时才启动数据通道,实现 “按需发送数据”。
  3. 撤销写数据请求(遵循突发传输协议规则) 代码注释明确了 AXI 突发写的核心要求:WVALID 一旦置位,不能主动撤销,必须等到整个突发传输完成(最后一个数据帧由 axi_wlast 标识)且该数据帧完成握手(wnext=1,即 M_AXI_WREADY && axi_wvalid)后,才能将 axi_wvalid 清零。
    • wnext 是组合逻辑定义的 “写数据握手完成” 标志,标识从机已成功接收当前数据帧;
    • axi_wlast 是 AXI 写数据通道的 “突发结束标志”,仅在单次突发传输的最后一个数据帧时置位;
    • 两者同时满足时清零 axi_wvalid,意味着 “整个突发传输的所有数据帧都已被从机接收”,此时撤销有效信号才符合协议规则,避免突发传输中途中断导致数据丢失。
  4. 状态保持(兜底逻辑) 若以上条件都不满足(比如 axi_wvalid=1M_AXI_WREADY=0,或还未到最后一个数据帧),则保持 axi_wvalid 的当前值不变。这意味着:
    • 当主机发起写数据请求后,若从机暂未就绪(M_AXI_WREADY=0),axi_wvalid 会持续高电平,直到从机响应,保证数据帧不会丢失;
    • 在突发传输过程中(未到最后一个数据帧,axi_wlast=0),即使单帧数据握手完成(wnext=1),axi_wvalid 也会保持高电平,继续发送下一个数据帧,直到突发传输结束。

5:axi-full-master 的 axi_master_last

axi_master_last 信号,当条件满足(((write_index == C_M_AXI_BURST_LEN-2 && C_M_AXI_BURST_LEN >= 2) && wnext) || (C_M_AXI_BURST_LEN == 1 )) == 1 的时候,axi_wlast <= 1'b1。这是 VIVADO 自带的模板,但是这里有个 bug,那就是必须确保 slave 可以连续接收数据,假设发送 last 的时候 wnext == 0,这样就不能把最后一个数据正确写入到 slave 中了。 AXI 主机写数据通道最后一个数据帧标志(axi_wlast)的生成逻辑,核心作用是精准标记单次突发写传输中的 “最后一个数据帧”,适配不同突发长度(C_M_AXI_BURST_LEN)的场景,且严格与写数据握手(wnext)同步,保证 AXI 突发写事务的完整性

  1. 复位 / 事务初始化(最高优先级)

    当 AXI 异步复位(M_AXI_ARESETN=0)或事务启动脉冲(init_txn_pulse=1)有效时,直接清零 axi_wlast。这是安全兜底逻辑:保证每次新事务启动时,“最后一个数据帧” 标志处于初始未触发状态,避免残留的 axi_wlast=1 导致突发传输提前终止。

  2. 置位 axi_wlast(核心逻辑,适配不同突发长度)

    这是代码的核心,分两种场景精准触发 axi_wlast=1,确保 “最后一个数据帧” 标记不提前、不滞后:

    • 场景 1:突发长度≥2(批量帧传输)

      触发条件:write_index == C_M_AXI_BURST_LEN-2 + C_M_AXI_BURST_LEN >= 2 + wnext=1

      逻辑本质:写索引(write_index)计数到 “突发长度 - 2”(倒数第二个数据帧)且该帧完成握手(wnext=1,从机已接收)时,置位 axi_wlast—— 提前一拍标记,确保下一个数据帧发送时,axi_wlast=1 同步生效,精准标记 “最后一个数据帧”。

      举例:若突发长度 = 4(需发送 4 帧数据),write_index=2(4-2=2)且第 2 帧握手完成时,置位 axi_wlast,第 3 帧(索引 3)发送时携带 axi_wlast=1,标识这是最后一帧。

    • 场景 2:突发长度 = 1(单帧传输)

      触发条件:C_M_AXI_BURST_LEN == 1

      逻辑本质:单帧传输时无需计数,直接置位 axi_wlast=1,标识这唯一的一帧就是最后一帧,符合 AXI 协议 “单帧突发也需置位 WLAST” 的要求。

  3. 清零 axi_wlast(通用场景)

    当写数据握手完成(wnext=1)时,直接清零 axi_wlast。这一逻辑的核心作用:

    无论 axi_wlast 是否置位,只要当前数据帧被从机接收,就撤销 “最后一个帧” 标志 —— 保证 axi_wlast 仅在 “最后一个帧传输期间” 有效,传输完成后立即清零,避免持续高电平导致后续传输误判。

  4. 单帧突发的特殊清零(兜底)

    触发条件:axi_wlast=1 + C_M_AXI_BURST_LEN == 1

    逻辑补充:针对单帧突发场景,若因时序问题导致 wnext 未及时触发清零,直接通过该条件清零 axi_wlast,避免单帧传输后 axi_wlast 残留高电平。

  5. 状态保持(兜底逻辑)

    若以上条件都不满足(比如 axi_wlast=1wnext=0,即最后一帧已标记但从机暂未接收),则保持 axi_wlast 不变,确保 “最后一个帧” 标志稳定到握手完成,符合 AXI 协议 “WLAST 需与对应数据帧的 WVALID 同步稳定” 的要求。

对原有 axi_wlast 生成逻辑的简化 + 时序优化版本,核心意义是通过 “组合逻辑判定 + 单拍延迟 + 边沿检测” 的方式,让 axi_wlast 生成逻辑更简洁、时序更稳定,且严格保证 axi_wlast 仅在 “最后一个数据帧握手完成” 的时刻产生单周期脉冲

  1. 逻辑极简:简化判定规则,降低出错概率

    • 原有逻辑:需区分 C_M_AXI_BURST_LEN≥2/C_M_AXI_BURST_LEN=1,还要计算 “倒数第二个索引(C_M_AXI_BURST_LEN-2)”,规则复杂且易因突发长度配置错误导致 WLAST 标记错位;
    • 改写后逻辑:核心判定仅 1 条 ——write_index==C_M_AXI_BURST_LEN-1(写索引到最后一帧计数)+ wnext(数据握手完成),直接标识 “最后一个数据帧已被从机接收”,无需区分单帧 / 多帧,规则直观且不易出错。
  2. 时序稳定:消除组合逻辑毛刺,提升可靠性

    • 原有逻辑:axi_wlast 由时序逻辑直接赋值,若 write_indexwnext 存在组合逻辑毛刺,会直接导致 axi_wlast 异常;

    • 改写后逻辑:

      ① 先通过组合逻辑 wlast 判定核心条件,再经寄存器 wlast_r 打拍延迟(同步到 AXI 时钟域),滤除组合逻辑的毛刺;

      ② 最终通过 “上升沿检测(wlast_r=0 且 wlast=1)” 生成 axi_wlast,保证 axi_wlast纯净的单周期脉冲,不会因信号抖动出现多周期高电平,时序稳定性大幅提升。

  3. 协议合规:精准生成单周期 WLAST,符合 AXI 时序要求 AXI 协议要求 axi_wlast 需与 “最后一个数据帧的 axi_wvalid” 同步,且仅需在该帧传输期间有效(单周期即可):

    • 原有逻辑:axi_wlast 可能因条件分支多,出现 “多周期高电平”(比如从机未及时响应时,WLAST 持续高),虽不违反协议,但易导致后续 axi_wvalid 撤销逻辑误判;
    • 改写后逻辑:axi_wlast 是严格的单周期脉冲,仅在 “最后一帧握手完成” 的时钟周期有效,既满足协议 “标记最后一帧” 的要求,又避免持续高电平带来的误判风险。
  4. 可维护性:代码量减少 80%,易调试 / 易扩展

    • 原有逻辑:7 + 行时序逻辑 + 多层条件分支,调试时需逐一验证 “单帧 / 多帧 / 复位 / 握手” 等场景;
    • 改写后逻辑:仅 3 段核心代码(组合判定 + 单拍延迟 + 边沿检测),逻辑链路清晰,后续修改突发长度、调整判定条件时,仅需修改 C_M_AXI_BURST_LEN 一个参数,维护成本大幅降低。

另外需要修改 reg axi_wlast;为 wire axi_wlast;这样就可以确保发送 wlast 的时候数据肯定是有效的。

6:写次数记录 write_index 计数器

AXI 主机突发写事务的帧计数寄存器(write_index)控制逻辑,核心作用是对单次突发写传输中的数据帧进行计数,通过 “初始化清零 + 逐帧递增 + 终端计数停止” 的逻辑,精准控制突发长度(C_M_AXI_BURST_LEN),且注释中提到的 “额外寄存器位简化解码逻辑” 是工业级设计的优化思路,

  1. 功能定位

write_index 是 AXI 突发写事务的数据帧计数器,核心作用是:对单次突发传输中的数据帧逐帧计数,严格匹配配置的突发长度 C_M_AXI_BURST_LEN,为 axi_wlast(最后一帧标记)、axi_wvalid(数据有效撤销)提供精准的计数基准。

  1. 逻辑层级(优先级从高到低)
条件类型触发场景操作设计目的
清零1. 异步复位(M_AXI_ARESETN=0

2. 全局事务启动(init_txn_pulse=1

3. 单次突发写启动(start_single_burst_write=1
计数置 0保证每次新突发写事务启动时,计数从 0 开始,避免旧值干扰
递增1. 数据帧握手完成(wnext=1,即 M_AXI_WREADY && axi_wvalid

2. 未到最后一帧(write_index != C_M_AXI_BURST_LEN-1
计数 + 1仅在 “实际传输完一帧数据” 且 “未到突发长度上限” 时递增,计数与实际传输帧同步
保持无清零 / 递增触发(如最后一帧握手完成、从机未就绪)计数不变避免 “未传输数据却计数” 或 “计数溢出”,保证计数精准
  1. 工业级优化思路(对应注释)

注释中 “Uses extra counter register bit to indicate terminal count” 是关键优化点:

  • 常规设计:用 write_index == C_M_AXI_BURST_LEN-1 判断最后一帧,需做 “相等比较” 的组合逻辑解码;
  • 优化设计:将 write_index 位宽设计为 “突发长度所需位宽 + 1”(如突发长度 4 用 3 位寄存器),“终端计数(C_M_AXI_BURST_LEN-1)” 可通过寄存器最高位直接标识,减少解码逻辑的延迟,提升时序收敛性(代码中简化为相等比较,核心逻辑一致)。

执行流程示例(C_M_AXI_BURST_LEN=4

阶段触发条件write_index 值说明
突发写启动start_single_burst_write=10计数初始化
第 1 帧传输完成wnext=11未到最后一帧,计数 + 1
第 2 帧传输完成wnext=12未到最后一帧,计数 + 1
第 3 帧传输完成wnext=13未到最后一帧,计数 + 1
第 4 帧传输完成wnext=13已到最后一帧(3=4-1),计数停止
下一次突发启动start_single_burst_write=10计数重新初始化

7:axi-full-master 的 axi_wdata

axi_full_master 写数据计数写数据

  1. 功能定位

axi_wdata 是 AXI 写数据通道的核心信号,这段代码实现简单递增型写数据生成逻辑:每次突发传输启动后,数据从初始值(1)开始,每成功传输一帧数据(握手完成)就自动 + 1,生成连续递增的数据流,用于 AXI 写事务的基础数据填充(如功能测试、数据校验)。

  1. 逻辑层级(优先级从高到低)
条件类型触发场景操作设计目的
初始化1. 异步复位(M_AXI_ARESETN=0

2. 全局事务启动(init_txn_pulse=1
axi_wdata 置 1保证每次新事务启动时,数据从固定初始值开始,避免旧数据干扰
数据递增数据帧握手完成(wnext=1,即 M_AXI_WREADY && axi_wvalidaxi_wdata + 1每成功传输一帧数据,数据值递增,生成连续递增的测试数据流
保持无初始化 / 递增触发(如从机未就绪、数据未传输)数据值不变保证数据在传输期间稳定,符合 AXI “WDATA 需与 WVALID 同步稳定” 的协议要求
  1. 注释掉的逻辑说明

verilog

//else if (wnext && axi_wlast) 
// axi_wdata <= 'b0;

这是可选的 “最后一帧数据清零” 逻辑,功能为:当最后一帧数据传输完成(wnext && axi_wlast)时,将 axi_wdata 置 0。未启用的原因通常是:

  • 测试场景下需连续递增数据流,无需最后一帧清零;
  • 若启用,需注意时序对齐(确保 axi_wlast 与最后一帧数据同步)。

8:axi-full-master 的 axi_bready

设置 axi_bready 信号

功能定位

axi_bready 是 AXI 写响应通道(B 通道)的主机就绪信号,这段代码实现AXI 写响应握手的极简控制逻辑:主机仅在从机发起写响应(M_AXI_BVALID=1)时置位就绪信号,且仅保持 1 个时钟周期,完成响应接收后立即清零,严格遵循 AXI 写响应通道的握手规则。

逻辑层级(优先级从高到低)

条件类型触发场景操作设计目的
初始化1. 异步复位(M_AXI_ARESETN=0

2. 全局事务启动(init_txn_pulse=1
置 0保证新事务启动 / 复位时,主机处于 “未就绪” 状态,避免误接收响应
响应接收准备1. 从机写响应有效(M_AXI_BVALID=1

2. 主机当前未就绪(~axi_bready
置 1仅在从机发起响应且主机未就绪时,置位就绪信号,准备接收写响应(BRESP)
响应接收完成主机就绪信号已置位(axi_bready=1置 0就绪信号仅保持 1 个时钟周期,完成响应握手后立即清零,避免持续就绪导致误响应
保持无上述触发条件(如从机未发起响应)保持当前值保证信号稳定,符合 AXI “BREADY 可异步变化,但需避免毛刺” 的要求

9:axi-full-master 的 axi_arvalid

Axi_full_master 读通道的分析非常类似,代码是对称的。当(~axi_arvalid && start_single_burst_read)== 1 条件满足,开始一次写传输,设置 axi_arvalid 有效

axi_arvalid 是 AXI 读地址通道(AR 通道)的主机有效信号,这段代码实现AXI 突发读事务的读地址请求控制逻辑,核心作用是:按 “初始化清零→按需发起请求→握手完成撤销” 的流程,精准管理读地址通道的握手,与写地址通道(axi_awvalid)逻辑完全对称,严格遵循 AXI 协议规则。

条件类型触发场景操作设计目的
初始化1. 异步复位(M_AXI_ARESETN=0

2. 全局事务启动(init_txn_pulse=1
置 0保证复位 / 新事务启动时,读地址通道处于 “无有效请求” 初始状态,避免误发起读请求
发起读地址请求1. 当前无有效读地址请求(~axi_arvalid

2. 触发单次突发读(start_single_burst_read=1
置 1仅在 “无当前请求 + 外部触发” 时发起读地址请求,避免多个请求冲突
撤销读地址请求读地址握手完成(M_AXI_ARREADY && axi_arvalid置 0遵循 AXI 协议 “VALID 一旦置位不可主动撤销,需等待 READY 响应后清零” 的规则
保持无上述触发条件(如 axi_arvalid=1M_AXI_ARREADY=0保持当前值保证读地址请求稳定到握手完成,避免请求丢失

10:axi-full-master 的 axi_araddr

读地址计算

axi_araddr 是 AXI 读地址通道(AR 通道)的地址寄存器,这段代码实现突发读事务的连续地址递增逻辑,核心作用是:在每次读地址握手完成后,自动将读地址递增一个突发字节数(burst_size_bytes),实现从连续地址空间(如 DDR、SRAM)批量读取数据,与写地址递增逻辑(axi_awaddr)完全对称。

11:axi-full-master 的 axi_rready

读数据准备好

条件类型触发场景操作设计目的
初始化1. 异步复位(M_AXI_ARESETN=0

2. 全局事务启动(init_txn_pulse=1
置 0保证复位 / 新事务启动时,主机处于 “未就绪” 初始状态,避免误接收数据
读数据传输阶段从机读数据有效(M_AXI_RVALID=1-分两种子场景控制就绪信号
├─ 突发传输完成M_AXI_RLAST=1(最后一帧)且 axi_rready=1(主机已就绪)置 0突发传输的最后一帧数据完成接收后,清零就绪信号,结束本次读数据传输
└─ 正常接收阶段非最后一帧 / 主机未就绪置 1主机置位就绪信号,准备接收从机发送的读数据(包括首帧 / 中间帧)
保持从机无读数据发送(M_AXI_RVALID=0保持当前值保证信号稳定,避免无意义的状态切换

12:读次数记录 read_index 计数器

读数据索引计数

元素类型功能说明
rnext组合逻辑读数据通道单帧握手完成判定:

M_AXI_RVALID(从机发送读数据有效) + axi_rready(主机准备接收) = 单帧数据接收完成
read_index时序寄存器突发读帧计数器,范围 0 ~ C_M_AXI_BURST_LEN-1,记录当前接收至第几个读数据帧,为 axi_rlast(最后一帧标记)提供计数基准
条件类型触发场景操作设计目的
计数清零1. 异步复位(M_AXI_ARESETN=0

2. 全局事务启动(init_txn_pulse=1

3. 单次突发读启动(start_single_burst_read=1
计数置 0保证每次新突发读事务独立计数,从 0 开始,避免旧计数干扰
计数递增1. 单帧读数据握手完成(rnext=1

2. 未到最后一帧(read_index ≠ C_M_AXI_BURST_LEN-1
计数 + 1仅在 “实际接收数据帧” 且 “未到突发长度上限” 时递增,计数与实际接收帧严格同步
计数保持无清零 / 递增触发(如最后一帧接收完成、从机未发数据、主机未就绪)计数不变避免 “未接收数据却计数” 或 “计数溢出”,保证计数精准

13:产生对比数据 expected_rdata

数据 expected_rdata 用于和读出的 M_AXI_RDATA 进行对比以此验证数据的正确性

  • 生成与 “写侧发送数据(axi_wdata)” 完全同步的递增序列;
  • 作为 “基准值” 与从机返回的实际读数据(M_AXI_RDATA)对比,快速检测读事务中的数据错误(如丢数、错数、乱序)。
条件类型触发场景操作设计目的
初始化1. M_AXI_ARESETN=0(异步复位)

2. init_txn_pulse=1(全局事务启动)
置为 1保证每次新事务启动时,预期数据从固定值开始,与写侧 axi_wdata 初始值对齐
递增M_AXI_RVALID && axi_rready(读数据帧握手完成,等价于 rnext自增 1每成功接收一帧读数据,预期数据同步递增,与写侧 axi_wdata 递增逻辑一致
保持无初始化 / 递增触发(如从机未发数据、主机未就绪)保持当前值避免 “未接收数据却递增”,保证校验基准的准确性
  • 初始值'b1:与写侧 axi_wdata 的初始值完全一致,确保 “写发送第 N 帧数据 = 读预期第 N 帧数据”;若需从 0 开始校验,可将 'b1 改为 'b0
  • 注释掉的|| M_AXI_RLAST:可选优化逻辑,作用是 “读突发最后一帧完成后清零预期数据”,适配多轮突发读的独立校验;未启用是因为 init_txn_pulse 已覆盖全局事务初始化需求。
  • 递增时机:严格同步于 “读数据实际接收完成”,而非 “仅从机发数据”,避免因主机未就绪导致的预期数据超前递增。

14:比对数据正确性

读写数据比较

这段代码是 AXI 读事务数据完整性校验的核心逻辑,通过对比 “从机返回的实际读数据(M_AXI_RDATA)” 和 “本地生成的预期读数据(expected_rdata)”,生成 read_mismatch 错误标志:

  • 标志置 1:数据传输出错(丢数、错数、乱序等);
  • 标志置 0:数据传输正确或无数据校验动作。
元素功能说明
read_mismatch读数据不匹配错误标志(1 = 出错,0 = 正常),是校验结果的核心输出
rnext读数据帧握手完成标志(M_AXI_RVALID && axi_rready),仅在此时校验数据
M_AXI_RDATA从机返回的实际读数据(待校验值)
expected_rdata本地生成的预期读数据(基准值)
条件类型触发场景操作设计目的
初始化1. 异步复位(M_AXI_ARESETN=0

2. 全局事务启动(init_txn_pulse=1
置 0保证新事务 / 复位时,错误标志处于 “无错误” 初始状态,避免误报
错误检测1. 读数据帧握手完成(rnext=1

2. 实际数据≠预期数据
置 1仅在 “有效数据传输完成” 时校验,避免无意义的空校验(如仅 RVALID 有效但主机未就绪)
错误清零无初始化 / 错误触发条件置 0无校验错误或无数据传输时,错误标志清零,保证标志仅在 “出错周期” 有效

15:读写状态机

读写状态机源码

“写→读→校验”

状态名核心功能关键输出 / 动作
IDLE空闲等待,接收事务启动触发(init_txn_pulse清零ERROR/compare_done,触发后跳转到INIT_WRITE
INIT_WRITE发起突发写事务,控制start_single_burst_write生成单周期脉冲脉冲触发写地址 / 数据逻辑;writes_done=1时跳转到INIT_READ
INIT_READ发起突发读事务,控制start_single_burst_read生成单周期脉冲脉冲触发读地址 / 数据逻辑;reads_done=1时跳转到INIT_COMPARE
INIT_COMPARE数据校验结果锁存,输出最终状态锁存error_regERROR,置位compare_done,完成后返回IDLE
信号名功能说明
start_single_burst_write单周期脉冲,触发单次突发写事务(控制写地址 / 数据逻辑启动)
start_single_burst_read单周期脉冲,触发单次突发读事务(控制读地址 / 数据逻辑启动)
writes_done/reads_done写 / 读事务完成标志(外部逻辑生成,标识所有突发传输完成)
burst_write_active/burst_read_active写 / 读突发活跃标志(标识当前有突发传输在执行)
error_reg数据校验错误寄存器(汇总read_mismatch等错误)
compare_done校验完成标志(1 = 读写校验流程结束)
ERROR最终错误标志(1 = 传输 / 校验出错,0 = 正常)

16:正在写 burst_write_active

burst_write_active 代表正在写操作

burst_write_activeAXI 写突发事务的 “活跃状态标志”,核心作用是:

  • 标识当前是否有写突发事务在执行(1 = 活跃,0 = 空闲);
  • 作为上层状态机(INIT_WRITE 态)的判断依据,避免重复触发同一写突发事务。
条件类型触发场景操作设计目的
初始化1. M_AXI_ARESETN=0(异步复位)

2. init_txn_pulse=1(全局事务启动)
置 0保证新事务 / 复位时,写突发处于 “空闲” 初始状态,避免误判
事务启动start_single_burst_write=1(写突发启动脉冲)置 1写突发事务被触发后,立即标识 “事务活跃”,阻止状态机重复触发
事务结束M_AXI_BVALID && axi_bready(写响应握手完成)置 0AXI 写事务的最终收尾(地址 + 数据 + 响应全完成),标识 “事务结束”
AXI 写事务闭环关联

AXI 写事务的完整流程为:地址通道(AW) → 数据通道(W) → 响应通道(B),该逻辑精准匹配这一流程:

  • start_single_burst_write 触发 → 地址 / 数据通道开始传输 → burst_write_active=1(事务中);
  • 从机完成地址 + 数据接收后,通过 M_AXI_BVALID 发起写响应 → 主机 axi_bready 应答 → 握手完成 → burst_write_active=0(事务结束)。

17:写完成 writes_done

写数据完成 writes_done 信号

writes_doneAXI 多突发写事务的 “全局完成判定标志”,核心作用:

  • 判定 C_NO_BURSTS_REQ 个预设的写突发事务是否全部执行完毕;
  • 作为上层状态机(INIT_WRITE 态)的跳转触发信号,当 writes_done=1 时,状态机从 “写阶段” 切换到 “读阶段”,保证 “写完再读” 的流程闭环。
元素含义与作用
writes_done1bit 标志位(1 = 所有写突发完成,0 = 未完成),是多突发写事务的 “最终收尾信号”
C_NO_BURSTS_REQ配置参数:需要执行的写突发总数(如配置为 3,表示要执行 3 次独立的突发写)
write_burst_counter计数器:记录已完成的写突发数量,write_burst_counter[C_NO_BURSTS_REQ]位索引式阈值判定(等价于 计数器 ≥ 2^C_NO_BURSTS_REQ
M_AXI_BVALID && axi_breadyAXI B 通道(写响应)握手完成:单次写突发的最终收尾(AXI 写事务 = AW 通道 + W 通道 + B 通道,B 通道完成才代表单次突发真的结束)
优先级条件操作核心目的
最高复位 / 全局事务启动置 0保证新事务启动时,标志位回到 “未完成” 初始状态,避免误判
次高写响应握手 + 计数器达阈值置 1仅当 “所有写突发执行完 + 最后一次写响应完成” 时,才判定全局完成
最低无触发条件保持原值避免标志位在 “未完成阶段” 频繁翻转,保证状态稳定

18:正在读 burst_read_active

读 burst_read_active 代表正在读数据

burst_read_activeAXI 读突发事务的 “活跃状态标志”,核心作用:

  • 标识当前是否有读突发事务在执行(1 = 活跃,0 = 空闲);
  • 作为上层状态机(INIT_READ 态)的判断依据,避免重复触发同一读突发事务;
  • 注释存在笔误(将 read 写成 write),实际逻辑完全服务于读事务。
条件类型触发场景操作设计目的
初始化1. M_AXI_ARESETN=0(异步复位)

2. init_txn_pulse=1(全局事务启动)
置 0保证新事务 / 复位时,读突发处于 “空闲” 初始状态,避免误判
事务启动start_single_burst_read=1(读突发启动脉冲)置 1读突发事务被触发后,立即标识 “事务活跃”,阻止状态机重复触发
事务结束M_AXI_RVALID && axi_rready && M_AXI_RLAST(最后一帧读数据握手完成)置 0AXI 读事务的最终收尾(最后一帧数据接收完成),标识 “事务结束”
AXI 读事务闭环关联

AXI 读事务的完整流程为:地址通道(AR) → 数据通道(R),该逻辑精准匹配这一流程:

  • start_single_burst_read 触发 → 地址通道开始传输 → burst_read_active=1(事务中);
  • 从机发送最后一帧读数据(M_AXI_RLAST=1)→ 主机接收完成(M_AXI_RVALID && axi_rready)→ burst_read_active=0(事务结束)。

19:读完成 reads_done

读数据完成 reads_done 信号

reads_doneAXI 多突发读事务的 “全局完成标志”,核心作用:

  • 标识配置的 C_NO_BURSTS_REQ 个读突发事务全部执行完成,且每个突发的 C_M_AXI_BURST_LEN 帧数据都接收完毕;
  • 作为上层状态机(INIT_READ 态)的跳转触发条件,当 reads_done=1 时,状态机从 “读阶段” 跳转到 “校验阶段”。
元素功能说明
reads_done1bit 标志位(1 = 所有读突发完成,0 = 仍在执行)
C_M_AXI_BURST_LEN单突发帧长度:每个读突发包含的帧数(如 4 表示单次突发读 4 帧数据)
read_index单突发帧计数器:记录当前突发已接收的帧数,read_index == C_M_AXI_BURST_LEN-1 表示单次突发的最后一帧已接收
C_NO_BURSTS_REQ总突发数:需要执行的读突发总数(如 3 表示执行 3 次独立的突发读)
read_burst_counter总突发数计数器:记录已完成的读突发数量,read_burst_counter[C_NO_BURSTS_REQ] 表示总突发数达到 2^C_NO_BURSTS_REQ(位索引阈值判定)
M_AXI_RVALID && axi_rready读数据握手完成:单帧读数据被主机成功接收(AXI R 通道核心握手逻辑)
条件类型触发场景操作设计目的
初始化复位(M_AXI_ARESETN=0)/ 全局事务启动(init_txn_pulse=1置 0保证新事务启动时,标志位处于 “未完成” 初始状态,避免误判
完成触发1. 最后一帧读数据握手(M_AXI_RVALID && axi_rready

2. 单突发帧计数达标(read_index == C_M_AXI_BURST_LEN-1

3. 总突发数计数达标(read_burst_counter[C_NO_BURSTS_REQ]
置 1仅当 “单次突发最后一帧接收 + 所有突发执行完毕” 时,才判定读事务全局完成
保持无初始化 / 完成触发条件保持避免标志位在 “未完成阶段” 频繁翻转,保证状态稳定

20:IP 的更新

由于修改了代码,需要先更新 IP 状态,完成 IP 更新 将axi_master_last代码替换成下列代码

需要重新更新ip

三、仿真分析

仿真结果

一次 axi4 写操作 burst lenth=16 如下图所示,由于 WREADY 信号不是连续的,所以可以传输效率不是最高的

一共进行 64 次 burst 共计写了 1024 个 32bit 数据

一次读操作的 burst lenth 也是 16 如下图,但是可以看到读数据时连续的,所以效率最高

一共进行 64 次 burst 共计读了 1024 个 32bit 数据

可以看到读出的数据 RDATA 和 expected_rdata 一致,所以代码正确。

贡献者

The avatar of contributor named as dz13718198068 dz13718198068

文件历史

撰写