ZYNQ 中 AXI BRAM 的使用详细的说明。
🧩 1. 基本概念
- BRAM (Block RAM)
FPGA 内部的片上存储器,容量一般在几 KB 到几百 KB,速度快,延迟低。 - AXI BRAM Controller
一个桥接 IP,用来把 AXI 总线协议 (PS 侧)转换为 BRAM 接口信号(PL 侧)。这样,PS 就能像访问内存一样访问 FPGA 内部的 BRAM。 - 支持协议
- AXI4-Lite:单次读写,适合控制寄存器。
- AXI4:支持突发传输,适合数据块读写。
⚙️ 2. 使用流程
(1) Vivado 硬件设计
- 在 Block Design 中添加:
- AXI BRAM Controller IP
- BRAM Generator IP
- 将 AXI BRAM Controller 的 AXI 接口 连接到 ZYNQ PS 的 M_AXI_GP0/GP1。
- 在 Address Editor 中分配地址空间,例如:
- 基地址:
0x4000_0000 - 大小:8KB
- 基地址:
- 生成 bitstream 并导出硬件到 SDK/Vitis。
(2) BRAM 配置
- 端口模式
- 单端口:一个读写口。
- 简单双端口:一个读口,一个写口。
- 真双端口:两个独立读写口,可并行访问。
- 位宽与深度
可配置,如 32-bit × 2048 深度。
(3) 软件访问方式
在 Linux 或裸机环境下,PS 可以通过 AXI 总线访问 BRAM。
-
裸机 (SDK/Vitis)
直接用指针访问分配的地址空间:
c#define BRAM_BASE 0x40000000 volatile int *bram_ptr = (int *)BRAM_BASE; bram_ptr[0] = 0x12345678; // 写入 int val = bram_ptr[0]; // 读取 -
Linux 环境
-
/dev/mem 映射
cint fd = open("/dev/mem", O_RDWR|O_SYNC); void *map_base = mmap(0, 8192, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0x40000000); volatile int *bram_ptr = (volatile int *)map_base; bram_ptr[0] = 0x55AA55AA; -
UIO 驱动
- Vivado 中配置 BRAM 为 UIO 设备。
- Linux 下通过
/dev/uioX访问。
-
自定义驱动
- 编写字符设备驱动,封装读写接口,适合复杂应用。
-
📊 3. 应用场景
- PS ↔ PL 数据交互
例如:PS 接收网络数据,写入 BRAM,PL 逻辑再读取处理。 - 缓存/缓冲区
在高速数据流中,BRAM 作为临时存储,减少 DDR 访问延迟。 - 共享内存
PS 与 PL 共享 BRAM,实现双向通信。 - 数据搬移
BRAM 作为中间缓冲区,配合 DMA 实现高速数据传输。
🔑 4. 注意事项
- 位宽匹配:AXI 总线位宽与 BRAM 位宽需一致。
- 地址对齐:访问时必须按字对齐,否则可能出错。
- 容量限制:BRAM 容量有限,适合小数据块缓存,不适合大规模存储。
- 性能优化:双端口模式可提高并行度;突发传输可提升带宽。
📝 总结
在 ZYNQ 中,AXI BRAM 控制器是 PS 与 PL 高效交互的关键机制。
- 硬件上:通过 Vivado 配置 AXI BRAM Controller + BRAM Generator,分配地址空间。
- 软件上:通过裸机指针访问或 Linux 下的
/dev/mem、UIO、自定义驱动来读写。 - 应用上:适合高速缓存、共享内存、数据缓冲等场景。