FC2カウンター FPGAの部屋
FC2ブログ

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

FPGAの部屋

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

「記憶にございません!」(映画)見てきました

今日は午後から奥さんと「記憶にございません!」(映画)見てきました。中居貴一がいい味出してました。笑っちゃいました。とっても良かったです。ストレスが解消されましたよ。。。
  1. 2019年09月16日 21:48 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

同じ Vivado HLS IP を複数個インスタンスした場合、Vivado 2018.3 でハードウェアをエクスポートしてSDKを立ち上げたときにその他のVivado HLS のIPのドライバがSDKのハードウェア・プラットフォームに入らない

Vivado 2018.3 でハードウェアをエクスポートしてSDKを立ち上げたときに、同じ Vivado HLS IP を複数個インスタンスした場合、その他のVivado HLS のIPのドライバが入らないという問題があったので、ブログに書いておく。多分バグじゃないのかな?

Vivado 2018.3 の sums_ex4 プロジェクトを示す。このプロジェクトはZybo Z7-10 用のプロジェクトだ。
SDK_bug_1_190914.png

sums_bd ブロックデザインを示す。
SDK_bug_2_190914.png

ブロックデザインを見ると DMA2axis8 IP が 2 つあるのが分かる。これらは、DDRメモリからDMA Read を行って、s_squares_axis IP にAIX4-Stream でデータを供給し、平方数の和を取って、axis2DMA IP にAIX4-Stream でデータを送る。axis2DMA IP はAXI4-Stream で送られてきたデータをDMA Write するというような回路になっている。
s_squares_axis IP のソースコードは”2つのAXI4 Stream 入力データを演算してAXI4 Stream 出力1”だ。
DMA2axis8.cpp を貼っておく。

// DMA2axis8.cpp (2019/09/10 by marsee)

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

int DMA2axis8(volatile ap_int<8> *in, hls::stream<ap_axis<8,1,1,1> >& outs){
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE m_axi depth=10 port=in offset=slave
    ap_axis<8,1,1,1> out_val;

    for(int i=0; i<10; i++){
#pragma HLS PIPELINE II=1
        out_val.data = in[i];
        if(i == 0)
            out_val.user = 1;
        else
            out_val.user = 0;
        if(i==9)
            out_val.last = 1;
        else
            out_val.last = 0;
        outs << out_val;
    }
    return(0);
}


axis2DMA.cpp を貼っておく。

// axis2DMA.cpp (2018/05/18 by marsee)

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

int axis2DMA(hls::stream<ap_axis<32,1,1,1> >& ins, volatile ap_int<32> *out){
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=10 port=out offset=slave
#pragma HLS INTERFACE axis register both port=ins
    ap_axis<32,1,1,1> in_val;

    for(int i=0; i<10; i++){
#pragma HLS PIPELINE II=1
        ins >> in_val;
        out[i] = in_val.data;
    }
    return(0);
}


論理合成、インプリメンテーション、ビットストリームの生成を行った。レポートを示す。
SDK_bug_3_190914.png
SDK_bug_4_190914.png

ハードウェアをエクスポートしてSDKを立ち上げた。
SDK_bug_5_190914.png

axis2DMA, DMA2axis8, s_squares_axis が入っているのは見えるが、ハードウェア・プラットフォームの drivers には、DMA2axis8 しか入っていないのが分かる。これだと他のVivado HLS IP のドライバ関数が使用できなかった。

次に Vivado 2018.3 で sums_ex4_temp プロジェクトを作成した。
SDK_bug_6_190914.png

sums_bd ブロックデザインを示す。
SDK_bug_7_190914.png

DMA2axis8 を 1 個のみインスタンスして、他は Constant で代用した。
これで論理合成、インプリメンテーション、ビットストリームの生成を行った。レポートを示す。
SDK_bug_8_190914.png
SDK_bug_9_190914.png

これでハードウェアをエクスポートしてSDKを立ち上げたところ、ハードウェア・プラットフォームには、3 個のVivado HLS で作成したIP のドライバが入っている。
SDK_bug_10_190914.png

やはり、Vivado 2018.3 のブロックデザインでVivado HLS で作成したIP を複数個入れているとSDK のハードウェア・プラットフォーム上に他のVivado HLS IP のドライバがロードされないようだ。バグじゃないだろうか?

なお、Vivado HLS IP のドライバがハードウェア・プラットフォームに入っていないことの回避方法としては、”SDKにVivado HLSで作製したIPのドライバをインポートする”がある。
この方法で、local Repositories か Global Repositories にIP のフォルダを追加しておけばよい。今回は、Global Repositories にIP のフォルダを追加した。これでVivado HLS で作成した IP のドライバを使えるようになる。
  1. 2019年09月15日 04:50 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Ultra96-V2 の高速、低速コネクタ用PMOD 拡張基板1

