当前位置: 首页 > news >正文

使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据

使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据

该项目介绍了如何在 PL 中的 HDL 与 FPGA 中的处理器上运行的嵌入式 C 之间传输数据的基本结构。

5540615d780a6be98c2a0d4d010d144c.png

介绍

鉴于机器学习和人工智能等应用的 FPGA 设计中硬件加速的兴起,现在是剥开几层“云雾”并讨论 HDL 之间来回传递数据(主要指FPGA 的可编程逻辑 (PL) 中运行的代码以及 FPGA 中的硬核或软核处理器上运行的相应软件之间传输数据)的基础知识的好时机。

硬件加速可以总结为在硬件(也称为 FPGA 的可编程逻辑)中实现某些功能的基本思想,这些功能之前在位于主机 PC 上或在 FPGA 上处理器(软核或者硬核)运行的软件。因此,要成为一名高效的设计人员,就必须掌握如何在硬件和软件之间来回传递数据的技巧。

在本例中,使用的是 Zynq SoC(片上系统)FPGA,它具有硬核 ARM 处理器。该 ARM 核心和外设称为处理系统或 PS。

虽然有几种不同的方法可以完成 PL 和 PS 之间的数据传输,包括编写自己的自定义接口,但我认为最常见的机制是通过直接内存访问 (DMA) 传输。这是因为 DMA 允许 ARM 内核的 CPU 简单地启动自身与 DDR 之间的数据传输,而 CPU 无需等待传输完成后再执行任何其他任务。DMA 还允许 CPU 启动外部设备和 DDR 之间的传输。

在此项目中,将通过使用 Xilinx DMA IP 演示 DMA 的功能,该IP可通过 AXIS 总线将内存映射接口转换为stream接口。将 32 字节写入嵌入式 C 中的内存,然后通过内存映射将其传输到 PL 到流 (MM2S) AXIS,通过寄存器处理每个值,然后通过流将数据传输回内存DMA IP 的内存映射 (S2MM) 端口。

虽然这个示例对于重型硬件加速应用来说过于简单,但当刚接触 FPGA 时,这种高速数据传输水平可能会变得非常复杂/难以学习。该项目重点介绍 DMA 的使用及其行为。虽然打算让这个项目更多地关注数据处理方面,但在 DMA 事务实现中发现了很多小“陷阱”,因此不得不将数据处理重点留给另一个项目。

ab42ca76acef9933f41cd2b7127ed97c.png

使用 AXI DMA 控制 PL 中的 HDL 与 PS 中的 C 代码之间的数据传输有两个主要层:

  1. Memory Map to Stream (MM2S) 和 Stream to Memory Map (S2MM) 通道上 PL 的 HDL 代码中的 AXI 流握手信号(DMA 的控制通道是使用普通 AXI 写入的,但这就是全部由 Vivado 自动处理,因此在这里只关注 AXI stream接口)。

  1. PS 的 C 代码中寄存器读/写 DMA 的顺序。

Verilog 中的 AXI-Stream握手

AXI stream接口使用一组简单的握手信号机制,用于嵌入式设计中的数据交换。AXI stream接口中有许多可选信号,但与 DMA MM2S 和 S2MM 数据交换相关且必需的信号是 tdata、tvalid、tready、tlast 和 tkeep。AXI stream中发送数据为主接口,接收数据为从接口。

  • tdata:数据总线

  • tvalid:当放置在 tdata 总线上的数据有效时,由主接口置位

  • tredy:当从机处于准备接收 tdata 总线上的数据的状态时,由从机置位

  • tlast:由主设备在 tdata 总线上流中最后一个数据包的持续时间内断言,以告诉从设备该数据包之后不会有数据

  • tkeep:由主设备设置的 tdata 总线上数据包的二次验证,指示数据包是否是流的一部分

AXI DMA IP 究竟如何实现此握手接口将数据传输出内存 (MM2S) 并传输到内存 (S2MM),这一点非常变化无常,尤其是在 S2MM 方面……

