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

[] [] []


パイプライン型トップ階層の例として、配列din[N]をパラレルポートとして入力して和を出力する回路の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[N] // (i) input data

  ,dout_t *dout // (o) output data

);

#endif

/* dut.cpp */

#include "dut.h"

void dut_hls

  (din_t din[N] // (i) input data

  ,dout_t *dout // (o) output data

) {

  #pragma HLS interface ap_ctrl_none port=return

  #pragma HLS interface ap_hs port=din

  #pragme HLS aggregate variable=din compact=bit

  #pragma HLS array_reshape variable=din complete

  #pragma HLS interface ap_hs register port=dout

  #pragma HLS pipeline II=1 style=flp

  dout_t acc = 0;

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

    acc += din[i];

  }

  *dout = acc;

}

◇◇

Cのテストベンチ

/* main.cpp */

#include <iostream>

#include "dut.h"

using namespace std;

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

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

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

void dut_golden(din_t din[N],dout_t dout) {

  int acc = 0;

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

    acc += din[i];

  }

  cout << "-- dout= " << dout;

  if(dout==acc) {

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

  } else {

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

  }

}

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

 * メインルーチン

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

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

  din_t din[N];

  dout_t dout;

 

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

    din[i] = i+1;

  }

  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               din_vld = 1'b0;

reg[N-1:0][7:0] din;

wire[7+WN:0]    dout;

 

dut_hls dut

  (.ap_clk(clk)

  ,.ap_rst(rst)

  ,.din_ap_ack (din_ack)        // (o)

  ,.din_ap_vld (din_vld)        // (i)

  ,.din          (din)           // (i)

  ,.dout_ap_ack (1'b1)          // (i)

  ,.dout_ap_vld (dout_vld)      // (o)

  ,.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

  repeat(num) @(posedge clk)

    begin

    din_vld <= 1'b1;

    for(int i=0; i<N; i++) din[i] <= base + i;

    base = base + 1'b1;

    end

  @(posedge clk);

  din_vld <= 1'b0;

  din <= 'bx;

  end

endtask

/* モニタ */

always @(negedge clk) begin

  if(~rst)

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

              ,$time,din_vld,din,dout_vld,dout);

end

/* シナリオ */

initial begin

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

  rst = 1'b1;

  #(15)

  rst = 1'b0;

  din_burst(.base(8'd1),.num(1));       // 1連続入力

  din_burst(.base(8'd2),.num(2));       // 2連続入力

  repeat(5) @(posedge clk);

  $finish;

end

endmodule


[] [] []