微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > FPGA和CPLD > Vivado HLS推动协议处理系统蓬勃发展(上)

Vivado HLS推动协议处理系统蓬勃发展(上)

时间:10-30 来源:互联网 点击:
  1 提高抽象层次
  Vivado HLS能提高系统设计的抽象层次,为设计人员带来切实的帮助。Vivado HLS通过下面两种方法提高抽象层次:
  ● 使用C/C++作为编程语言,充分利用该语言中提供的高级结构;
  ● 提供更多数据原语,便于设计人员使用基础硬件构建块(位向量、队列等)。
  与使用RTL相比,这两大特性有助于设计人员使用Vivado HLS更轻松地解决常见的协议系统设计难题。最终简化系统汇编,简化FIFO和存储器访问,实现控制流程的抽象。HLS的另一大优势是便于架构研究和仿真。
  Vivado HLS把C++函数视为模块,函数定义等效于模块的RTL描述,函数调用等效于模块实例化。这种方法能减少需要用户编写的代码量,进而显著简化用于系统描述的结构代码,最终加速系统汇编进程。
  在Vivado HLS中,存储器或FIFO可通过两种方法访问。一种是通过合适的对象(比如对流对象的读写)。另一种是直接访问综合工具随后将实现为Block RAM或分布式RAM的标准C阵列。综合工具会根据需要处理额外的信令、同步或寻址问题。
  从控制流的角度,Vivado HLS从简单的FIFO接口到完整的AXI4-Stream均可提供整套流控制感知接口。使用这些接口,设计人员可直接访问数据,无需检查背压或数据可用性。Vivado HLS会适当地调度执行,应对一切紧急情况,同时确保正确完成执行。
  设计人员还会感激Vivado HLS提供的另一项功能,即简便的架构研究功能。用户只需在代码中插入程序指令(如使用GUI或批处理模式时的Tcl命令),就可以把设计所需特性传递给综合工具。这样用户可以在不修改设计代码本身的情况下研究大量备选架构方案。研究的范围可以是模块流水线化等根本性问题,也可以是FIFO队列深度等较常见的问题。
  最后,C和RTL仿真是Vivado HLS另一个大放异彩的地方。设计一般采用两步流程验证:第一步是C语言仿真。这个步骤中C/C++的编译和执行与常见的C/C++程序相同;第二步是C/RTL协仿真。在这步骤中,Vivado HLS会根据C/C++测试平台自动生成RTL测试平台,然后设置并执行RTL仿真,检查实现方案8的正确性。
  如能充分发挥这些优势,这将对于用户的系统设计大有裨益。这不仅体现在开发时间和生产力上,还由于Vivado HLS代码更加紧凑的特点,体现在代码可维护性和可读性上。此外通过高层次综合,用户仍能有效控制架构及其特性。正确理解和使用Vivado HLS程序对实现这一控制起着根本作用。
  高层次综合在赛灵思提供的包处理解决方案的层级结构中起着承上启下、承前启后的作用。而Vivado SDNet和RTL则对其起到补充作用。Vivado SDnet使用特定领域语言,提供一种大为简便但相当受限的协议处理系统表达方法。RTL则可以用于Vivado HLS无法表达的大量系统的实现工作(例如使用DCM或差分信号并需要详细时钟管理的各类系统)。虽然有种种局限,Vivado HLS仍然是在保证结果质量或设计人员灵活性的前提下设计大部分协议处理解决方案的有效途径。
  2 设置简单系统
  开始新设计时需要完成的最基本工作首先是确定设计的结构,然后将其实现在Vivado HLS中。Vivado HLS中的基本系统构建块是C/C++函数。构建一个由模块和子模块组成的系统意味着需要用一个顶层函数来调用底层函数。图1所示的是一个极为简单的三级流水线,我们以此为例来介绍Vivado HLS中系统构建的基本思路。一般采用流水线化设计执行协议处理,由每一级负责解决处理的特定部分。
  如图1所示。


  构建一个由模块和子模块组成的系统意味着需要用一个顶层函数来调用底层函数。
  例1:在Vivado HLS中创建简单系统
  1 void topLevelModule(stream&inData,
  stream&outData) {
  2 #pragma HLS dataflow interval=1
  3
                               
                  4 #pragma INTERFACE axis port=inData
  5 #pragma INTERFACE axis port=outData
  6
  7 static stream> modOne2modTwo;
  8 static stream> modTwo2modThree;
  9
  10 moduleOne(inData, modOne2modTwo);
  11 moduleTwo(modOne2modTwo, modTwo2modThree);
  12 moduleThree(modTwo2modThree, outData);
  13 }
  例1中的代码用于创建顶层模块函数,供调用所有其它子函数使用。顶层模块函数使用两个参数,均属于“流”(stream)类(Vivado HLS库中提供的模块类之一)。流是一种HLS建模架构,代表准备以流方式交换的数据通过的接口。流可以实现为FIFO队列或内存,也可以是一种能够配合任何C++架构使用的模板类。在本例中,我们定义了一种称为axiWord的数据结构(Struct),如例2所示。


  例2:定义流接口使用的C++ 结构
  struct axiWord {
  ap_uint data;
  ap_uint strb;
  ap_uint last;
  };
  该struct用于定义AXI4-Stream接口的部分字段。Vivado HLS能自动支持此类接口,使用编译指令(pragma)语句即可完成设定。编译指令是对高层次综合工具的指令,用于指导工具实现要求的结果。例1中第4行和第5行的编译指令用于告知Vivado HLS这两个指令(具体是顶层模块的输入和输出端口)将使用AXI4-Stream接口。AXI4-Stream I/F包含两个必备信号,分别是有效信号和就绪信号,但它们没有包含在声明的数据结构中。这是由于Vivado HLS AX4 I/F会在内部处理这些信号,也就是说它们对用户逻辑而言是透明的。如前文所述,在使用AXI4-Stream I/F时,从用户处抽象流控制完全由Vivado HLS完成。
  当然未必一定使用AXI4-Stream接口。Vivado HLS提供有丰富的总线接口。这里选择AXI4-Stream作为常见标准接口的示例,供用户进行包处理。
  实现我们的设计的下一项工作是确保我们的三个模块彼此互联。这项工作也通过流完成,不过这次它们是位于顶层模块的内部。第7行和第8行用于声明实现这一目标的两个流。这两个流使用了另一种Vivado HLS结构ap_uint。这是一种无符号一维位阵列,随后将按此对其操作。同时这也是又一种模板类,因此必须设定这个阵列的宽度。在本例中使用64位,与顶层模块输入输出I/F的数据成员宽带匹配。还有一点需要详细说明的是这些流全部声明为静态变量。静态变量是指其值不随函数调用变化的一种变量。由于在作为顺序C/C++程序执行时顶层模块(以及全部的子模块)每个时钟周期会被调用一次,所以任何需要保持其值不随时钟周期变化的变量都需要声明为静态变量。
  

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top