Ultra96-V2 の低速コネクタに接続する PMOD 拡張基板を作ってきたが、PMOD が 2 個だと、CMOS カメラを接続するので、精一杯で、ロボットを動かすPWM を出力するPMOD が確保できなかった。よって、高速コネクタのピンも使用して、最大PMOD 6 個出力できるようにしようと思う。

当初は、低速コネクタのPMOD 拡張基板と高速コネクタの拡張基板を分けようと思っていたのだが、Ultra96-V2 の回路図を見ると高速コネクタに電源の出力がない。回路図を一部を引用する。
Ultra96V2_HL_exp_board_1_190913.png

低速コネクタの方には、+5V と+VCC_PSAUX (1.8V) が出力されているので、高速コネクタと一緒に低速コネクタ用のヘッダを基板に搭載する必要がある。回路図の一部を引用する。
Ultra96V2_HL_exp_board_2_190913.png

やはり +5.0V を電源に使用する必要がある。+5.0V は 6A ということなので、電流容量に不安はないはず。
高速コネクタのFPGA 出力ピンの電圧はほとんど 1.2V ということが分かった。制約ファイル Ultra96_constraints_180318.xdc の一部を引用する。

# ----------------------------------------------------------------------------
# High-speed expansion connector
# ---------------------------------------------------------------------------- 
# Bank 65
set_property PACKAGE_PIN P1   [get_ports {CSI0_C_N                }];  # "P1.CSI0_C_N"
set_property PACKAGE_PIN N2   [get_ports {CSI0_C_P                }];  # "N2.CSI0_C_P"
set_property PACKAGE_PIN N4   [get_ports {CSI0_D0_N               }];  # "N4.CSI0_D0_N"
set_property PACKAGE_PIN N5   [get_ports {CSI0_D0_P               }];  # "N5.CSI0_D0_P"
set_property PACKAGE_PIN M1   [get_ports {CSI0_D1_N               }];  # "M1.CSI0_D1_N"
set_property PACKAGE_PIN M2   [get_ports {CSI0_D1_P               }];  # "M2.CSI0_D1_P"
set_property PACKAGE_PIN M4   [get_ports {CSI0_D2_N               }];  # "M4.CSI0_D2_N"
set_property PACKAGE_PIN M5   [get_ports {CSI0_D2_P               }];  # "M5.CSI0_D2_P"
set_property PACKAGE_PIN L1   [get_ports {CSI0_D3_N               }];  # "L1.CSI0_D3_N"
set_property PACKAGE_PIN L2   [get_ports {CSI0_D3_P               }];  # "L2.CSI0_D3_P"
set_property PACKAGE_PIN T2   [get_ports {CSI1_C_N                }];  # "T2.CSI1_C_N"
set_property PACKAGE_PIN T3   [get_ports {CSI1_C_P                }];  # "T3.CSI1_C_P"
set_property PACKAGE_PIN R3   [get_ports {CSI1_D0_N               }];  # "R3.CSI1_D0_N"
set_property PACKAGE_PIN P3   [get_ports {CSI1_D0_P               }];  # "P3.CSI1_D0_P"
set_property PACKAGE_PIN U1   [get_ports {CSI1_D1_N               }];  # "U1.CSI1_D1_N"
set_property PACKAGE_PIN U2   [get_ports {CSI1_D1_P               }];  # "U2.CSI1_D1_P"
set_property PACKAGE_PIN H5   [get_ports {DSI_CLK_N               }];  # "H5.DSI_CLK_N"
set_property PACKAGE_PIN J5   [get_ports {DSI_CLK_P               }];  # "J5.DSI_CLK_P"
set_property PACKAGE_PIN F1   [get_ports {DSI_D0_N                }];  # "F1.DSI_D0_N"
set_property PACKAGE_PIN G1   [get_ports {DSI_D0_P                }];  # "G1.DSI_D0_P"
set_property PACKAGE_PIN E3   [get_ports {DSI_D1_N                }];  # "E3.DSI_D1_N"
set_property PACKAGE_PIN E4   [get_ports {DSI_D1_P                }];  # "E4.DSI_D1_P"
set_property PACKAGE_PIN D1   [get_ports {DSI_D2_N                }];  # "D1.DSI_D2_N"
set_property PACKAGE_PIN E1   [get_ports {DSI_D2_P                }];  # "E1.DSI_D2_P"
set_property PACKAGE_PIN C3   [get_ports {DSI_D3_N                }];  # "C3.DSI_D3_N"
set_property PACKAGE_PIN D3   [get_ports {DSI_D3_P                }];  # "D3.DSI_D3_P"
set_property PACKAGE_PIN C2   [get_ports {HSIC_DATA               }];  # "C2.HSIC_DATA"
# Bank 66
set_property PACKAGE_PIN A2   [get_ports {HSIC_STR                }];  # "A2.HSIC_STR"
# Bank 26
set_property PACKAGE_PIN E8   [get_ports {CSI0_MCLK               }];  # "E8.CSI0_MCLK"
set_property PACKAGE_PIN D8   [get_ports {CSI1_MCLK               }];  # "D8.CSI1_MCLK"


