0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

一種在HLS中插入HDL代碼的方式

OpenFPGA ? 來源:OpenFPGA ? 2024-07-16 18:01 ? 次閱讀

很多人都比較反感用C/C++開發(fā)(HLS)FPGA,大家第一拒絕的理由就是耗費資源太多。但是HLS也有自己的優(yōu)點,除了快速構(gòu)建算法外,還有一個就是接口的生成,尤其對于AXI類接口,按照標準語法就可以很方便地生成相關(guān)接口。

那么有沒有能利用HLS的優(yōu)點,又囊括HDL的優(yōu)點的方法呢?今天就來介紹一種在HLS中插入HDL代碼的方式,結(jié)合兩者的優(yōu)勢為FPGA開發(fā)打造一把“利劍”。

c56d0048-4279-11ef-b8af-92fbcf53809c.png

說明

接下來,將介紹如何創(chuàng)建 Vitis-HLS 項目并將其與自定義 Verilog 模塊集成一起。

將插入兩個黑盒函數(shù) - 第一個在流水線區(qū)域(線路接口,ap_none),第二個在數(shù)據(jù)流區(qū)域(FIFO 接口,ap_ctrl_chain)。

步驟

1. 創(chuàng)建C/C++源文件(基于C的HLS模型+Testbench)

創(chuàng)建模塊的 C/C++ 模型,其中包括函數(shù)源代碼(模塊預期行為)和測試平臺(io 刺激和結(jié)果檢查)。

根據(jù)ug1399-vitis-hls rtl黑盒,rtl黑盒受到幾個因素的限制:

應該是Verilog(.v)代碼。

必須具有唯一的時鐘信號和唯一的高電平有效復位信號。

必須有一個 CE 信號,用于啟用或停止 RTL IP。

可以使用 ap_ctrl_chain 或 ap_ctrl_none 塊級控制協(xié)議。

僅支持 C++。

無法連接到頂層接口 I/O 信號。

不能直接作為被測設計(DUT)。

不支持結(jié)構(gòu)或類類型接口。

main.cpp ——C/C++ 測試臺。

