FC2カウンター FPGAの部屋 Zybot に超音波距離センサを搭載する3(Vivado HLSでインターフェースIPを作製)

FPGAやCPLDの話題やFPGA用のツールの話題などです。 マニアックです。 日記も書きます。

FPGAの部屋

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。Xilinx ISEの初心者の方には、FPGAリテラシーおよびチュートリアルのページをお勧めいたします。

Zybot に超音波距離センサを搭載する3(Vivado HLSでインターフェースIPを作製)

Zybot に超音波距離センサを搭載する2(Arduino でセンサをテストする)”の続き。

追記:パララックス社の超音波距離センサを使うとするとこの超音波距離センサ用インターフェースIP にはバグがあります。
パララックス社の超音波距離センサは、SIG 1ポートのみで、インターフェースIPからのトリガパルスと超音波距離センサからの距離のパルスの両方が入出力されます。よって、sensor_in をHLS ストリームで宣言しているとインターフェースIPが自分で出力したトリガパルスもsensor_in に入ってきてこれを計測してしまいます。
これについては修正版のブログを後で掲載します。
超音波距離センサー HC-SR04 だと、トリガパルスの長さを 10 us に変更する必要がありますが、Trig ピンと Echo ピンに入力と出力が分かれているので、この超音波距離センサ・インターフェースIPを使うことができると思います。

(2016/12/08 : 追記)
最後から2番目のタイミング波形を見るとトリガパルスが出ている間は、sensor_in の ack が 0 になっていて、信号を受け付けないことが示されています。つまり、vld を 1 に固定して、sensor_in に 超音波距離センサのSIG を入れていると、ack が 0 なので、トリガパルスは無視されると思います。つまり、このIP で問題なく動作すると思います。

前回はArduino を使用して秋月電子の「パララックス社超音波距離センサーモジュール」を使ってみた。今回は、「パララックス社超音波距離センサーモジュール」を使うためのインターフェースIP をVivado HLS で作製してみよう。

Vivado HLS 2016.3 で ultrasonic_sensor_inf プロジェクトを新規作成した。ソースファイルとして ultrasonic_sensor_inf.cpp とテストベンチファイルとして、ultrasonic_sensor_inf_tb.cpp を作成した。
Ultrasonic_senser_inf_7_161206.png

ultrasonic_sensor_inf.cpp を示す。クロック周波数は 100 MHz とする。
(2016/12/08 : 追記)Loop_mesure_high ループに入ったときに、すでに1つ sensor_in に 1 が来ていたので、Loop_mesure_high ループの開始を 1 にしました。

// ultrasonic_sensor_inf.cpp
// 2016/12/05 by marsee
// count_val は超音波距離センサからのパルス長を示す。単位は 10 ns とする
// 
// ライセンスは二条項BSDライセンス (2-clause BSD license)とします。
//

#include <stdio.h>
#include <string.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include <ap_utils.h>

#define COUNT_LIMIT    2000000 // clock = 100MHz, 20ms

int ultrasonic_sensor_inf(int &count_val, volatile ap_uint<1> &sensor_out,
        volatile ap_uint<1> &sensor_out_en, hls::stream<ap_uint<1> >& sensor_in){
#pragma HLS INTERFACE ap_hs port=sensor_in
#pragma HLS INTERFACE ap_none register port=sensor_out_en
#pragma HLS INTERFACE ap_none register port=sensor_out
#pragma HLS INTERFACE s_axilite port=count_val
#pragma HLS INTERFACE s_axilite port=return

    int cnt;
    ap_uint<1> sensor_in_node;

    Loop_1out5us: for(cnt=0; cnt<500; cnt++){ // 5 us のパルスを出力
#pragma HLS PIPELINE II=1
        sensor_out = 1;
        sensor_out_en = 1;
    }

    sensor_out = 0;
    Loop_wait1us: for(cnt=0; cnt<100; cnt++){ // 1 us の間 senser_out に 0 を保持
#pragma HLS PIPELINE II=1
        sensor_out = 0;
        sensor_out_en = 1;
    }

    sensor_out_en = 0// sensor_out のバッファをディスエーブル

    Loop_wait_high: for(cnt=0; cnt<COUNT_LIMIT; cnt++){
#pragma HLS PIPELINE II=1
        sensor_in >> sensor_in_node;
        if((int)sensor_in_node)
            break;
    }
    if(cnt == COUNT_LIMIT)
        return(1); // error, overflow

    Loop_mesure_high: for(cnt=1; cnt<COUNT_LIMIT; cnt++){ // リミットは 20 ms
#pragma HLS PIPELINE II=1
#pragma HLS LOOP_TRIPCOUNT min=11500 max=1850000 avg=20000
        sensor_in >> sensor_in_node;
        if(!(int)sensor_in_node)
            break;
    }

    count_val = cnt;
    if (cnt == COUNT_LIMIT)
        return(2); // error, overflow
    else
        return(0); // normal end
}


