ZYNQ之路--HLS入门实例

        上一节我们介绍了如何建立一个HLS工程以及HLS的工程结构,这一节我们着眼于HLS的优化部分,通过Xilinx官方提供的小示例来宏观了解HLS的优化操作。

建立新的Solution(解决方案)

        我们知道,HLS一个工程只能有一个TopFunction,但是却可以有多种硬件实现方式(Solution),为了和不做任何优化的工程进行对比,我们首先新建一个Solution。

        

        我们可以选择是否复制某个Solution的约束。

         点击确认后,新的Solution就创建好了。

Step 1 :I/O接口优化

        正如咱们写Verilog代码需要先声明module的各个接口一样,因为设计规范包括I/O协议,所以执行的第一个优化是创建正确的I/O协议和端口,这一步越早越好

        我们可以查看综合报告的内容来查看我们模块的端口:

         我们的要求是:

  • 端口C必须是一个单口RAM
  • 端口X必须是一个带有有效信号的输入端口
  • 端口Y必须一样一个带有有效信号的输出端口
        我们可以从综合报告中看到,端口C已经是一个单端口的RAM。但是,如果不指定RAM访问类型,那么High-Level Synthesis可能使用双端口RAM接口。原因是这样做可能可以创建具有更高吞吐量的设计。
        如果我们需要一个单端口的RAM,则应该主动地在设计中添加使用单端口RAM的I/O协议指示。
  1. 确保Solution2处于激活状态
  2. 在右边栏的Directive中找到变量C,右击选择Insert Directive
  3. Directive的类型选择RESOURCE
  4. 找到RAM_1PBRAM,点击OK
        

         在第二步当中,Destination选项可以选择这条优化的指令是写入C文件还是单独的优化指示文件中。因为I/O协议不太可能更改,所以我们可以将这些优化指令作为pragmas添加到源代码中,以确保在设计中嵌入了正确的I/O协议。

        我们可以看到,源文件中出现了下面这个指示:

#pragma HLS RESOURCE variable=c core=RAM_1P_BRAM

         本着记录积累的原则,我们现在笔记下我们第一个约束类型:RESOURCE(资源)

        RESOURCE指令用于指定特定的库资源(核心),用于实现变量(数组、算术)操作或函数参数)。例如,要指定库中的哪个内存元素用于实现数组,可以使用资源编译指示。

         我们在本例子中,指定了变量C实现所使用的RAM类型。因为数组c在函数参数列表中,所以在函数外部,因此我们创建一个数据端口来访问函数外部的单端口块RAM的RTL实现。

        同样的步骤,大家可以尝试将X的接口变成带有valid信号的输入端口(Derivative类型为Interface,选择ap_vld)

#pragma HLS RESOURCE variable=c core=RAM_1P_BRAM

 (修改后的接口报告)

Step 2 :理解代码(通过 Analysis perspective 窗口)

        正所谓“粮草未动,兵马先行”,我们优化未开始,先进行一波分析理解代码是很有必要的!

        在之前的文章中展示了如何查看综合报告,然而,Analysis窗口以交互的方式提供更详细的信息,通过这个窗口我们能更加深入地理解算法的实现,这对我们后期的优化十分重要。

        如果说优化是在解一个问题,那么分析就是在仔细阅读我们的题干。

我们点开分析视图:

         展现在我们面前的窗口如下图所示:

         我们首先要理解一下,Analysis Perspective的核心理念:资源调度

         我个人理解,其实实现一个功能无非就是干两件事:把数据取出来,然后处理一下,再存回去。

        因此流程窗口分为了两个:任务调度的视角 与 资源使用的视角;通过左下角的选项卡进行切换。

        那流程窗口是怎么看的呢?

        左边是具体的任务,右边看则类似一个状态机,一共有六个状态。我们可以清晰地看到我们的循环是怎么样被组织的,点击任务条,可以跳转到相应的代码,这使得我们可以更好地理解代码的执行过程。

        下图是用资源的视角来分析代码的执行流程:

