可変長シフトレジスタ
Xilinx社のFPGAではLUT-RAMがシフトレジスタとして使えるようになっている。これを合成させるにはRTLではリセットなしのシフトレジスタを書けばよい(→LUT-RAMを使ったシフトレジスタのRTL記述)が、高位合成ではCコードで次のようにシフトレジスタを書いてもこのRTL記述にはならず、リセットなしFFのシフトレジスタとそれをMUX出力したようなRTL記述になり、必ずしもLUT-RAMは使われない。
例) × 可変長シフトレジスタ、必ずしもLUT-RAMは使われない
/* dut.cpp */ #include "dut.h" void dut_hls (dat_t din // (i) input data ,dat_t *dout // (o) output data ,loc_t loc // (i) location of output ) { #pragma HLS interface ap_ctrl_none port=return #pragma HLS interface ap_none port=din #pragma HLS interface ap_none port=dout #pragma HLS pipeline II=1 static dat_t d[N]; #pragma HLS array_patition variable=d complete *dout = d[loc]; for(int i=N-1; i>0; i--) { d[i] = d[i-1]; } d[0] = din; } |
ただし
*dout = d[N-3]; |
のように、固定長ならばただのリセットなしFFのシフトレジスタのRTL記述になるのでLUT-RAMが使われる。
ここでVitisHLSの設定で、全FFでなく制御信号のFFだけにリセットが付く設定にしておく必要がある。
◇
VitisHLSではLUT-RAMを使うRTL記述が合成されるように「ap_shift_regクラス」が用意されており、これを使う必要がある。
例) 〇 可変長シフトレジスタ、必ずLUT-RAMが使われる
/* dut.cpp */ #include "dut.h" #include <ap_shift_reg.h> void dut_hls (dat_t din // (i) input data ,dat_t *dout // (o) output data ,loc_t loc // (i) location of output (0 to N-1) ) { #pragma HLS interface ap_ctrl_none port=return #pragma HLS interface ap_none port=din #pragma HLS interface ap_none port=dout #pragma HLS pipeline II=1 // データ型 dat_t,N段のシフトレジスタ ap_shift_reg<dat_t,N> sreg; // 0段目にdinを入力し,loc段目から出力する *dout = sreg.shift(din,loc); } |
ちなみにap_shift_reg.hを見ると、コードはあくまでCシミュレーション用であり合成時は読み飛ばすようになっているので、VivadoHLSはap_shift_regというキーワードだけ見て、シフトレジスタのRTL記述を生成していると思われる。