当前位置:   article > 正文

Vitis指南 | Xilinx Vitis 系列(一)

xilinx vitis

大侠好,欢迎来到“艮林子”专栏,本次为艮林子首次和大侠见面,新春佳节之际,略备薄礼,不成敬意,给大侠带来“Xilinx Vitis 系列连载”,给大侠提供参考学习的资料,如有不足之处,还请多多指教。

由于内容过多,首篇给大侠列出目录,后续有时间分篇连载发出,欢迎各位大侠关注“FPGA技术江湖”,我们是真正做事的团队,希望大家多多支持,如果想获取更多资源,可以加大辉哥微信,进交流群,可以永久性交流学习,共同进步。

今天带来第一篇,介绍Vitis 2019.2软件平台发行说明、安装以及Vitis加速环境简介。后续还会带来详细的开发教程,敬请关注。话不多说,咱们就进入正题。

VITIS简介

作者:艮林子  校对:陆辉

连载目录

一、Vitis 2019.2软件平台发行说明

  1.1 Vitis软件平台中的内容

    1.1.1 硬件加速的应用程序开发流程

  1.2 改变行为

    1.2.1 从SDAccel迁移

    1.2.2 从SDSoC迁移

  1.3 支持平台

    1.3.1 数据中心加速卡

    1.3.2 嵌入式平台

二、安装

三、Vitis加速环境简介

  3.1 简介与概述

  3.2 FPGA加速

  3.3 执行模型

  3.4 建立过程

    3.4.1 主机程序构建过程

    3.4.2 FPGA二进制构建过程

  3.5 建立目标

    3.5.1 软件仿真

    3.5.2 硬件仿真

    3.5.3 系统

  3.6 使用Vitis软件平台加速应用程序的方法论

    3.6.1 文件受众和范围

    3.6.2 加速:工业类比

    3.6.3 设计设备加速应用程序的方法

    3.6.4 开发C / C ++内核的方法论

四、开发应用程序

  4.1 程序设计模型

  4.2 主机申请

    4.2.1 设置OpenCL环境

    4.2.2 在FPGA中执行命令

    4.2.3 后处理和FPGA清理

    4.2.4 摘要

  4.3 RTL内核

    4.3.1 RTL内核的要求

    4.3.2 RTL内核开发流程

      4.3.2.1 将RTL代码打包为Vivado IP

      4.3.2.2 创建内核描述XML文件

      4.3.2.3 从RTL内核创建XO文件

    4.3.3 RTL内核向导

    4.3.4 摘要

五、构建和运行程序

  5.1 设置Vitis环境

  5.2 建立目标

    5.2.1 软件仿真

    5.2.2 硬件仿真

    5.2.3 系统硬件目标

  5.3 构建主机程序

  5.4 构建FPGA二进制文件

    5.4.1 在Vivado HLS中创建内核

六、对应用程序进行性能分析,优化和调试

七、使用Vitis分析仪

  7.1 处理报告

 7.2 了解葡萄分析仪

 7.3 创建运行配置

 7.4 配置葡萄分析仪

八、使用Vitis IDE

  8.1 Vitis命令选项

  8.2 创建Vitis IDE项目

    8.2.1 启动Vitis IDE工作区

    8.2.2 创建一个应用程序项目

    8.2.3 管理平台和存储库

    8.2.4 了解Vitis IDE

    8.2.5 添加源

      8.2.5.1 添加源文件

      8.2.5.2 创建和编辑新的源文件

      8.2.5.3 在项目编辑器视图中工作

      8.2.5.4 在助理视图中工作

  8.3 建立系统

    8.3.1 Vitis IDE指导视图

    8.3.2 从Vitis IDE使用Vivado工具

  8.4 建立系统

  8.5 配置Vitis IDE

    8.5.1 Vitis项目设置

    8.5.2 Vitis Build配置设置

    8.5.3 Vitis运行配置设置

    8.5.4 Vitis二进制容器设置

    8.5.5 Vitis硬件功能设置

    8.5.6 Vitis工具链设置

      4.5.6.1 Vitis内核编译器和链接器选项

      4.5.6.2 emconfigutil设置

      4.5.6.3 G ++主机编译器和链接器设置

  8.6 项目进出口

    8.6.1 导出Vitis项目

    8.6.2 导入葡萄项目

 

正文

一 Vitis 2019.2软件平台发行说明

