别再死记硬背了!用状态机图解 AXI4 读写 BRAM 的完整握手时序

张开发
2026/5/30 6:29:16 15 分钟阅读
别再死记硬背了!用状态机图解 AXI4 读写 BRAM 的完整握手时序
状态机视角AXI4协议读写BRAM的时序逻辑拆解第一次接触AXI4协议时很多人会被它复杂的握手信号和通道机制弄得晕头转向。协议文档里那些VALID/READY的时序图看起来抽象难懂而仿真波形又总是和预期对不上。本文将从一个硬件工程师的实战视角用状态机的思维模型带你重新理解AXI4协议的操作时序。1. AXI4协议的核心握手机制AXI4协议的精髓在于它的双向握手机制——每个通道的传输都由VALID和READY两个信号共同控制。这种设计让主从设备可以自主控制传输节奏但也带来了理解上的挑战。1.1 基本握手规则在AXI4中每个通道的传输都遵循以下黄金法则VALID由发送方产生表示数据/控制信息已经准备好READY由接收方产生表示可以接收数据/控制信息传输发生在VALID和READY同时为高的时钟沿这里有个关键细节经常被忽视VALID信号的置起是完全独立的。发送方不能等待接收方的READY信号再置起VALID否则会导致死锁。举个例子// 错误示例等待READY会导致死锁 always (posedge clk) begin if (!awvalid some_condition) begin awvalid 1b1; // 正确独立置起VALID // 错误if (awready) awvalid 1b1; end end1.2 各通道的握手信号AXI4协议包含五个独立的通道每个通道都有自己的握手信号对通道类型VALID信号READY信号携带信息写地址通道AWVALIDAWREADY地址、突发长度等信息写数据通道WVALIDWREADY实际写入的数据写响应通道BVALIDBREADY写操作的状态响应读地址通道ARVALIDARREADY读取的地址信息读数据通道RVALIDRREADY读取到的数据2. 写操作的状态机分解让我们用一个具体的单次写操作案例看看状态机如何描述整个流程。假设我们要向地址0x0000写入32位数据0x12345678。2.1 写地址阶段状态从IDLE转移到WR_ADDR后主设备需要设置以下信号awaddr 32h0000; // 写入地址 awsize 3b010; // 4字节传输(32位) awlen 8h00; // 突发长度为1 awburst 2b01; // 增量突发模式 awvalid 1b1; // 地址有效此时状态机等待awready信号形成典型的握手场景__ __ __ __ clk | |__| |__| |__| | awvalid ______________| awready ______________ ^ 传输发生在这里2.2 写数据阶段地址握手完成后进入WR_DATA状态设置数据通道信号wdata 32h12345678; wstrb 4b1111; // 所有字节有效 wvalid 1b1;对于单次写操作需要同时置起wlast信号表示这是最后一个数据wlast 1b1; // 单次写时立即置位2.3 写响应阶段数据成功传输后从设备会通过写响应通道返回操作状态// 主设备需要准备好接收响应 bready 1b1; // 从设备返回的响应可能为 bresp 2b00; // OKAY - 正常响应 bresp 2b01; // EXOKAY - 独占访问成功 bresp 2b10; // SLVERR - 从设备错误 bresp 2b11; // DECERR - 解码错误(通常由互连组件产生)3. 突发读操作的状态流转突发读操作比单次读更复杂主要体现在地址计算和rlast信号的生成上。假设我们要从地址0x0000开始连续读取8个32位数据。3.1 读地址通道设置araddr 32h0000; arsize 3b010; // 4字节/次 arlen 8h07; // 突发长度8(0-7) arburst 2b01; // 增量模式 arvalid 1b1;注意AXI4协议中arlen表示传输次数-1所以8次传输对应arlen73.2 读数据通道处理从设备会按顺序返回8个数据主设备需要保持rready有效如果随时可以接收检测rlast信号判断传输结束always (posedge clk) begin if (rvalid rready) begin // 存储接收到的数据 data_buffer[count] rdata; count count 1; if (rlast) begin // 突发传输结束 state IDLE; end end end4. 关键信号详解与避坑指南4.1 awsize/arsize的实际含义这两个3位信号决定了每次传输的数据量但有几个易错点size与数据总线宽度的关系size不应超过总线物理宽度。比如32位总线(4字节)上设置size3b011(8字节)是非法的地址对齐要求起始地址必须是传输大小的整数倍。例如size2(4字节)地址必须是4的倍数(0x0,0x4,0x8,...)size3(8字节)地址必须是8的倍数(0x0,0x8,0x10,...)4.2 突发类型与地址计算AXI4支持三种突发类型通过awburst/arburst指定类型值地址计算方式典型应用场景FIXED2b00地址保持不变重复访问同一位置INCR2b01地址按传输大小递增线性内存访问WRAP2b10地址递增到达边界后回绕缓存行填充地址计算示例// INCR模式下的地址生成 always (posedge clk) begin if (wvalid wready) begin next_addr current_addr (1 awsize); end end4.3 wlast/rlast的生成逻辑这两个信号分别表示写和读的最后一个数据传输它们的正确生成至关重要// 写操作last信号生成示例 reg [7:0] write_count; always (posedge clk) begin if (wvalid wready) begin write_count write_count 1; wlast (write_count awlen); // 计数达到突发长度 end end // 读操作的rlast由从设备生成 // 主设备需要检测它来判断传输结束5. 状态机实现的完整示例下面是一个简化的AXI4主设备状态机框架支持基本的读写操作localparam [2:0] IDLE 3d0, WR_ADDR 3d1, WR_DATA 3d2, WR_RESP 3d3, RD_ADDR 3d4, RD_DATA 3d5; reg [2:0] current_state, next_state; reg [7:0] burst_counter; // 状态转移逻辑 always (posedge clk or negedge resetn) begin if (!resetn) begin current_state IDLE; end else begin current_state next_state; end end // 状态机主体 always (*) begin case (current_state) IDLE: begin if (write_req) next_state WR_ADDR; else if (read_req) next_state RD_ADDR; else next_state IDLE; end WR_ADDR: begin if (awvalid awready) next_state WR_DATA; else next_state WR_ADDR; end WR_DATA: begin if (wvalid wready wlast) next_state WR_RESP; else next_state WR_DATA; end WR_RESP: begin if (bvalid bready) next_state IDLE; else next_state WR_RESP; end RD_ADDR: begin if (arvalid arready) next_state RD_DATA; else next_state RD_ADDR; end RD_DATA: begin if (rvalid rready rlast) next_state IDLE; else next_state RD_DATA; end default: next_state IDLE; endcase end // 突发计数器控制 always (posedge clk or negedge resetn) begin if (!resetn) begin burst_counter 8d0; end else if (current_state WR_DATA wvalid wready) begin burst_counter burst_counter 1; end else if (current_state IDLE) begin burst_counter 8d0; end end // wlast生成 assign wlast (burst_counter awlen);6. 仿真调试技巧在实际调试AXI4接口时有几个关键点需要特别关注波形查看重点所有VALID/READY信号的时序关系地址通道的awlen/arlen与实际传输数据量的匹配wlast/rlast信号在正确的位置置位常见错误排查死锁通常因为VALID和READY互相等待导致地址不对齐检查起始地址是否是传输大小的整数倍突发长度不匹配实际传输数据量与arlen/awlen设置不符Vivado仿真小技巧使用AXI Protocol CheckerIP核自动检测协议违规在波形窗口中添加AXI4专用的解码格式更直观查看总线状态# Tcl命令添加AXI解码 add_wave_divider AXI4 Signals add_wave -radix hex /tb/dut/awaddr add_wave -radix bin /tb/dut/awvalid add_wave -radix bin /tb/dut/awready7. 性能优化考量理解了基本握手机制后我们可以进一步优化AXI4接口的性能流水线操作同时进行不同通道的操作如在前一个写操作的数据阶段启动下一个写的地址阶段需要小心处理数据依赖关系OUTSTANDING传输允许在未收到前一个传输响应时就发起新的传输需要设计ID信号来匹配请求和响应数据宽度转换当主从设备数据宽度不一致时如主设备64位从设备32位需要正确处理wstrb信号和地址对齐// 简单的数据宽度转换示例 assign narrow_wdata (awaddr[2]) ? wide_wdata[63:32] : wide_wdata[31:0]; assign narrow_wstrb (awaddr[2]) ? wide_wstrb[7:4] : wide_wstrb[3:0];掌握AXI4协议的状态机视角后你会发现它不再是一堆难以理解的信号而是一个有明确状态流转的清晰逻辑。这种理解方式不仅能帮助正确实现接口还能在出现问题时快速定位原因。

更多文章