然而,我们首先需要了解的是有关 AXI DMA 的 S2MM 事务的信息,大部分可以总结为一句话:必须设置 S2MM 事务,并且在尝试向 DMA 发送任何数据之前,以适当的顺序写入 DMA 中的适当控制寄存器来启动事务,一旦 S2MM 通道看到 tlast 信号,它就会停止事务。

数据传输发生在每个时钟周期的 S2MM 和 MM2S 事务中的 tdata 总线上,其中tready 和 tvalid 均被置位(true)。因此,当负责断言 tvalid 时,在 AXI 接口的主端必须小心,当从从机传入的 trety 信号也为 tvalid 断言时,不要让 tvalid 断言超过一个时钟周期。否则,从设备将在同一个数据包计时两次,作为两个单独的数据包。并且因为必须在控制寄存器中指定传输中有多少字节,所以 DMA 通道(在本例中为 S2MM)会在看到提供 tlast 信号之前认为交换已结束,因为计数已关闭。

e926ad6384b27b6047a8dbb3ca212257.png

我用 Verilog 编写了一个简单的状态机,它实现了一个从 AXI stream接口来从 DMA 的 MM2S 通道接收数据,通过寄存器传递stream中的每个数据包,然后实现一个主 AXI strean接口来将数据流发回到S2MM通道。来自 tdata 总线的数据通过的寄存器旨在充当占位符,用于为硬件加速进行任何自定义数据处理。

从 Vivado 中的 ILA 中截取了一张屏幕截图,显示使用状态机实现的时序图。顶部是 MM2S 侧,底部是 S2MM 侧。

这是 Verilog 状态机的流程图,实际文件附在本文末尾。值得注意的是,流程图中的主/从接口是从 Verilog 状态机的角度来看的。

cebdd373e39521ca0d450dfa57e399e5.png

对于 DMA IP 的具体设置,因为在直接寄存器模式下使用 DMA,所以未选中分散收集选项。然后,将其他所有设置保留为默认设置,并选中允许未对齐传输的选项,我发现在将自定义 AXI 流接口写入 DMA 时,这给了更多的自由空间。

e6cd904fd8ecf88edd4db0e653f66e96.png

为了将 Verilog 状态机添加到模块设计中,我右键单击模块设计的空白区域,然后选择“添加模块...”选项,该选项将显示 Vivado 可以在设计源中找到的所有有效 Verilog 模块在BD中使用的文件。

47237336e4bf0ee851130d79b7e11044.png

值得注意的是,信号命名约定分别遵循从接口和主接口的“s_axis”和“m_axis”标准。

46d8423991437933c2f6a698a8db4daf.png

DMA 寄存器读/写控制序列

以下是裸机使用 DMA 时更简单的顺序:

  • 1.通过将 1 写入 MM2S(偏移量 0x00)和 S2MM(偏移量 0x30)控制寄存器的位 2 来复位 DMA。

  • 2.将 S2MM 通道要写入数据的 DDR 中位置的目标地址写入 S2MM DMA 目标地址寄存器(偏移量 0x48)。

  • 3.通过将 1 写入 S2MM 控制寄存器(偏移量 0x30)的位 0 来启动 DMA S2MM 通道。

  • 4.通过将 S2MM 通道上要读入内存的总字节数值写入 S2MM 缓冲区长度寄存器(偏移量 0x58),写入 S2MM 通道缓冲区的长度。这将启动 S2MM 传输,以便 DMA 准备好从 FPGA 逻辑中的设备接收数据流(直到实际馈送数据并且 AXI 流总线上的 tvalid 由 FPGA 逻辑中的设备断言后,该过程才会真正启动)逻辑)。

  • 5.将 MM2S 通道要读取的数据的 DDR 中的源地址写入 MM2S DMA 源地址寄存器(偏移量 0x18)。

  • 6.通过将 1 写入 MM2S 控制寄存器的位 0(偏移量 0x00)来启动 DMA MM2S 通道。

  • 7.通过将要发送的总字节数值写入 MM2S 传输长度寄存器(偏移量 0x28),写入 MM2S 通道的传输长度。这将启动从 DMA 到 FPGA 逻辑中的接收设备的 MM2S 传输。

