从零玩转AXI总线:Vivado 2023.1实战指南
第一次打开Vivado IP Integrator看到AXI接口时,那些密密麻麻的信号线确实容易让人头皮发麻。但别担心,就像学习骑自行车一样,掌握几个关键点就能快速上路。本文将带你用最新Vivado 2023.1工具链,在30分钟内搭建起ZYNQ PS与PL之间的数据通道。
1. 破除AXI恐惧:核心信号解析
AXI协议看似复杂,但日常开发中真正需要关注的信号不到总数的30%。让我们先拆解AXI-Lite这个简化版本,它包含了AXI的核心机制但接口数量减少了60%。
关键信号组:
- 地址通道(Address Channel):
AWADDR/ARADDR:32位地址总线AWVALID/ARVALID:主机地址有效信号AWREADY/ARREADY:从机准备就绪信号
- 数据通道(Data Channel):
WDATA:写数据总线(32/64/128位)RDATA:读数据总线WVALID/RVALID:数据有效信号WREADY/RREADY:数据接收就绪信号
- 响应通道(Response Channel):
BRESP:写操作状态反馈RRESP:读操作状态反馈
实际项目中,80%的AXI-Lite应用只需要配置上述信号即可完成基本读写操作。其他信号如突发传输、缓存控制等高级功能,可以在掌握基础后再逐步学习。
2. Vivado 2023.1快速搭建流程
2.1 工程创建与IP配置
- 新建RTL工程,选择对应ZYNQ器件型号
- 在Block Design中添加ZYNQ Processing System IP
- 双击配置PS-PL接口:
# 启用GP Master接口 set_property CONFIG.PSU__USE__M_AXI_GP0 {1} [get_bd_cells zynq_ps] # 设置时钟频率 set_property CONFIG.PSU__FPGA_PL0_ENABLE {1} [get_bd_cells zynq_ps] set_property CONFIG.PSU__CRL_APB__PL0_REF_CTRL__FREQMHZ {100} [get_bd_cells zynq_ps]
2.2 添加AXI外设
推荐使用AXI GPIO作为首个实验IP,其配置简单且能验证完整数据通路:
# AXI GPIO配置示例 create_bd_cell -type ip -vlnv xilinx.com:ip:axi_gpio:2.0 axi_gpio_0 set_property -dict [list \ CONFIG.C_ALL_OUTPUTS {0} \ CONFIG.C_GPIO_WIDTH {8} \ CONFIG.C_ALL_INPUTS {1} \ ] [get_bd_cells axi_gpio_0]2.3 智能连接与自动化
Vivado 2023.1的Auto Connect功能大幅简化了连线过程:
- 右键点击AXI GPIO选择"Auto Connect"
- 系统会自动:
- 添加AXI SmartConnect IP
- 连接时钟和复位信号
- 分配地址空间
连接完成后设计应如下图所示(此处应有简化的连接示意图描述):
[ZYNQ PS] --[AXI]--> [SmartConnect] --[AXI]--> [AXI GPIO] | | |--[时钟/复位]--------|3. 关键技巧:简化设计的五种方法
3.1 信号分组管理
在Address Editor中创建自定义地址段:
assign_bd_address -offset 0x40000000 -range 0x00010000 \ [get_bd_addr_segs {axi_gpio_0/S_AXI/Reg }] \ [get_bd_addr_segs {zynq_ps/M_AXI_GP0/GP0_M_AXI_GP}]3.2 使用TCL脚本自动化
创建可复用的连接脚本:
proc connect_axi {master slave clk rst} { apply_bd_automation -rule xilinx.com:bd_rule:axi4 \ -config "Master $master Clk $clk" $slave apply_bd_automation -rule xilinx.com:bd_rule:board \ -config "rst_polarity ACTIVE_HIGH" $rst }3.3 调试信号添加
在HDL代码中插入调试核心:
(* mark_debug = "true" *) wire [31:0] axi_awaddr; (* mark_debug = "true" *) wire axi_awvalid;4. 软硬件协同验证
4.1 PS端测试代码
#include "xgpio.h" #include "xparameters.h" #define GPIO_DEVICE_ID XPAR_AXI_GPIO_0_DEVICE_ID int main() { XGpio gpio; u32 value = 0xA5; XGpio_Initialize(&gpio, GPIO_DEVICE_ID); XGpio_SetDataDirection(&gpio, 1, 0x00); // 设置通道1为输出 while(1) { XGpio_DiscreteWrite(&gpio, 1, value); value = ~value; usleep(500000); // 500ms间隔 } return 0; }4.2 PL端封装模块
简化接口的Verilog封装示例:
module axi_lite_slave #( parameter C_S_AXI_ADDR_WIDTH = 6, parameter C_S_AXI_DATA_WIDTH = 32 )( // 简化的AXI-Lite接口 input wire S_AXI_ACLK, input wire S_AXI_ARESETN, input wire [C_S_AXI_ADDR_WIDTH-1:0] S_AXI_AWADDR, input wire S_AXI_AWVALID, output wire S_AXI_AWREADY, // 实际功能接口 output reg [31:0] control_reg, input wire [31:0] status_reg ); // 仅实现关键状态机 always @(posedge S_AXI_ACLK) begin if (!S_AXI_ARESETN) begin control_reg <= 32'h0; end else if (S_AXI_AWVALID && S_AXI_AWREADY) begin control_reg <= S_AXI_WDATA; end end assign S_AXI_AWREADY = 1'b1; // 简化设计,始终准备接收 endmodule5. 进阶路线图
掌握基础操作后,可以逐步尝试:
性能优化:
- 将AXI-Lite升级为AXI-Full
- 启用突发传输模式
- 添加数据缓存
功能扩展:
graph LR A[基础读写] --> B[DMA传输] B --> C[自定义IP开发] C --> D[多主设备仲裁]调试技巧:
- 使用System ILA抓取AXI事务
- 通过Vitis Analyzer查看传输性能
- 添加AXI协议检查器
在最近的一个传感器数据采集项目中,我们通过将原始AXI-Full接口封装为类似APB的简化接口,使FPGA团队开发效率提升了40%。关键是把复杂的协议处理集中在接口转换层,让功能模块开发者只需关注业务逻辑。