下一篇:Vivado实战:封装AXI4-Lite配置寄存器IP核(AXI_Reg)
在FPGA开发中,将常用功能模块封装成IP核可以大大提高代码的复用性和开发效率。本文将详细介绍如何使用Vivado工具将自定义程序封装成IP核,特别以创建新的AXI4接口程序为例。
一、创建新IP核
1.1 启动IP创建向导
首先打开一个现有工程(或新建工程),在Vivado菜单栏中选择:Tools-->Create and Package New IP

点击"Next"进入下一步。
1.2 选择IP创建类型
这里有两个重要选项:
-
Package your current project:将当前正在使用的工程封装为IP核
-
Create a new AXI4 peripheral:生成一个AXI4接口的模板程序
我们选择"Create a new AXI4 peripheral",这是更常用的方式,特别是当需要与处理器进行数据交互时。

1.3 配置IP核基本信息
在这一步中,需要定义:
-
IP核名称:建议使用有意义的命名,如
my_axi_ip -
存储路径:选择一个方便管理的路径存放IP核文件
点击"Next"继续。

1.4 设置AXI4接口参数
根据实际需求配置接口参数:
-
接口数量:根据设计需求选择
-
接口类型:通常选择AXI4-Lite用于寄存器配置,AXI4-Full用于大数据量传输
-
数据位宽:32位、64位等,根据数据传输需求选择

1.5 选择IP核处理方式
完成基本配置后,有两个选项:
-
Add IP to the repository:将IP添加到IP库
-
Edit IP:直接编辑IP

两个选择都可以,如果选择前者,完成后可以在IP Catalog中搜索到你的IP,然后右键选择"Edit IP Packager"进行编辑。

二、编辑IP核源码
2.1 了解自动生成的代码结构
打开IP编辑界面后,会看到自动生成的工程文件,主要包括:
-
顶层模块(如
myip_v1_0):对外提供AXI4-Lite从接口 -
AXI接口模块(如
myip_v1_0_S00_AXI):实现AXI4-Lite协议,默认生成4个寄存器

