天天看點

HLS:接口完整學習與綜合測試

目錄

    • 一、引言
    • 二、案例
    • 三、實驗
    • 四、小結
    • 五、時間線

一、引言

之前HLS工具幫忙生成的m_axi和s_axi接口,可以很簡單的挂接到PS端,進行通信。這次學習的是其他接口的lab,這些接口雖然不能直接與PS端進行通信,但與dma等子產品進行組合後,也可以完成與PS端的通信。

之是以要學其他接口,是因為m_axi和s_axi接口功能特定,無法自己更改成自己想要的讀寫方式。

HLS生成電路:接口功能+子產品功能,都可以按照自己的想要的生成。

涉及的接口:ap_hs、ap_fifo、ap_ack、ap_vld、ap_ovld、ap_stable、ap_memory、ap_none和ap_bus。

二、案例

以一個FIR(有限沖擊響應濾波器)的例子,來實驗這些接口。

HLS:接口完整學習與綜合測試

1、fir.h檔案。

#ifndef __FIR_H__
#define __FIR_H__

typedef int dtype;
// volatile表示不要對變量進行優化。 為了防止同個變量名讀出的結果一直一樣,避免被優化掉。
void fir(volatile dtype *in,volatile dtype *out,unsigned int length);

#endif
           

2、fir.cpp檔案。

#include "fir.h"

void fir(volatile dtype *in,volatile dtype *out,unsigned int length)
{

	dtype para1,para2,para3;    // 3個參數,表示3個抽頭的濾波器。
	para1=1;para2=1;para3=1; 

	dtype d0=0,d1=0,d2=0;

	for(int i=0;i<length;i++)
	{
		// 每次進來一個數in,就把該數儲存到d1裡,而d1又把數儲存到d2中,如此往複。
		// 每次進來一個數,先做延遲,一個in的就産生一個out出去。
		d2=d1;d1=d0;d0=*in;
		*out=para1*d0+para2*d1+para3*d2;

	}
}
           

3、main.cpp檔案。

#include "fir.h"

int main()
{
	dtype in[10];
	dtype out[10];
	// 指派
	for(int i=0;i<10;i++)
	{
		in[i]=1;
	}
	// 進去10個數,出來10個數
	fir(in,out,10);

	return 0;
}
           

4、預期目标。

一個周期,in一個數,out一個數。至少周期數是length。

三、實驗

1、第一次嘗試。

第一次綜合的結果出現了問号,這是因為length的長度是不确定的,綜合工具也不知道需要多少個latency才能完成一個功能。一種比較笨的方法,是可以直接把length改成定值,後續再改回來就好,但比較麻煩。有一個選項可以告訴HLS循環多少次,在Vivado HLS Directive Editor的LOOP_TRIPCOUNT中,等價于#pragma HLS LOOP_TRIPCOUNT min=100 max=100 avg=100指令。這個指令隻對性能評估有作用,解決問号的問題,但對子產品的功能,并沒有影響。

HLS:接口完整學習與綜合測試

添加指令後的測試結果。

HLS:接口完整學習與綜合測試

2、第二次嘗試。

首先,看接口部分,in_r的接口類型預設是ap_none,隻有一個端口,沒有啥使能之類的。out_r的類型是ap_vld,表示還有一個out_r_ap_vld信号,當out_r輸出一次時,就會拉高一個周期的out_r_ap_vld脈沖信号,連續輸出十次,就出現拉高out_r_ap_vld信号十個周期。

HLS:接口完整學習與綜合測試

為了做接口部分的修改,先對接口做一個學習。這些接口可以在頁籤中看到。

HLS:接口完整學習與綜合測試

1°ap_none:僅僅有資料,沒有資料有效信号的這種接口,就是ap_none。測試時,把out_r信号的接口給改成ap_none,發現也确實沒有了vld信号。這種ap_none在一個地方有用到,就是組合邏輯的實作時。

HLS:接口完整學習與綜合測試

