本文是 Arm Ethos‑U65 学习与实践系列笔记的第三篇从芯片设计与验证的角度梳理该 NPU IP 的集成与功能验证流程。集成IP配置U65包含两种MAC单元数 256 和 512 两种规格需要在生成时通过配置文件指定。打开 logical/config/ethosu65.yaml 配置文件进行配置可以看到只有2个配置项第1个是修改顶层 moudle 名称保持注释就会使用默认名称第2个是配置 MAC 单元数量可以选256或512。IP生成然后在 logical 目录执行生成脚本通过 -output 指定生成 rtl 的路径整体生成流程比较简单。./generate -config yaml configuration file -output directory for configured RTL output然后在 output 路径会出现生成文件其中 ethoseu65 前缀为设计文件设计文件语言为system verilogmodels路径为待替换的 ram 等模型testbench 路径为验证环境。验证验证环境包含 execution_tb、ram_integration_tb和 integration_kit 三个目录分别为APB读写、RAM读写和运算程序三个环境。下面会用 execution_tb 的验证环境 integration_kit 的程序进行功能仿真。验证环境首先查看 execution_tb 路径参照 README 可以直接执行 vcs 仿真默认 dump 波形需要自己再写一个 verdi 指令打开波形。make compile SIMvcs make run SIMvcs TESTNAMEconfig_check验证环境中将 IP 和 axi slave ram 模型 包成了一个小系统ethosu_exetb_wrappertestbench 顶层只需要提供时钟、复位就可以 通过 apb 配置 IP 工作。环境中还包含 apb 读写方法和 memory 后门读写方法memory 模型是按页划分的三维数组最好简化修改一下后续自己 readmemh 命令流和数据会方便一些。task write_reg; input [APB_ADDR_WIDTH-1:0] address; input [APB_DATA_WIDTH-1:0] data; output error;task read_reg; input [APB_ADDR_WIDTH-1:0] address; output [APB_DATA_WIDTH-1:0] data; output error;task write_memory; input [48:0] address; input [3:0] wmask; input [31:0] wdata; input mark_as_written;task read_memory; input [48:0] address; output [31:0] rdata; input mark_as_read;环境包含 5 个 case分别为 apb 读写和功耗评估 case下图为 apb 写读写读波形case 内容参考性一般主要是借用 testbench 环境进行后续验证验证用例ram_integration_tb 路径下为存储访问这里不再做参考integration_kit 路径为 pooling、conv2d 等算子实现程序下面进行说明。integration_kit 路径实际是一个软件编译环境环境下均为 c 程序makefile.inc 中可以指定处理器为 M33 或 M55然后通过 Makefile 编译出 axf 二进制文件。环境运行首先需要 CMSIS从 github 上下载再在 makefile.inc 里指定 CMSIS 路径即可https://github.com/ARM-software/CMSIS_6。然后需要 Arm Compilerlinux 环境下没有 keil剩余的方法就是安装 Arm Development Studio 或直接安装 Arm CompilerArm Compiler 可以用 DS 的 license。最后执行 make all可以看到编译出来的 test0~3但由于本人没有 M33 系统仿真环境或实物测试环境所以上述过程其实没什么用哈哈。因为不编译也可以直接在 test 路径下查看几个 test 的 c 程序然后转到 systemverilog 环境。其中 test0 是空程序test1 是 poolingtest2 是带权重的点运算test3 是不带 pad 的卷积test4 是带 pad 的卷积。仿真结果integration_kit 路径下 tests/common/test_commands.h 中包含了 NPU 的配置流程test0~4 的区别仅在命令流、输入数据、权重有的 test 没有不同APB 配置基本是完全一样的。这里使用上述路径下的 test3 卷积case 的命令流结合 execution_tb 路径的验证环境进行功能运算的仿真。首先将配置程序从 c 转成 sv在 ethosu65_exetb.sv 中加入配置可以直接用环境附带的 apb 方法配置中区域 0、1、2、3 的定义是由命令流决定的。write_reg(NPU_REG_AXI_LIMIT0, 32h0f0f0001, error); //AXI 0 接口配置 write_reg(NPU_REG_AXI_LIMIT1, 32h0f0f0001, error); write_reg(NPU_REG_AXI_LIMIT2, 32h0f0f0001, error); //AXI 1 接口配置 write_reg(NPU_REG_AXI_LIMIT3, 32h0f0f0001, error); write_reg(NPU_REG_BASEP0, addr_weights, error); //区域0地址 权重 write_reg(NPU_REG_BASEP2, addr_scratch, error); //区域1地址 缓存数据 write_reg(NPU_REG_BASEP4, addr_data_in, error); //区域2地址 输入图像 write_reg(NPU_REG_BASEP6, addr_data_out, error); //区域3地址 输出图像 write_reg(NPU_REG_QBASE0, addr_cmd, error); //命令流地址 write_reg(NPU_REG_QSIZE, cmd_st.size(), error); //命令流大小 write_reg(NPU_REG_REGIONCFG, 32h00000022, error); //指定区域AXI接口 read_reg(NPU_REG_CMD, read_val, error); write_reg(NPU_REG_CMD, read_val | 32h00000001, error); //触发NPU工作然后将命令流、权重、输入、输出数组从 c 转成 sv 命令流数组 readmemh 到 QBASE0 地址命令流中可以看到权重需要 readmemh 到区域0地址输入数据IFM需要 $readmemh 到区域2地址IP会将输出写到区域3地址输出数组是用来结果比对的不用存。从命令流中可以看到会执行 conv2d 运算不带 pad输入尺寸 [1, 8, 16, 16]输出尺寸相同然后拆成 2 个 block。波形和命令相符哪个区域通过哪个 AXI 实现是由寄存器 REG_REGIONCFG 配置。