制約ファイルに書いてあったが、Bank 26 は 1.8V 、Bank 65 は 1.2V だそうだ。

# IO standard for Bank 26 Vcco supply is fixed at 1.8V
# IO standard for Bank 65 Vcco supply is fixed at 1.2V


となると 1.2V 電源を用意する必要があるが、1.8V だと秋月電子のシリーズ・レギュレータに対応品があるが、1.2V だとない。
そこで、可変電圧レギュレータを使うことにしようと思う。
ムラタ表面実装DC-DCコンバーター OKL-T/3-W5N-C
◆入力電圧:DC2.4V~5.5V(3V/5V兼用)
◆出力電圧:0.6V~3.63V(可変)
◆出力電流:最大3A
なので、良さそうだ。
1.2V 出力のときの抵抗は 2.0 kΩだそうだ。
表面実装品の抵抗は秋月電子では5% 精度なので、これだけはアキシャルでよいか。
小型 金属皮膜抵抗1/4W2kΩ(100本入)
「従来の1/6Wと同サイズの小型1/4W、±1%の金属皮膜抵抗です。」ということなので、小さくて良さそうだ。
  1. 2019年09月13日 05:33 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

2つのAXI4 Stream 入力データを演算してAXI4 Stream 出力2

2つのAXI4 Stream 入力データを演算してAXI4 Stream 出力1”の続き。

普通の C ソースコードで、2つのAXI4 Stream 入力からデータを受け取る方法を見つけたので、ソースコードを貼って、C シミュレーションを行った。今回は、C コードの合成、C/RTL 協調シミュレーション、Export RTL を行う。なお、Vivado HLS 2019.1 を使用している。

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

Loop2 のLatency が 11 クロックと長めだが、1 クロックで 1 出力できるようだ。
リソース使用量はBRAM_18K は 0 個、DSP48E は 1 個、FF が 282 個、LUT が 676 個だった。

C/RTL 協調シミュレーションを行った。
s_squares_axis_4_190912.png

Latency は 44 クロックだった。

C/RTL 協調シミュレーション波形を示す。全体波形から。
s_squares_axis_5_190912.png

データ転送している辺りを拡大してみよう。
s_squares_axis_6_190912.png

入力 x と y は途中で、TREADY が 0 になってうけらない部分はあるが、その後は順調に 1 入力を 1 クロックでこなしている。
出力は、順調に 1 出力を 1 クロックでこなせている。

Export RTL を行った。結果を示す。
s_squares_axis_7_190912.png

LUT が 141 個、FF が 189 個、DSP が 2 個、使用されている。
CP achieved post-implementation は、 6.859 ns で問題無さそうだ。
  1. 2019年09月12日 04:39 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Ultra96のPMOD拡張ボード計画(高速、低速コネクタをPMODへ変換)の部品調査結果の覚書2

Ultra96のPMOD拡張ボード計画(高速、低速コネクタをPMODへ変換)の部品調査結果の覚書”の続き。

前回は、Ultra96のコネクタや拡張ボードを作るためのコネクタについて考察した。
石原ひでみさんの”FPGAの内容の薄い本2”を見て、改めてPMOD X 6 個のボードを作りたくなったので、もう一度コネクタを考えてみよう。

Hi speedコネクタ 5177983-2
勘合する相手方コネクタ たぶんコネクタ勘合時の高さ 8mmの5179031-2
MIPI Adapter Mezzanineカードを入れると少し斜めになっている(低速コネクタより高速コネクタの高さが高い)。だが、そうでないとUSBコネクタの金属部分に基板が当たってしまうためだろう?
Mouser https://www.mouser.jp/ProductDetail/TE-Connectivity-AMP/5179031-2?qs=sGAEpiMZZMvffgRu4KC1R8rBJR2XJ4CGVDXQfomnbnc%3D
データシート https://www.mouser.jp/datasheet/2/418/NG_CD_5179031_A4-1251986.pdf

