分割RAM和FIFO接口
三种数组分割的方法 进行数组分割的三种方法如下,
Block:可以进行设置Block的方式进行分割,该分组方式是顺序分割的。
Cycllc:可以进行设置Cycllc的方式进行分割,该分组方式是轮序分割的。
Register:设置为register发方式,循环将会展开成完全并行。指令的参数设置为complete
性能评估对比:Block、Cycllc的性能基本一致,而Register(complete)的方式是最佳的。
将设计中的d_o进行分割,设置分割类型为Block,在 Vivado HLS Directive Editor 对话框中,将因子设置为 4。点击OK完成设置。
也可以对d_i进行添加分割指令,设置分割类型为Block,在 Vivado HLS Directive Editor 对话框中,将因子设置为2。点击OK完成设置。
完成插入指令后进行C综合。接口列表如下:
性能报告:
经过优化设计后,整体的执行延时降低,接口根据分割指令增加了相应的个数。
修改进行全分割
新建解决方案,修改成分割指令为完全分割。
在 Directive 选项卡中,选择 d_i 上的 RESOURCE 指令,用鼠标右键单击并选择 Remove Directive。 如果数组被划分为单独的元素,则不能将其分配给块 RAM。
完成插入指令后进行C综合。接口列表如下:
性能报告:
对比资源和性能分析:
从该图中可以看出,对数组进行展开设计可以优化性能,在一定情况下可以优化资源的使用。
AXI接口设计
新建工程并添加文件
添加UG871提供的文件如下: 将axi_interfaces.c和axi_interfaces.h添加到source,函数和上个设计相同。
axi_interfaces.c
#include "axi_interfaces.h" // The data comes in organized in a single array. // - The first sample for the first channel (CHAN) // - Then the first sample for the 2nd channel etc. // The channels are accumulated independently // E.g. For 8 channels: // Array Order : 0 1 2 3 4 5 6 7 8 9 10 etc. 16 etc... // Sample Order: A0 B0 C0 D0 E0 F0 G0 H0 A1 B1 C2 etc. A2 etc... // Output Order: A0 B0 C0 D0 E0 F0 G0 H0 A0+A1 B0+B1 C0+C2 etc. A0+A1+A2 etc... void axi_interfaces (dout_t d_o[N], din_t d_i[N]) { int i, rem; // Store accumulated data static dacc_t acc[CHANNELS]; // Accumulate each channel For_Loop: for (i=0;i<N;i++) { rem=i%CHANNELS; acc[rem] = acc[rem] + d_i[i]; d_o[i] = acc[rem]; } }
axi_interfaces.h
#ifndef AXI_INTERFACES_H_ #define AXI_INTERFACES_H_ #include <stdio.h> typedef short din_t; typedef short dout_t; typedef int dacc_t; #define CHANNELS 8 #define SAMPLES 4 #define N CHANNELS * SAMPLES void axi_interfaces (dout_t d_o[N], din_t d_i[N]); #endif
使用 AXI4-Stream 接口创建优化设计
在本工程中,指定要实现为 AXI4-Stream 接口的数组参数。 如果阵列被划分为通道,您可以通过设计并行传输每个通道的样本。如果 I/O 端口被配置为提供和使用单独的通道数据流,部分展开 for 循环可以确保专用硬件处理每个通道。
首先进行数据通道展开,也就是使用数组分割进行优化输出,确保可以同时输出8个通道的数据。对d_o进行添加分割指令,设置分割类型为cyclic,在 Vivado HLS Directive Editor 对话框中,将因子设置为8。点击OK完成设置。
同时设置d_o的接口为axis类型的,也就是axi-stream流的接口。
同理对输入的d_i进行设置,设置完成后在指令辅助界面如下所示:
然后对循环进行优化处理,期望把循环进行展开8份,所以使用UNROLL进行展开,部分展开的系数设置为8。
然后为了进一步并行化,可以使用pipeline指令进行流水展开操作。并且勾选上rewind操作。
在未使用rewind操作时,每执行一次for循环中间会有一个时钟周期的延时,在使用了rewind操作后,执行完上一个循环后,下一个for循环直接进流水,而不需要等待一个时钟周期的延迟。
指令优化界面此时如下图所示:
因为使用AXI协议,所以在层级接口可以使用AXI-Lite接口进行对模块进行控制。在指令控制界面添加块级的接口,声明为s_axilite。
运行c综合后出现对应的AXI总线接口,
并会自动综合生成相关驱动文件,以方便调用。
reference
- UG871