目录
1. 简介
2. 用法详解
2.1 需要的文件
2.1.1 RTL 函数签名
2.1.2 黑盒 JSON 描述文件
2.1.3 RTL IP 文件
2.2 操作步骤
3. 总结
1. 简介
Vitis HLS 工具可以将现有的 Verilog RTL IP(即硬件描述语言编写的模块)集成到 C/C++ HLS 项目中。通过这种方式,Vitis HLS 能够将 RTL 代码与 C/C++ 代码一起综合,形成最终的硬件设计。
RTL 黑盒允许设计者在 HLS 设计中的特定区域(如顺序区域、流水线区域或数据流区域)内使用 Verilog 或 VHDL 编写的 RTL IP。这样做的好处是可以重用现有的硬件模块,同时利用 HLS 的优势来加速整个设计和开发过程。
简单的说,如果你有一个用 Verilog 编写的性能优化好的 IP,可以将其作为黑盒插入到 HLS 项目中,而不需要将其重新用 C/C++ 实现。这样可以节省时间,并确保硬件设计的高效性和可靠性。
2. 用法详解
2.1 需要的文件
2.1.1 RTL 函数签名
RTL 代码的 C 语言函数签名,是指用于代表RTL模块的C函数的声明。这个签名定义了函数的名称、输入参数和返回类型,这样C代码就可以调用它,就像调用任何其他C函数一样。这个签名通常放在一个头文件(.h)中,以便在整个项目中使用。
#include "ap_int.h"//--------------------------------------------------------
//RTL 代码的 C 语言函数签名
//--------------------------------------------------------
void rtl_model(ap_int<10> a1, ap_int<10> a2, ap_int<10> a3, ap_int<10> a4,ap_int<10> b1, ap_int<10> b2, ap_int<10> b3, ap_int<10> b4,ap_int<10>& z1, ap_int<10>& z2, ap_int<10>& z3, ap_int<10>& z4);//--------------------------------------------------------
void example(ap_int<10> a1, ap_int<10> a2, ap_int<10> a3, ap_int<10> a4,ap_int<10> b1, ap_int<10> b2, ap_int<10> b3, ap_int<10> b4,ap_int<10>& sigma) {ap_int<10> tmp1, tmp2, tmp3, tmp4;rtl_model(a1, a2, a3, a4, b1, b2, b3, b4, tmp1, tmp2, tmp3, tmp4);sigma = tmp1 + tmp2 + tmp3 + tmp4;
}
2.1.2 黑盒 JSON 描述文件
{
"c_function_name" : "rtl_model",
"rtl_top_module_name" : "rtl_model",
"c_files" : [{ "c_file" : "rtl_model.cpp","cflag" : ""}],
"rtl_files" : ["rtl_model.v"],
"c_parameters" : [{"c_name" : "a1","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a1"}},{"c_name" : "a2","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a2"}},{"c_name" : "a3","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a3"}},{"c_name" : "a4","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "a4"}},{"c_name" : "b1","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b1"}},{"c_name" : "b2","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b2"}},{"c_name" : "b3","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b3"}},{"c_name" : "b4","c_port_direction" : "in","rtl_ports" : {"data_read_in" : "b4"}},{"c_name" : "z1","c_port_direction" : "out","rtl_ports" : {"data_write_out" : "z1","data_write_valid" : "z1_ap_vld"}},{"c_name" : "z2","c_port_direction" : "out","rtl_ports" : {"data_write_out" : "z2","data_write_valid" : "z2_ap_vld"}},{"c_name" : "z3","c_port_direction" : "out","rtl_ports" : {"data_write_out" : "z3","data_write_valid" : "z3_ap_vld"}},{"c_name" : "z4","c_port_direction" : "out","rtl_ports" : {"data_write_out" : "z4","data_write_valid" : "z4_ap_vld"}}],
"rtl_common_signal" : {"module_clock" : "ap_clk","module_reset" : "ap_rst","module_clock_enable" : "ap_ce","ap_ctrl_chain_protocol_idle" : "ap_idle","ap_ctrl_chain_protocol_start" : "ap_start","ap_ctrl_chain_protocol_ready" : "ap_ready","ap_ctrl_chain_protocol_done" : "ap_done","ap_ctrl_chain_protocol_continue" : "ap_continue"},
"rtl_performance" : {"latency" : "2","II" : "1"},
"rtl_resource_usage" : {"FF" : "0","LUT" : "0","BRAM" : "0","URAM" : "0","DSP" : "1"}
}
2.1.3 RTL IP 文件
`timescale 100ps/100ps(* use_dsp = "simd" *)
(* dont_touch = "1" *)
module rtl_model (input ap_clk, ap_rst, ap_ce, ap_start, ap_continue,input [9:0] a1, a2, a3, a4, b1, b2, b3, b4,output ap_idle, ap_done, ap_ready,output z1_ap_vld, z2_ap_vld, z3_ap_vld, z4_ap_vld,output reg [9:0] z1, z2, z3, z4);wire ce = ap_ce;reg [9:0] areg1, areg2, areg3, areg4;reg [9:0] breg1, breg2, breg3, breg4;reg dly1, dly2;always @ (posedge ap_clk)if (ap_rst)beginz1 <= 0;z2 <= 0;z3 <= 0;z4 <= 0;areg1 <= 0;areg2 <= 0;areg3 <= 0;areg4 <= 0;breg1 <= 0;breg2 <= 0;breg3 <= 0;breg4 <= 0;dly1 <= 0;dly2 <= 0; endelse if (ce)beginz1 <= areg1 + breg1;z2 <= areg2 + breg2;z3 <= areg3 + breg3;z4 <= areg4 + breg4;areg1 <= a1;areg2 <= a2;areg3 <= a3;areg4 <= a4;breg1 <= b1;breg2 <= b2;breg3 <= b3;breg4 <= b4;dly1 <= ap_start;dly2 <= dly1; endassign z1_ap_vld = dly2;assign z2_ap_vld = dly2;assign z3_ap_vld = dly2;assign z4_ap_vld = dly2;assign ap_ready = dly2;assign ap_done = dly2;assign ap_idle = ~ap_start;endmodule // rtl_model
2.2 使用 RTL 黑盒向导
整体步骤和常规的 Vitis HLS 步骤一致,特殊点在于多了一个 JSON 文件需要配置:
- 从顶层函数内或者从 Vitis HLS 工程的子函数内调用 C 语言函数签名。
- 在 Vitis HLS IDE 中使用“Add Files”(添加文件),将黑盒 JSON 描述文件添加到 HLS 工程中。
- 运行 Vitis HLS 设计文件照常进行仿真、综合和协同仿真。
使用 RTL 黑盒向导操作步骤:
在导航到工程中,打开 RTL 黑盒向导:
3. 总结
Vitis HLS 的引入为硬件设计师提供了一种灵活高效的设计途径,通过允许 RTL 黑盒的使用,设计师可以在不牺牲性能的前提下,重用现有的硬件模块,同时利用 HLS 的高层次抽象和快速迭代能力来加速设计和开发过程。这种方法既节省了将硬件模块重新用 C/C++ 实现的时间,也保持了设计的高效性和可靠性。通过简化操作步骤和提供直观的工具,如 RTL Blackbox Wizard,Vitis HLS 降低了硬件设计的复杂性,使得开发者能够更加专注于创新和优化。