高層次綜合(High Level Synthesis, HLS)是Xilinx公司推出的最新一代的FPGA設(shè)計工具,它能讓用戶通過編寫C/C++等高級語言代碼實現(xiàn)RTL級的硬件功能。隨著這款工具的出現(xiàn),軟硬之間的區(qū)別越來越模糊,即使你對于硬件完全不懂,你也能編寫出符合工程功能要求的RTL代碼。看到HLS工具具有如此神奇的功能,你是否想立即嘗試一下呢?
接下來我們將談?wù)凥LS相關(guān)的簡單操作以及C/C++到VHDL的一個轉(zhuǎn)換關(guān)系:
首先確保你已經(jīng)下好了vivado相關(guān)套件,并且HLS的license(官網(wǎng)有試用的,但只能用一個月)已經(jīng)下到,然后打開桌面上,就可以按照一般的軟件建工程一樣,這里我們寫了一個很簡單的函數(shù)int andfunction(int array[2],int array1[2]);這里我們注意到函數(shù)返回值是整形,同時兩個形參是都是數(shù)組,這個函數(shù)代碼如下:
int andfunction(int array[2],int array1[2])
{
int i,sum;
sum=0;
for(i=0;i《2;i++)
{
array[i]=i*2;
array1[i]=array[i]+i;
sum+=array1[i];
}
return sum;
}
寫好了這個函數(shù)后,那么我們不妨看看綜合后的VHDL是怎樣的。點擊綠色三角按鈕后生成硬件描述語言,solution1-》syn-》vhdl里可以看到生成的VHDL,代碼如下:
-- ==============================================================
-- RTL generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC
-- Version: 2012.4
-- Copyright (C) 2012 Xilinx Inc. All rights reserved.
--
-- ===========================================================
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity andfunction is
port (
ap_clk : IN STD_LOGIC;
ap_rst : IN STD_LOGIC;
ap_start : IN STD_LOGIC;
ap_done : OUT STD_LOGIC;
ap_idle : OUT STD_LOGIC;
ap_ready : OUT STD_LOGIC;
array_r_address0 : OUT STD_LOGIC_VECTOR (0 downto 0);
array_r_ce0 : OUT STD_LOGIC;
array_r_we0 : OUT STD_LOGIC;
array_r_d0 : OUT STD_LOGIC_VECTOR (31 downto 0);
array1_address0 : OUT STD_LOGIC_VECTOR (0 downto 0);
array1_ce0 : OUT STD_LOGIC;
array1_we0 : OUT STD_LOGIC;
array1_d0 : OUT STD_LOGIC_VECTOR (31 downto 0);
ap_return : OUT STD_LOGIC_VECTOR (31 downto 0) );
end;
architecture behav of andfunction is
attribute CORE_GENERATION_INFO : STRING;
attribute CORE_GENERATION_INFO of behav : architecture is
“andfunction,hls_ip_2012_4,{HLS_INPUT_TYPE=c,HLS_INPUT_FLOAT=0,HLS_INPUT_FIXED=0,HLS_INPUT_PART=xc5vlx110tff1136-1,HLS_INPUT_CLOCK=10.000000,HLS_INPUT_ARCH=others,HLS_SYN_CLOCK=3.090000,HLS_SYN_LAT=3,HLS_SYN_TPT=none,HLS_SYN_MEM=0,HLS_SYN_DSP=0,HLS_SYN_FF=3,HLS_SYN_LUT=8}”;
constant ap_const_logic_1 : STD_LOGIC := ‘1’;
constant ap_const_logic_0 : STD_LOGIC := ‘0’;
constant ap_ST_st1_fsm_0 : STD_LOGIC_VECTOR (0 downto 0) := “0”;
constant ap_ST_st2_fsm_1 : STD_LOGIC_VECTOR (0 downto 0) := “1”;
constant ap_const_lv2_0 : STD_LOGIC_VECTOR (1 downto 0) := “00”;
constant ap_const_lv1_0 : STD_LOGIC_VECTOR (0 downto 0) := “0”;
constant ap_const_lv2_2 : STD_LOGIC_VECTOR (1 downto 0) := “10”;
constant ap_const_lv2_1 : STD_LOGIC_VECTOR (1 downto 0) := “01”;
constant ap_const_lv32_3 : STD_LOGIC_VECTOR (31 downto 0) := “00000000000000000000000000000011”;
signal ap_CS_fsm : STD_LOGIC_VECTOR (0 downto 0) := “0”;
signal i_1_fu_66_p2 : STD_LOGIC_VECTOR (1 downto 0);
signal i_reg_42 : STD_LOGIC_VECTOR (1 downto 0);
signal exitcond1_fu_60_p2 : STD_LOGIC_VECTOR (0 downto 0);
signal i_cast_fu_54_p1 : STD_LOGIC_VECTOR (31 downto 0);
signal tmp_fu_72_p2 : STD_LOGIC_VECTOR (1 downto 0);
signal tmp_1_fu_83_p2 : STD_LOGIC_VECTOR (1 downto 0);
signal ap_NS_fsm : STD_LOGIC_VECTOR (0 downto 0);
begin
-- the current state (ap_CS_fsm) of the state machine. --
ap_CS_fsm_assign_proc : process(ap_clk)
begin
if (ap_clk‘event and ap_clk = ’1‘) then
if (ap_rst = ’1‘) then
ap_CS_fsm 《= ap_ST_st1_fsm_0;
else
ap_CS_fsm 《= ap_NS_fsm;
end if;
end if;
end process;
-- ap_reg assign process. --
ap_reg_proc : process(ap_clk)
begin
if (ap_clk’event and ap_clk = ‘1’) then
if (((ap_ST_st2_fsm_1 = ap_CS_fsm) and (exitcond1_fu_60_p2 = ap_const_lv1_0))) then
i_reg_42 《= i_1_fu_66_p2;
elsif (((ap_ST_st1_fsm_0 = ap_CS_fsm) and not((ap_start = ap_const_logic_0)))) then
i_reg_42 《= ap_const_lv2_0;
end if;
end if;
end process;
-- the next state (ap_NS_fsm) of the state machine. --
ap_NS_fsm_assign_proc : process(ap_start, ap_CS_fsm, exitcond1_fu_60_p2)
begin
if (((ap_ST_st2_fsm_1 = ap_CS_fsm) and not((exitcond1_fu_60_p2 = ap_const_lv1_0)))) then
ap_NS_fsm 《= ap_ST_st1_fsm_0;
elsif ((((ap_ST_st1_fsm_0 = ap_CS_fsm) and not((ap_start = ap_const_logic_0))) or ((ap_ST_st2_fsm_1 = ap_CS_fsm) and (exitcond1_fu_60_p2 = ap_const_lv1_0)))) then
ap_NS_fsm 《= ap_ST_st2_fsm_1;
else
ap_NS_fsm 《= ap_CS_fsm;
end if;
end process;
-- ap_done assign process. --
ap_done_assign_proc : process(ap_CS_fsm, exitcond1_fu_60_p2)
begin
if (((ap_ST_st2_fsm_1 = ap_CS_fsm) and not((exitcond1_fu_60_p2 = ap_const_lv1_0)))) then
ap_done 《= ap_const_logic_1;
else
ap_done 《= ap_const_logic_0;
end if;
end process;
-- ap_idle assign process. --
ap_idle_assign_proc : process(ap_start, ap_CS_fsm)
begin
if ((not((ap_const_logic_1 = ap_start)) and (ap_ST_st1_fsm_0 = ap_CS_fsm))) then
ap_idle 《= ap_const_logic_1;
else
ap_idle 《= ap_const_logic_0;
end if;
end process;
-- ap_ready assign process. --
ap_ready_assign_proc : process(ap_CS_fsm, exitcond1_fu_60_p2)
begin
if (((ap_ST_st2_fsm_1 = ap_CS_fsm) and not((exitcond1_fu_60_p2 = ap_const_lv1_0)))) then
ap_ready 《= ap_const_logic_1;
else
ap_ready 《= ap_const_logic_0;
end if;
end process;
ap_return 《= ap_const_lv32_3;
array1_address0 《= i_cast_fu_54_p1(1 - 1 downto 0);
-- array1_ce0 assign process. --
array1_ce0_assign_proc : process(ap_CS_fsm, exitcond1_fu_60_p2)
begin
if (((ap_ST_st2_fsm_1 = ap_CS_fsm) and (exitcond1_fu_60_p2 = ap_const_lv1_0))) then
array1_ce0 《= ap_const_logic_1;
else
array1_ce0 《= ap_const_logic_0;
end if;
end process;
array1_d0 《= std_logic_vector(resize(unsigned(tmp_1_fu_83_p2),32));
-- array1_we0 assign process. --
array1_we0_assign_proc : process(ap_CS_fsm, exitcond1_fu_60_p2)
begin
if ((((ap_ST_st2_fsm_1 = ap_CS_fsm) and (exitcond1_fu_60_p2 = ap_const_lv1_0)))) then
array1_we0 《= ap_const_logic_1;
else
array1_we0 《= ap_const_logic_0;
end if;
end process;
array_r_address0 《= i_cast_fu_54_p1(1 - 1 downto 0);
-- array_r_ce0 assign process. --
array_r_ce0_assign_proc : process(ap_CS_fsm, exitcond1_fu_60_p2)
begin
if (((ap_ST_st2_fsm_1 = ap_CS_fsm) and (exitcond1_fu_60_p2 = ap_const_lv1_0))) then
array_r_ce0 《= ap_const_logic_1;
else
array_r_ce0 《= ap_const_logic_0;
end if;
end process;
array_r_d0 《= std_logic_vector(resize(unsigned(tmp_fu_72_p2),32));
-- array_r_we0 assign process. --
array_r_we0_assign_proc : process(ap_CS_fsm, exitcond1_fu_60_p2)
begin
if ((((ap_ST_st2_fsm_1 = ap_CS_fsm) and (exitcond1_fu_60_p2 = ap_const_lv1_0)))) then
array_r_we0 《= ap_const_logic_1;
else
array_r_we0 《= ap_const_logic_0;
end if;
end process;
exitcond1_fu_60_p2 《= “1” when (i_reg_42 = ap_const_lv2_2) else “0”;
i_1_fu_66_p2 《= std_logic_vector(unsigned(i_reg_42) + unsigned(ap_const_lv2_1));
i_cast_fu_54_p1 《= std_logic_vector(resize(unsigned(i_reg_42),32));
tmp_1_fu_83_p2 《= std_logic_vector(unsigned(tmp_fu_72_p2) + unsigned(i_reg_42));
tmp_fu_72_p2 《= std_logic_vector(shift_left(unsigned(i_reg_42),to_integer(unsigned(‘0’ & ap_const_lv2_1(2-1 downto 0)))));
end behav;
看到這么長一大串代碼后,你或許會說看起來太復(fù)雜來人,還不如自己寫;一兩個簡單的可以自己寫,成千上萬個呢?這里我們不去關(guān)注architecture里面具體的實現(xiàn)過程(這里面包含很多優(yōu)化),這里我們僅僅討論從C/C++到VHDL的entity的關(guān)系。
看到VHDL后,你也許第一眼就看到了VHDL中的entity了,但是你不一定理解其管腳到底指代什么,下面給出一張int andfunction(int array[2],int array1[2])這個函數(shù)的硬件結(jié)構(gòu)圖
硬件引腳的具體含義是(這部分是參考的):
ap_rst:設(shè)計的復(fù)位信號
ap_start:開始計算的開始信號
ap_done:計算結(jié)束和輸出就緒的完成信號
ap_idle:表示實體(設(shè)計)空閑的空閑信號
ap_ready:表示設(shè)計為新輸入數(shù)據(jù)做好準(zhǔn)備,與ap_idle 配合使用
ap_return:設(shè)計的返回值
name_address:存儲器的讀地址 (name指代array或array1,因為它們都是數(shù)組,在硬件中綜合成了寄存器)
name_ce0:存儲器的芯片使能
name_we0:存儲器的寫使能
name_do0:存儲器的寫數(shù)據(jù)
ap_return: 函數(shù)返回值端口
分析上面的硬件管腳,其中ap_clk、ap_rst、ap_start、ap_done、ap_idle、ap_ready為大多數(shù)綜合后硬件默認必有的,因為這些引腳便于處理器對其進行控制;name_address0、name_ce0、name_we0、name_do0這些引腳是為了獲取所使用到寄存器的狀態(tài),在這里我們應(yīng)當(dāng)注意:數(shù)組開辟的空間盡量不要大,過大容易造成硬件資源不足,無法開辟滿足要求的寄存器。
今天就對HLS從C/C++到VHDL的轉(zhuǎn)換大致說到這里,由于剛接觸這一塊,難免有所紕漏,歡迎大家指出!
-
vhdl
+關(guān)注
關(guān)注
30文章
817瀏覽量
128374 -
HLS
+關(guān)注
關(guān)注
1文章
130瀏覽量
24216
發(fā)布評論請先 登錄
相關(guān)推薦
怎么從.c轉(zhuǎn)換.m文件到.vhdl文件或.vhdl文件
【正點原子FPGA連載】第一章HLS簡介-領(lǐng)航者ZYNQ之HLS 開發(fā)指南
HLS系列 – High LevelSynthesis(HLS) 從一個最簡單的fir濾波器開始
![<b class='flag-5'>HLS</b>系列 – High LevelSynthesis(<b class='flag-5'>HLS</b>) 從<b class='flag-5'>一</b>個最簡單的fir濾波器開始](https://file1.elecfans.com//web2/M00/A6/A6/wKgZomUMP2SAVfhOAAAk8A9f4Ao222.png)
HLS系列 – High Level Synthesis(HLS) 的一些基本概念1
![<b class='flag-5'>HLS</b>系列 – High Level Synthesis(<b class='flag-5'>HLS</b>) 的<b class='flag-5'>一</b>些基本概念1](https://file1.elecfans.com//web2/M00/A6/A6/wKgZomUMP2SAGWF6AABC7raKSag141.png)
關(guān)于ZYNQ HLS圖像處理加速總結(jié)的分享
![關(guān)于ZYNQ <b class='flag-5'>HLS</b>圖像處理加速總結(jié)的分享](https://file1.elecfans.com//web2/M00/A6/A6/wKgZomUMP2WATcXZAAApcxFzek0234.png)
C到VHDL的編譯器設(shè)計與實現(xiàn)詳解
TCL腳本簡介 vivado hls 的設(shè)計流程
![TCL腳本簡介 vivado <b class='flag-5'>hls</b> 的設(shè)計流程](https://file1.elecfans.com//web2/M00/A7/4A/wKgZomUMQ5yAdOyKAAAgcR3a9yo765.png)
EE-128:C++中的DSP:從C++調(diào)用匯編類成員函數(shù)
![EE-128:<b class='flag-5'>C++</b>中的DSP:<b class='flag-5'>從</b><b class='flag-5'>C++</b>調(diào)用匯編類成員函數(shù)](https://file.elecfans.com/web1/M00/D9/4E/pIYBAF_1ac2Ac0EEAABDkS1IP1s689.png)
嵌入式編程中C語言到C++詳解
如何使用xilinx的HLS工具進行算法的硬件加速
使用網(wǎng)絡(luò)實例比較FPGA RTL與HLS C/C++的區(qū)別
![使用網(wǎng)絡(luò)實例比較FPGA RTL與<b class='flag-5'>HLS</b> <b class='flag-5'>C</b>/<b class='flag-5'>C++</b>的區(qū)別](https://file.elecfans.com/web2/M00/1F/69/pYYBAGGYHhaAZJRcAABX4pHw8Gc695.png)
Vitis HLS相關(guān)問答詳解
C++在Linux內(nèi)核開發(fā)中從爭議到成熟
![<b class='flag-5'>C++</b>在Linux內(nèi)核開發(fā)中<b class='flag-5'>從</b>爭議<b class='flag-5'>到</b>成熟](https://file1.elecfans.com/web2/M00/BF/FC/wKgaomW55OmAWdjiAAA0L7Qc6Co977.png)
評論