Ultra96 と MIPI Adapter Mezzanine が勘合した時の高さは 7.9 mm 。低速コネクタの勘合高は 7.3 mm で 0.5 mm 斜めになっている。低速コネクタ高さは基板から 6.5 mm だった。

コネクタ高さ 12.5 mm と 9.5 mm の低速コネクタ用ヘッダを買ったのだが、標準ヘッダとの高さは 3 mm刻みだった。

石原ひでみさんの”FPGAの内容の薄い本2”で知った”96Boards Consumer Edition Low Cost Hardware Platform Specification Version 1.0, January 2015”にExpansion Board Connectors が載っている。
TE 5179030-2: High speed”は、高さ 6.6 mm のコネクタだったので、”5179031-2”よりも背が低いPULGコネクタとなっている。

もう1つHi Speed 用のPULG コネクタは、”FCI 61083-063400LF”で、これは、6.7 mm の高さのPULG コネクタになっている。データシートを見ると、4.7 mm, 5.7 mm, 6.7 mm, 7.7 mm の 4 種類の高さのコネクタがあるようだ。

MIPI Adapter Mezzanineカードでは、7.7 mm の高さのコネクタが使用されている。
値段は、”5179031-2”が 1 個で 454 円、”61083-064400LF”が 615 円なので、”5179031-2”が良さそうだ。
もっと背の高いPULG コネクタは無さそうなので、斜めになってしまうな。。。
またまたIDAさんからHi Speed コネクタの KiCad モデルについて教えてもらった。


低速コネクタ用のヘッダは、表面実装品よりも背が多少低いが秋月電子の”2mmピッチピンヘッダ 2×40 (80P)”にしよう。
理由は、表面実装品だと位置がいい加減になってしまって、コネクタに入らないことがあるかも知れないからだ。スルーホールだったら、Ultra96に入れといて、はんだ付けすればバッチリ。ちょっと怖いけど。。。

PMOD コネクタ 2X6P が欲しいのだが、MOUSERで検索できない。分かる方型番教えてください。
IDAさんに教えてもらいました。ありがとうございました。
SSW-106-02-T-D-RA
10 個で 126 円なので、秋月電子の 2.5 倍の価格か。。。でも割らなくて良いので、この方が見栄えも良いな。。。

中国の部品屋さんをIDAさんに教えてもらいました。ありがとうございます。
Changjiang Connectors A2541HWR-2x6P

レベル変換ICのプルアップ抵抗
PMOD 1 個のみ 1608 の 1 kΩを 8 個実装して、後は集合抵抗を実装する。

集合抵抗
チップネットワーク抵抗器 CND2A10Y 1kΩ (5個入)
http://akizukidenshi.com/catalog/g/gP-10717/

上の秋月電子の集合抵抗のパッケージ互換品(データシートのフットプリント例も参考になる)
CAT25-102JALF
https://www.mouser.jp/ProductDetail/Bourns/CAT25-102JALF?qs=sGAEpiMZZMvrmc6UYKmaNYMTSqkpbtN5ShD9l70ohz4%3D
  1. 2019年09月11日 04:34 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

2つのAXI4 Stream 入力データを演算してAXI4 Stream 出力1

以前、”2つのHLSストリームを同時に入力して演算してHLSストリーム出力2”でDATAFLOW 指示子を使って、2 つのHLS Stream 入力を同時に受け取ることができた。
しかし、その方法は大げさというかソースコードが分かりにくくなるため、普通の C ソースコードで、2つのAXI4 Stream 入力からデータを受け取る方法を見つけたので、書いておく。

s_squares_axis.cpp のコンセプトは、user == 1 だったら、AXI4 Stream 入力を止めて、2 つのAXI4 Steam 入力が共に user == 1 になることを待つということだ。
それでは、s_squares_axis.cpp を貼っておく。

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