2°ap_vld:産生一個資料有效的标志。因為,在1°提到的,在資料傳輸中,如果隻單獨有資料信号,在傳輸中無法判斷哪些信号是有效的,必須要一個資料有效信号,而ap_vld接口就産生了這種資料的有效信号。再舉個輸入的例子,如果把in的接口設成ap_vld,那麼當資料輸入時,也會有一個資料的有效信号輸入,如果子產品需要檢測到4個資料輸入後,再進行工作,就會不斷等待4個vld的标志。如果在輸出子產品與輸入子產品之間,都使用ap_vld接口,可以實作點對點的通信,也即相連基本沒有阻礙。但也會存在一個問題,就是後面一個子產品是否可以接收資料,前一個子產品是不知道的,如果一直發出去,後一個子產品無法接收,那還是會出錯。需要一個ready回報信号,變成了3°中的ap_hs信号。

3°ap_hs:handshake,即握手信号,後續用的非常多的一個接口類型。握手是為了解決子產品間是否能通信而誕生的,之前在AXI等很多地方都學過,但一直無法很有把握說自己懂了,這次用一段篇幅整理下。

3_1°舉一個例子,A子產品需要通過握手信号,往B子產品中傳4個資料。握手信号包括vld和ready兩個。

HLS:接口完整學習與綜合測試

3_2°當A子產品資料準備好,放在資料線上後,開始拉高vld信号,但ready信号還是低的,表示子產品B沒有準備好接收資料。

3_3°當B準備好可以接收資料時,ready信号被拉高,此時滿足了vld&ready的結果為1的條件,放在資料線上的資料就被傳入B子產品了。

3_4°B接收完資料。vld信号為高,表示A子產品待輸出的下一個資料也準備好了,放在資料線上了。但B子產品還無法接收,是以資料在資料線上一直保持,直到ready為1,可以接收。并且後面ready和vld持續為1,表示同時發送和接收多個資料了。

3_5°vld為0時,表示A子產品資料還沒有準備好,需要等待下,即使此時ready為1,B子產品可以接資料了,資料線上沒準備好的資料,也不會傳輸到B子產品中。

3_6°這裡将輸入接口和輸出接口設為ap_hs,可以發現輸出多了一個ack信号,就是之前講的ready信号。

HLS:接口完整學習與綜合測試

3_7°仿真跑跑波形。得到下面的圖。

HLS:接口完整學習與綜合測試

4°ap_ack:這種接口相當于ap_hs的特例,即原來的vld信号給去除掉了。資料傳輸時隻有data和ack兩根線,當後一級子產品需要接收X個資料時,就會發出X個脈沖的ack信号,而前一級子產品收到ack為1的情況,就會把資料傳輸給後一級子產品。這種接口适合于前一級子產品的資料都是有效的情況。這種接口其實不是很保險,因為前一級子產品的資料很難做到都有效,或者說很難ack一為高,資料就準備好。

5°ap_fifo:和ap_hs非常的像,會形成一個fifo的通路,ap_hs中的vld和ready相當于ap_fifo中的wr_en和full(read和empty)。更改後綜合的效果如下面這圖。

HLS:接口完整學習與綜合測試

5°ap_ovld:這種接口和ap_vld基本是一樣的,沒啥差別,隻是将輸入的信号設為ap_ovld後,是沒有效果的,隻針對輸出有效。但ap_vld對輸入和輸出都是有效的。

HLS:接口完整學習與綜合測試

6°ap_stable:這個接口和ap_none很像,用于表示某個接口的信号在一次工作期間都是穩定的,用在配置寄存器中非常多,比如fir子產品中的length就可以做成ap_stable的形式,每次工作期間都是個常數,但這次工作和下次工作期間可能會發生變化。再舉個例子:卷積運算時需要KX和KY來配置kernel的大小,33或55,先配置好,單次運算的過程中,并不會發生改變。

7°ap_memory:之前數組就是這種,假設資料來源于存儲器的接口。

7°ap_bus:這種接口是Xilinx自己定義的一個接口,基本上用不着。通常都是用ap_hs來代替其。

HLS:接口完整學習與綜合測試

四、小結

ap_hs最重要,很多都是其變形。ap_stable也是個重點。

五、時間線

一些關鍵時間點的記錄:

2021年04月13日:學習各種接口,并綜合測試。

後續可能做的工作:暫無,但接口的很多思想可以在其他功能設計中展現。