还记得之前提到过,在 PL 中的设备尝试向 S2MM 通道发送数据之前,必须启动并运行 S2MM 通道吗?嗯,这就是为什么要按顺序执行上述步骤。步骤 2 - 4 配置并启动 S2MM 通道,步骤 5 - 7 配置并启动 MM2S 通道。

在步骤 4 和 5 之间发生一些其他进程是可以的,但步骤 2 - 4 必须在步骤 5 - 7 之前发生。执行步骤 4 后,S2MM AXI 流通道将断言其 Tready 信号,此时 HDL 代码可以开始向其发送数据。

这也解释了当我第一次开始使用 DMA 时,在 SDK/Vitis 中的示例 DMA 项目中注意到的一些事情。总是认为示例代码似乎是在使用 MM2S - XAXIDMA_DMA_TO_DEVICE 传输从 DDR 中写入任何内容之前尝试将数据拉入 DDR(通过首先执行 S2MM - XAXIDMA_DEVICE_TO_DMA 传输)。然而,S2MM 通道必须准备好并等待接收数据才能正常工作并且不会锁定。

在 FPGA 设计中,DMA 似乎是一种棘手的入门方法,但一旦你弄清楚它就会非常有帮助。

代码

https://github.com/suisuisi/FPGATechnologyGroup/tree/main/AXIS-DMA

相关文章:

使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据

使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据 该项目介绍了如何在 PL 中的 HDL 与 FPGA 中的处理器上运行的嵌入式 C 之间传输数据的基本结构。 介绍 鉴于机器学习和人工智能等应用的 FPGA 设计中硬件加速的兴起,现在是剥开几层“云雾”并讨论 HDL 之间来回传…...

uniapp地图基本使用及解决添加markers不生效问题?

uniapp地图使用 App端 通过 nvue 页面实现地图 文章目录 uniapp地图使用效果图templatejs添加 marker使用地图查看位置移到到当前位置 效果图 template <template><view class"mapWrap"><!-- #ifdef APP-NVUE --><map class"map-containe…...

使用系统ProgressBar实现三色进度条

使用系统ProgressBar实现如图三色进度条&#xff1a; //布局中<ProgressBarandroid:layout_width"0dp"android:layout_height"8dp"android:layout_marginLeft"16dp"app:layout_constraintBottom_toBottomOf"id/photo"app:layout_c…...

Vue3中的组合式API的详细教程和介绍

文章目录 前言介绍组合式 API 基础setup 组件选项 带 ref 的响应式变量生命周期钩子注册内部 setupwatch 响应式更改独立的 computed 属性后言 前言 hello world欢迎来到前端的新世界 &#x1f61c;当前文章系列专栏&#xff1a;vue.js &#x1f431;‍&#x1f453;博主在前端…...

Java后端开发——JDBC(万字详解)

Java后端开发——JDBC&#xff08;万字详解&#xff09; 今日目标 掌握JDBC的的CRUD理解JDBC中各个对象的作用掌握Druid的使用 1&#xff0c;JDBC概述 在开发中我们使用的是java语言&#xff0c;那么势必要通过java语言操作数据库中的数据。这就是接下来要学习的JDBC。 1.1 …...

python etree.HTML 以及xpath 解析网页的工具

文章目录 导入模块相关语法实战 导入模块 from lxml import etree相关语法 XPath&#xff08;XML Path Language&#xff09;是一种用于在XML文档中定位和选择元素的语言。XPath的主要应用领域是在XML文档中进行导航和查询&#xff0c;通常用于在XML中选择节点或节点集合。以…...

电机伺服驱动学习笔记(7)待编辑

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、pandas是什么&#xff1f;二、使用步骤1.引入库2.读入数据 总结 前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a; 例如&#xff1a;…...

【云备份】业务处理