int s_squares_axis(hls::stream<ap_axis<8,1,1,1> >& x,
    hls::stream<ap_axis<8,1,1,1> >& y, hls::stream<ap_axis<32,1,1,1> >& result){
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE axis register both port=result
#pragma HLS INTERFACE axis register both port=y
#pragma HLS INTERFACE axis register both port=x
    ap_axis<8,1,1,1> xt;
    ap_axis<8,1,1,1> yt;
    ap_axis<32,1,1,1> rlt;

    xt.user = 0; yt.user = 0;
    Loop1 : while(!(xt.user==1 && yt.user==1)){
#pragma HLS PIPELINE II=1
    // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        if(xt.user == 0)
            x >> xt;
        if(yt.user == 0)
            y >> yt;
    }

    Loop2 : for(int i=0; i<10; i++){
#pragma HLS PIPELINE II=1
        if(i != 0){
            x >> xt; y >> yt;
        }
        rlt.data = xt.data*xt.data + yt.data*yt.data;
        if(i == 0)
            rlt.user = 1;
        else
            rlt.user = 0;
        if(i==9)
            rlt.last = 1;
        else
            rlt.last = 0;
        result << rlt;
    }
    return(0);
}


なお、いつもの do{ } while( ); 文を使用すると、PIPELINE 指示子の II を 1 にしても、ループを 1 回回るのに 2 クロックかかってしまう。 do{ } while( ); 文を使用すると、ストリーム用のパイプから入力した user 信号をそのクロックで処理する必要があるから、1 クロックで処理することができなくなってしまうのだろう? while() 文を使用すると、現在のクロックでストリーム用のパイプから入力した user 信号は次のクロックで評価することができるので、ループを 1 回回るのに 1 クロックで済むのだと思う。
このように、ソフトウェアとしてではなく、ハードウェアとして、ソースコードを書く必要がある。

次に、テストベンチの s_squares_axis_tb.cpp を示す。

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

int s_squares_axis(hls::stream<ap_axis<8,1,1,1> >& x,
    hls::stream<ap_axis<8,1,1,1> >& y, hls::stream<ap_axis<32,1,1,1> >& result);

int main(){
    using namespace std;
    hls::stream<ap_axis<8,1,1,1> > x;
    hls::stream<ap_axis<8,1,1,1> > y;
    hls::stream<ap_axis<32,1,1,1> > result;
    ap_axis<8,1,1,1> xt;
    ap_axis<8,1,1,1> yt;
    ap_axis<32,1,1,1> rlt;

    for(int i=0; i<5; i++){ // dummy data
        xt.user = 0; yt.user = 0;
        xt.data = i; yt.data = i;
        x << xt;
        if(i>2)
            y << yt;
    }
    for(int i=0; i<10; i++){
        xt.data = i; yt.data = i+1;
        if(i == 0){
            xt.user = 1; yt.user = 1;
        }else{
            xt.user = 0; yt.user = 0;
        }
        if(i == 9){
            xt.last = 1; yt.last = 1;
        }else{
            xt.last = 0; yt.last = 0;
        }
        x << xt; y << yt;
    }
    s_squares_axis(x, y, result);

    cout << endl;
    cout << "result" << endl;
    for(int i=0; i<10; i++){
        result >> rlt;
        cout << "i = " << i << " result = " << rlt.data << " user = "
                << rlt.user << " last = " << rlt.last << endl;
    }
    cout << endl;
    return(0);
}


AXI4 Stream の x パイプでは、5 つのダミーデータを入れてあるが、y パイプでは、2 つになっている。これで、本体のデータを正常に受けることができれば成功だ。

s_squares_axis2 プロジェクトを示す。
s_squares_axis_1_190910.png

C シミュレーションを行った。問題ないようだ。
s_squares_axis_2_190910.png
  1. 2019年09月10日 05:08 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

台風15号で暴風雨です

今日は、台風15号が来ていて暴風雨となっています。雨風強くて不安な早朝です。
今日は技術的なブログはお休みで、強い直撃台風15号のことを日記として書いておこうと思います。
台風15号は今、横須賀市付近ですが、これから茨城県に来るようです。
taifu15_1_190909.jpg

ファクサイは、960 hPa の強い台風で最大瞬間風速は 60 m/s です。怖いですね。。。アンテナが飛ばされないかどうか?不安です。
taifu15_2_190909.png

雨雲レーダーが真っ赤というのは、経験が無いやばい状態ですね。特にこれから台風がやってくるというのが怖いです。
taifu15_3_190909.jpg

なんとか被害が無いことを祈ります。。。

(結果)
千葉と違って、風は強かったんですが、ものすごい暴風とまでは行かなかった感じです。被害なくてよかったですが、千葉は停電もしているようでかわいそうです。
職場ではメインで使用しているパソコンが壊れました。サブのVivado 用パソコンをメインに仕立てていました。メースソフトをインストール、設定してさてメールを出そうという時にネットワーク・スイッチが壊れました。orz
気圧が低いとコンデンサが膨れやすくて、壊れやすいということがあるのでしょうか?厄日でした。。。
  1. 2019年09月09日 04:48 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0
»