可変長シフトレジスタ

[] [] []


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シミュレーション用であり合成時は読み飛ばすようになっているので、VivadoHLSap_shift_regというキーワードだけ見て、シフトレジスタのRTL記述を生成していると思われる。


[] [] []