文章目录 1. 业务处理作用功能 2. 代码框架编写构造函数UpLoad ——文件上传请求ListShow —— 展示页面请求处理实现Download —— 下载请求的处理实现断点续传实现 1. 业务处理 作用 业务处理模块是对客户端的业务请求进行处理 功能 1.文件上传请求&#xff1a;备份客户端…...

JVM GC算法

一, 垃圾回收分类: 按线程数分&#xff0c;可以分为串行垃圾回收器和并行垃圾回收器。 按工作模式分&#xff0c;可以分为并发垃圾回收器和独占式垃圾回收器 按碎片处理方式分&#xff0c;可以分为压缩式垃圾回收器和非压缩式垃圾回收器按工作的内存区间分&#xff0c;又可分为…...

对Spring框架的一些总结

对Spring框架的一些总结 在文章开头我真心推荐大家一个优秀的编程老师&#xff1a;孙帅老师(孙哥suns)&#xff0c;孙帅老师在哔哩哔哩的Spring5教学视频时长接近33个小时&#xff0c;从0基础到一步一步手把手的教你抽丝剥茧分析Spring框架的所有知识&#xff0c;孙帅老师的教…...

C# WPF上位机开发(第一个应用)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 万事开头难&#xff0c;很多事情都是难在第一步。走出了这第一步&#xff0c;回过头看以前走的每一步&#xff0c;发现其实也不难。用c# wpf编写界…...

有点迷糊class和初始化参数的用法了

翻阅手册https://www.runoob.com/python3/python3-class.html Python从设计之初就已经是一门面向对象的语言&#xff0c;正因为如此&#xff0c;在Python中创建一个类和对象是很容易的。本章节我们将详细介绍Python的面向对象编程。 如果你以前没有接触过面向对象的编程语言&…...

如何选择一款安全稳定的跨境浏览器?

选择适合自己的跨境浏览器是进行跨境电商和跨境交流的关键一步。本文将为您介绍如何客观地选择一款安全稳定的跨境浏览器&#xff0c;以便更好地进行跨境业务。 在选择跨境浏览器时&#xff0c;以下几个因素是需要考虑的&#xff1a; 网络速度&#xff1a;跨境业务需要稳定而高…...

SQL Server 数据库,使用函数查询统计信息

4.1 在查询中使用函数 在前面章节已经学习了一些简单的增、删、改、查询的T-SOL.语句&#xff0c;但是为了更方便快捷地完 成大量的任务&#xff0c;SOLServer提供了一些内部函数&#xff0c;可以和SOLServer的SELECT语句联合使用&#xff0c;也可 以与UPDATE和INSERT一起使用&…...

mysql区分大小写吗

mysql在windows下默认是不区分大小写的&#xff0c;在linux下默认是区分大小写的。 所以&#xff0c;为了避免出问题&#xff0c;许多公司的数据库编程规范中明确规定&#xff1a;库名、表名、列名、索引名一律小写&#xff0c;不同单词之间以下划线分割&#xff0c;且控制在3…...

HarmonyOS 开发案例分享:万能卡片也能用来玩游戏

一、前言 作为一名开发爱好者&#xff0c;从大了讲&#xff0c;我学习并进行 HarmonyOS 相关开发是为了能为鸿蒙生态建设尽一份绵薄之力&#xff0c;从小了讲&#xff0c;就是为了自己的兴趣。而万能卡片是一个让我非常感兴趣的东西。 很多时候我跟别人解释什么是万能卡片&…...

Could NOT find resource [logback-test.xml]

修改 之后就可以正常启动了...

11.28 C++作业

提示并输入一个字符串&#xff0c;统计该字符中大写、小写字母个数、数字个数、空格个数以及其他字符个数 要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {string str;cout << "请输入一个字符串&#xff1a;" <<…...

126. 单词接龙 II

126. 单词接龙 II 需要注意的是&#xff0c;由于要找最短路径&#xff0c;连接 dot 与 lot 之间的边就不可以被记录下来&#xff0c;同理连接 dog 与 log 之间的边也不可以被记录。这是因为经过它们的边一定不会是最短路径。因此在广度优先遍历的时候&#xff0c;需要记录的图…...

