Cコード例 - 1個ずつ入力して直近N個の和を1個ずつ出力する回路

[] [] []


シフトレジスタ型の例として、データを1個ずつ入力して直近N個の和を1個ずつ出力する回路のCコードを示す。

合成対象のCコード

/* dut.h */

#ifndef DUT_H

#define DUT_H

#include <ap_int.h>

static const int N=10; // number of din

static const int WN=4; // bit width of N

typedef ap_int<8> din_t;

typedef ap_int<8+WN> dout_t;

void dut_hls

  (din_t  din   // (i) input data

  ,dout_t *dout // (o) output data

);

#endif

/* dut.cpp */

#include "dut.h"

void dut_hls

  (din_t  din   // (i) input data

  ,dout_t *dout // (o) output data

) {

  #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 dout_t d[N];

  #pragma HLS array_patition variable=d complete

  #pragma HLS reset variable=d  // リセット端子をつける

  *dout = d[N-1];

  for(int i=N-1; i>0; i--) {

    d[i] = d[i-1] + din;

  }

  d[0] = din;

}

◇◇

Cのテストベンチ

/* main.cpp */

#include <iostream>

#include "dut.h"

using namespace std;

/************************

 * サブルーチン - 期待値比較

 ************************/

void dut_golden(din_t din,dout_t dout) {

  static dout_t d[N];

  dout_t dout_tmp;

  dout_tmp = d[N-1];

  for(int i=N-1; i>0; i--) {

    d[i] = d[i-1] + din;

  }

  d[0] = din;

  cout << "-- din=" << din;

  cout << " dout= " << dout;

  if(dout==dout_tmp) {

    cout << "[PASS]" << endl;

  } else {

    cout << "[FAIL]" << endl;

  }

}

/************************

 * メインルーチン

 ************************/

int main(int argc,char *argv[]) {

  din_t  din;

  dout_t dout;

  for(int i=0; i<=2*N; i++) {

    din = (i<N)? (i+1) : 0;

    dut_hls(din,&dout);

    dut_golden(din,dout);

  }

  return 0;

}

◇◇

合成後RTLのテストベンチ

/* tb.sv */

`timescale 1ns/1ps

module tb;

parameter N=10;          // number of din

parameter WN=$clog2(N); // bit width of N

reg clk;

reg rst;

reg[7:0]    din;

wire[7+WN:0] dout;

 

dut_hls dut

  (.ap_clk(clk)

  ,.ap_rst(rst)

  ,.din (din)           // (i)

  ,.dout(dout)          // (o)

  );

/* クロック生成 */

initial begin

  clk = 1'b1;

  forever #(5) clk = ~clk; // 10ns

end

/* ドライバタスク */

task din_burst

  (input[7:0] base      // din[i]=base+i

  ,input int num        // 連続入力数

  );

  begin

  for(int i=0; i<num; i++) begin

    @(posedge clk);

    din     <= base+i;

  end

  for(int i=0; i<2*N-num; i++) begin

    @(posedge clk);

    din     <= 8'd0;

  end

  end

endtask

/* モニタ */

always @(negedge clk) begin

  if(~rst)

    $display("--(%t) din=%h dout=%h"

              ,$time,din,dout);

end

/* シナリオ */

initial begin

  $timeformat(-6,3," us",10);

  rst = 1'b1;

  #(15)

  rst = 1'b0;

  din_burst(.base(8'd2),.num(1));

  din_burst(.base(8'd1),.num(N));

  repeat(5) @(posedge clk);

  $finish;

end

endmodule


[] [] []