赞
踩
笔者最近拿到了一块Ultra96v2的开发板,尝试部署一个用于cifar10数据集识别的卷积神经网络,算是入门异构版型开发的demo实现吧。由于是第一次接触此部分内容,若有部分偏颇还请批评斧正。
Ultra96-V2板子中集成了一块ARM硬核(processing system,PS端)和一块FPGA软核(programmable logic,PL端),其中PS端通常用来处理一些便于CPU进行的调度运算,例如一些常见的预处理指令等;PL端通常用来处理一些大规模并行运算,以逻辑电路的形式实现算法,例如实现卷积神经网络等需要高速并行运算等需求。并使用xilinx提供的AXI总线完成PL和PS端的互联互通。
Ultra96-V2支持使用PYNQ进行开发,PYNQ提供了一种利用Python在顶层通过overlay方式烧录FPGA相关的IP核,其主要构架如下图所示:
这里我们在PYNQ官网下载相关镜像,选择Borads,然后下载用于Ultra96v2的镜像:
由于笔者在后续开发中发现v2.6版本会将“找不到hwh文件”这一问题识别为一个error,而v2.5版本则是waring可忽略,仅用tcl和bit流文件即可实现Overlay调用,所以笔者后续开发使用的为v2.5版本。PYNQ官网中并没有给出v2.5版本的旧版镜像,这里给出适用Ultra96v2等安富利公司一些开发板的旧版本镜像汇总,建议使用v2.5版本。下载完镜像后,使用Win32 Disk Imager将下载的ISO镜像烧录至SD卡中,烧录完成中将SD卡插入板子,并将拨码开关拨至SD卡启动模式(SW3_1 = OFF, SW3_2 = ON),至此PYNQ环境搭建完成。
后续开发过程中还需要Xilinx公司的Vivado和Vivado HLS等EDA工具,笔者使用的版本为2019.1,请读者自行下载安装。
由于开发板BRAM资源有限,无法实现大规模模型,在这里我仅训练了一个非常基础非常小型的卷积神经网络模型作为入门。后续部署大型模型时可采用模型压缩方法降低BRAM利用率。在整个流程中,PS端通过USB读取图像信息,再进行预处理,例如切换为RGB通道、resize为32x32等;后送入PL端执行两层卷积、激活、池化,两层全连接网络后输出识别结果输出至PS端;PS端根据输出的数字0~9判断得到的识别结果,并将其和图像一起通过MiniDP接口输出至外接显示器。
在python3.7,tensorflow2.1环境中训练卷积神经网络模型,并将参数保存至txt文件中。这里建议导出参数时的输出方式和C语言的变量定义方式一致,方便下一步导入HLS的头文件中。相关训练代码已上传至Github,参见后记。对tensorflow代码基础不扎实的读者可学习北京大学曹健副教授开设的MOOC课程:《tensorflow笔记》。
在PL端的IP核编写过程中,读者可利用Xilinx公司提供的HLS高级语言综合工具,即利用C、C++、SystemC等语言编写相关描述代码,HLS等EDA软件可将C等高级语言综合为Verilog、VHDL等硬件描述语言,并生成IP核,还可进行C仿真、RTL/C联合仿真等。
void predict(uint8_t *in_b,uint8_t *in_g,uint8_t *in_r,uint8_t *out_t) { #pragma HLS INTERFACE m_axi depth=1024 port=in_b offset=slave bundle=part_b #pragma HLS INTERFACE m_axi depth=1024 port=in_g offset=slave bundle=part_g #pragma HLS INTERFACE m_axi depth=1024 port=in_r offset=slave bundle=part_r #pragma HLS INTERFACE m_axi depth=1 port=out_t offset=slave bundle=part_out #pragma HLS INTERFACE s_axilite register port=in_b bundle=control #pragma HLS INTERFACE s_axilite register port=in_g bundle=control #pragma HLS INTERFACE s_axilite register port=in_r bundle=control #pragma HLS INTERFACE s_axilite register port=out_t bundle=control #pragma HLS INTERFACE s_axilite register port=return bundle=control DTYPE img[IMG_DMNIN][IMG_DMNIN][IMG_CHANNELS]; uint8_t in_b_buffer[IMG_DMNIN*IMG_DMNIN]; uint8_t in_g_buffer[IMG_DMNIN*IMG_DMNIN]; uint8_t in_r_buffer[IMG_DMNIN*IMG_DMNIN]; memcpy(in_b_buffer,in_b,IMG_DMNIN*IMG_DMNIN * sizeof(uint8_t)); memcpy(in_g_buffer,in_g,IMG_DMNIN*IMG_DMNIN * sizeof(uint8_t)); memcpy(in_r_buffer,in_r,IMG_DMNIN*IMG_DMNIN * sizeof(uint8_t)); for(uint8_t r = 0; r < IMG_DMNIN ;r++) { for(uint8_t c = 0; c < IMG_DMNIN ; c++
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。