ZYNQ7100部署VIT算子的IP核过程记录
·
ZYNQ7100部署VIT算子的IP核过程记录
1、创建vivado工程
“xc7z100ffg900-2”型号
2、使用 IP Integrator 创建 Processing System
接下来我们将在IP集成器中完成ZYNQ嵌入式系统的搭建
- 在左侧导航栏(Flow Navigator)中,单击IP Integrator 下的Create Block Design。然后在弹出的对
话框中指定所创建的Block Design的名称,在Design name栏中输入“system”,Directory和Specify source
set 保持默认即可,然后点击“OK”
- 接下来在Diagram窗口中给设计添加 IP。点击上图中箭头所指示的加号“+”,会打开IP目录(IP
Catalog),也可以通过快捷键Ctrl + I,或者右键点击Diagram工作区中的空白位置,然后选择“ADD IP”。
打开IP目录后,在搜索栏中键入“zynq”,找到并双击“ZYNQ7 Processing System”,将ZYNQ7
处理系统IP添加到设计中



- 配置PS的DDR3控制器

- 配置PS的时钟

- 关于PS中与PL端交互的接口信号


3、使用 Vitis HLS生成VIT的IP核
#include <ap_fixed.h>
#include <ap_int.h>
// 定义数据类型:16位定点数(6位整数,10位小数)
typedef ap_fixed<16, 6> data_t;
// 定义算子维度 32x32
#define DIM 32
// 顶层函数 - 名字已改为 vit,与你的项目设置匹配
void vit(
data_t external_input[DIM], // 外部输入
data_t output[DIM], // 计算结果
ap_uint<2> mode, // 模式:0-外部, 1-内建Patch1, 2-内建Patch2
ap_uint<1> *trigger // TDC 触发信号引脚
) {
// --- 接口协议定义 ---
#pragma HLS INTERFACE s_axilite port=external_input bundle=control
#pragma HLS INTERFACE s_axilite port=output bundle=control
#pragma HLS INTERFACE s_axilite port=mode bundle=control
#pragma HLS INTERFACE s_axilite port=return bundle=control
#pragma HLS INTERFACE ap_none port=trigger
// --- 1. 静态权重矩阵 (1024个数据) ---
// 使用宏自动生成 32x32 的填充数据
static const data_t weights[DIM][DIM] = {
#define R4(n) n*0.11, n*(-0.21), n*0.31, n*(-0.41)
#define R8(n) R4(n), R4(n+1)
#define R16(n) R8(n), R8(n+2)
#define R32(n) R16(n), R16(n+4)
R32(1), R32(2), R32(3), R32(4), R32(5), R32(6), R32(7), R32(8),
R32(9), R32(10), R32(11), R32(12), R32(13), R32(14), R32(15), R32(16),
R32(-1), R32(-2), R32(-3), R32(-4), R32(-5), R32(-6), R32(-7), R32(-8),
R32(-9), R32(-10), R32(-11), R32(-12), R32(-13), R32(-14), R32(-15), R32(-16)
};
// --- 2. 内建测试 Patch (2组各32个数据) ---
static const data_t internal_patch1[DIM] = {
0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0,
1.1, 1.2, 1.3, 1.4, 1.5, 1.6, 1.7, 1.8, 1.9, 2.0,
2.1, 2.2, 2.3, 2.4, 2.5, 2.6, 2.7, 2.8, 2.9, 3.0, 3.1, 3.2
};
static const data_t internal_patch2[DIM] = {
-3.2, -3.1, -3.0, -2.9, -2.8, -2.7, -2.6, -2.5, -2.4, -2.3,
-2.2, -2.1, -2.0, -1.9, -1.8, -1.7, -1.6, -1.5, -1.4, -1.3,
-1.2, -1.1, -1.0, -0.9, -0.8, -0.7, -0.6, -0.5, -0.4, -0.3, -0.2, -0.1
};
// --- 3. 输入缓冲与选择 ---
data_t current_input[DIM];
#pragma HLS ARRAY_PARTITION variable=current_input complete
if (mode == 1) {
for(int k=0; k<DIM; k++) current_input[k] = internal_patch1[k];
} else if (mode == 2) {
for(int k=0; k<DIM; k++) current_input[k] = internal_patch2[k];
} else {
for(int k=0; k<DIM; k++) current_input[k] = external_input[k];
}
// --- 4. 触发信号拉高:计算正式开始 ---
*trigger = 1;
// --- 5. 核心 32x32 矩阵乘法 ---
// 完全展开循环,确保 1024 个 DSP 单元在相近时间点翻转
for (int i = 0; i < DIM; i++) {
#pragma HLS UNROLL
data_t sum = 0;
for (int j = 0; j < DIM; j++) {
#pragma HLS UNROLL
sum += current_input[j] * weights[i][j];
}
output[i] = sum;
}
// --- 6. 计算结束:拉低触发信号 ---
*trigger = 0;
}
导出IP核时由于时间戳溢出报错
需要打补丁,教程见该链接 Xilinx系列bug
然后把这个生成的IP核导入block design
4、生成TDC IP核

5、生成顶层HDL模块











6、软件设计










main.c代码如下:
#include <stdio.h>
#include "platform.h"
#include "xil_printf.h"
#include "xvit.h" // HLS 生成的驱动
#include "xparameters.h" // 包含硬件基地址信息
// 实例定义
XVit VitInst;
int main()
{
init_platform();
printf("--- ViT Side-Channel Experiment: Started ---\n\r");
int status;
// 1. 初始化 IP 核
// 注意:这里的 XPAR_VIT_0_DEVICE_ID 需检查 xparameters.h 是否对应
status = XVit_Initialize(&VitInst, XPAR_VIT_0_DEVICE_ID);
if (status != XST_SUCCESS) {
printf("Error: ViT Initialization Failed!\n\r");
return -1;
}
// 2. 准备数据
// 虽然 HLS 内部是 ap_fixed<16,6>,但 AXI 总线传输的是 32 位 Word (u32)
u32 my_input[32];
u32 my_output[32];
// 初始化输入数据(比如设置为全 1 的定点数表示,或者任意随机值)
for(int i = 0; i < 32; i++) {
my_input[i] = 0x0040; // 这是一个示例定点数值
}
// 3. 将输入数据写入 IP 核内部缓冲区
// 对应 xvit.h 第 97 行
XVit_Write_external_input_Words(&VitInst, 0, my_input, 32);
// 4. 设置运行模式
// Mode 0: 外部数据 (my_input)
// Mode 1: 内置 Patch 1
// Mode 2: 内置 Patch 2
XVit_Set_mode(&VitInst, 1);
// 5. 启动计算 (核心触发点)
// 执行这一行时,PL 端的 trigger 引脚会立刻拉高,ILA 开始记录 TDC
XVit_Start(&VitInst);
printf("ViT Op Triggered. Calculating...\n\r");
// 6. 等待硬件计算完成
while (!XVit_IsDone(&VitInst));
// 7. 读取结果 (使用正确的带 _r 的函数名)
// 对应 xvit.h 第 108 行
XVit_Read_output_r_Words(&VitInst, 0, my_output, 32);
printf("Calculation Finished! Output[0] = %08x\n\r", (unsigned int)my_output[0]);
cleanup_platform();
return 0;
}


7、下载验证









openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。
更多推荐

所有评论(0)