1. 创建IP核管理工程
2. 自定义一个带有AXI4接口的IP核
2.1 创建IP核
- 选择创建AXI4外设
- 设置IP核的存储位置
- 配置AXI4接口
- 中间的加减号可以添加AXI4接口
Interface Type :Lite、Full、Stream
Interface Mode :Master、Slave
Data Width :32 // DDR的位宽
-
也可以尝试添加AXI4-Lite和AXI4-Stream接口,此次实验不需要添加。
-
AXI-Lite
Number of Registers:4 // 寄存器数量
- AXI-Stream
2.2 AXI4 协议
- 系统复位后, 状态机处于IDLE状态。
- 在IDLE状态下,一旦检测到启动传输脉冲init_txn_pulse为高电平,状态机跳转到INIT_WRITE状态。
- 在INIT_WRITE状态下,状态机拉高start_single_burst_write信号,来不断地启动AXI4 Master接口对Slave端大小为4KB的存储空间进行突发写操作。
写操作完成后 write_done信号会拉高,状态机进入INIT_READ状态。- 在INIT_READ状态下,状态机拉高start_single_burst_read信号,不断地启动AXI4 Master接口对Slave端同一存储空间进行突发读操作,同时将读出的数据与写入的数据进行对比。
读操作完成后read_done信号拉高,状态机进入INIT_COMPARE状态。- 在INIT_COMPARE状态下,判断读写过程中是否发生错误,并将错误状态赋值给ERROR信号,然后将compare_done信号拉高,表示一次读写测试完成。
- 最后跳转到IDLE状态,等待下一次读写操作的启动信号。
- 4KB (4096 B)
在AXI4协议中,memory空间划分为4KB的块,一个burst transfer不能跨越4K地址边界,即访存操作的起始地址和终止地址必须处于相邻的两个4K边界对齐地址点(即0x0000_0000、0x0000_1000、0x0000_2000等)区间内。
3. 调用IP核
m_axi_init_axi_txn:IP核检测到端口的上升沿后会启动读写过程
m_axi_txn_done: IP核会将读出的数据与写入的数据作比较,比较完成后,m_axi_txn_done输出 高电平。
m_axi_error: 在比较完成后,m_axi_error信号会指示整个过程是否出错;如果数据不一致,那么m_axi_error将会 拉高。
C M AXI TARGET SLAVE BASE ADDR:0x1000_0000 //映射到DDR3中的地址空间,是IP核进行读写操作的起始地址。将该地址之前的存储空间预留下来,用于运行PS中的软件程序。
4. SDK开发
#include "stdio.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "xil_io.h"
int main()
{
int i;
char c;
Xil_DCacheDisable();
printf("AXI4 PL DDR TEST!\n\r");
while(1)
{
scanf("%c",&c);
if(c == 'c'){
printf("start\r\n");
for(i=0;i<4096;i=i+4)
{
printf("%d is %d\n",i,(int)(Xil_In32(0x10000000+i)));
}
}
}
return 0;
}
- 通过调用函数 Xil_DCacheDisable() 来关闭数据缓存(Data Cache),以避免从缓存中读取数据。这是因为在对同一地址进行读操作时,读出的有可能是 Data Cache 中缓存的数据,而不是DDR中真正的数据。
- 用函数Xil_In32()读取内存数据,每次读取32 bit,而内存地址是以字节为单位的,所以每次操作完成后地址变量 i 应该累加4。
总结:AXI4 Full接口为PL端提供了直接存储访问,SDK不需要进行任何配置。