1.1 Vitis软件平台中的内容

1.1.1 硬件加速的应用程序开发流程

对于基于FPGA的加速,Vitis核心开发工具包允许使用API构建软件应用程序,比如建立一个软件应用程序的OpenCL™ API,运行硬件(HW)内核上加速卡,如赛灵思 Alveo数据中心加速卡。所述葡萄核心开发套件还支持运行运行Linux,如嵌入式处理器平台上的软件应用ZYNQ的UltraScale +片上多核设备。对于嵌入式处理器平台,Vitis核心开发套件执行模型还使用OpenCL API和基于Linux的Xilinx 运行时(XRT),用于调度硬件内核并控制数据移动。

VItis具包可支持Alove 200,U250,U280和数据中心加速卡,还有zcu102_base,zcu104_base,zc702_base和zc706_base嵌入式处理器平台。除了这些现成的平台以外,还支持自定义平台。

通过Vitis软件平台,您可以将数据中心应用程序迁移到嵌入式平台。所述Vitis核心开发工具包括在V++台上的硬件内核编译器,g++编译器用于编译在x86主机上运行的应用,以及ARM®用于交叉编译应用程序到的嵌入式处理器上运行的编译器的Xilinx设备。

1.2 改变行为

1.2.1 从SDAccel迁移

下表列出了SDAccel开发环境和Vitis软件平台之间的差异。

1.2.2 从SDSoC迁移

  • 总览

该葡萄的核心开发工具包是仿照SDAccel™编程和执行模型。Vitis环境的一项优势是它对数据中心和边缘应用程序的支持。这意味着您可以在标准数据中心平台(例如Alveo™数据中心U200加速卡)上对应用程序进行原型设计,然后在可用时将应用程序重定向到边缘平台。有关更多信息,请参阅构建主机程序。

在Vitis环境中,您需要调用Arm交叉编译器以构建主应用程序代码,并调用Vitis编译器以构建硬件内核。您为主机(.elf)创建一个可执行文件,为硬件内核(.xclbin)创建一个映像。您将使用OpenCL API和基于Linux的Xilinx运行时(XRT)来控制主应用程序和内核之间的数据移动,并计划任务的执行。

对于嵌入式处理器平台(或项目),Vitis环境仅支持运行Linux主机操作系统且平台已将XRT和ZOCL驱动程序添加到根文件系统的平台。平台创建者需要提供一个sysroot,以便通过OpenCL包含文件和库交叉编译到Arm 核心。在主机编译期间,您将需要使用适当的标头。

要从SDSoC环境迁移到Vitis环境,您将必须修改构建脚本和源代码。本节讨论迁移步骤,包括命令行示例,这些示例使用sysroot中的文件,使用Vitis编译器编译硬件内核,并使用Arm cross编译器编译主机应用程序。提供的代码示例仅用于教育目的,不应用于您的设计。

基本迁移步骤如下:

  • 迁移主机应用程序

    • 更新所需的#include文件

    • 根据需要编辑主要功能以及任何其他软件的仅特定功能

  • 迁移硬件功能

    • 使用编译指示定义内核接口

  • 建立系统

    • 构建和链接内核

    • 编译和链接应用程序

  • 迁移主机应用程序

在本节中,您将回顾具有和加速功能的简单SDSoC™程序,main()以识别必须更改的元素。要开始将应用程序和硬件功能迁移到Vitis环境平台和工具的过程,请检查您的主要功能和硬件功能代码。此处提供的代码是mmult示例应用程序。

