目录
1. 概述
- 在Vivado中自定义IP核是一个常见的任务,特别是在开发Zynq平台时。
- 自定义IP核可以通过Vivado设计套件中的工具来创建、打包和重用。通常,
- 自定义IP核可以与DMA核相连,以实现数据传输和处理。
- 在Vivado中创建自定义IP核涉及使用Create and Package IP wizard等工具,同时也可以使用AXI协议来定义IP核的接口。
- 通过自定义IP核,开发人员可以实现特定功能的硬件加速,以提高系统性能和效率。
2. IP Packager 重要参数
2.1 参数说明
// Width of S_AXI data bus
parameter integer C_S_AXI_DATA_WIDTH = 32,
// Width of S_AXI address bus
parameter integer C_S_AXI_ADDR_WIDTH = 4
定义了4个32bit位宽的寄存器
// 主设备将启动对从设备的读写事务,基地址在此处作为参数指定。
parameter integer C_M_AXI_ADDR_WIDTH = 32,// 主设备发出写数据并接受读数据,其中数据总线的宽度为C_M_AXI_DATA_WIDTH
parameter integer C_M_AXI_DATA_WIDTH = 32,// 事务数量是指主设备将执行的写和读事务的数量
parameter integer C_M_TRANSACTIONS_NUM = 4,
3. AXI4 Lite 写操作逻辑
// 1.从写地址通道空闲 2.主写地址通道就绪 3.主写数据通道就绪 4.从aw_en就绪; 此条件为主机发起AXI写数据请求
if (~axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
// 2.主写响应通道忙 <- 1.从写响应通道就绪; 此条件为写响应通道握手
if (S_AXI_BREADY && axi_bvalid)
// 1.从写数据通道忙 2.主写数据通道就绪 3.从写地址通道忙 4.主写地址通道就绪;此条件为从机准备锁存数据
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
//slv_reg_wren, slave register write enable
// ADDR_LSB参数,取决于AXI数据位宽,32bit/64bit分别对应AXI每时钟周期传输4bytes/8bytes,分别占用2bit/3bit地址空间
localparam integer ADDR_LSB = (C_S_AXI_DATA_WIDTH/32) + 1;
localparam integer OPT_MEM_ADDR_BITS = 1; // OPT_MEM_ADDR_BITS参数由用户定义的寄存器数量决定
reg [C_S_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; //用于锁存AXI总线的AXI_AWADDR,即写地址通道的地址信息
case ( axi_awaddr[ ADDR_LSB + OPT_MEM_ADDR_BITS : ADDR_LSB ] ) // 下一页有详解
2'h0:
// for在always块中,用于生成多份代码
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
3.1 写数据请求发起
首段代码检查了是否满足主机(通常是处理器)向从机(如存储器或外设)发起AXI写数据请求的条件。这些条件包括:
- 写地址通道(AW通道)未就绪 (~axi_awready)
- 从机写地址有效 (S_AXI_AWVALID)
- 从机写数据有效 (S_AXI_WVALID)
- 写使能 (aw_en) 信号就绪
当这些条件同时满足时,表示主机准备好发送写地址和写数据到从机。
3.2 写响应通道握手
检查是否满足以下条件:
- 主机准备接收写响应 (S_AXI_BREADY)
- 从机的写响应有效 (axi_bvalid)
当这些条件同时满足时,表示写操作已完成,主机和从机之间完成了一次写响应通道的握手。
3.3 从机锁存数据
第三段代码通过assign语句定义了一个条件,用于判断从机是否准备好锁存(存储)数据。这个条件包括:
- 写数据通道(W通道)就绪 (axi_wready)
- 主机写数据有效 (S_AXI_WVALID)
- 写地址通道(AW通道)就绪 (axi_awready)
- 主机写地址有效 (S_AXI_AWVALID)
当这些条件同时满足时,表示从机准备好锁存从主机发来的写数据。
3.4 地址和数据处理
代码中定义了一些参数来处理地址和数据宽度的不同配置,例如ADDR_LSB根据AXI数据位宽(32位或64位)来确定地址的最低有效位,这对于确定如何根据地址访问或修改数据很重要。
接着,使用case语句和一个循环来处理不同地址下的数据写入操作。这里,根据地址和写入使能(S_AXI_WSTRB)来确定哪些字节需要被更新。对于选定的地址,循环遍历所有的数据字节,如果相应的写入使能位被设置,则更新从机寄存器(slv_reg0)中对应的字节。
3.5 地址空间详解
4. 写入和读取请求
详解case,以数据位宽32bit,用户寄存器数量4个,为例:
case ( axi_awaddr[ADDR_LSB+OPT_MEM_ADDR_BITS:ADDR_LSB] )
case ( axi_awaddr[3:2] ) // axi_awaddr[3:2] 有两位地址空间,最多可以容纳4个用户定义寄存器,本例中刚好为4个;
2‘h0: // 类似于DDR,AXI数据位每8bit有一个strobe信号
if ( S_AXI_WSTRB[0] == 1 ) slv_reg0[ 7: 0] <= S_AXI_WDATA[ 7: 0];
if ( S_AXI_WSTRB[1] == 1 ) slv_reg0[15: 8] <= S_AXI_WDATA[15: 8];
if ( S_AXI_WSTRB[2] == 1 ) slv_reg0[23:16] <= S_AXI_WDATA[23:16];
if ( S_AXI_WSTRB[3] == 1 ) slv_reg0[31:24] <= S_AXI_WDATA[31:24];
2'h1: …
2'h2: …
2'h3: …
// 以上case段功能:根据 AXI 总线中的 S_AXI_AWADDR (写地址通道的地址信息)更新从机对应地址寄存器的值,即数据锁存,
// 用户逻辑,则可由锁存的数据,来实现具体逻辑层操作。
// 1.从写地址通道忙 2.主写地址通道就绪 3.从写响应通道空闲 4.从写数据通道忙 5.主写数据通道就绪; 写地址、写数据均握手
if (axi_awready && S_AXI_AWVALID && ~axi_bvalid && axi_wready && S_AXI_WVALID) //此条件为从机锁存数据完毕
// 1.从读地址通道空闲 2.主读地址通道就绪; 此条件为主机发起AXI读数据请求
if (~axi_arready && S_AXI_ARVALID) //将执行地址锁存
// 1.主读地址通道忙 2.从读地址通道就绪 3.从读数据通道未就绪 ; 此条件为读地址通道握手,从机发送AXI读数据通道请求
if (axi_arready && S_AXI_ARVALID && ~axi_rvalid)
4.1 寄存器写入逻辑
通过case语句,根据写地址(axi_awaddr),决定更新哪一个用户定义的寄存器(slv_reg0到slv_reg3)。每个寄存器的更新是基于写数据(S_AXI_WDATA)和写入使能(S_AXI_WSTRB)信号。这里,S_AXI_WSTRB信号用于控制哪些字节应被写入,类似于动态随机存取存储器(DDR)中的字节使能信号。
以32位数据位宽的情况为例,寄存器写入逻辑支持最多4个用户定义寄存器。写地址信号的特定位(在这个例子中是axi_awaddr[3:2])用于选择具体的寄存器进行操作。
4.2 写操作握手
当写地址通道(AW)就绪且有效,写数据通道(W)就绪且有效,且写响应通道(B)未被占用时,表示一个写操作已经完成握手,数据可以被锁存到从机的寄存器中。这是一个标准的写操作流程,包括发送写地址、写数据和接收写响应。
4.3 读请求发起
当读地址通道(AR)空闲且读地址有效时,表示主机发起了一个AXI读数据请求。此时,从机将锁存读请求的地址,准备后续的数据传输。
4.4 读操作握手
当读地址通道就绪且有效,但读数据通道(R)未就绪时,表示读地址通道已经完成握手,从机准备发送读数据请求。这是读操作的一个关键步骤,确保了数据能够从指定地址被读出并传输给请求方。
5. 读数据请求的处理逻辑
5.1 读请求的接收与响应
从机接收到主机的读请求并准备好响应的逻辑,当以下条件同时满足时:
- 读地址通道就绪(axi_arready)
- 主机的读地址有效(S_AXI_ARVALID)
- 读数据通道未就绪(~axi_rvalid)
此时,从机将axi_rvalid标志置为1,表示从机已经准备好发送读数据。同时,axi_rresp被设置为0,表示读操作成功,无错误。
5.2 读响应的完成与握手
当从机已经标记读数据通道为就绪(axi_rvalid为1),且主机准备接收数据(S_AXI_RREADY)时,表示读响应的握手成功。
此时,从机将axi_rvalid标志拉低,完成一次读操作的数据传输过程。
5.3 读取数据的选择与输出
通过一个always块和case语句,根据读请求的地址(axi_araddr),选择相应的从机寄存器(slv_reg0到slv_reg3)中的数据准备输出。这里,地址的特定位用于选择具体的寄存器。
5.4 读数据的锁存
通过slv_reg_rden信号,当从机准备好读数据时,选中的寄存器数据(reg_data_out)被锁存到axi_rdata中,准备通过AXI接口发送给主机。slv_reg_rden信号的条件与读请求接收与响应的条件一致,确保了数据的正确输出。