ultrasonic_sensor_inf_tb.cpp を示す。
(2016/12/08 : 追記) Pulse width を表示するようにしました。

// ultrasonic_sensor_inf_tb.cpp
// 2016/12/06 by marsee
//
// ライセンスは二条項BSDライセンス (2-clause BSD license)とします。
//

#include <ap_int.h>
#include <hls_stream.h>

int ultrasonic_sensor_inf(int &count_val, volatile ap_uint<1> &sensor_out,
        volatile ap_uint<1> &sensor_out_en, hls::stream<ap_uint<1> >& sensor_in);

int main(){
    using namespace std;

    hls::stream<ap_uint<1> > sensor_in;
    int count_val;
    ap_uint<1> sensor_out, sensor_out_en;
    int return_val;

    for(int i=0; i<75600; i++){ // 756 us wait
        sensor_in << (ap_uint<1>)0;
    }
    for(int i=0; i<20000; i++){ // 200 usの間 sensor_in を 1 にする
        sensor_in << (ap_uint<1>)1;
    }
    for(int i=0; i<20000; i++){ // 1 usの間 sensor_in を 0 にする
        sensor_in << (ap_uint<1>)0;
    }

    return_val = ultrasonic_sensor_inf(count_val, sensor_out, sensor_out_en, sensor_in);

    if(return_val){
        printf("Error: return_val = %d\n");
        exit(1);
    }

    printf("Pulse width = %f us\n", (float)count_val/100.0);

    return(0);
}


C シミュレーションを行った。
Ultrasonic_senser_inf_8_161206.png

C コードの合成を行った。
Ultrasonic_senser_inf_9_161206.png

C/RTL協調シミュレーションを行った。96242 クロックかかった。
Ultrasonic_senser_inf_10_161206.png

C/RTL協調シミュレーションの波形を示す。
sensor_in_V_V を見ると予定の 200 us に対して 200.01 us の間 1 になっている。
Ultrasonic_senser_inf_11_161207.png

sensor_out_V は5.02 us の間 1 になって、sensor_out_en_V は 6.03 us の間 1 になっていた。これで問題ない。
Ultrasonic_senser_inf_12_161207.png

sensor_out_en_V が 0 になるまで、sensor_in_V_V_ap_ack が 0 になっていて、sensor_in が受け取れない状況になっている。この時に sensor_out にトリガパルスが出ているので、このトリガパルスは無視されるはずだ。

AXI4-Lite Slave のアドレスマップを示す。

//------------------------Address Info-------------------
// 0x00 : Control signals
//        bit 0  - ap_start (Read/Write/COH)
//        bit 1  - ap_done (Read/COR)
//        bit 2  - ap_idle (Read)
//        bit 3  - ap_ready (Read)
//        bit 7  - auto_restart (Read/Write)
//        others - reserved
// 0x04 : Global Interrupt Enable Register
//        bit 0  - Global Interrupt Enable (Read/Write)
//        others - reserved
// 0x08 : IP Interrupt Enable Register (Read/Write)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved
// 0x0c : IP Interrupt Status Register (Read/TOW)
//        bit 0  - Channel 0 (ap_done)
//        bit 1  - Channel 1 (ap_ready)
//        others - reserved
// 0x10 : Data signal of ap_return
//        bit 31~0 - ap_return[31:0] (Read)
// 0x18 : Data signal of count_val
//        bit 31~0 - count_val[31:0] (Read)
// 0x1c : Control signal of count_val
//        bit 0  - count_val_ap_vld (Read/COR)
//        others - reserved
// (SC = Self Clear, COR = Clear on Read, TOW = Toggle on Write, COH = Clear on Handshake)


アドレスマップによると count_val は 0x18 番地だということがわかる。
もう一度、C/RTL協調シミュレーションの波形の終わりのほうを見てみよう。
Ultrasonic_senser_inf_13_161207.png

0x18 番地が Read され、20000 という値であることがわかる。

次には、IOBUF のIP を作ってVivado のIPI で接続しよう。
  1. 2016年12月08日 23:07 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
http://marsee101.blog19.fc2.com/tb.php/3654-1455a8d8
この記事にトラックバックする(FC2ブログユーザー)