以下代码段是main()原始开发应用程序项目中的示例函数。

  1. #include <stdlib.h>
  2. #include <iostream>
  3. #include "mmult.h"
  4. #include "sds_lib.h"
  5. #define NUM_TESTS 5
  6. void printMatrix(int *mat, int col, int row) {
  7.  for (int i = 0; i < col; i++) {
  8.   for (int j = 0; j < row; j++) {
  9.    std::cout << mat[i*row+j] << "\t";
  10.   }
  11.   std::cout << std::endl;
  12.  }
  13.  std::cout << std::endl;
  14. }
  15. int main() {
  16.  int col = BUFFER_SIZE;
  17.  int row = BUFFER_SIZE;
  18.  int *matA = (int*)sds_alloc(col*row*sizeof(int));
  19.  int *matB = (int*)sds_alloc(col*row*sizeof(int));
  20.  int *matC = (int*)sds_alloc(col*row*sizeof(int));
  21.  std::cout << "Mat A" << std::endl;
  22.  printMatrix(matA, col, row);
  23.  std::cout << "Mat B" << std::endl;
  24.  printMatrix(matB, col, row);
  25.  //Run the hardware function multiple times
  26.  for(int i = 0; i < NUM_TESTS; i++) {
  27.   std::cout << "Test #: " << i << std::endl;
  28.   // Populate matA and matB
  29.   srand(time(NULL));
  30.   for (int i = 0; i < col*row; i++) {
  31.    matA[i] = rand()%10;
  32.    matB[i] = rand()%10;
  33.   }
  34.   std::cout << "MatA * MatB" << std::endl;
  35.   mmult(matA, matB, matC, col, row);
  36.  }
  37.  printMatrix(matC, col, row);
  38.  return 0;

该代码为存储为一维数组的三个不同的二维矩阵分配内存matA,matB使用随机数填充和 ,然后相乘matA并matB计算 matC。结果打印到屏幕上,测试运行十次。

转到Vitis环境sds++时,需要由应用程序开发人员显式管理由编译器和运行时隐式处理的一些任务。

  • 迁移硬件功能

从SDSoC™环境迁移硬件功能以用于Vitis环境时,需要记住的内容很少。

为了在PL中执行,现在将硬件功能单独编译为.xo文件,因此它不包含在main()函数中,并且不需要像SDSoC环境中那样的用于函数定义的特定头文件。在丢弃头文件之前,必须将BUFFER_SIZE声明复制 到mmult函数中。您还可以评论或删除该 #include语句。

  • 建立系统

在SDSoC™环境中,sds++编译器同时构建主应用程序(.elf)和硬件加速功能(PL区域的位流)。在简单的示例中,用于编译main()函数和mmult硬件函数的命令行如下:

  1. sds++ -Wall -O0 -g -I"../src" -c -fmessage-length=0 -MT"src/mmult.o" -MMD \
  2. -MP -MF"src/mmult.d" -MT"src/mmult.o" -o "src/mmult.o" "../src/mmult.cpp" \
  3. -sds-hw mmult mmult.cpp -sds-end -sds-sys-config a53_linux -sds-proc      \
  4. a53_linux -sds-pf "zcu102"

从该单个命令中,该sds++命令处理该sds-hw块以编译mmult函数,然后再链接main.o对象文件以构建目标应用程序main.elf。最后,它将生成sd_card文件夹,其中包含启动和运行应用程序所需的适当文件。

在Vitis环境中,硬件内核和主要应用程序的编译由两个单独的编译器执行。

  • 高级主题:多个计算单元和内核流

1.3 支持平台

1.3.1 数据中心加速卡

Xilinx提供了几种可用于数据中心的加速卡:

  • Alveo U50数据中心加速卡

  • Alveo U200数据中心加速卡

  • Alveo U250数据中心加速卡

  • Alveo U280数据中心加速卡

有关每个加速卡和可用目标平台的规格,请参阅数据中心加速卡。

1.3.2 嵌入式平台

不支持 Artix®-7,Kintex®-7,Virtex®-7以及裸机和RTOS平台进行加速。对于基于非加速的设计,请参见《Vitis Unified软件平台文档:嵌入式软件开发(UG1400)》。

下面列出了可与Vitis核心开发套件一起使用的嵌入式平台,可以在Xilinx官网上找到它们。

  • zcu102_base:基于ZCU102 Zynq UltraScale + MPSoC和XRT。

  • zcu104_base:基于ZCU104 Zynq UltraScale + MPSoC和XRT。

  • zc702_base:基于ZC702Zynq®- 7000SoC 和XRT。

  • zc706_base:基于ZC706Zynq®- 7000SoC 和XRT。

二、安装

三、Vitis 加速环境简介

3.1 简介与概述

Vitis unified 软件是一个将Xilinx软件开发的各个方面结合到一个统一环境中的新工具。Vitis软件平台既支持Vitis嵌入式软件开发流程,也支持Vitis应用程序加速开发流程,Vitis嵌入式软件开发流程是为希望使用下一代技术的Xilinx软件开发工具包(SDK)用户设计的,Vitis应用程序加速开发流程是为希望使用最新的Xilinx FPGA软件加速开发流程的软件开发人员设计的。该内容主要涉及应用程序加速流,以及Vitis核心开发工具包和Xilinx运行时(XRT)的使用。

Vitis应用程序加速开发流程为使用软件和硬件组件的标准编程语言开发和交付FPGA加速应用程序提供了一个框架。软件组件或主机程序是使用C/ c++开发的,可以在x86或嵌入式处理器上运行,并使用OpenCL API调用来管理与加速器的运行时交互。可以使用C/ c++、OpenCL C或RTL开发硬件组件或内核。Vitis软件平台支持各种方法,允许您从开发应用程序或内核开始。

下图是Vitis软件平台示意图。如图所示,Vitis 统一软件平台包含以下功能和元素:

  • Vitis技术的目标是加速硬件平台,例如Alveo™数据中心加速器卡或Zynq®UltraScale +™MPSoC和基于Zynq®-7000SoC的嵌入式处理器平台。

  • XRT为您的宿主程序提供了API和驱动程序,以使其与目标平台连接,并处理宿主程序和加速内核之间的事务。

  • Vitis核心开发套件提供了软件开发工具堆栈(例如编译器和交叉编译器),用于构建主机程序和内核代码;分析器(可让您分析和分析应用程序的性能);调试器(可帮助您定位和修复任何问题)您的应用程序中的问题。

  • Vitis加速库通过最少的代码更改即可提供性能优化的FPGA加速,而无需重新实现算法即可利用Xilinx自适应计算的优势。Vitis加速库可用于数学,统计,线性代数和DSP的常用功能,也可用于特定领域的应用程序,例如视觉和图像处理,定量财务,数据库,数据分析和数据压缩。有关Vitis加速库的更多信息,请参见Xilinx github库,https://xilinx.github.io/Vitis_Libraries/。。

3.2 FPGA加速

与传统的CPU / GPU加速相比,Xilinx FPGA具有许多优势,包括能够实现可在处理器上运行的任何功能的自定义架构,从而以较低的功耗实现了更好的性能。与处理器体系结构相比,在Xilinx器件中包含可编程逻辑(PL)架构的结构在应用程序执行中实现了高度的并行性。

为了在Xilinx器件上实现软件加速的优势,可以考虑在硬件中加速应用程序的大型计算密集型部分。在自定义硬件中实现这些功能可以使您在性能和功耗之间达到理想的平衡。

有关如何构建具有最佳性能的应用程序以及其他推荐设计技术的更多信息,请查看使用Vitis软件平台加速应用程序的方法。

3.3 执行模型

在Vitis核心开发套件中,应用程序在主机应用程序和硬件加速的内核之间分割,并在它们之间建立通信通道。使用C / C ++编写并使用API抽象(例如OpenCL)的主机程序在主机处理器(例如x86服务器或 用于嵌入式平台的Arm处理器)上运行,而硬件加速的内核则在主机的可编程逻辑(PL)区域内运行。一个赛灵思设备。

由XRT管理的API调用用于处理主机程序和硬件加速器之间的事务。主机和内核之间的通信(包括控制和数据传输)通过PCIe®总线或嵌入式平台的AXI总线进行。当控制信息在硬件中的特定内存位置之间传输时,全局内存用于在主机程序和内核之间传输数据。主机处理器和硬件加速器均可访问全局内存,而主机应用程序只能访问主机内存。

例如,在典型的应用程序中,主机首先将要由内核操作的数据从主机内存传输到全局内存。内核随后对数据进行操作,将结果存储回全局内存中。内核完成后,主机将结果传输回主机内存。主机和全局内存之间的数据传输会引入延迟,这可能会给整个应用程序带来巨大的成本。为了在实际系统中实现加速,硬件加速内核所获得的好处必须超过数据传输所增加的延迟。

Vitis核心开发套件应用程序的体系结构

目标平台包含FPGA加速内核,全局存储器以及用于存储器传输的直接存储器访问(DMA)。内核可以具有一个或多个全局存储器接口,并且是可编程的。该葡萄的核心开发工具包执行模型可以分解为以下步骤:

  • 1.主机程序通过Alveo数据中心加速器卡上的PCIe接口,或通过嵌入式平台上的AXI总线,将内核所需的数据写入连接的设备的全局存储器中。

  • 12.主机程序使用其输入参数设置内核。

  • 13.主机程序触发FPGA上内核功能的执行。

  • 14.内核根据需要执行所需的计算,同时从全局内存中读取数据。

  • 15.内核将数据写回到全局内存,并通知主机它已完成任务。

  • 16.主机程序将数据从全局存储器读回主机存储器,并根据需要继续处理。

FPGA可以在加速器上容纳多个内核实例,不同类型的内核以及同一内核的多个实例。XRT透明地协调了主机程序和加速器中内核之间的交互。Xilinx Github存储库上提供了XRT体系结构文档,https://xilinx.github.io/XRT/。。

3.4 建立过程

Vitis的核心开发工具包提供了所有标准的软件开发环境的特点:

  • 在x86或Arm®处理器上运行的主机应用程序的编译器或交叉编译器。

  • 交叉编译器,用于构建FPGA二进制文件。

  • 调试环境可帮助识别和解决代码中的问题。

  • 性能分析器可识别瓶颈并帮助您优化应用程序。

构建过程遵循主机程序和内核代码的标准编译和链接过程。如下图所示,主机程序是使用GNU C ++编译器(g++)或GNU C ++ Arm交叉编译器为基于MPSoC的设备构建的。FPGA二进制文件是使用Vitis编译器构建的。

3.4.1 主机程序构建过程

主应用程序g++通过以下两步过程进行编译并与编译器链接:

  • 1.将任何所需的代码编译到目标文件(.o)中。

  • 2.将对象文件(.o)与XRT共享库链接以创建可执行文件。

3.4.2 FPGA二进制构建过程

内核可以用C / C ++或OpenCL C代码描述,也可以从打包的RTL设计中创建。如上图所示,每个硬件内核都独立编译为Xilinx目标(.xo)文件。

Xilinx对象(.xo)文件与硬件平台链接,以创建FPGA二进制文件(.xclbin),该文件已加载到目标平台上的Xilinx设备中。

构建FPGA二进制文件的关键是确定要生成的构建目标。有关更多信息,请参阅构建目标。

有关构建过程的详细说明,请参见构建FPGA二进制文件。

3.5 建立目标

Vitis编译器生成过程生成主机程序可执行文件和FPGA二进制(.xclbin)。FPGA二进制文件的性质由构建目标确定。

  • 当构建目标是软件或硬件仿真时,Vitis编译器会生成FPGA二进制文件中内核的仿真模型。这些仿真目标使您可以在相对较快的周期内构建,运行和迭代设计。调试应用程序并评估性能。

  • 当构建目标是硬件系统时,Vitis编译器使用Vivado Design Suite运行综合和实现,从而为硬件加速器生成.xclbin 。它使用这些工具进行预定义的设置,这些设置被证明可以提供良好的结果质量。使用Vitis核心开发套件不需要这些工具的知识。但是,精通硬件的开发人员可以充分利用这些工具,并使用所有可用功能来实现内核。

Vitis编译器提供了三种不同的构建目标,用于调试和验证目的的两个仿真目标,用来产生实际的FPGA二进制文件的默认硬件目标:

  • 软件仿真(sw_emu)

主机应用程序代码和内核代码都被编译为在主机处理器上运行。这样可以通过快速的构建和运行循环来优化迭代算法。该目标对于识别语法错误,对与应用程序一起运行的内核代码执行源代码级调试以及验证系统的行为很有用。

  • 硬件仿真(hw_emu)

内核代码被编译成硬件模型(RTL),该模型在专用模拟器中运行。这种构建和运行循环需要更长的时间,但可以提供详细的,周期精确的内核活动视图。该目标对于测试将在FPGA中使用的逻辑功能以及获得初始性能估计非常有用。

  • 系统(hw)

内核代码被编译成硬件模型(RTL),然后在FPGA上实现,从而产生可以在实际FPGA上运行的二进制文件。

3.6 使用Vitis软件平台加速应用程序的方法论

3.6.1 文件受众和范围

本指南的目的是使系统设计师和软件开发人员熟悉以下内容:

  • 架构设备加速应用程序的方法

  • 开发C / C ++内核的方法

3.6.2 加速:工业类比

CPU,GPU和可编程设备之间存在明显差异。了解这些差异是有效开发每种设备的应用程序并实现最佳加速的关键。

CPU和GPU均具有预定义的体系结构,具有固定数量的内核,固定指令集和刚性内存体系结构。GPU通过内核数量和采用SIMD / SIMT并行性来扩展性能。相反,可编程设备是完全可定制的体系结构。开发人员创建针对应用程序需求进行了优化的计算单元。通过创建深度流水线化的数据路径来实现性能,而不是乘以计算单元的数量。

可以将CPU视为一组研讨会,每个研讨会都雇用一名非常熟练的工人。这些工人可以使用通用工具,使他们可以构建几乎所有东西。每个工人一次制作一件商品,先后使用不同的工具将原材料变成成品。此顺序转换过程可能需要许多步骤,具体取决于任务的性质。讲习班是独立的,工人都可以完成不同的任务,而不会分散注意力或出现协调问题。

GPU也有车间和工人,但其中有很多,工人也更专业。他们只能访问特定的工具,只能做更少的事情,但是他们做得非常有效。当GPU工人重复执行相同的几个任务,并且所有人都同时执行相同的事情时,它们的功能最佳。毕竟,在有这么多不同的工人的情况下,给他们所有相同的订单会更有效率。

可编程设备使这个车间类似于工业时代。如果CPU和GPU是一组单独的工人,并采取顺序步骤将输入转换为输出,则可编程设备是具有装配线和传送带的工厂。沿组装线分派的工人将原材料逐步转变为制成品。每个工人重复执行相同的任务,并且部分成品在传送带上从一个工人转移到另一个工人。这导致更高的生产吞吐量。

可编程设备的另一个主要区别是工厂和装配线不存在,这与CPU和GPU的车间和工人不同。为了完善我们的类比,可编程设备就像是一批待开发的空批。这意味着设备开发人员可以建立工厂,装配线和工作站,然后针对所需任务自定义它们,而不必使用通用工具。就像批量一样,设备的房地产也不是无限的,这限制了可以在设备中建立工厂的数量和规模。因此,正确设计和配置这些工厂是设备编程过程的关键部分。

传统的软件开发是关于在预定义的体系结构上进行编程的功能。可编程设备开发是关于对体系结构进行编程以实现所需功能。

3.6.3 设计设备加速应用程序的方法

在开始开发加速应用程序之前,正确地架构它很重要。在此阶段,开发人员将对应用程序的体系结构做出关键决策,并确定诸如应将哪些软件功能映射到设备内核,需要多少并行性以及如何交付并行化等因素。

  • 步骤1:建立基准应用程序性能并建立目标

  • 步骤2:确定要加速的功能

  • 步骤3:确定设备并行化需求

  • 步骤4:确定软件应用程序并行化需求

  • 步骤5:细化建筑细节

3.6.4 开发C / C ++内核的方法论

Vitis软件平台支持建模内核用C / C ++或RTL(的Verilog,VHDL,系统的Verilog)。本方法指南适用于C / C ++内核。有关开发RTL内核的详细信息,请参见RTL内核。

关于高级综合编译器

在开始内核开发过程之前,开发人员应该熟悉高级综合(HLS)概念。HLS编译器将C / C ++代码转换为RTL设计,然后将其映射到设备结构上。

HLS编译器比标准软件编译器更具限制性。例如,存在不支持的构造,包括:系统函数调用,动态内存分配和递归函数。有关更多信息,请参见《Vivado Design Suite用户指南:高级综合(UG902)》中的“不受支持的C构造” 。

更重要的是,请始终牢记C / C ++源代码的结构会对所生成的硬件实现的性能产生重大影响。该方法指南将帮助您构建代码,以满足应用程序吞吐量的目标。有关编程内核的特定信息,请参见C / C ++内核。

  • 步骤1:将代码划分为负载计算-存储模式

  • 步骤2:将计算块划分为较小的函数

  • 步骤3:确定需要优化的循环

  • 步骤4:改善循环延迟

  • 步骤5:提高环路吞吐量

END

后续会持续更新,带来Vivado、 ISE、Quartus II 、candence等安装相关设计教程,学习资源、项目资源、好文推荐等,希望大侠持续关注。

大侠们,江湖偌大,继续闯荡,愿一切安好,有缘再见!

往期精选 

 

【免费】FPGA工程师招聘平台

汇总篇 | FPGA零基础学习系列

FPGA零基础学习:SPI 协议驱动设计

FPGA设计中,对SPI进行参数化结构设计

精品 | FPGA时序分析专题课,欢迎购买!

开课通知 | FPGA就业班3月2日正式开课!

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/凡人多烦事01/article/detail/162953
推荐阅读
相关标签
  

闽ICP备14008679号