Vivado HLS推动协议处理系统蓬勃发展(下)
接上篇
本文引用地址:https://www.eepw.com.cn/article/273295.htm4 设置简单系统
协议处理一般情况下属于状态事务。必须先顺序读取在多个时钟周期内进入总线的数据包字,然后根据数据包的某些字段决定进一步操作。通常应对这种处理的方法是使用状态机,对数据包进行迭代运算,完成必要的处理。例3是一种简单的状态机,用于根据上一级的输入丢弃或转发数据包。该函数接收三个参数:一个是通过“inData”流接收到的输入分组数据;一个是通过“validBuffer”流显示数据包是否有效的1位旗标;第三个是称为“outData”的输出分组数据流。注意Vivado HLS函数中的参数是按引用传递的。这在使用较为复杂的Vivado HLS流的时候是必要的。ap_uint等较为简单的数据类型则可按值传递。
第2行中的流水线编译指令指示Vivado HLS将该函数流水线化,让初始化间隔为1(II=1),即每个时钟周期处理一个新的输入数据字。Vivado HLS负责核验设计,并确定需要在设计中引入多少个流水线级来满足调度限制要求。
例3:使用Vivado HLS的有限状态机
1 void dropper(stream& inData,
stream>& validBuffer,
stream& outData) {
2 #pragma HLS pipeline II=1 enable_flush
3
4 static enum dState {D_IDLE = 0, D_STREAM, D_
DROP} dropState;
5 axiWord currWord = {0, 0, 0, 0};
6
7 switch(dropState) {
8 case D_IDLE:
9 if (!validBuffer.empty() && !inData.empty()) {
10 ap_uint<1> valid = validBuffer.read();
11 inData.read(currWord);
12 if (valid) {
13 outData.write(currWord);
14 dropState = D_STREAM;
15 }
16 }
17 else
18 dropState = D_DROP;
19 break;
20 case D_STREAM:
21 if (!inData.empty()) {
22 inData.read(currWord);
23 outData.write(currWord);
24 if (currWord.last)
25 dropState = D_IDLE;
26 }
27 break;
28 case D_DROP:
29 if (!inData.empty()) {
30 inData.read(currWord);
31 if (currWord.last)
32 dropState = D_IDLE;
33 }
34 break;
35 }
36 }
第4行用于声明一个静态枚举变量,用于表达该FSM中的状态。使用枚举与否可以选择,不过能让代码更容易阅读,因为可以给状态适当地命名。不过使用任何整数或ap_unit变量也能得到与之类似的结果。第5行用于声明一个“axiWord”类型的变量,用于存储准备从输入中读取的分组数据。
第7行中的开关语句用于表达实际的状态机。建议使用开关,但非强制要求。使用if-else决策树也能执行同样的功能。开关语句能够让Vivado HLS工具更高效地枚举所有状态,并优化得到的状态机RTL代码。
执行从D_IDLE状态开始,此时FSM从第10行和第11行的两个输入流读取。这两行分别代表两种流对象读取方法。这两种方法均从设定的流读取,然后将结果存储到给定变量中。这种方法采取阻塞式读取,意味着如果该方法调用无法顺序执行,就会暂停执行该函数调用中的其余代码。在试图读取空流的时候会发生这种情况。
c++相关文章:c++教程
评论