创建一个带有AXI接口的IP核,该IP核通过AXI协议实现PS和PL的数据通信 AXI 协议是一种高性能、高带宽、低延迟的片内总线
创建新IP核
开发板型号在使用ip时会重新指定,所以此处Part默认即可
创建封装 选择封装 IP 或者创建一个带 AXI4 接口的 IP 核 我们这里选择创建一个带 AXI 接口的 IP核 选中“Creat a new AXI4 peripheral” 
对 AXI 接口进行设置
- Name(名称):S0_AXI。
- Interface Tpye(接口类型):三种接口类型,Lite、Full、Stream
- AXI4-Lite 接口是简化版的 AXI4 接口, 用于较少数据量的存储映射通信;
- AXI4-Full 接口是高性能存储映射接口,用于较多数据量的存储映射通信;
- AXI4-Stream 用于高速数据流传输,非存储映射接口。
- Interface Mode(接口模式):接口模式有 Slave(从机)和 Master(主机)两种模式可选, AXI 协议是主机和从机通过“握手”的方式建立连接,这里选择默认的 Slave 接口模式。
- Data Width(数据宽度):数据位宽保持默认,即 32 位位宽。
- Memory Size(存储器大小): 在 AXI4-Lite 接口模式下,该选项不可设置。
- Number of Registers(寄存器数量):用于配置 PL LED 呼吸灯寄存器的数量,这里保持默认。
保持默认,即将 IP 添加至 IP 库中
在IP catalog中成功添加了AXI IP
右键编辑IP核,即打开IP的工程
添加所需代码,IP核里都标注好了user应该在哪里写代码 
增加IP核例化端口
breath_led_ip_v1_0_S0_AXI 模块实现了 AXI4 协议下的读写寄存器的功能, 我们只需要对该模块稍作修改, 即可实现控制 PL LED 呼吸灯的功能。 向寄存器中写入数据和读出数据的部分代码如下 

在创建和封装 IP 核向导中,我们总共定义了 4 个寄存器, 代码中的 slv_reg0 至 slv_reg3 是寄存器地址0 至寄存器地址 3 对应的数据, 通过例化呼吸灯模块,将寄存器地址对应的数据和呼吸灯模块的控制端口相连接, 即可实现对呼吸灯的控制 再次添加代码:
例化 breath_led.v文件
代码中的 slv_reg0 和 slv_reg1 是寄存器地址 0 和寄存器地址 1 对应的数据, 通过 寄存器地址 0 对应的数据来控制呼吸灯的使能(sw_ctrl), 寄存器地址 1 对应数据的最高位控制呼吸灯频率的设置有效信号(set_en), 寄存器地址 1 对应数据的低 10 位控制呼吸灯频率的步长(set_freq_step)。
保存后,缺少子模块,把之前做过的.v移植过来即可
添加创建源文件
写个呼吸灯的代码接口对好了就ok了
代码无误后综合编译
设置 IP 封装,将界面切换至 Package IP, 如果不小心关闭的话,可以通过 IP-XACT界面下的 component.xml 重新打开,
Categories 选项下的“ +”按钮可用来修改 IP 的分类(此处不改)
Compatibility,修改该 IP 核支持的器件
Life-cycle 表明该 IP 核当前的产品生命周期,选择“ Pre-Production” 
Merge Changes三板斧,点就行 



这是对代码中parameter参数的设定 
参数拖动到page0里
更新总结界面
封装完成
Vivado软件会自动生成.c 和.h 文件,方便在 SDK 软件中对 IP 核进行操作 
创建工程,把自定义ip核添加到此工程ip库中 



创建 Processing System 保留 FCLK_CLK0、 FCLK_RESET0_N 和M_AXI_GP0_ACLK 接口, 添加 UART 控制器( MIO14 和 MIO15) 修改 DDR3 的存储器类型型号,
添加Breath LED IP核
查看可配置参数,与设定一致
“Run Connection Automation”来自动连线
增加LED引脚并改名
最终原理图
生成顶层 HDL 模块 添加xdc
生成硬件,导出硬件Include bitstream 打开SDK,创建空例程,新建main函数 Xilinx → Program FPGA → Program Run As → Lunch on Hardware Led呼吸并切换频率
/*
* main.c
*
* Created on: 2025年5月19日
* Author: 13172
*/
#include "stdio.h"
#include "xparameters.h"
#include "xil_printf.h"
#include "breath_led_ip.h"
#include "xil_io.h"
#include "sleep.h"
#define LED_IP_BASEADDR XPAR_BREATH_LED_IP_0_S0_AXI_BASEADDR //LED IP 基地址
#define LED_IP_REG0 BREATH_LED_IP_S0_AXI_SLV_REG0_OFFSET //LED IP 寄存器地址 0
#define LED_IP_REG1 BREATH_LED_IP_S0_AXI_SLV_REG1_OFFSET //LED IP 寄存器地址 1
//main 函数
int main() {
int freq_flag; //定义频率状态,用于循环改变呼吸灯的呼吸频率
int led_state; //定义 LED 灯的状态
xil_printf("LED User IP Test!\n");
while(1) {
//根据 freq_flag 的标志位,切换呼吸灯的频率
if(freq_flag == 0) {
BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x800000ef);
freq_flag = 1;
} else {
BREATH_LED_IP_mWriteReg(LED_IP_BASEADDR,LED_IP_REG1,0x8000002f);
freq_flag = 0;
}
//获取 LED 当前开关状态 1:打开 0:关闭
led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);
//如果开关关闭,打开呼吸灯
if(led_state == 0) {
BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 1);
xil_printf("Breath LED ON\n");
}
sleep(5);
//获取 LED 当前开关状态 1:打开 0:关闭
led_state = BREATH_LED_IP_mReadReg(LED_IP_BASEADDR,LED_IP_REG0);
//如果开关打开,关闭呼吸灯
if(led_state == 1) {
BREATH_LED_IP_mWriteReg (LED_IP_BASEADDR, LED_IP_REG0, 0);
xil_printf("Breath LED OFF\n");
}
sleep(1);
}
}
保持默认,即将 IP 添加至 IP 库中
在IP catalog中成功添加了AXI IP
右键编辑IP核,即打开IP的工程
添加所需代码,IP核里都标注好了user应该在哪里写代码 
增加IP核例化端口
breath_led_ip_v1_0_S0_AXI 模块实现了 AXI4 协议下的读写寄存器的功能, 我们只需要对该模块稍作修改, 即可实现控制 PL LED 呼吸灯的功能。 向寄存器中写入数据和读出数据的部分代码如下 

在创建和封装 IP 核向导中,我们总共定义了 4 个寄存器, 代码中的 slv_reg0 至 slv_reg3 是寄存器地址0 至寄存器地址 3 对应的数据, 通过例化呼吸灯模块,将寄存器地址对应的数据和呼吸灯模块的控制端口相连接, 即可实现对呼吸灯的控制 再次添加代码:
例化 breath_led.v文件
代码中的 slv_reg0 和 slv_reg1 是寄存器地址 0 和寄存器地址 1 对应的数据, 通过 寄存器地址 0 对应的数据来控制呼吸灯的使能(sw_ctrl), 寄存器地址 1 对应数据的最高位控制呼吸灯频率的设置有效信号(set_en), 寄存器地址 1 对应数据的低 10 位控制呼吸灯频率的步长(set_freq_step)。