SpringBoot+SSM项目实战 苍穹外卖(2)

继续上一节的内容&#xff0c;本节完成新增员工、员工分页查询、启用禁用员工账号、编辑员工、导入分类模块功能代码。 目录 新增员工(完整流程分为以下五个部分)需求分析和设计代码开发功能测试代码完善 (ThreadLocal 线程局部变量)代码提交 员工分页查询代码完善 扩展Spring …...

golang循环变量捕获问题​​

在 Go 语言中&#xff0c;当在循环中启动协程&#xff08;goroutine&#xff09;时&#xff0c;如果在协程闭包中直接引用循环变量&#xff0c;可能会遇到一个常见的陷阱 - ​​循环变量捕获问题​​。让我详细解释一下&#xff1a; 问题背景 看这个代码片段&#xff1a; fo…...

【解密LSTM、GRU如何解决传统RNN梯度消失问题】

解密LSTM与GRU&#xff1a;如何让RNN变得更聪明&#xff1f; 在深度学习的世界里&#xff0c;循环神经网络&#xff08;RNN&#xff09;以其卓越的序列数据处理能力广泛应用于自然语言处理、时间序列预测等领域。然而&#xff0c;传统RNN存在的一个严重问题——梯度消失&#…...

Element Plus 表单(el-form)中关于正整数输入的校验规则

目录 1 单个正整数输入1.1 模板1.2 校验规则 2 两个正整数输入&#xff08;联动&#xff09;2.1 模板2.2 校验规则2.3 CSS 1 单个正整数输入 1.1 模板 <el-formref"formRef":model"formData":rules"formRules"label-width"150px"…...

大语言模型(LLM)中的KV缓存压缩与动态稀疏注意力机制设计

随着大语言模型&#xff08;LLM&#xff09;参数规模的增长&#xff0c;推理阶段的内存占用和计算复杂度成为核心挑战。传统注意力机制的计算复杂度随序列长度呈二次方增长&#xff0c;而KV缓存的内存消耗可能高达数十GB&#xff08;例如Llama2-7B处理100K token时需50GB内存&a…...

AI,如何重构理解、匹配与决策?

AI 时代&#xff0c;我们如何理解消费&#xff1f; 作者&#xff5c;王彬 封面&#xff5c;Unplash 人们通过信息理解世界。 曾几何时&#xff0c;PC 与移动互联网重塑了人们的购物路径&#xff1a;信息变得唾手可得&#xff0c;商品决策变得高度依赖内容。 但 AI 时代的来…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)

RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发&#xff0c;后来由Pivotal Software Inc.&#xff08;现为VMware子公司&#xff09;接管。RabbitMQ 是一个开源的消息代理和队列服务器&#xff0c;用 Erlang 语言编写。广泛应用于各种分布…...

Proxmox Mail Gateway安装指南:从零开始配置高效邮件过滤系统

&#x1f49d;&#x1f49d;&#x1f49d;欢迎莅临我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐&#xff1a;「storms…...

[论文阅读]TrustRAG: Enhancing Robustness and Trustworthiness in RAG

TrustRAG: Enhancing Robustness and Trustworthiness in RAG [2501.00879] TrustRAG: Enhancing Robustness and Trustworthiness in Retrieval-Augmented Generation 代码&#xff1a;HuichiZhou/TrustRAG: Code for "TrustRAG: Enhancing Robustness and Trustworthin…...

C++实现分布式网络通信框架RPC(2)——rpc发布端

有了上篇文章的项目的基本知识的了解&#xff0c;现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...

DAY 26 函数专题1

函数定义与参数知识点回顾&#xff1a;1. 函数的定义2. 变量作用域&#xff1a;局部变量和全局变量3. 函数的参数类型&#xff1a;位置参数、默认参数、不定参数4. 传递参数的手段&#xff1a;关键词参数5 题目1&#xff1a;计算圆的面积 任务&#xff1a; 编写一…...