2.2 顶层模块分析
module myip_v1_0 #
(
parameter integer C_S00_AXI_DATA_WIDTH = 32,
parameter integer C_S00_AXI_ADDR_WIDTH = 4
)
(
// 时钟和复位
input wire s00_axi_aclk,
input wire s00_axi_aresetn,
// AXI4Lite接口
input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_awaddr,
input wire [2 : 0] s00_axi_awprot,
input wire s00_axi_awvalid,
output wire s00_axi_awready,
input wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_wdata,
input wire [(C_S00_AXI_DATA_WIDTH/8)-1 : 0] s00_axi_wstrb,
input wire s00_axi_wvalid,
output wire s00_axi_wready,
output wire [1 : 0] s00_axi_bresp,
output wire s00_axi_bvalid,
input wire s00_axi_bready,
input wire [C_S00_AXI_ADDR_WIDTH-1 : 0] s00_axi_araddr,
input wire [2 : 0] s00_axi_arprot,
input wire s00_axi_arvalid,
output wire s00_axi_arready,
output wire [C_S00_AXI_DATA_WIDTH-1 : 0] s00_axi_rdata,
output wire [1 : 0] s00_axi_rresp,
output wire s00_axi_rvalid,
input wire s00_axi_rready
);
// Instantiation of Axi Bus Interface S00_AXI
myip_v1_0_S00_AXI # (
.C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),
.C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)
) myip_v1_0_S00_AXI_inst (
.S_AXI_ACLK(s00_axi_aclk),
.S_AXI_ARESETN(s00_axi_aresetn),
.S_AXI_AWADDR(s00_axi_awaddr),
.S_AXI_AWPROT(s00_axi_awprot),
.S_AXI_AWVALID(s00_axi_awvalid),
.S_AXI_AWREADY(s00_axi_awready),
.S_AXI_WDATA(s00_axi_wdata),
.S_AXI_WSTRB(s00_axi_wstrb),
.S_AXI_WVALID(s00_axi_wvalid),
.S_AXI_WREADY(s00_axi_wready),
.S_AXI_BRESP(s00_axi_bresp),
.S_AXI_BVALID(s00_axi_bvalid),
.S_AXI_BREADY(s00_axi_bready),
.S_AXI_ARADDR(s00_axi_araddr),
.S_AXI_ARPROT(s00_axi_arprot),
.S_AXI_ARVALID(s00_axi_arvalid),
.S_AXI_ARREADY(s00_axi_arready),
.S_AXI_RDATA(s00_axi_rdata),
.S_AXI_RRESP(s00_axi_rresp),
.S_AXI_RVALID(s00_axi_rvalid),
.S_AXI_RREADY(s00_axi_rready)
);
// Add user logic here
// User logic ends
endmodule
默认配置:
-
数据位宽:32位
-
地址位宽:4位
这些参数都可以根据实际需求进行修改。
2.3 自定义功能实现
在AXI接口模块中,可以找到自动生成的4个寄存器,对应地址:
-
0x00:slv_reg0 -
0x04:slv_reg1 -
0x08:slv_reg2 -
0x0C:slv_reg3
你可以在此基础上添加自己的逻辑功能。
always @( posedge S_AXI_ACLK )
begin
if ( S_AXI_ARESETN == 1'b0 )
begin
slv_reg0 <= 0;
slv_reg1 <= 0;
slv_reg2 <= 0;
slv_reg3 <= 0;
end
else begin
if (slv_reg_wren)
begin
case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
2'h0:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 0
slv_reg0[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
2'h1:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 1
slv_reg1[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
2'h2:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 2
slv_reg2[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
2'h3:
for ( byte_index = 0; byte_index <= (C_S_AXI_DATA_WIDTH/8)-1; byte_index = byte_index+1 )
if ( S_AXI_WSTRB[byte_index] == 1 ) begin
// Respective byte enables are asserted as per write strobes
// Slave register 3
slv_reg3[(byte_index*8) +: 8] <= S_AXI_WDATA[(byte_index*8) +: 8];
end
default : begin
slv_reg0 <= slv_reg0;
slv_reg1 <= slv_reg1;
slv_reg2 <= slv_reg2;
slv_reg3 <= slv_reg3;
end
endcase
end
end
end
三、打包IP核配置
3.1 Identification(标识信息)
-
修改IP核名称和版本号
-
添加描述信息

3.2 Compatibility(兼容性)
选择可以使用该IP核的器件系列。重要:如果要在不同系列的FPGA上使用,需要手动添加对应的器件支持。

3.3 File Groups(文件组)
自动显示IP核包含的所有文件,通常不需要手动修改。

3.4 Customization Parameters(定制参数)
这是最重要的配置部分之一,可以定义IP核的参数化特性。

示例:配置C_S00_DATA_WIDTH数据位宽为可调参数
-
双击
C_S00_AXI_DATA_WIDTH参数 -
设置取值范围:最小值1,最大值32
-
保存配置
这样在IP核实例化时,用户就可以在1-32之间选择数据位宽。


3.5 Interfaces(接口配置)
如果自动生成的接口不符合要求,可以手动配置:
添加AXI总线接口:
-
点击"Add Bus Interface"
-
选择总线类型:AXI

3.定义接口名称和主从关系

4.进入"Port Mapping"界面映射具体信号

配置时钟和复位:
-
右键总线接口选择"Associate Clocks"
-
选择对应的时钟信号

3.6 Addressing and Memory(地址和存储空间)
对于AXI4这类需要地址的接口,会自动生成存储空间映射信息。

3.7 IP GUI(图形界面)
这是最终用户看到的IP核配置界面。通过前面的参数配置,现在可以看到:
-
DATA_WIDTH参数变为可编辑状态,范围1-32 -
其他未修改的参数保持灰色(不可编辑)

3.8 完成打包
在"Review and Package"界面,点击"Re-Package IP"完成整个IP核的打包过程。

四、验证和使用
4.1 在工程中使用IP核
比如我生成的ip核叫做AXI_reg,我们按照如下的步骤将ip核添加到工程里面。


添加完成之后,我们就可以在IP Catalog中搜索到这个IP

4.2 软件端访问
通过AXI4-Lite接口,处理器可以像访问内存一样访问IP核中的寄存器。
五、总结
通过本文的步骤,你可以:
-
创建基于AXI4接口的自定义IP核
-
配置IP核的参数化特性
-
定制IP核的图形化配置界面
-
打包生成可重用的IP核
下一篇预告:我们将以具体的"配置寄存器模块(AXI_Reg)"为例,详细演示如何封装一个实用的IP核,并展示如何在工程中实例化和使用它。
封装IP核是FPGA开发中的重要技能,掌握这一技能将大大提高你的开发效率和代码质量。建议在实际项目中多加练习,逐步掌握各种高级配置技巧。
1063

被折叠的 条评论
为什么被折叠?



