トップ階層の回路タイプ
トップ階層はCの関数で書くがRTLのmoduleと異なるのは、moduleの中が無限ループ(always文)なのに対して、Cの関数は上から下まで実行したら終了してしまう点である。そこで普通は、トップの関数には入力開始からそれに対する出力完了までの一連の動作を書き、それがステートマシンとして合成される。ただこれだと出力が完了するまで次の入力を開始できないが、RTL記述のように1クロック分の動作を書いて、パイプライン型またはシフトレジスタ型の回路を合成させることもできる。
◇
(1) 非パイプライン型のトップ階層
・複数クロック分の入力開始からそれに対する出力完了までの一連の動作を書く
・出力完了まで次の入力は開始できない
・入力開始から出力完了までのクロック数(レイテンシ)はおまかせになる
例) 1個ずつ3回入力して和を1回出力
void dut (ap_uint<8> din[3] // (i) ,ap_uint<8> *dout // (o) ) { #pragma HLS interface ap_ctrl_none port=return #pragma HLS interface ap_hs port=din #pragma HLS interface ap_hs port=dout for(int i=0; i<=2; i++) { acc += din[i]; } *dout = acc; } |
◇◇
(2) パイプライン型のトップ階層
・1クロック分の入力からそれに対する出力の動作を書いてpragma HLS pipelineを指定する
・出力完了前に次の入力を入れてよい
・入力から出力までクロック数(レイテンシ)はおまかせになる
例) 3個を1回入力して和を1回出力
void dut (ap_uint<8> din[3] // (i) ,ap_uint<8> *dout // (o) ) { #pragma HLS interface ap_ctrl_none port=return #pragma HLS interface ap_hs port=din #pragma HLS interface ap_hs port=dout #pragma HLS array_reshape variable=din complete #pragma HLS pipeline II=1 style=flp for(int i=0; i<=2; i++) { acc += din[i]; } *dout = acc; } |
◇◇◇
(3) シフトレジスタ型のトップ階層
・1クロック分のFFの代入を出力側から順に書いてpragma HLS pipelineを指定する
・関数は1クロック毎に終了するが、次クロックへ値が残るようにFFはstatic宣言する
例) 1個ずつ入力して直近3個の和を1個ずつ出力
void dut (ap_uint<8> din // (i) ,ap_uint<8> *dout // (o) ) { #pragma HLS interface ap_ctrl_none port=return #pragma HLS pipeline II=1 static ap_uint<8> d[3]; *dout = d[2]; for(int i=2; i>=1; i--) { d[i] = d[i-1] + din; } d[0] = din; } |
◇◇◇◇
なお、普通の非パイプライン型のトップ階層の中でも、下位関数やループにpragma HLS pipelineを指定すればパイプライン型の回路が合成され、さらに代入を出力側から順にかけばシフトレジスタ型の回路が合成される。
dut(...) { ... /* ループにpragmaを指定すればパイプライン型回路になる */ for(int i=0; i<=2; i++) { #pragma HLS pipeline II=1 acc += din[i]; } ... /* 代入を出力側から順に書けばシフトレジスタ型回路になる */ for(...) { #pragma HLS pipeline II=1 *dout = d[2]; for(int i=2; i>=1; i--) { d[i] = d[i-1] + din; } d[0] = din; } ... } |