FPGA 进阶实战 · 02 AXI4-Lite 寄存器与反压
独立接收 AW/W、落实 WSTRB 与错误响应,并保持 B/R 响应直到握手。
先修知识完成 FPGA FIFO 六章基础实战;理解同步时序、非阻塞赋值与 ready/valid。
适用环境Basys 3 / xc7a35tcpg236-1;板上 100/50 MHz 同源时钟;Icarus Verilog、Python 3;Vivado 2024.1 命令参考。
验证状态三组时钟 RTL 测试、两类负向测试及板上自检器的软件模型已通过;Vivado、物理 CDC 和 ILA 上板尚需实测。
将五个通道分开观察
一次软件写操作在总线上拆成地址、数据和响应过程,地址与数据到达次序不能由从设备猜测。本工程分别锁存地址和数据,凑齐后才提交寄存器操作;读通道按地址握手建立一份响应快照。由此可以解释为什么地址已经握手仍没有写响应,也能在波形中区分尚未收齐输入与下游执行变慢。
定义软件可依赖的寄存器语义
DATA 支持按字节写入,START 只在最低字节有效且最低数据位为一时触发。忙时再次启动返回错误而不排队,但允许更新 DATA 暂存下一笔,已经锁存的跨域数据保持不变。STATUS 的 done 由新命令清除、结果返回置位,读取本身不清除;RESULT 只在当前命令完成后有效,避免隐藏的读副作用干扰排障。
| 地址 / 方向 | 含义与边界 |
|---|---|
| 0x00 RW DATA | WSTRB 字节合并;全零 WSTRB 不修改 |
| 0x04 WO START | bit0 启动;忙时 SLVERR,零写无副作用 |
| 0x08 RO STATUS | bit0 busy,bit1 done;读取不清除 |
| 0x0c RO RESULT | 最后一次完成的 32 位结果 |
| 其他地址 / 错误方向 | SLVERR;非对齐访问也返回错误 |
| AWPROT / ARPROT | 接收但忽略,本外设不形成安全隔离边界 |
完整 AXI 外设实现,与下载包一致;只支持本表规定的寄存器行为。
`timescale 1ns/1ps
module axi_mailbox #(parameter INJECT_ERROR=0)(
input wire aclk,arst,dclk,drst,
input wire [7:0] awaddr,input wire [2:0] awprot,input wire awvalid,output wire awready,
input wire [31:0] wdata,input wire [3:0] wstrb,input wire wvalid,output wire wready,
output reg [1:0] bresp,output reg bvalid,input wire bready,
input wire [7:0] araddr,input wire [2:0] arprot,input wire arvalid,output wire arready,
output reg [31:0] rdata,output reg [1:0] rresp,output reg rvalid,input wire rready,
output wire [79:0] debug_s,debug_d);
reg aw_pending,w_pending;reg [7:0] addr_q;reg [31:0] data_q;reg [3:0] strb_q;
reg [31:0] data_reg,result_reg;reg busy,done,start;
wire mb_ready,mb_valid;wire [31:0] mb_result;
// PROT is accepted but not used: no security boundary in this teaching peripheral.
assign awready=!arst && !aw_pending && !bvalid;
assign wready=!arst && !w_pending && !bvalid;
assign arready=!arst && !rvalid;
cdc_mailbox #(.INJECT_ERROR(INJECT_ERROR)) u_cdc(aclk,arst,dclk,drst,start,data_reg,mb_ready,mb_valid,mb_result,debug_s,debug_d);
integer k;
always @(posedge aclk or posedge arst) begin
if(arst) begin
aw_pending<=0;w_pending<=0;addr_q<=0;data_q<=0;strb_q<=0;
bresp<=0;bvalid<=0;rresp<=0;rvalid<=0;rdata<=0;
data_reg<=0;result_reg<=0;busy<=0;done<=0;start<=0;
end else begin
start<=0;
if(bvalid && bready)bvalid<=0;
if(rvalid && rready)rvalid<=0;
`ifdef BUG_AW_W
// Intentional fault: wrongly requires simultaneous AWVALID and WVALID.
if(awvalid && awready && wvalid)begin addr_q<=awaddr;aw_pending<=1;end
if(wvalid && wready && awvalid)begin data_q<=wdata;strb_q<=wstrb;w_pending<=1;end
`else
if(awvalid && awready)begin addr_q<=awaddr;aw_pending<=1;end
if(wvalid && wready)begin data_q<=wdata;strb_q<=wstrb;w_pending<=1;end
`endif
if(mb_valid)begin result_reg<=mb_result;busy<=0;done<=1;end
if(aw_pending && w_pending && !bvalid)begin
aw_pending<=0;w_pending<=0;bvalid<=1;bresp<=0;
case(addr_q)
8'h00:for(k=0;k<4;k=k+1)if(strb_q[k])data_reg[k*8+:8]<=data_q[k*8+:8];
8'h04:if(strb_q[0] && data_q[0])begin
if(busy || !mb_ready)bresp<=2; // SLVERR, no command accepted
else begin busy<=1;done<=0;start<=1;end
end
default:bresp<=2;
endcase
end
if(arvalid && arready)begin
rvalid<=1;rresp<=0;
case(araddr)
8'h00:rdata<=data_reg;
8'h08:rdata<={30'b0,done,busy};
8'h0c:rdata<=result_reg;
default:begin rdata<=0;rresp<=2;end
endcase
end
end
end
endmodule
用错开到达与反压验证接口
测试既要检查最终读写值,也要检查等待期间接口是否稳定。测试任务让 AW 先到、W 先到或同时到达,随后故意推迟 BREADY 和 RREADY,确认响应不会消失或改变。字节合并用有辨识度的数据验证,非法访问则检查响应码,避免把工具没有报错误认为总线协议实现正确。
- 分离地址与数据
预期与判定:确认 AW 先到与 W 先到都能形成一次写响应。
- 推迟响应接收
预期与判定:B 等待四拍、R 等待三拍期间 VALID 与载荷保持。
- 检查边界访问
预期与判定:部分字节、全零写使能、非法和非对齐地址结果正确。
- 验证负向测试
预期与判定:BUG_AW_W 版本必须被超时检查检出。
在解压后的 fpga-advanced 目录执行。软件仿真不需要 Vivado;硬件步骤需目标工具与板卡。
python3 flow.py sim
# 测试中的字节写:
# DATA <- 0x11223344, WSTRB=0xf
# DATA <- 0xaabbccdd, WSTRB=0x5
# 读回应为 0x11bb33dd;WSTRB=0 不修改
python3 flow.py sim --axi-fault
# 预期:AXI_TIMEOUT,随后 ADV_NEGATIVE_PASS典型故障:错误等待同拍 AW/W
故障版本对地址和数据接收都增加了另一通道有效的条件,却仍对外声称能够握手。于是主设备认为地址已被接受,随后撤销地址有效,而从设备实际上没有保存地址。这个例子说明不能靠延长软件等待或要求上游固定发送顺序修复协议问题,必须修复接收缓存和握手事件的一致性。
完成检查
- AW/W 任意先后均能独立接收。
- WSTRB、SLVERR 与响应保持得到验证。
- 故障版被 AXI_TIMEOUT 明确检出。
延伸阅读与来源
本文为黄河电子原创教学说明。产品命令与支持范围请以实际安装版本的官方文档为准。
- Arm AMBA AXI / ACE IHI0022H
A3 通道握手;B1 AXI4-Lite。寄存器行为与示例实现为本文原创设计。
- AMD UG903 · Constraining Asynchronous Signals
跨域数据路径最大延时与时钟组例外的优先级。
- AMD UG908 · Programming and Debugging
Hardware Manager 与 ILA 配置、触发及采集。
继续阅读
FPGA从 RTL 到板上运行的完整流程
建立约束、实现、下载与观测的最小工程闭环。
第一个工程的引脚与时钟约束
区分电气连接与时间要求,避免“能生成位流就算正确”。
如何读懂时序报告
从起点、终点、时钟和裕量找出失败路径的原因。
黄河电子