Step 3 :代码优化

        代码优化其实就是用资源换速度,在本例中,核心的计算是一个for循环,因此主要影响设计吞吐量的两个因素分别是:

  1. for循环。默认情况下for语句是循环往复执行的,循环体的核心语句被综合成一个模块,并在每次迭代中重用。这确保了循环的每次迭代都是按顺序执行的。所以我们可以展开for循环让所有操作并行执行。
  2. BRAM。因为变量shift_reg在C源代码中是一个数组,它在默认情况下被实现为BRAM。然而,它的实际功能是一个移位寄存器。因此,我们可以将这个BRAM分割为单独的寄存器,以提升吞吐量。

        这两段话是根据UG871进行翻译的,我个人的理解其实很简单:

首先是for循环的问题,for循环总是执行完一次之后,再执行第二次。如果我要把某个数组的数据都加1或者干其它什么事情,其实我可以把for循环拆开来,第二个元素+1和第一个元素+1同时进行,这就是所谓for循环的并行,使用Unroll命令执行:

其次是BRAM的问题,其实也很好理解,本例中有个关键的代码如下:

         shift_reg[i]的值等于shift_reg[i-1],并且还需要把shift_reg[i]的值赋给data,这里由于默认综合的shift_reg只有一个BRAM存储,因此首先需要读取 shift_reg[i-1],然后再写入shift_reg[i],然后再读取shift_reg[i],再赋值给data;如果我们把shift_reg分割成两个数组,例如一个存储1,3,5的数据,一个存储2,4,6的数据,那么我们就可以同时对shift_reg[i]和shift_reg[i-1]进行操作,使用array_partition 命令执行

        这两个命令的详细内容我想写一期新的博客进行记录。

Step 5 :比较和总结

按照如下步骤进行操作:

         我们可以清晰地看到各个不同的解决方案之间的比较:

        本节到此结束。

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: UG585-Zynq-7000-TRM是一份关于Xilinx Zynq-7000 SoC处理器的技术参考手册。Zynq-7000 SoC处理器是一款配备ARM Cortex-A9双核处理器和Xilinx可编程逻辑部分(PL)的可扩展平台,旨在为嵌入式系统开发者提供卓越的灵活性和可编程性。 TRM代表Technical Reference Manual(技术参考手册),其中包含了该处理器的体系结构和功能特性的详细描述,包括处理器内部的各种模块、外设、总线结构等等。该手册的主要目的是为开发者提供全面的指导和支持,从而加速其系统设计和开发应用,减少错误和风险。 UG585-Zynq-7000-TRM手册的内容包括Zynq-7000的基本特征、处理器硬件和软件架构、可编程逻辑PL和PS之间的通信、外设接口和寄存器映射、中断控制等内容。开发者可以根据手册中的详细说明,了解Zynq-7000的构成和功能,从而基于此设计和实现自己的应用。 总之,UG585-Zynq-7000-TRM手册是一份非常重要的技术参考资料,为开发者提供全面的指导和支持,促进了Zynq-7000处理器的应用和拓展,也为未来的嵌入式系统设计提供了参考和借鉴。 ### 回答2: UG585是Xilinx公司发布的Zynq-7000系列技术手册,全称为“Zynq-7000 All Programmable SoC Technical Reference Manual”。Zynq-7000系列是Xilinx公司推出的一款功能强大的FPGA芯片,集成了双核ARM Cortex-A9处理器和可编程逻辑资源,支持高性能中间件、操作系统和外围设备的支持。该手册详细介绍了Zynq-7000系列SoC的架构、功能、性能、测试和验证、软件和硬件开发等方面的知识。他对于学习、使用和开发Zynq-7000 SoC具有非常重要的意义,使得开发人员能够深入了解这个芯片的细节,掌握它的特性和功能,以便更加高效地使用它进行开发。如果你想要学习和使用Zynq-7000 SoC,UG585是一个非常重要的参考文献,值得认真阅读和研究。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值