#include"add.hpp"
intmain(void){
staticuint32_ta[1024];
staticuint32_tb[1024];
staticuint32_tc[1024];
staticuint32_tc_stream[1024];
for(uint32_ti=0;i

add.hpp——函數(shù)聲明。

#ifndefADD_HPP
#defineADD_HPP
#include
#include
voidadd(uint32_ta,uint32_tb,uint32_t&c);
voidadd_stream(
hls::stream&a,
hls::stream&b,
hls::stream&c
);
voidscalar_to_stream(uint32_ta,hls::stream&a_stream);
voidstream_to_scalar(hls::stream&a_stream,uint32_t&a);
voidwrap(uint32_ta,uint32_tb,uint32_t&c);
voidtop_module(uint32_t*a,uint32_t*b,uint32_t*c,uint32_t*c_stream);
#endif

add.cpp——函數(shù)源代碼。

#include"add.hpp"
voidadd(uint32_ta,uint32_tb,uint32_t&c){
c=a+b;
};
voidadd_stream(
hls::stream&a,
hls::stream&b,
hls::stream&c
){
c.write(a.read()+b.read());
};
voidscalar_to_stream(uint32_ta,hls::stream&a_stream){
a_stream.write(a);
};
voidstream_to_scalar(hls::stream&a_stream,uint32_t&a){
a=a_stream.read();
};
voidwrap(uint32_ta,uint32_tb,uint32_t&c){
#pragmaHLSDATAFLOW
hls::streamc_s;
hls::streama_s;
hls::streamb_s;
scalar_to_stream(a,a_s);
scalar_to_stream(b,b_s);
add_stream(a_s,b_s,c_s);
stream_to_scalar(c_s,c);
};
voidtop_module(uint32_t*a,uint32_t*b,uint32_t*c,uint32_t*c_stream){
#pragmaHLSINTERFACEmode=m_axiport=adepth=1024bundle=first
#pragmaHLSINTERFACEmode=m_axiport=bdepth=1024bundle=second
#pragmaHLSINTERFACEmode=m_axiport=cdepth=1024bundle=first
#pragmaHLSINTERFACEmode=m_axiport=c_streamdepth=1024bundle=second
#pragmaHLSINTERFACEmode=s_axiliteport=return
main_loop_pipeline:for(uint32_ti=0;i

2. 為 Vitis HLS創(chuàng)建配置文件

Vitis HLS需要配置文件來構(gòu)建項目?;九渲梦募?/p>

Part——FPGA 部件編號。

syn.top——頂級函數(shù)名稱。

tb.file——測試臺文件。

syn.file — HLS 中使用的文件。

在此示例中,cfg 文件的最小版本如下所示:

part=xc7z007sclg225-1
[hls]
syn.top=top_module
tb.file=main.cpp
syn.file=add.cpp
syn.file=add.hpp
package.output.format=ip_catalog
flow_target=vivado

3. 創(chuàng)建并構(gòu)建最小項目

啟動 Vitis,選擇工作區(qū)并點擊“創(chuàng)建 HLS 組件”。

c59fdf72-4279-11ef-b8af-92fbcf53809c.png

更改組件位置和名稱,單擊下一步。

c5bb16c0-4279-11ef-b8af-92fbcf53809c.png

選擇從現(xiàn)有配置文件創(chuàng)建,點擊下一步。

c5d8977c-4279-11ef-b8af-92fbcf53809c.png

項目結(jié)構(gòu)如下所示:

c5dc3ada-4279-11ef-b8af-92fbcf53809c.png

無需添加額外的標志,只需仔細檢查頂部函數(shù)是否是“top_module”,然后單擊下一步。

c5f061a4-4279-11ef-b8af-92fbcf53809c.png

選擇芯片(默認部分應該是cfg文件中寫的),單擊下一步

c61d5574-4279-11ef-b8af-92fbcf53809c.png

確認flow_target和package.output.format,點擊next。

c6378ad4-4279-11ef-b8af-92fbcf53809c.png

檢查摘要并單擊完成。

c6637f72-4279-11ef-b8af-92fbcf53809c.png

最后運行所有步驟以確保所有配置均已配置并正常運行。

c681d5b2-4279-11ef-b8af-92fbcf53809c.png

4.創(chuàng)建blackbox函數(shù)json

在此步驟中,我們將用 blackbox verilog 代碼替換我們的添加函數(shù)。在pipeline區(qū)域:

c6a4b29e-4279-11ef-b8af-92fbcf53809c.png

右鍵單擊 hls_component 并單擊“創(chuàng)建 RTL blackbox”,將生成 JSON 文件,描述 verilog 模塊與其 C 函數(shù)之間的連接。

c74dba6a-4279-11ef-b8af-92fbcf53809c.png

選擇包含 C 模塊描述的文件。

c761e184-4279-11ef-b8af-92fbcf53809c.png

選擇端口方向并填寫RTL組配置(verilog模塊中的端口名稱)。

c784ef58-4279-11ef-b8af-92fbcf53809c.pngc79ca01c-4279-11ef-b8af-92fbcf53809c.png

選擇verilog文件,如有必要再填寫其他框,單擊下一步。

c7b584f6-4279-11ef-b8af-92fbcf53809c.png

刪除 ap_ctrl_chain_protocol 字符串,保留空白。單擊完成。

c7d1d89a-4279-11ef-b8af-92fbcf53809c.png

對 add_stream 函數(shù)重復所有這些步驟。

輸入先進先出:

c7eb3524-4279-11ef-b8af-92fbcf53809c.png

輸出先進先出:

c8042cbe-4279-11ef-b8af-92fbcf53809c.png

概括:

c8182f16-4279-11ef-b8af-92fbcf53809c.pngc82d1c32-4279-11ef-b8af-92fbcf53809c.png

不要修改 ap_ctrl_chain 信號,因為該模塊將使用 ap_ctrl_chain 協(xié)議。

c843380a-4279-11ef-b8af-92fbcf53809c.png

此后,hls_component 文件夾中應該會生成兩個 json 文件。

add.json

{
"c_files":[
{
"c_file":"add.cpp",
"cflag":""
}
],
"c_function_name":"add",
"rtl_files":[
"add.v"
],
"c_parameters":[
{
"c_name":"a",
"c_port_direction":"in",
"rtl_ports":{
"data_read_in":"a"
}
},
{
"c_name":"b",
"c_port_direction":"in",
"rtl_ports":{
"data_read_in":"b"
}
},
{
"c_name":"c",
"c_port_direction":"out",
"rtl_ports":{
"data_write_out":"c",
"data_write_valid":"c_vld"
}
}
],
"rtl_top_module_name":"add",
"rtl_performance":{
"II":"0",
"latency":"0"
},
"rtl_resource_usage":{
"BRAM":"0",
"DSP":"0",
"FF":"0",
"LUT":"0",
"URAM":"0"
},
"rtl_common_signal":{
"module_clock":"ap_clk",
"module_reset":"ap_rst",
"module_clock_enable":"ap_ce",
"ap_ctrl_chain_protocol_idle":"",
"ap_ctrl_chain_protocol_start":"",
"ap_ctrl_chain_protocol_ready":"",
"ap_ctrl_chain_protocol_done":"",
"ap_ctrl_chain_protocol_continue":""
}
}

add_stream.json

{
"c_files":[
{
"c_file":"add.cpp",
"cflag":""
}
],
"c_function_name":"add_stream",
"rtl_files":[
"add_stream.v"
],
"c_parameters":[
{
"c_name":"a",
"c_port_direction":"in",
"rtl_ports":{
"FIFO_empty_flag":"a_empty_flag",
"FIFO_read_enable":"a_read_enable",
"FIFO_data_read_in":"a"
}
},
{
"c_name":"b",
"c_port_direction":"in",
"rtl_ports":{
"FIFO_empty_flag":"b_empty_flag",
"FIFO_read_enable":"b_read_enable",
"FIFO_data_read_in":"b"
}
},
{
"c_name":"c",
"c_port_direction":"out",
"rtl_ports":{
"FIFO_full_flag":"c_full_flag",
"FIFO_write_enable":"c_write_enable",
"FIFO_data_write_out":"c"
}
}
],
"rtl_top_module_name":"add_stream",
"rtl_performance":{
"II":"0",
"latency":"0"
},
"rtl_resource_usage":{
"BRAM":"0",
"DSP":"0",
"FF":"0",
"LUT":"0",
"URAM":"0"
},
"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"
}
}

主文件夾應與此類似:

c86c30b6-4279-11ef-b8af-92fbcf53809c.png

hls_config.cfg 文件應該添加兩新行( syn.blackbox.file)

part=xc7z007sclg225-1
[hls]
flow_target=vivado
csim.code_analyzer=0
syn.top=top_module
syn.blackbox.file=add.json
syn.blackbox.file=add_stream.json
tb.file=main.cpp
syn.file=add.cpp
syn.file=add.hpp

5.創(chuàng)建Verilog黑盒函數(shù)

函數(shù)“add”必須具有ap_none接口,并且 ap_none 作為模塊接口。(有關(guān)模塊接口的更多信息,請查看https://docs.amd.com/r/en-US/ug1399-vitis-hls/JSON-File-for-RTL-Blackbox 。)

c87f4f5c-4279-11ef-b8af-92fbcf53809c.pngc8abed0a-4279-11ef-b8af-92fbcf53809c.png

根據(jù)UG1399,端口a和b是32位寬度的輸入端口,輸出c端口也是32位寬度,但帶有額外的有效信號,我們稱之為c_vld。模塊還需要ap_clk,ap_ce,ap_rst端口。

Verilog 如下所示:

add.v

`timescale1ns/1ps
moduleadd(
input[31:0]a,
input[31:0]b,
output[31:0]c,
outputc_vld,
inputap_ce,
inputap_rst,
inputap_clk
);
reg[31:0]c_d;
regc_vld_d;
assignc=c_d;
assignc_vld=c_vld_d;
always@(posedgeap_clk)begin
if(ap_rst==1'b1)begin
c_d<=?32'b0;
????????c_vld_d?<=?1'b0;
????end?else?begin
????????c_d?<=?(a?+?b)?&?{32{ap_ce}};
????????c_vld_d?<=?ap_ce;
????end
end
endmodule

運行 C 綜合和 C/RTL 協(xié)同仿真。能夠在 HLS 模塊中看到打包的 add.v 文件。

c8bf1c86-4279-11ef-b8af-92fbcf53809c.png

單擊 hls_config.cfg 文件,在 Vitis GUI 的幫助下將 cosim.trace_level 更改為全部并運行聯(lián)合仿真。

c8dd1fb0-4279-11ef-b8af-92fbcf53809c.png

單擊波形查看器。Vivado 會彈出 XSIM。

c902e68c-4279-11ef-b8af-92fbcf53809c.png

將 grp_add_fu_134 信號添加到 wcfg

c91651d6-4279-11ef-b8af-92fbcf53809c.pngc92b4244-4279-11ef-b8af-92fbcf53809c.png

函數(shù)行為很奇怪,接下來在 json 中更改黑盒函數(shù) II,看看它如何影響仿真。打開 add.json 并將 II 更改為 10。再次運行 C 綜合并重新運行 C/RTL 協(xié)同仿真。

c9487dc8-4279-11ef-b8af-92fbcf53809c.png

add.v 模塊是否良好且可以正常工作?其行為是否正確?模塊是否正常工作由哪些因素決定?“fixing”模塊對資源使用有何影響?

那么 add_stream 呢?函數(shù)位于數(shù)據(jù)流區(qū)域,并且必須包含 fifo 端口和 ap_ctrl_chain 協(xié)議。

add_stream.v

`timescale1ns/1ps
moduleadd_stream(
input[31:0]a,
inputa_empty_flag,
outputa_read_enable,
input[31:0]b,
inputb_empty_flag,
outputb_read_enable,
output[31:0]c,
inputc_full_flag,
outputc_write_enable,
outputap_idle,
inputap_start,
outputap_ready,
outputap_done,
inputap_continue,
inputap_ce,
inputap_rst,
inputap_clk
);
rega_read_enable_d;
regb_read_enable_d;
regc_write_enable_d;
reg[31:0]c_d;
assigna_read_enable=a_read_enable_d;
assignb_read_enable=b_read_enable_d;
assignc_write_enable=c_write_enable_d;
assignc=c_d;
assignap_idle=!ap_start;
assignap_ready=ap_start;
assignap_done=ap_start;
//Flagsarenegated...
assignflags_good=a_empty_flag&&b_empty_flag&&c_full_flag;
assignhs_good=ap_start&&ap_continue;
always@(posedgeap_clk)begin
if(ap_rst==1'b1)begin
a_read_enable_d<=?0;
????????????b_read_enable_d?<=?0;
????????????c_write_enable_d?<=?0;
????????????c_d?<=?0;
????end?else?if?(ap_ce?==?1'b1)?begin
????????????a_read_enable_d?<=?flags_good?&&?hs_good;
????????????b_read_enable_d?<=?flags_good?&&?hs_good;
????????????c_write_enable_d?<=?flags_good?&&?hs_good;
????????????c_d?<=?a?+?b;
????????end
????end
endmodule

看起來放置在數(shù)據(jù)流區(qū)域的模塊工作正常:

c970332c-4279-11ef-b8af-92fbcf53809c.png

打開 add_stream.json 并將延遲更改為 10。再次運行 C 綜合并重新運行 C/RTL 協(xié)同仿真。這會影響仿真嗎?

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • FPGA
    +關(guān)注

    關(guān)注

    1624

    文章

    21538

    瀏覽量

    600450
  • 函數(shù)
    +關(guān)注

    關(guān)注

    3

    文章

    4256

    瀏覽量

    62223
  • 代碼
    +關(guān)注

    關(guān)注

    30

    文章

    4694

    瀏覽量

    68075
  • HLS
    HLS
    +關(guān)注

    關(guān)注

    1

    文章

    128

    瀏覽量

    23966

原文標題:在HLS中插入HDL代碼

文章出處:【微信號:Open_FPGA,微信公眾號:OpenFPGA】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。

收藏 人收藏

    評論

    相關(guān)推薦

    如何用HLS實現(xiàn)UART

    UART 是一種舊的串行通信機制,但仍在很多平臺中使用。它在 HDL 語言中的實現(xiàn)并不棘手,可以被視為本科生的作業(yè)。在這里,我將通過這個例子來展示 HLS
    的頭像 發(fā)表于 11-20 09:48 ?496次閱讀
    如何用<b class='flag-5'>HLS</b>實現(xiàn)UART

    如何用HLS實現(xiàn)UART呢?

    UART 是一種舊的串行通信機制,但仍在很多平臺中使用。它在 HDL 語言中的實現(xiàn)并不棘手,可以被視為本科生的作業(yè)。在這里,我將通過這個例子來展示 HLS
    的頭像 發(fā)表于 11-20 09:50 ?592次閱讀
    如何用<b class='flag-5'>HLS</b>實現(xiàn)UART呢?

    編程是一種思維方式,而代碼一種表現(xiàn)形式,硬件只不過是對思維方式的物理體現(xiàn)

    編程是一種思維方式,而代碼一種表現(xiàn)形式,硬件只不過是對思維方式的物理體現(xiàn)關(guān)于這句話,你怎么看?
    發(fā)表于 08-25 13:18

    如何在HLS 14.3編寫pow功能?

    嗨? 如何在HLS 14.3編寫pow功能? HLS 14.3不支持exp和pow功能。我我的代碼
    發(fā)表于 03-05 13:40

    手動插入代碼MHC合并過程不會出現(xiàn)延遲嗎?

    HIIS有一種方法將HANCE項目中的手動代碼結(jié)合起來,當從配置器生成代碼時,這些手動插入代碼
    發(fā)表于 05-05 16:55

    Vivado中進行HDL代碼設計

    Vivado中進行HDL代碼設計,不僅需要描述數(shù)字邏輯電路的常用功能,還要考慮如何發(fā)揮Xilinx器件的架構(gòu)優(yōu)勢。目前常用的HDL語言有
    發(fā)表于 09-29 10:08

    【正點原子FPGA連載】第HLS簡介-領(lǐng)航者ZYNQ之HLS 開發(fā)指南

    Vivado HLS可以使用三語言進行設計開發(fā),分別是 C、C++ 和 SystemC。其中C語言是一種非常通用的面向過程的編程語言,我們
    發(fā)表于 10-10 16:44

    一種基于信號延遲的光網(wǎng)絡攻擊方式

    針對光網(wǎng)絡攻擊易被發(fā)現(xiàn)的問題,提出一種基于信號延遲插入的光網(wǎng)絡攻擊方式。該方法不改變鏈路光學性能的基礎上,利用信號延遲系統(tǒng)
    發(fā)表于 03-20 15:34 ?27次下載
    <b class='flag-5'>一種</b>基于信號延遲的光網(wǎng)絡攻擊<b class='flag-5'>方式</b>

    使用教程分享:Zynq AP SoC設計中高效使用HLS IP(

    高層次綜合設計最常見的的使用就是為CPU創(chuàng)建個加速器,將在CPU執(zhí)行的代碼移動到FPGA可編程邏輯去提高性能。本文展示了如何在Zynq AP SoC設計中使用HLS IP。
    發(fā)表于 02-07 18:08 ?3555次閱讀
    使用教程分享:<b class='flag-5'>在</b>Zynq AP SoC設計中高效使用<b class='flag-5'>HLS</b> IP(<b class='flag-5'>一</b>)

    如何在C代碼插入寄存器?

    寄存。這起到了隔離關(guān)鍵路徑的作用。 但是,如果使用的RTL代碼HLS轉(zhuǎn)換生成的,例如使用Vitis HLS綜合的,其可讀性較差,想要在其生成的HDL
    的頭像 發(fā)表于 02-02 17:07 ?2999次閱讀
    如何在C<b class='flag-5'>代碼</b><b class='flag-5'>中</b><b class='flag-5'>插入</b>寄存器?

    并行CRC電路HDL代碼的快速生成

    CRC校驗的實現(xiàn)基于串行位移寄存器,如果要處理并行數(shù)據(jù),需要對電路進行改進。本文介紹了一種并行CRC電路HDL代碼的快速生成鐘算法,只需要帶入不同的參數(shù),可自動生成不同長度以及并行度的并行CRC電路的
    發(fā)表于 03-28 09:29 ?16次下載
    并行CRC電路<b class='flag-5'>HDL</b><b class='flag-5'>代碼</b>的快速生成

    一種可以快速將CFG文件參數(shù)固化到應用代碼的實現(xiàn)方式

    固化參數(shù)的產(chǎn)品而言,將參數(shù)固化代碼中會是項明確的需求。本文介紹一種可以快速將CFG文件參數(shù)固化到應用代碼
    的頭像 發(fā)表于 02-15 13:36 ?2953次閱讀
    <b class='flag-5'>一種</b>可以快速將CFG文件參數(shù)固化到應用<b class='flag-5'>代碼</b><b class='flag-5'>中</b>的實現(xiàn)<b class='flag-5'>方式</b>

    Vitis HLS工具簡介及設計流程

    Vitis HLS一種高層次綜合工具,支持將 C、C++ 和 OpenCL 函數(shù)硬連線到器件邏輯互連結(jié)構(gòu)和 RAM/DSP 塊上。Vitis HLS 可在Vitis 應用加速開發(fā)流程
    的頭像 發(fā)表于 05-25 09:43 ?2265次閱讀

    MATLAB/simulink建模時的兩不同實現(xiàn)方式

    導讀:本期文章主要介紹MATLAB/simulink建模時的兩不同實現(xiàn)方式一種是直接用現(xiàn)成的文件庫
    的頭像 發(fā)表于 09-15 10:07 ?1783次閱讀

    FPGA基礎之HLS

    1、HLS簡介 HLS(High-Level Synthesis)高層綜合,就是將 C/C++的功能用 RTL 來實現(xiàn),將 FPGA 的組件個軟件環(huán)境
    的頭像 發(fā)表于 12-02 12:30 ?4957次閱讀