pragma HLS interface 端口综合

本文深入解析pragmaHLS接口语法,涵盖多种接口模式如ap_vld、ap_ack及AXI系列,详解如何在VivadoHLS中指定端口协议、寄存选项与深度配置,帮助读者掌握高效RTL设计技巧。

这是针对pragma HLS interface 语法的翻译笔记,可以作为原英文文档的辅助文档,原文地址是SDSoc Development Help

正文

在vivado HLS基于C的设计中,函数形式参数代表了输入和输出操作。但是在RTL设计中,必须设计接口来执行这些输入和输出操作,并且通常使用特定的I / O(输入-输出)协议进行操作。有关更多信息,请参考《Vivado Design Suite用户指南:高级综合(UG902)》中的“Ch.1 Manage Interface” 。(推荐参考:对ug902中manage interface部分的优质翻译

INTERFACEpragma指定如何在接口合成期间依据函数定义创建RTL端口。
RTL实现中的端口派生自:

  • 指定的任何函数级协议
  • 函数参数
  • 由顶级函数访问的,并且是在其作用域之外定义的全局变量

Function-level protocols(函数层级的协议)也称为block-level I/O protocols(块级I/O协议),用于提供信号来控制函数何时开始操作,并指示函数操作何时结束、空闲和准备好接受新的输入。函数级协议的实现:

  • 由值指定为三种模式ap_ctrl_noneap_ctrl_hsap_ctrl_chain。其中的 ap_ctrl_hs是默认的块级I / O协议。
  • 与函数名相关联。

port-level (I/O) interface protocol(端口级I / O接口协议):可以为每个函数参数指定port-level (I/O) interface protocol(端口级I / O接口协议),如有效握手(ap_vld)或确认握手(ap_ack)。如果函数会返回一个值,则为顶层函数和函数返回中的每个参数创建端口级I/O接口协议。创建的默认I/O协议取决于C参数的类型。在使用块级IO协议启动块的操作后,使用端口级IO协议对数据进行序列输入和输出

如果访问了全局变量,但所有读和写操作都是design的本地操作,即是在design中创建资源,那么在RTL中不需要I/O端口。如果全局变量是外部源或地址,则以类似的方式将其接口指定为标准函数参数。参见下面的示例。
INTERFACEpragma用于子函数时,只能使用register选项。子函数不支持< mode>选项。

提示:Vivado HLS自动确定任何子函数使用的I/O协议。除了指定端口是否寄存外,您无法控制这些端口。

语法

将pragma放在函数内。

#pragma HLS interface <mode> port=<name> bundle=<string> \
register register_mode=<mode> depth=<int> offset=<string> \
clock=<string> name=<string> \
num_read_outstanding=<int> num_write_outstan
分析一下这段代码:#include "SmoothProfileOnXAxisMean.h" void SmoothProfileOnXAxisMean(hls::stream<float>& points_in_z, hls::stream<float>& smoothed_z, ap_uint<6> mean_win_size, float invalid_z) { #pragma HLS INTERFACE axis port=points_in_z #pragma HLS INTERFACE axis port=smoothed_z #pragma HLS INTERFACE ap_none port=mean_win_size #pragma HLS INTERFACE ap_none port=invalid_z #pragma HLS INTERFACE ap_ctrl_none port=return #pragma HLS PIPELINE II=1 // 使用移位寄存器实现窗口存储 static float shift_reg[33]; #pragma HLS ARRAY_PARTITION variable=shift_reg type=complete dim=1 // 窗口状态管理 static ap_uint<6> last_win_size = 0; static ap_uint<1> win_size_changed = 0; static int data_count = 0; // 并行计算单元 float window_sum = 0; int valid_count = 0; float center_value = 0; // 读取新数据(流控制) float new_value = (data_count < 3200) ? points_in_z.read() : invalid_z; // 窗口大小变化检测与处理 if (mean_win_size != last_win_size) { last_win_size = mean_win_size; win_size_changed = 1; } // 窗口大小变化时重置寄存器 if (win_size_changed) { #pragma HLS UNROLL for (int i = 0; i < 33; i++) { shift_reg[i] = invalid_z; } win_size_changed = 0; data_count = 0; } // 计算窗口中心位置 const int half_win = last_win_size >> 1; // 等价于/2 // 并行移位寄存器更新 #pragma HLS UNROLL for (int i = 32; i > 0; i--) { shift_reg[i] = shift_reg[i-1]; } shift_reg[0] = new_value; // 获取中心点值(用于边界判断) center_value = shift_reg[half_win]; // 并行窗口求和与有效计数 #pragma HLS UNROLL for (int i = 0; i < 33; i++) { #pragma HLS EXPRESSION_BALANCE bool in_window = (i < last_win_size); bool is_valid = (shift_reg[i] != invalid_z); if (in_window && is_valid) { window_sum += shift_reg[i]; valid_count++; } } // 边界处理逻辑 bool is_boundary = (data_count < last_win_size) || (data_count >= 3200); bool center_invalid = (center_value == invalid_z); // 输出决策 if (center_invalid || is_boundary) { smoothed_z.write(center_value); } else { float result = (valid_count > 0) ? (window_sum / valid_count) : invalid_z; smoothed_z.write(result); } // 更新数据计数器 if (data_count < 3200 + half_win) { data_count++; } }
07-23
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值