建网站多少钱一平方,订阅号怎么做免费的视频网站吗,模具编程入门先学什么,宁波网站建设公司立找亿企邦使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据 该项目介绍了如何在 PL 中的 HDL 与 FPGA 中的处理器上运行的嵌入式 C 之间传输数据的基本结构。 介绍 鉴于机器学习和人工智能等应用的 FPGA 设计中硬件加速的兴起#xff0c;现在是剥开几层“云雾”并讨论 HDL 之间来回传… 使用 DMA 在 FPGA 中的 HDL 和嵌入式 C 之间传输数据 该项目介绍了如何在 PL 中的 HDL 与 FPGA 中的处理器上运行的嵌入式 C 之间传输数据的基本结构。 介绍 鉴于机器学习和人工智能等应用的 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 事务实现中发现了很多小“陷阱”因此不得不将数据处理重点留给另一个项目。 使用 AXI DMA 控制 PL 中的 HDL 与 PS 中的 C 代码之间的数据传输有两个主要层 Memory Map to Stream (MM2S) 和 Stream to Memory Map (S2MM) 通道上 PL 的 HDL 代码中的 AXI 流握手信号DMA 的控制通道是使用普通 AXI 写入的但这就是全部由 Vivado 自动处理因此在这里只关注 AXI stream接口。 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 信号之前认为交换已结束因为计数已关闭。 我用 Verilog 编写了一个简单的状态机它实现了一个从 AXI stream接口来从 DMA 的 MM2S 通道接收数据通过寄存器传递stream中的每个数据包然后实现一个主 AXI strean接口来将数据流发回到S2MM通道。来自 tdata 总线的数据通过的寄存器旨在充当占位符用于为硬件加速进行任何自定义数据处理。 从 Vivado 中的 ILA 中截取了一张屏幕截图显示使用状态机实现的时序图。顶部是 MM2S 侧底部是 S2MM 侧。 这是 Verilog 状态机的流程图实际文件附在本文末尾。值得注意的是流程图中的主/从接口是从 Verilog 状态机的角度来看的。 对于 DMA IP 的具体设置因为在直接寄存器模式下使用 DMA所以未选中分散收集选项。然后将其他所有设置保留为默认设置并选中允许未对齐传输的选项我发现在将自定义 AXI 流接口写入 DMA 时这给了更多的自由空间。 为了将 Verilog 状态机添加到模块设计中我右键单击模块设计的空白区域然后选择“添加模块...”选项该选项将显示 Vivado 可以在设计源中找到的所有有效 Verilog 模块在BD中使用的文件。 值得注意的是信号命名约定分别遵循从接口和主接口的“s_axis”和“m_axis”标准。 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