FC2カウンター FPGAの部屋 2019年06月
FC2ブログ

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

FPGAの部屋

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

hls4mlをやってみた2(KERAS_3layer ネットワークの構成)

hls4mlをやってみた1”の続き。

前回は、Vivado HLS を使用して機械学習をハードウェア化するフレームワークのhls4ml をインストールし、KERAS_3layer ネットワークをVivado HLS のプロジェクトとして生成し、C シミュレーション、C コードの合成、C/RTL 協調シミュレーション、Export RTL をTCL スクリプトで行った。今回は、Vivado HLS のIP として生成した KERAS_3layer ネットワークがどのようななネットワークか知らないので、調べていこう。

まずは myproject.cpp を貼っておく。

//
//    rfnoc-hls-neuralnet: Vivado HLS code for neural-net building blocks
//
//    Copyright (C) 2017 EJ Kreinar
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.
//
#include <iostream>

#include "myproject.h"

//hls-fpga-machine-learning insert weights
#include "weights/w2.h"
#include "weights/b2.h"
#include "weights/w4.h"
#include "weights/b4.h"
#include "weights/w6.h"
#include "weights/b6.h"
#include "weights/w8.h"
#include "weights/b8.h"

void myproject(
    input_t input_1[N_INPUT_1_1],
    result_t layer9_out[N_LAYER_8],
    unsigned short &const_size_in_1,
    unsigned short &const_size_out_1
) {

    //hls-fpga-machine-learning insert IO
    #pragma HLS ARRAY_RESHAPE variable=input_1 complete dim=0 
    #pragma HLS ARRAY_RESHAPE variable=layer9_out complete dim=0 
    #pragma HLS INTERFACE ap_vld port=input_1,layer9_out 
    #pragma HLS PIPELINE 

    const_size_in_1 = N_INPUT_1_1;
    const_size_out_1 = N_LAYER_8;

    // ****************************************
    // NETWORK INSTANTIATION
    // ****************************************

    //hls-fpga-machine-learning insert layers

    layer2_t layer2_out[N_LAYER_2];
    #pragma HLS ARRAY_PARTITION variable=layer2_out complete dim=0
    nnet::dense<input_t, layer2_t, config2>(input_1, layer2_out, w2, b2);

    layer3_t layer3_out[N_LAYER_2];
    #pragma HLS ARRAY_PARTITION variable=layer3_out complete dim=0
    nnet::relu<layer2_t, layer3_t, relu_config3>(layer2_out, layer3_out);

    layer4_t layer4_out[N_LAYER_4];
    #pragma HLS ARRAY_PARTITION variable=layer4_out complete dim=0
    nnet::dense<layer3_t, layer4_t, config4>(layer3_out, layer4_out, w4, b4);

    layer5_t layer5_out[N_LAYER_4];
    #pragma HLS ARRAY_PARTITION variable=layer5_out complete dim=0
    nnet::relu<layer4_t, layer5_t, relu_config5>(layer4_out, layer5_out);

    layer6_t layer6_out[N_LAYER_6];
    #pragma HLS ARRAY_PARTITION variable=layer6_out complete dim=0
    nnet::dense<layer5_t, layer6_t, config6>(layer5_out, layer6_out, w6, b6);

    layer7_t layer7_out[N_LAYER_6];
    #pragma HLS ARRAY_PARTITION variable=layer7_out complete dim=0
    nnet::relu<layer6_t, layer7_t, relu_config7>(layer6_out, layer7_out);

    layer8_t layer8_out[N_LAYER_8];
    #pragma HLS ARRAY_PARTITION variable=layer8_out complete dim=0
    nnet::dense<layer7_t, layer8_t, config8>(layer7_out, layer8_out, w8, b8);

    nnet::softmax<layer8_t, result_t, softmax_config9>(layer8_out, layer9_out);


}


myproject .cpp と parameters.h から推定した層構成を示す。

入力層 16 入力
dense 16 入力 64 出力
relu
dense 64 入力 32 出力
relu
dense 32 入力 32 出力
relu
dense 32 入力 5 出力
softmax 5 出力


入力、出力のデータ型は、ap_fixed<16,6> だった。

IP の入力と出力のフォーマットだが、 myproject.cpp で dim=0 で ARRAY_RESHAPE ディレクティブが書かれている。
よって、入力の input_1 が ap_fixed<16,6> が 16 個なので、256 ビット幅となり、
出力の layer9_out が ap_fixed<16,6> が 5 個なので、 80 ビット幅となっている。
myproject.vhd の entity 部分を引用する。

entity myproject is
port (
    ap_clk : IN STD_LOGIC;
    ap_rst : IN STD_LOGIC;
    ap_start : IN STD_LOGIC;
    ap_done : OUT STD_LOGIC;
    ap_idle : OUT STD_LOGIC;
    ap_ready : OUT STD_LOGIC;
    input_1_V_ap_vld : IN STD_LOGIC;
    input_1_V : IN STD_LOGIC_VECTOR (255 downto 0);
    layer9_out_V : OUT STD_LOGIC_VECTOR (79 downto 0);
    layer9_out_V_ap_vld : OUT STD_LOGIC;
    const_size_in_1 : OUT STD_LOGIC_VECTOR (15 downto 0);
    const_size_in_1_ap_vld : OUT STD_LOGIC;
    const_size_out_1 : OUT STD_LOGIC_VECTOR (15 downto 0);
    const_size_out_1_ap_vld : OUT STD_LOGIC );
end;

  1. 2019年06月30日 05:23 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

注文したDonkey Car が来ました

「AI RCカー勉強会@柏の葉「Donkey Carハンズオン」」に行ってきました”でハンズオンしたDonkey Car を思い切って買っちゃいました。お値段は、4万円ですが、消費税 3,200円に送料が 2,500 円付いて、総額 45,700 円でした。
それで、先週の木曜日6月27日に届きました。

箱を開けるとラジコンカーの箱とジョイスティックが入ってました。
donkey_car_1_190630.jpg

箱の中身です。
donkey_car_2_190630.jpg

ラジコンカーの箱を開けるとDonkey Car の部品が入っていました。
donkey_car_3_190630.jpg

Donkey Car を作って、まずはノーマルで走らせてみたいです。十分遊んだら、Ultra96 + Pcam5C に載せ替えてシステム構築してみたいですね。。。
  1. 2019年06月30日 04:50 |
  2. Donkey Car
  3. | トラックバック:0
  4. | コメント:0

hls4mlをやってみた1

hls4ml をやってみた。hls4ml はVivado HLS を使用して機械学習をハードウェア化するフレームワークだ。
なお、OS は Ubuntu 18.04 を使用している。

インストール前の環境のインストールは、Setup -> Dependencies を見れば分かるが、numpy,h5py, pyyaml, PyTorch, scikit-learn だ。だいたいインストールされていると思うので、ここは飛ばす。後で不具合が出たらインストールを確認することにする。

次に、Setup -> Quick Start をやってみよう。
まずは、リポジトリを git clone する。
git clone https://github.com/hls-fpga-machine-learning/hls4ml.git
hls4ml_1_190628.png

hls4ml ディレクトリの内容を示す。
hls4ml_2_190628.png

Quick Start に従ってやっていこう。
cd hls4ml/keras-to-hls/
2to3 -w keras-to-hls.py

hls4ml_3_190628.png

cd ../hls-writer/
2to3 -w hls_writer.py

hls4ml_4_190628.png

Vivado 2019.1 WebPACK なので、指定されたFPGA が無いため、hls4ml/keras-to-hls/keras-config.yml ファイルの XilinxPart を WebPACKでも使えるUltraScale+ (xcku5p-sfvb784-1-e) に変更した。
hls4ml_5_190628.png

cd ../keras-to-hls/
python keras-to-hls.py -c keras-config.yml

hls4ml_6_190628.png

my-hls-test ディレクトリが生成された。Viavdo HLS 2019.1 を設定して、build.tcl をVivado HLS 2019.1 で実行した。
cd my-hls-test/
ls
source /tools/Xilinx/Vivado/2019.1/settings64.sh
vivado_hls -f build_prj.tcl

hls4ml_7_190628.png

終了するまで、時間かかりました。
hls4ml_8_190629.png

Vivado HLS 2019.1 をGUI 付きで立ち上げ、my-hls-test/myproject_prj ディレクトリのVivado HLS プロジェクトをロードした。
vivado_hls &
hls4ml_9_190629.png

C コードの合成済みなので、レポートを見てみよう。
hls4ml_10_190629.png
hls4ml_11_190629.png

凄い。Latency が 15 クロックで、Interval が 1 だった。つまり、15 クロックで出力できて、次のクロックには次のデータ入れられるということね。。。それで 200 MHz 動作か。
でもWebPACK で使えるFPGA だと、DSP48E がオーバーフローしてしまっている。実装のリソースをDSP48E に集めているのかも?

Analysis を見てみよう。
hls4ml_12_190629.png

hls4ml_13_190629.png

softmax にクロック数がかかっている。
  1. 2019年06月29日 04:51 |
  2. DNN
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作6(ZYBO Z7-20 編)

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作6(PYNQ編3)”の続き。

今年も筑波大学でやる予定のVivado HLS 勉強会の出し物として、 AXI4 Stream 版のラプラシアンフィルタの実習用回路を作成することにした。勉強会というかセミナでは、なかなか機材が揃わないのでカメラを用意することができない。よって、画像は、C のヘッダ・ファイルに変換した画像を使用してラプラシアンフィルタをかけてディスプレイに表示した。前回は、PYNQ の実機で動作を確認できた。今回は、ZYBO Z7-20 で同様に動作を確認する。

まずは、Vivado HLS 2017.4 で lapfilter_axis_zybo_z7_20 プロジェクトを作成した。
IP をコピーしてIP Catalog に登録し、ブロック・デザイン lapfilter_axis を作成して回路を構成した。
lapfilter_axis_zybo_36_190628.png

lapfilter_axis_zybo_37_190628.png

lapfilter_axis_zybo_38_190628.png

回路が出来上がったので、制約ファイル lapfilter_axis.xdc を追加した。

set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_0_B_p]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_1_R_p]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_2_G_p]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_clk_p]
set_property PACKAGE_PIN H16 [get_ports TMDS_tx_clk_p]
set_property PACKAGE_PIN D19 [get_ports TMDS_tx_0_B_p]
set_property PACKAGE_PIN C20 [get_ports TMDS_tx_1_R_p]
set_property PACKAGE_PIN B19 [get_ports TMDS_tx_2_G_p]

set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks [get_clocks -of_objects [get_pins lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]]]

set_false_path -from [get_clocks [get_clocks -of_objects [get_pins lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]]] -to [get_clocks clk_fpga_0]


論理合成、インプリメンテーション、ビットストリームの生成を行った。結果を示す。
lapfilter_axis_zybo_39_190628.png
lapfilter_axis_zybo_40_190628.png

タイミング違反もなく、問題なさそうだ。
ハードウェアをエクスポートし、SDK を起動した。
lapfilter_axis アプリケーション・プロジェクトを作成し、lapfilter_axis.c と bmp_data.h をコピーした。
lapfilter_axis_zybo_41_190628.png

SDK からビットストリームをPYNQ にダウンロードして、アプリケーションソフトを起動するとTeraTerm に表示が出て、ディスプレイにも画像が出た。
lapfilter_axis_zybo_32_190626.png

lapfilter_axis_zybo_16_190623.jpg

TeraTerm 上で、 1 を入力すると、回路上で、AXI4 Stream が切り替わって、ラプラシアンフィルタの画像が表示された。
lapfilter_axis_zybo_17_190623.jpg

ZYBO Z7-20 でも成功した。
  1. 2019年06月28日 04:00 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作6(PYNQ編3)

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作5(PYNQ編2)”の続き。

今年も筑波大学でやる予定のVivado HLS 勉強会の出し物として、 AXI4 Stream 版のラプラシアンフィルタの実習用回路を作成することにした。勉強会というかセミナでは、なかなか機材が揃わないのでカメラを用意することができない。よって、画像は、C のヘッダ・ファイルに変換した画像を使用してラプラシアンフィルタをかけてディスプレイに表示した。前回は、PYNQ でIP を使用して、ディスプレイに表示する回路を構成し、論理合成、インプリメンテーション、ビットストリームの生成を行った。今回は、SDK でアプリケーションソフトを作成し、PYNQ の実機での動作を確認してみよう。

Vivado 2017.4 でハードウェアをエクスポートし、SDK を起動した。
lapfiler_axis アプリケーション・プロジェクトを作成し、”Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作3”で作成した lapfilter_axis.c を lapfilter_axis/src フォルダに追加した。更に、bmp_data.h の画像のヘッダ・ファイルも lapfilter_axis/src フォルダに追加した。
lapfilter_axis_zybo_31_190626.png

SDK からビットストリームをPYNQ にダウンロードして、アプリケーションソフトを起動するとTeraTerm に表示が出て、ディスプレイにも画像が出た。
lapfilter_axis_zybo_32_190626.png

lapfilter_axis_zybo_16_190623.jpg

TeraTerm 上で、 1 を入力すると、回路上で、AXI4 Stream が切り替わって、ラプラシアンフィルタの画像が表示された。
lapfilter_axis_zybo_17_190623.jpg

PYNQ でも成功した。
  1. 2019年06月27日 04:59 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作5(PYNQ編2)

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作4(PYNQ編1)”の続き。

今年も筑波大学でやる予定のVivado HLS 勉強会の出し物として、 AXI4 Stream 版のラプラシアンフィルタの実習用回路を作成することにした。勉強会というかセミナでは、なかなか機材が揃わないのでカメラを用意することができない。よって、画像は、C のヘッダ・ファイルに変換した画像を使用してラプラシアンフィルタをかけてディスプレイに表示した。PYNQ でIP を使用して、ディスプレイに表示する回路を構成し、論理合成、インプリメンテーション、ビットストリームの生成を行ったが、インプリメンテーションしたときにタイミング違反になり、Vivado HLS で修正を試みた。しかし、C コードの合成結果が異なるもののExport RTLのレポートに変化が無かった。やはりこれは何かがおかしいということでもう一度、やってみることにした。

Vivado HLS 2017.4 で、solution1 の impl フォルダを削除してからExport RTL をやってみたところ、やはり、Export RTL のレポートに変化はなかった。そこで、solution2 を作って、Uncertainty を 2 ns に設定して、C コードの合成を行った。
lapfilter_axis_zybo_33_190627.png

Export RTL を行った。CP achieved post-implementation は 6.607 ns で変化があった。
lapfilter_axis_zybo_34_190627.png

これでラプラシアンフィルタ IP が再生成されたので、Vivado の lapfilter_axis_pynq プロジェクトのラプラシアンフィルタ IP を変更した。次に、” Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作4(PYNQ編1)”で変更した ZYNQ の PS の FCLK_CLK0 の周波数を 90 MHz から 100 MHz に戻した。
これでもう一度、論理合成、インプリメンテーション、ビットストリームの生成を行った。結果を示す。
lapfilter_axis_zybo_35_190627.png

タイミング違反は無くなった。
やはり、solution1 のExport RTL を行ってもファイルが更新されなくなっていたようだ。どれかのファイルを見て、そのアクセス権が解消されなくなったのだろうか?新しい solution を作れば問題なかった。

Vivado HLS で Uncertainty を変更してレポートも変わったのに、Export RTL のVivado の解析結果が変わらない場合は、新しい solution を作ってやってみると良いと思う。
  1. 2019年06月27日 04:30 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作4(PYNQ編1)

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作3”の続き。

(2019/06/27:追記)この記事で、Vivado HLS のC コードの合成結果が変わっても、Export RTL のレポートが変更されなかった問題は、solution を新たに作成すると解消されました。詳しくは、”Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作5(PYNQ編2)”をご覧ください。

今年も筑波大学でやる予定のVivado HLS 勉強会の出し物として、 AXI4 Stream 版のラプラシアンフィルタの実習用回路を作成することにした。勉強会というかセミナでは、なかなか機材が揃わないのでカメラを用意することができない。よって、画像は、C のヘッダ・ファイルに変換した画像を使用してラプラシアンフィルタをかけてディスプレイに表示した。前回までは、ZYBO だったが、今回はPYNQ を使用することにする。同様に、IP を使用して、ディスプレイに表示する回路を構成し、論理合成、インプリメンテーション、ビットストリームの生成を行っていこう。

PYNQ はボード・ファイルが存在しないので、設定用ファイルとして、Digilent 社の”PYNQ-Z1”のページから”Zynq Presets”をダウンロードして、使用する。

さて、Vivado 2017.4 を使用して、プロジェクトを作成し、ブロック・デザインを生成しよう。

Vivado 2017.4 を立ち上げて、lapfilter_axis_pynq プロジェクトを作成した。
lapfilter_axis_zybo_16_190625.png

lapfilter_axis ブロック・デザインを作成した。
PS をAdd IP し、PYNQ のPS 設定情報をロードした。PS の設定情報のロードについては、”PYNQボードでカメラ画像をリアルタイムにFASTX コーナー検出1”を参照のこと。
IP をAdd IP して接続し、ブロック・デザインを完成させた。
lapfilter_axis_zybo_17_190625.png

Address Editor を示す。
lapfilter_axis_zybo_30_190626.png

制約ファイルのlapfilter_axis.xdc を示す。

set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_0_B_p]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_1_R_p]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_2_G_p]
set_property IOSTANDARD TMDS_33 [get_ports TMDS_tx_clk_p]
set_property PACKAGE_PIN K17 [get_ports TMDS_tx_0_B_p]
set_property PACKAGE_PIN K19 [get_ports TMDS_tx_1_R_p]
set_property PACKAGE_PIN J18 [get_ports TMDS_tx_2_G_p]
set_property PACKAGE_PIN L16 [get_ports TMDS_tx_clk_p]

set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks [get_clocks -of_objects [get_pins lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]]]

set_false_path -from [get_clocks [get_clocks -of_objects [get_pins lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]]] -to [get_clocks clk_fpga_0]


clk_fpga_0 と pclk_buf 間のFalse Path 制約も入れてある。

これで、論理合成、インプリメンテーション、ビットストリーム生成を行った。Project Summary を示す。
lapfilter_axis_zybo_18_190625.png

Timing のエラーが出ている。
Open Implemented Design をクリックして、タイミングの情報を見てみると、clk_fpga_0 のラプラシアンフィルタ IP 内でタイミングのエラーが出ていた。
lapfilter_axis_zybo_19_190625.png

こうなると、Vivado HLS に戻って、ラプラシアンフィルタ IP のタイミングを改善しよう。(ほんの少しのタイミング違反なので、Vivado に頑張ってもらって、タイミングを改善する方法もあるが、時間がかかる)

現在のVivado HLS でのラプラシアンフィルタ IP の性能は、CP achieved post-implementation が 9.421 ns でタイミングを満たしているが、ギリギリだ。
lapfilter_axis_zybo_20_190625.png

現在のC コードの合成時のEstimated は 10.75 ns だった。
lapfilter_axis_zybo_21_190625.png

Vivado HLS 2017.4 の Solution メニューから Solution Settings... を選択して、Synthesis を選択し、Uncertainty を 2 ns に設定した。
lapfilter_axis_zybo_22_190625.png

これで C コードの合成を行った。結果を示す。
lapfilter_axis_zybo_23_190625.png

Estimated は 8.95 ns とだいぶ改善した。
しかし、Export RTL の結果は、CP achieved post-implementation が 9.421 ns で変化が無い。
lapfilter_axis_zybo_24_190625.png

もう一度、Vivado HLS 2017.4 の Solution メニューから Solution Settings... を選択して、Synthesis を選択し、Uncertainty を 3 ns に設定した。
lapfilter_axis_zybo_25_190625.png

C コードの合成を行った。結果を示す。
lapfilter_axis_zybo_26_190625.png

Estimated は 9.40 ns となり、Uncertainty を 2 ns にしたときよりも結果が悪くなった。
もう一度、Export RTL をやってみると、やはり、CP achieved post-implementation が 9.421 ns で変化が無い。

Uncertainty を 5 ns にすると、C コードの合成結果は更に良くなったが、Export RTL をやってみると、やはり、CP achieved post-implementation が 9.421 ns で変化が無い。
lapfilter_axis_zybo_27_190625.png

いくらUncertainty を変更しても回路に変更はないようだ。Vivado HLS では時としてこういうこともある。

ということで、回路の改善は望めないので、動作周波数を変更しよう。
DMAからAXI4 Stream に変換する、またはその逆のIP のスループットは 2 クロックで 1 転送になっている。現在は 100 MHz で駆動しているので、50 MHz で 1 クロックで 1 転送しているのと同じことになる。表示する SVGA のピクセル・クロックは 40 MHz なので、40 MHz に 1 転送できれば十分である。ということで、クロックを下げる余地があることが分かる。よってクロックを 100 MHz から 90 MHz に変更しよう。

ブロック・デザインの processing_system7_0 をダブルクリックして開き、FCLK_CLK0 を 90 MHz に設定する。
lapfilter_axis_zybo_28_190625.png

これで、もう一度、論理合成、インプリメンテーション、ビットストリーム生成を行った。Project Summary を示す。
lapfilter_axis_zybo_29_190625.png

これでタイミング制約も満足した。
  1. 2019年06月26日 04:22 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

FPGAの部屋のまとめサイトの更新(2019年6月24日)

FPGAの部屋のまとめサイトを更新しました。Donkey Car, ROS, Jetson Nano の記事を追加して、その他の記事を更新しました。
  1. 2019年06月24日 20:32 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

「AI RCカー勉強会@柏の葉「Donkey Carハンズオン」」に行ってきました

AI RCカー勉強会@柏の葉「Donkey Carハンズオン」」に行ってきました。

Donkey Car はRaspberry Pi 3+ + Pi Camera で動作するロボットカー・キットです。4 輪駆動車をベースにしていて前輪の向きを変えて曲がることができます。ジョイスティックで自分でコースを走らせて、学習データを取得します。Raspberry Pi 3+ のアプリケーションソフトで、学習データを作成して、それを Google のColab にアップロードして学習します。そのモデルをDonkey Car に入れてコースを走らせます。

最初にDonkey Car を組み立てましたが、さほど苦労せずに組み立てることができました。
DonkeyCar_1_190623.jpg

パソコンでマニュアルを見ながらやっています。後で、SSH でRaspberry Pi 3+ に入るときや、SFTP で学習データをRaspberry Pi 3+ から取り出すときや、学習済みモデルをRaspberry Pi 3+ にアップロードするときにもパソコンを使いました。
DonkeyCar_2_190623.jpg

Donkey Car を無線LAN に接続します。
DonkeyCar_3_190623.jpg

学習データを取得するアプリケーションソフトを起動して、Donkey Car を走らせます。学習データはJPG ファイルとステアのアングルとスロットルのデータが書かれたJSON ファイルの組でした。これを 5000 個程度取得しました。
DonkeyCar_4_190623.jpg
DonkeyCar_5_190623.jpg
DonkeyCar_6_190623.jpg

とにかく、私には走らせるのが難しいですね。。。練習が必要でした。ですので、学習データの質は推して知るべしです。。。

学習データをColab にアップロードして学習させます。
学習が終了したら、生成されたモデルをダウンロードしてRaspberry Pi 3+ にアップロードします。
そして、他の方ですが、学習済みモデルで走らせているところです。
DonkeyCar_7_190623.jpg

私のは、学習の時にスピードが出てなかったので、スロットルの値が低く、そのままでは走り出しませんでしたが、ズルしてスロットルに下駄をはかせて走るようにしました。でも学習データがよろしくなく、途中でコースアウトしちゃいました。
とっても面白かったです。それにツールが充実しているのがとっても良いですね。Zybot と違ってステアリング切れるし、欲しくなりました。4万円だそうです。買っちゃおうかな?でも、コースが取れないんですよね。特に今回のDonkey Car はスピード出るので、ある程度の広さの場所が必要です。

Donkey Car ではないですが、JetBot を持ってきていらっしゃる方がいらしゃいました。
DonkeyCar_8_190623.jpg
  1. 2019年06月23日 04:49 |
  2. Donkey Car
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作3

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作2”の続き。

今年も筑波大学でやる予定のVivado HLS 勉強会の出し物として、 AXI4 Stream 版のラプラシアンフィルタの実習用回路を作成することにした。ということで、前回までは、Windows 10 の Vivado 2017.4 で lapfilter_axis_zybo プロジェクトを作成し、lap_filter_axis 、axis2DMA2st と DMA2axis2st IP をリポジトリに登録し、lapfilter_axis ブロック・デザインを新規作成して、IP をAdd IP して、回路を作り始めた。今回は、回路を完成させて、論理合成、インプリメンテーション、ビットストリームの生成を行った。今回は、ハードウェアをエクスポートして、SDK を起動し、アプリケーションソフトを作成して実機確認を行う。

ハードウェアをエクスポートして、SDK を起動した。
そして、lapfilter_axis.c という名前のアプリケーションソフトを作成した。
lapfilter_axis_zybo_14_190623.png

lapfilter_axis.c のソースコードを貼っておく。

/*
 * lapfilter_axis.c
 *
 *  Created on: 2019/06/21
 *      Author: marsee
 */

#include <stdio.h>
#include "xil_io.h"
#include "xparameters.h"

#include "xlap_filter_axis.h"
#include "xdma2axis.h"
#include "xaxis2dma2st.h"
#include "bmp_data.h"

#define FRAME_BUFFER_ADDRESS 0x10000000
#define DMA_DEST_ADDRESS 0x10200000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

int bmp_write(unsigned int addr);

int main(){
    XLap_filter_axis xlf_axis_ap;
    XDma2axis xdma2axis_ap;
    XAxis2dma2st xaxis2dma_ap;
    int inbyte_in;

    XLap_filter_axis_Initialize(&xlf_axis_ap, 0);
    XDma2axis_Initialize(&xdma2axis_ap, 0);
    XAxis2dma2st_Initialize(&xaxis2dma_ap, 0);

    XDma2axis_Set_y_size(&xdma2axis_ap, (u32)VERTICAL_LINES);
    XDma2axis_Set_x_size(&xdma2axis_ap, (u32)HORIZONTAL_PIXELS);
    XDma2axis_Set_sel(&xdma2axis_ap, (u32)0);
    XDma2axis_Set_in_V(&xdma2axis_ap, (u32)FRAME_BUFFER_ADDRESS);

    XAxis2dma2st_Set_y_size(&xaxis2dma_ap, (u32)VERTICAL_LINES);
    XAxis2dma2st_Set_x_size(&xaxis2dma_ap, (u32)HORIZONTAL_PIXELS);
    XAxis2dma2st_Set_sel(&xaxis2dma_ap, (u32)0);
    XAxis2dma2st_Set_out_V(&xaxis2dma_ap, (u32)DMA_DEST_ADDRESS);

    bmp_write(FRAME_BUFFER_ADDRESS);
    bmp_write(FRAME_BUFFER_ADDRESS);

    XAxis2dma2st_Start(&xaxis2dma_ap);
    XLap_filter_axis_Start(&xlf_axis_ap);
    XDma2axis_Start(&xdma2axis_ap);

    Xil_Out32(XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_BASEADDR, DMA_DEST_ADDRESS);

    while(1){
        printf("\nPlease input <0> or <1> (<q> : exit) = ");
        fflush(stdout);
        inbyte_in = inbyte();
        printf("%c", inbyte_in);
        fflush(stdout);
        switch(inbyte_in) {
            case '0': //bmp image
                XDma2axis_Set_sel(&xdma2axis_ap, (u32)0);
                XAxis2dma2st_Set_sel(&xaxis2dma_ap, (u32)0);

                XAxis2dma2st_Start(&xaxis2dma_ap);
                XLap_filter_axis_Start(&xlf_axis_ap);
                XDma2axis_Start(&xdma2axis_ap);
                break;
            case '1': // Laplacian filter
                XDma2axis_Set_sel(&xdma2axis_ap, (u32)1);
                XAxis2dma2st_Set_sel(&xaxis2dma_ap, (u32)1);

                XAxis2dma2st_Start(&xaxis2dma_ap);
                XLap_filter_axis_Start(&xlf_axis_ap);
                XDma2axis_Start(&xdma2axis_ap);
                break;
            case 'q': // exit
                return(0);
        }
    }
}

int bmp_write(unsigned int addr){
    for(int y=0; y<VERTICAL_LINES; y++){
        for(int x=0; x<HORIZONTAL_PIXELS; x++){
            Xil_Out32(addr+(y*HORIZONTAL_PIXELS+x)*sizeof(int),
                ((int)bmp_file_array[y][x][2]<<16)+((int)bmp_file_array[y][x][1]<<8)+(int)bmp_file_array[y][x][0]);
        }
    }
    return(0);
}


なお、bmp_write(FRAME_BUFFER_ADDRESS); を 2 回書いているのは、そうしないと画像にゴミが入ってしまうからだ。もしかしてキャッシュの関係で実は 1 回では書けていないのかもしれない?

SDK からビットストリームをZYBO にダウンロードして、アプリケーションソフトを起動するとTeraTerm に表示が出て、ディスプレイにも画像が出た。
lapfilter_axis_zybo_15_190623.png

lapfilter_axis_zybo_16_190623.jpg

TeraTerm 上で、 1 を入力すると、回路上で、AXI4 Stream が切り替わって、ラプラシアンフィルタの画像が表示された。
lapfilter_axis_zybo_17_190623.jpg

TeraTerm 上で 0 を入力すると、元の画像に戻った。
lapfilter_axis_zybo_16_190623.jpg

これでZYBO 版は完成だが、PYNQ 版とZYBO Z7-20 版も開発する予定だ。
  1. 2019年06月23日 04:11 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作2

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作1”の続き。

今年も筑波大学でやる予定のVivado HLS 勉強会の出し物として、 AXI4 Stream 版のラプラシアンフィルタの実習用回路を作成することにした。ということで、前回は、Windows 10 の Vivado 2017.4 で lapfilter_axis_zybo プロジェクトを作成し、lap_filter_axis 、axis2DMA2st と DMA2axis2st IP をリポジトリに登録し、lapfilter_axis ブロック・デザインを新規作成して、IP をAdd IP して、回路を作り始めた。今回は、回路を完成させて、論理合成、インプリメンテーション、ビットストリームの生成を行う。

まずは、ビットマップ・ディスプレイ・コントローラを追加して、完成したブロック・デザインを示す。
lapfilter_axis_zybo_5_190621.png

アドレスマップを示す。
lapfilter_axis_zybo_6_190621.png

これで、論理合成、インプリメンテーション、ビットストリームの生成を行ったところ、Critical Warning が 1 つ出ている。Open Implemented Design を開いて、タイミングを見た。

clk_fpga_0 to pclk_buf のセットアップ・タイムがエラーだった。
lapfilter_axis_zybo_8_190621.png

Source が lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/bitmap_disp_eng_inst/hv_count_enable_reg/C で、Destination が lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/bitmap_disp_eng_inst/hv_cnt_ena_d1_reg/D だった。
これは、bitmap_disp_eng.v のソースコードのこの部分に相当する。
lapfilter_axis_zybo_9_190621.png

これは、AXI のクロックからディスプレイのクロックに明示的に載せ替えている部分なので、問題無い。

次に pclk_buf から clk_fpga_0 のパスもエラーになっていた。
Source が lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/bitmap_disp_eng_inst/vsyncx_node_reg/C で Destination が lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/bitmap_disp_eng_inst/vsync_axi_b1_reg/D だ。
これは、bitmap_disp_eng.v のソースコードのこの部分に相当する。
lapfilter_axis_zybo_10_190621.png

これも、ディスプレイのクロック・ドメインの信号をAXI のクロック・ドメインの信号に明示的に載せ替えているので、問題無い。

ということで、クロック・ドメイン同士に False Path の設定をした。
制約ファイルを示す。
lapfilter_axis_zybo_11_190621.png

set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[0]}]
set_property PACKAGE_PIN J18 [get_ports {vga_blue[3]}]
set_property PACKAGE_PIN K19 [get_ports {vga_blue[2]}]
set_property PACKAGE_PIN M20 [get_ports {vga_blue[1]}]
set_property PACKAGE_PIN P20 [get_ports {vga_blue[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_blue[4]}]
set_property PACKAGE_PIN G19 [get_ports {vga_blue[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_green[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {vga_red[0]}]
set_property PACKAGE_PIN F20 [get_ports {vga_green[5]}]
set_property PACKAGE_PIN H20 [get_ports {vga_green[4]}]
set_property PACKAGE_PIN J19 [get_ports {vga_green[3]}]
set_property PACKAGE_PIN L19 [get_ports {vga_green[2]}]
set_property PACKAGE_PIN N20 [get_ports {vga_green[1]}]
set_property PACKAGE_PIN H18 [get_ports {vga_green[0]}]
set_property PACKAGE_PIN F19 [get_ports {vga_red[4]}]
set_property PACKAGE_PIN G20 [get_ports {vga_red[3]}]
set_property PACKAGE_PIN J20 [get_ports {vga_red[2]}]
set_property PACKAGE_PIN L20 [get_ports {vga_red[1]}]
set_property PACKAGE_PIN M19 [get_ports {vga_red[0]}]
set_property IOSTANDARD LVCMOS33 [get_ports vga_hsync]
set_property IOSTANDARD LVCMOS33 [get_ports vga_vsync]
set_property PACKAGE_PIN P19 [get_ports vga_hsync]
set_property PACKAGE_PIN R19 [get_ports vga_vsync]

set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks [get_clocks -of_objects [get_pins lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]]]

set_false_path -from [get_clocks [get_clocks -of_objects [get_pins lapfilter_axis_i/bitmap_disp_cntrler_axi_master_0/inst/dvi_disp_i/BUFR_pixel_clk_io/O]]] -to [get_clocks clk_fpga_0]


これで、もう一度、論理合成、インプリメンテーション、ビットストリームの生成を行ったところ、Critical Warning が出なくなって、タイミングもOK になった。
lapfilter_axis_zybo_12_190621.png
lapfilter_axis_zybo_13_190621.png
  1. 2019年06月21日 05:12 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS勉強会用のラプラシアンフィルタ実習用回路の製作1

Zybot のモーター制御回路の製作はひとまずペンディングにして、今年も筑波大学でやる予定のVivado HLS 勉強会の出し物として、 AXI4 Stream 版のラプラシアンフィルタの実習用回路を作成することにした。
下の一連のブログのシリーズはAXI4 Stream 版のラプラシアンフィルタの実習用回路の下準備だったのだ。
Vivado HLS 2019.1 を使用してBMPファイルをC のヘッダファイルに変換する
BMPファイルをC のヘッダファイルに変換したファイルを検証してみた
AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 1
AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 2
AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP 1
AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP 2

ただし、Vivado HLS 勉強会の資料は Vivado HLS 2017.4 で作成されているため、Vivado HLS 2017.4 で、このようにIP を再度作成した。
lapfilter_axis_zybo_1_190620.png

Windows 10 の Vivado 2017.4 で lapfilter_axis_zybo プロジェクトを作成し、lap_filter_axis 、axis2DMA2st と DMA2axis2st IP をリポジトリに登録した。
lapfilter_axis_zybo_3_190620.png

lapfilter_axis_zybo_2_190620.png

lapfilter_axis ブロック・デザインを新規作成して、IP をAdd IP して、回路を作り始めた。まだ途中だけれど下に示す。
lapfilter_axis_zybo_4_190620.png

後はビットマップ・ディスプレイ・コントローラを追加する予定だ。
そして、カメラがない状態でもBMP ファイルを変換した C のヘッダ・ファイルを使用して、ラプラシアンフィルタを通した画像をディスプレイに表示する。これは、主にベアメタル・アプリケーションで画像を表示したいからだ。
  1. 2019年06月20日 05:27 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Zybot のモーターの回転数と回転方向を取得する3(HDLシミュレーションにVivado HLS を使用する2)

Zybot のモーターの回転数と回転方向を取得する2(HDLシミュレーションにVivado HLS を使用する1)”の続き。

HDL を作成したら次はHDL シミュレーションだが、HDL シミュレーションもSA, SB のタイミングを作成する回路をVivado HLS で作ったら、とっても便利なんじゃない?ということで、作ってみた。ということで、前回は、ソースコードをブログに貼った。今回は、C コードの合成、C/RTL 協調シミュレーション、Export RTL(IP として使うことはないのだけれど)を行う。

まずは C コードの合成を行った。結果を示す。
rot_sim_2_190619.png

Estimated が 0 ns なのが変だが、Latency は 40 クロックで合っている。FF と LUT も使用されているということで大丈夫だろう?

次に、C/RTL 協調シミュレーションを行った。
rot_sim_3_190619.png

これも 40 クロックで予定通りだ。

C/RTL 協調シミュレーションの波形を見てみよう。
rot_sim_4_190619.png

sa_V と sb_V からとってもそれらしい波形が出ている。

最後に Export RTL をやってみたが、本当は、IP 化することはないので必要ない。ただし、Vivado synthesis, place and route にチェックを入れてある。
rot_sim_5_190619.png

LUT や FF が使用されているので、大丈夫だろう?
CP achieved post-implementation も 3.095 ns だった。
  1. 2019年06月19日 03:54 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Zybot のモーターの回転数と回転方向を取得する2(HDLシミュレーションにVivado HLS を使用する1)

Zybot のモーターの回転数と回転方向を取得する1”の続き。

HDL を作成したら次はHDL シミュレーションだが、HDL シミュレーションもSA, SB のタイミングを作成する回路をVivado HLS で作ったら、とっても便利なんじゃない?ということで、作ってみた。

作成した Vivado HLS 2019.1 の rot_sim プロジェクトを示す。
rot_sim_1_190618.png

rot_sim.cpp を示す。

// rot_sim.cpp
// 2019/06/15 by marsee
//

#include <ap_int.h>
#include "ap_utils.h"

#define WAIT_COUNT  10

int rot_sim(ap_uint<1> rev, volatile ap_uint<1> &sa, volatile ap_uint<1> &sb){
#pragma HLS INTERFACE ap_none port=sb
#pragma HLS INTERFACE ap_none port=sa
    if(rev == 0){ // Normal rotation
        sa = 0; sb = 0;
        ap_wait_n(WAIT_COUNT);
        sa = 1; sb = 0;
        ap_wait_n(WAIT_COUNT);
        sa = 1; sb = 1;
        ap_wait_n(WAIT_COUNT);
        sa = 0; sb = 1;
        ap_wait_n(WAIT_COUNT);
    }else{
        sa = 0; sb = 0;
        ap_wait_n(WAIT_COUNT);
        sa = 0; sb = 1;
        ap_wait_n(WAIT_COUNT);
        sa = 1; sb = 1;
        ap_wait_n(WAIT_COUNT);
        sa = 1; sb = 0;
        ap_wait_n(WAIT_COUNT);
    }
    return(0);
}


なお、ap_wait_n() は初めて使ったと思うが、”Vivado Design Suite ユーザーガイド 高位合成 UG902 (v2018.3) 2018 年 12 月 20 日”の 90 ページに書いてある。ap_wait_n() を使用すると複数のクロックサイクルの wait を挿入できる。

テストベンチの rot_sim_tb.cpp を示す。これは、SA, SB の極性を変えて、2 回 rot_sim() を呼び出す。

// rot_sim_tb.cpp
// 2019/06/15 by marsee
//

#include <ap_int.h>

int rot_sim(ap_uint<1> rev, ap_uint<1> &sa, ap_uint<1> &sb);

int main(){
    ap_uint<1> sa, sb;

    rot_sim(0, sa, sb);
    rot_sim(1, sa, sb);

    return(0);
}

  1. 2019年06月18日 04:59 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Zybot のモーターの回転数と回転方向を取得する1

以前、Zybot を作成したのだが、モーター回転数を取得する部分はいい加減だった。

Digilent のZYBOt Tutorial
FPGAの部屋のブログのZybot カテゴリ


今回、Zybot のFPGA ボードをUltra96 に変更するにあって、ギアボックス付きモーター回転数と回転方向を取得したい。
以前、Vivado HLS で作ったのだが、いまいち精度が出ていない気がするので、HDL で作り直すことにした。
なお、SA, SB のタイミングチャートは、”Project 10: Frequency Measurement Using Input Capture”の 13 ページの”Figure 2. Screen capture of the seven monitored signals.”に載っている。

どうHDL で書くかを考えながら、いろいろとツィッターに書いていたところ、@izumitomonori さんにHDL のサンプルコードを教えていただいて、積分するんだよ。。。という貴重なご意見をいただいた。サンプルコードそのままでも良いのだが、私のアレンジ(悪くなっているかも知れないが。。。)を加えた久しぶりのVerilog HDL コードを書いてみた。ありがとうございました。

motor_count.v をここに載せるが、まだ全く検証していないので、バグはあると思う。これから検証していこう。
なお、@izumitomonori さんの名誉のために書いておきますが、元のコードはとってもシンプルな素晴らしいコードです。私がコードの切れ味をだいぶ鈍らせてしまった気がするが、どうもこんなふうに書かないと気がすまないもので。。。すみません。。。

// motor_count.v
// 2019/06/14 by marsee
// このファイルは、立命館大学の泉先生のVerilogコードを元に作成しました。泉先生ありがとうございました。
//

`default_nettype none

module moter_count #(
    parameter integer BW =32
)
(
   input  wire          sa,
   input  wire          sb,
   output wire [BW-1:0] count,
   input  wire          clk,
   input  wire          rst,
   input  wire          cnt_clr
);

    reg sa1b=1'b0, sa2b=1'b0;
    reg sb1b=1'b0, sb2b=1'b0;
    wire [1:0] sasb_state;
    reg [BW-1:0] count_r=0;
    
    parameter [3:0]     NOR_STATE_00 = 4'b0001,
                        NOR_STATE_10 = 4'b0010,
                        NOR_STATE_11 = 4'b0100,
                        NOR_STATE_01 = 4'b1000;

    reg [3:0] rev_rot, rev_rot_1b;
    parameter [3:0]     REV_STATE_00 = 4'b0001,
                        REV_STATE_01 = 4'b0010,
                        REV_STATE_11 = 4'b0100,
                        REV_STATE_10 = 4'b1000;
    reg [3:0] nor_rot=NOR_STATE_00, nor_rot_1b=REV_STATE_00;
    
    assign count = count_r;
    
    always @(posedge clk) begin
        sa1b <= sa;
        sb1b <= sb;
        sa2b <= sa1b;
        sb2b <= sb1b;

        nor_rot_1b <= nor_rot;
        rev_rot_1b <= rev_rot;
    end
    
    always @(posedge clk) begin
        if(rst)
            count_r <= 0;
        else if(cnt_clr)
            count_r <= 0;
        else begin
            if(nor_rot==NOR_STATE_00 && nor_rot_1b==NOR_STATE_01) begin
                if(rev_rot==REV_STATE_00 && rev_rot_1b==REV_STATE_10) begin
                    count_r <= count_r;
                end else begin
                    count_r <= count_r + 1;
                end
            end else begin
                if(rev_rot==REV_STATE_00 && rev_rot_1b==REV_STATE_10) begin
                    count_r <= count_r - 1;
                end else begin
                    count_r <= count_r;
                end
            end
        end
    end
    
    assign sasb_state = {sa2b, sb2b};
    
    // nor_rot state machine
    always @(posedge clk) begin
        if(rst)
            nor_rot <= NOR_STATE_00;
        else begin
            case(nor_rot)
                NOR_STATE_00:
                    if(sasb_state==2'b10)
                        nor_rot <= NOR_STATE_10;
                NOR_STATE_10:
                    if(sasb_state == 2'b11)
                        nor_rot <= NOR_STATE_11;
                NOR_STATE_11:
                    if(sasb_state == 2'b01)
                        nor_rot <= NOR_STATE_01;
                NOR_STATE_01:
                    if(sasb_state == 2'b00)
                        nor_rot <= NOR_STATE_00;
            endcase
        end
    end
    
    // rev_rot state machine
    always @(posedge clk) begin
        if(rst)
            rev_rot <= REV_STATE_00;
        else begin
            case(rev_rot)
                REV_STATE_00:
                    if(sasb_state==2'b01)
                        nor_rot <= NOR_STATE_01;
                REV_STATE_01:
                    if(sasb_state == 2'b11)
                        nor_rot <= NOR_STATE_11;
                REV_STATE_11:
                    if(sasb_state == 2'b10)
                        nor_rot <= NOR_STATE_10;
                REV_STATE_10:
                    if(sasb_state == 2'b00)
                        nor_rot <= NOR_STATE_00;
            endcase
        end
    end
endmodule

`default_nettype wire


とても久しぶりにVerilog HDL のコードを書いた。いろいろと忘れている。。。大丈夫かな?あとで修正します。
次は、検証用の回路をVivado HLS で作っていくことにする。
  1. 2019年06月17日 23:17 |
  2. Zybot
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP 2

AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP 1”の続き。

AX4 Stream 入力したデータをDMA Write するIP を作成する。ただし、AXI4 Stream 入力は、2 つあり、それらを切り替えてデータを取得することとする。つまり、AXI4 Stream スイッチ付きのDMA Write IP を作る。ということで、axis2DMA2st を作成し、C コードの合成まで行った。今回は、C/RTL 協調シミュレーションとIP 化を行う。

C/RTL 協調シミュレーションを行った。結果を示す。
bmp_header_file_29_190616.png

Latency の max は 966646 クロックだった。966646 / 480000 ≒ 2.01 クロック / 処理ピクセルということで予定通りだ。

C/RTL 協調シミュレーションの波形を見てみよう。前回波形から見てみる。
bmp_header_file_30_190616.png
bmp_header_file_31_190616.png

うまく、ins0 と ins1 を切り替え出来ている。

波形を拡大してみよう。
bmp_header_file_32_190616.png
bmp_header_file_33_190616.png

AXI4 Master のWVALID とAXI4 Stream のTREADY が 1 と 0 を交互に繰り返してることが分かる。これでだいたい 2 クロック/処理ピクセルということが分かる。

Export RTL を行った。ただし、Vivado synthesis, place and route にチェックを入れてある。
bmp_header_file_34_190616.png

C コードの合成のリソース使用量に比べて、FF は増えているが、LUT は減っている。
CP achieved post-implementation は 6.700 ns で問題なさそうだ。
  1. 2019年06月16日 05:29 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 入力にAXI4 Stream スイッチ付きのDMA Write IP 1

AX4 Stream 入力したデータをDMA Write するIP を作成する。ただし、AXI4 Stream 入力は、2 つあり、それらを切り替えてデータを取得することとする。つまり、AXI4 Stream スイッチ付きのDMA Write IP を作る。
これは、”AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 1”と”AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 2”とセットになるDMA Write IP である。1つのAXI4 Stream は画像そのまま、もう1つの間にラプラシアン・フィルタを挿入する予定だ。

最初に作成した Vivado HLS 2019.2 のプロジェクトの axis2DMA2st を示す。
bmp_header_file_20_190612.png

ソースコードの axis2DMA2st.cpp を示す。

// axis2DMA2st.cpp
// 2019/06/08 by marsee
//

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

int axis2DMA2st(hls::stream<ap_axis<32,1,1,1> >& ins0, hls::stream<ap_axis<32,1,1,1> >& ins1,
    int sel,  int x_size, int y_size, volatile ap_int<32> *out){
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=480000 port=out offset=slave
#pragma HLS INTERFACE axis register both port=ins1
#pragma HLS INTERFACE axis register both port=ins0
    ap_axis<32,1,1,1> val;

    Loop1 : do {    // user が 1 になった時にスタート
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        if(sel == 0)
            ins0 >> val;
        else
            ins1 >> val;
    } while(val.user == 0);
    
    for(int y=0; y<y_size; y++){
#pragma HLS LOOP_TRIPCOUNT min=600 max=600 avg=600
        for(int x=0; x<x_size; x++){
#pragma HLS LOOP_TRIPCOUNT min=800 max=800 avg=800
//#pragma HLS PIPELINE II=1
            if(!(y==0 && x==0)){
                if(sel == 0)
                    ins0 >> val;
                else
                    ins1 >> val;
            }
            out[y*x_size+x] = val.data;
        }
    }
    
    return(0);
}


x のループの内側のPIPELINE 指示子は入れるとリソースを食いすぎるため除いてある。

テストベンチの axis2DMA2st_tb.cpp を示す。

// axis2DMA2st_tb.cpp
// 2019/06/09 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>

#include "bmp_data.h"

char OUTPUT_BMP_FILE0[] = "test0.bmp";
char OUTPUT_BMP_FILE1[] = "test1.bmp";

int axis2DMA2st(hls::stream<ap_axis<32,1,1,1> >& ins0, hls::stream<ap_axis<32,1,1,1> >& ins1,
    int sel,  int x_size, int y_size, volatile ap_int<32> *out);
    
int main(){
    hls::stream<ap_axis<32,1,1,1> > ins0;
    hls::stream<ap_axis<32,1,1,1> > ins1;
    ap_axis<32,1,1,1> axisp;
    ap_int<32> *wr_bmp0, *wr_bmp1;

    for(int y=0; y<Y_SIZE; y++){
        for(int x=0; x<X_SIZE; x++){
            axisp.data = (ap_int<32>)bmp_file_array[y][x][0] | ((ap_int<32>)bmp_file_array[y][x][1])<<8 | ((ap_int<32>)bmp_file_array[y][x][2])<<16;
            
            if(y==0 && x==0)
                axisp.user = 1;
            else
                axisp.user = 0;
                
            if(x == X_SIZE-1)
                axisp.last = 1;
            else
                axisp.last = 0;
            
            ins0 << axisp;
            ins1 << axisp;
        }
    }
    
    if((wr_bmp0 =(ap_int<32> *)malloc(sizeof(ap_int<32>) * (X_SIZE * Y_SIZE))) == NULL){
        fprintf(stderr, "Can't allocate wr_bmp0 memory\n");
        exit(1);
    }

    if((wr_bmp1 =(ap_int<32> *)malloc(sizeof(ap_int<32>) * (X_SIZE * Y_SIZE))) == NULL){
        fprintf(stderr, "Can't allocate wr_bmp1 memory\n");
        exit(1);
    }

    axis2DMA2st(ins0, ins1, 0, X_SIZE, Y_SIZE, wr_bmp0);

    cv::Mat img(Y_SIZE, X_SIZE, CV_8UC3);
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            ap_int<32> data = wr_bmp0[y*X_SIZE+x];
            cv::Vec3b pixel;
            pixel[0] = data & 0xff; // blue
            pixel[1] = (data >> 8) & 0xff; // green
            pixel[2] = (data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }
    
    cv::imwrite(OUTPUT_BMP_FILE0, img);

    axis2DMA2st(ins0, ins1, 1, X_SIZE, Y_SIZE, wr_bmp1);
    
    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            ap_int<32> data = wr_bmp1[y*X_SIZE+x];
            cv::Vec3b pixel;
            pixel[0] = data & 0xff; // blue
            pixel[1] = (data >> 8) & 0xff; // green
            pixel[2] = (data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_BMP_FILE1, img);

    return(0);
}


なお、bmp_data.h は下の画像を”Vivado HLS 2019.1 を使用してBMPファイルをC のヘッダファイルに変換する”でヘッダファイルに変換してある。
bmp_header_file_11_190612.jpg

C シミュレーションを行った。結果を示す。
bmp_header_file_25_190615.png

axis2DMA2st/solution1/csim/build/ ディレクトリを見ると、test0.bmp, test1.bmp ができている。成功だ。
bmp_header_file_26_190615.png

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

Estimated は 8.75 ns で問題ない。
Latency は、 962402 クロックで、 962402 / 480000 ≒ 2.0-1 クロック/処理ピクセルので、予定通りだ。
リソース使用量もBRAM_18K が 1 % 、FF が 3%、 LUT が 7 % なので、問題ない。

Analysis 画面を見てみよう。
bmp_header_file_28_190615.png

gmem_addr_write_ln36(write) は x のループ (Loop 2.1) の 2 ステート目でWrite するのは 1 クロックのようだが、下の gmem_addr_wr_resp(writeresp) は 5 ステート必要なようだ。

(2019/06/20:修正)
axis2DMA2st.cpp の sel, x_size, y_size がAXI4 Lite Slave として、レジスタにマップされていなかったので修正する。

// axis2DMA2st.cpp
// 2019/06/08 by marsee
// 2019/06/20 bug fix
//

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

int axis2DMA2st(hls::stream<ap_axis<32,1,1,1> >& ins0, hls::stream<ap_axis<32,1,1,1> >& ins1,
    int sel,  int x_size, int y_size, volatile ap_int<32> *out){
#pragma HLS INTERFACE s_axilite port=y_size
#pragma HLS INTERFACE s_axilite port=x_size
#pragma HLS INTERFACE s_axilite port=sel
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE m_axi depth=480000 port=out offset=slave
#pragma HLS INTERFACE axis register both port=ins1
#pragma HLS INTERFACE axis register both port=ins0
    ap_axis<32,1,1,1> val;

    Loop1 : do {    // user が 1 になった時にスタート
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        if(sel == 0)
            ins0 >> val;
        else
            ins1 >> val;
    } while(val.user == 0);

    for(int y=0; y<y_size; y++){
#pragma HLS LOOP_TRIPCOUNT min=600 max=600 avg=600
        for(int x=0; x<x_size; x++){
#pragma HLS LOOP_TRIPCOUNT min=800 max=800 avg=800
//#pragma HLS PIPELINE II=1
            if(!(y==0 && x==0)){
                if(sel == 0)
                    ins0 >> val;
                else
                    ins1 >> val;
            }
            out[y*x_size+x] = val.data;
        }
    }

    return(0);
}

  1. 2019年06月15日 08:39 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2019.1 のprintf() の振る舞い

Ubuntu 18.04 上の Vivado HLS 2019.1 でソースコードを修正している時に printf() で ap_int<32> 型の変数を見ようとした。
通常は int にキャストして値を表示するが、それを忘れると ap_int<32> 型の変数の値が変化しているのにもかかわらずに値が一定で変化しなかった。

printf("val.data = %x\n", val.data);


bmp_header_file_21_190614.png

ap_int<32> 型の変数を int でキャストすると正常な値が表示された。

printf("val.data = %x\n", (int)val.data);


bmp_header_file_22_190614.png

しかし、int でキャストしていない ap_int<32> 型の変数の値を printf() で表示しようとすると、以前はC シミュレーションのコンパイル時にエラーになったはず?
試しに、Windows 10 のVivado HLS 2017.4 でやってみると、 int でキャストしていない ap_int<32> 型の変数の値を printf() で表示しようとするとエラーになった。
bmp_header_file_23_190614.png

これを int でキャストするとエラー無く表示できた。
bmp_header_file_24_190614.png

Vivado HLS 2017.4 のエラー表示されたほうが、Vivado HLS 2019.1 でエラー無く一定の値を表示するより、よほど良いと思う。
値が変化しないのか?を思ってびっくりしてしまった。
  1. 2019年06月14日 04:13 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 2

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 1”の続き。

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP を作るの第2回目。
前回は、DMA Read したデータをAXI4 Stream 出力するIP で、AXI4 Stream 出力が 2 つあり、そのどちらかを sel 引数によって使用できる AXI4 Stream スイッチ付き出力を備えている IP のソースコードを貼って、C シミュレーション、C コードの合成を行った。
今回は、残りの C/RTL 協調シミュレーション、C コードの合成を行う。

まずは、C コードの合成のAnalysis 画面を示す。Vivado HLS 2018.2 から Schedule Viewer が搭載されて、”Vivado 2018.2 が出た”で使ってみたが、複雑なソースコードでやってみたので、いまいち Schedule Viewer の見方が分からなかったが、今回 Schedule Viewer を見てみたところ、見やすいと感じた。簡単なソースコードだったからだろうとは思う。
Schedule Viewer の画面を示す。
bmp_header_file_15_190612.png

add_ln186(+) は、ソースコードのうちの

out_val.data = in[y*x_size+x];

の足し算部分だと思うが、in_V_read(read) のオフセットアドレスのRead と Loop1 の y の値 を受けて、out_val_data_V(read) に影響を及ぼしているという様に見るのだと思う。
何か今回は素直に見やすく思えた。具体的な変数名を踏襲しているのも良さそうだ。

次は、C/RTL 協調シミュレーションを行った。結果を示す。
bmp_header_file_16_190612.png

Latency の avg が 969068 だった。
969068 / 480000 ≒ 2.019 なので、やはり、1 出力に 2 クロックかかる計算だ。

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

最初に outs0 に出力して、その後 outs1 に出力しているのが見て取れた。
出力の切り替え部分を拡大してみよう。
bmp_header_file_18_190612.png

outs0_TVALID と outs1_TVALID がそれぞれ有効な部分では、1 と 0 を交互に繰り返してる。よって、 2 クロック毎に 1 出力というのが分かる。
うまく行っているようだ。

最後に、Vivado synthesis, place and route にチェックを入れた状態で、Export RTL を実行した。結果を示す。
bmp_header_file_19_190612.png

C コードの合成結果と比べて、LUT は減っているが、FF はむしろ増えている。合成結果から増えることもあるんだ。。。
CP achieved post-implementation は 6.125 ns で問題なさそうだ。
  1. 2019年06月13日 05:19 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP 1

AXI4 Stream 出力にAXI4 Stream スイッチ付きのDMA Read IP を作るの第1回目。

DMA Read したデータをAXI4 Stream 出力するIP を作りたいのだが、AXI4 Stream 出力は 2 つにして、そのどちらかにAXI4 Stream を出力するIP を作る。これは、Xilinx のAXI Stream スイッチを使わずに、通常の画像出力とフィルタを通った画像を切り替えるために使用する。
このIP は、Vivado HLS セミナの第8回目のAXI4 Stream 応用編の例として使用する予定だ。

まずは、ソースコードの DMA2axis2st.cpp を示す。

// DMA2axis2st.cpp
// 2019/06/07 by marsee
//

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

int DMA2axis(volatile ap_int<32> *in, int sel, int x_size, int y_size,
    hls::stream<ap_axis<32,1,1,1> >& outs0, hls::stream<ap_axis<32,1,1,1> >& outs1){
#pragma HLS INTERFACE s_axilite port=y_size
#pragma HLS INTERFACE s_axilite port=x_size
#pragma HLS INTERFACE s_axilite port=sel
#pragma HLS INTERFACE s_axilite port=return
#pragma HLS INTERFACE axis register both port=outs0
#pragma HLS INTERFACE axis register both port=outs1
#pragma HLS INTERFACE m_axi depth=480000 port=in offset=slave
    ap_axis<32,1,1,1> out_val;

    for(int y=0; y<y_size; y++){
#pragma HLS LOOP_TRIPCOUNT min=600 max=600 avg=600
        for(int x=0; x<x_size; x++){
#pragma HLS LOOP_TRIPCOUNT min=800 max=800 avg=800
#pragma HLS PIPELINE II=1
            out_val.data = in[y*x_size+x];
            if(x==0 && y==0)
                out_val.user = 1;
            else
                out_val.user = 0;
            if(x == x_size-1)
                out_val.last = 1;
            else
                out_val.last = 0;
            if(sel == 0)
                outs0 << out_val;
            else
                outs1 << out_val;
        }
    }
    return(0);
}


テストベンチの DMA2axis2st_tb.cpp を示す。

// DMA2axis2st_tb.cpp
// 2019/06/07 by marsee
//

#include <iostream>
#include "hls_opencv.h"

#include "bmp_data.h"

#define Y_SIZE  600
#define X_SIZE  800

char OUTPUT_BMP_FILE0[] = "test0.bmp";
char OUTPUT_BMP_FILE1[] = "test1.bmp";

int DMA2axis(volatile ap_int<32> *in, int sel, int x_size, int y_size,
    hls::stream<ap_axis<32,1,1,1> >& outs0, hls::stream<ap_axis<32,1,1,1> >& outs1);

int main(){
    hls::stream<ap_axis<32,1,1,1> > outs0;
    hls::stream<ap_axis<32,1,1,1> > outs1;
    ap_axis<32,1,1,1> axisp;
    ap_int<32> *rd_bmp;

    if((rd_bmp =(ap_int<32> *)malloc(sizeof(ap_int<32>) * (X_SIZE * Y_SIZE))) == NULL){
        fprintf(stderr, "Can't allocate rd_bmp memory\n");
        exit(1);
    }

    for(int y=0; y<Y_SIZE; y++){
        for(int x=0; x<X_SIZE; x++){
            rd_bmp[y*X_SIZE+x] = (int)(bmp_file_array[y][x][0]) | ((int)(bmp_file_array[y][x][1])<<8) | ((int)(bmp_file_array[y][x][2]) <<16);
        }
    }

    DMA2axis(rd_bmp, 0, X_SIZE, Y_SIZE, outs0, outs1);

    cv::Mat img(Y_SIZE, X_SIZE, CV_8UC3);
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            outs0 >> axisp;
            cv::Vec3b pixel;
            pixel[0] = axisp.data & 0xff; // blue
            pixel[1] = (axisp.data >> 8) & 0xff; // green
            pixel[2] = (axisp.data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_BMP_FILE0, img);

    DMA2axis(rd_bmp, 1, X_SIZE, Y_SIZE, outs0, outs1);

    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            outs1 >> axisp;
            cv::Vec3b pixel;
            pixel[0] = axisp.data & 0xff; // blue
            pixel[1] = (axisp.data >> 8) & 0xff; // green
            pixel[2] = (axisp.data >> 16) & 0xff; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_BMP_FILE1, img);

    return(0);
}


なお、bmp_data.h はこの画像を”Vivado HLS 2019.1 を使用してBMPファイルをC のヘッダファイルに変換する”を使用して、ヘッダファイルに変換してある。
bmp_header_file_11_190612.jpg

Vivado HLS 2019.1 のプロジェクトの DMA2axis2st を示す。
bmp_header_file_8_190612.png

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

DMA2axis2st/solution1/csim/build/ ディレクトリを見てみよう。
bmp_header_file_12_190612.png

test0.bmp と test1.bmp ができている。成功だ。

C コードの合成を行った。結果を示す。
bmp_header_file_10_190612.png

Estimated は 8.750 ns で大丈夫そうだ。
Latency は 480078 クロックで、ほとんど 1 クロックで 1 ピクセルを処理できている。問題ない。
リソースは、FF が 29 % で LUT が 50 % 使用されているので、リソース使い過ぎか。。。

それでは、 x の for ループの下のPIPELINE 指示子を取ってみよう。
bmp_header_file_13_190612.png

このソースコードでの合成結果を示す。
bmp_header_file_14_190612.png

Estimated は 8.750 ns だった。

Latency は 965401 クロックで、約 2 クロックで 1 出力となった。倍の時間がかかるようになったが、FF は 3 % で、LUT は 9 % の使用率で相当低減されている。bmp_data.h をメモリに展開して送るので、これで全く問題ない。よって、遅いけど、リソースを使用しない方を採用する。

指示子(プラグマ)や設定によって、リソース使用量を取るか、スループットや動作周波数を取るかを選べるのが、Vivado HLS の最大の利点ではないか?と思っている。
  1. 2019年06月12日 00:54 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

BMPファイルをC のヘッダファイルに変換したファイルを検証してみた

Vivado HLS 2019.1 を使用してBMPファイルをC のヘッダファイルに変換する”の続き。

前回は、Vivado HLS 2019.1 でBMPファイルをC のヘッダファイルに変換するソフトウェアを作成した。しかし、生成されたC のヘッダファイルを見ただけでは、そこから本当にBMP 画像がふくげんできるのか?が分からない。よって、今回は、C のヘッダファイルをBMP 画像に変換するソフトウェアを作成することにした。

作成した bmp_header2image.cpp のソースコードを示す。

// bmp_header2image.cpp
// 2019/06/07 by marsee
//

#include <iostream>
#include "hls_opencv.h"

#include "bmp_data.h"

char OUTPUT_BMP_FILE[] = "test.bmp";

int main(){
    cv::Mat img(Y_SIZE, X_SIZE, CV_8UC3);
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<Y_SIZE; y++){
        for (int x=0; x<X_SIZE; x++){
            cv::Vec3b pixel;
            pixel[0] = bmp_file_array[y][x][0]; // blue
            pixel[1] = bmp_file_array[y][x][1]; // green
            pixel[2] = bmp_file_array[y][x][2]; // red
            dst_vec3b(y,x) = pixel;
        }
    }

    cv::imwrite(OUTPUT_BMP_FILE, img);

    return(0);
}



Vivado HLS 2019.1 の bmp_header2image プロジェクトを示す。
bmp_header_file_5_190609.png

Test Bench ディレクトリには、”Vivado HLS 2019.1 を使用してBMPファイルをC のヘッダファイルに変換する” で作成した bmp_data.h も入っている。これをBMP 画像に変換する。

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

test.bmp ができているのが分かる。
test.bmp を見ると、”A”のBMP画像になっていた。成功だ。。。
bmp_header_file_7_190609.png
  1. 2019年06月09日 04:44 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

映画『ゴジラ キング・オブ・モンスターズ』を見てきた

映画『ゴジラ キング・オブ・モンスターズ』を見てきた。タイトル通りに、ゴジラとキングギドラが暴れまわる映画だった。それなりに楽しめた。
  1. 2019年06月08日 20:27 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2019.1 を使用してBMPファイルをC のヘッダファイルに変換する

Vivado HLS 2019.1 を使用して、BMPファイルをC のヘッダファイルに変換するソフトウェアを作成してみよう。

Vivado HLS の C シミュレーションを使用して、ソフトウェアを実行することにする。
Vivado HLS のTest Bench ディレクトリだけを使用することになる。

Vivado HLS 2019.1 の bmp_header_file ディレクトリを示す。
すでに、Test Bench ディレクトリに bmp_header_file.cpp と test.bmp が入っている。
bmp_header_file_1_190608.png

bmp_header_file.cpp のソースコードを貼っておく。

// bmp_header_file.cpp
// 2019/06/08 by marsee
//

#include <iostream>
#include "hls_opencv.h"
#include <stdlib.h>

char INPUT_BMP_FILE[] = "test.bmp";
char OUTPUT_HEADER_FILE[] = "bmp_data.h";

int main(){
    uint8_t *red, *green, *blue;
    FILE *fbmpw;

    // BMPファイルをMat に読み込む
    cv::Mat img = cv::imread(INPUT_BMP_FILE);

    // ピクセルを入れるメモリをアロケートする
    if ((red =(uint8_t *)malloc(sizeof(uint8_t) * (img.rows * img.cols))) == NULL){
        fprintf(stderr, "Can't allocate red memory\n");
        exit(1);
    }
    if ((green =(uint8_t *)malloc(sizeof(uint8_t) * (img.rows * img.cols))) == NULL){
        fprintf(stderr, "Can't allocate green memory\n");
        exit(1);
    }
    if ((blue =(uint8_t *)malloc(sizeof(uint8_t) * (img.rows * img.cols))) == NULL){
        fprintf(stderr, "Can't allocate blue memory\n");
        exit(1);
    }

    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<img.rows; y++){
        for (int x=0; x<img.cols; x++){
            cv::Vec3b pixel;
            pixel = dst_vec3b(y,x);
            blue[y*img.cols+x] = pixel[0]; // blue
            green[y*img.cols+x] = pixel[1]; // green
            red[y*img.cols+x] = pixel[2]; // red
        }
    }

    // BMP画像データのヘッダを画像出力ファイルに書き込む
    if ((fbmpw = fopen(OUTPUT_HEADER_FILE, "w")) == NULL){
        fprintf(stderr, "Can't open bmp header file\n");
        exit(1);
    }

    fprintf(fbmpw, "// %s\n", OUTPUT_HEADER_FILE);
    time_t now = std::time(nullptr);
    struct tm* jst = std::localtime(&now);
    fprintf(fbmpw, "// %04d/%02d/%02d %02d:%02d:%02d by marsee\n", jst->tm_year+1900, jst->tm_mon+1, jst->tm_mday,
            jst->tm_hour, jst->tm_min, jst->tm_sec);
    fprintf(fbmpw, "//\n\n");

    fprintf(fbmpw, "#define X_SIZE %d\n", img.cols);
    fprintf(fbmpw, "#define Y_SIZE %d\n\n", img.rows);

    fprintf(fbmpw, "unsigned char bmp_file_array[%d][%d][3] = {\n", img.rows, img.cols);
    for (int y=0; y<img.rows; y++){
        fprintf(fbmpw, "\t{");
        for (int x=0; x<img.cols; x++){
            if (x != 0)
                fprintf(fbmpw, ",");

            fprintf(fbmpw, "{%d,%d,%d}", blue[y*img.cols+x], green[y*img.cols+x], red[y*img.cols+x]);
        }
        if (y == (img.rows-1))
            fprintf(fbmpw, "}\n");
        else
            fprintf(fbmpw, "},\n");
    }
    fprintf(fbmpw, "\n};");

    fclose(fbmpw);

    return(0);
}


test.bmp は”A”という画像だ。
bmp_header_file_2_190608.png

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

solution1/csim に bmp_data.h ができている。
bmp_data.h を示す。
bmp_header_file_4_190608.png

うまくBMP 画像が C 言語のヘッダファイルになった。
bmp_data.h を貼っておく。

// bmp_data.h
// 2019/06/08 05:09:49 by marsee
//

#define X_SIZE 64
#define Y_SIZE 48

unsigned char bmp_file_array[48][64][3] = {
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,254},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{254,255,254},{252,253,253},{248,249,250},{247,246,245},{251,248,246},{254,252,250},{255,255,253},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{249,255,254},{221,242,247},{175,192,214},{164,153,159},{208,178,168},{244,229,215},{255,255,251},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{234,255,255},{158,211,234},{58,99,142},{45,39,46},{131,82,57},{221,189,151},{255,255,236},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,253},{255,255,253},{217,243,254},{113,174,219},{4,52,102},{0,0,0},{71,30,0},{195,152,96},{255,246,207},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{255,255,252},{253,255,255},{202,217,245},{108,138,199},{38,74,115},{12,39,42},{46,29,9},{166,117,59},{253,220,167},{255,255,255},{255,255,253},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{255,255,252},{242,255,255},{189,191,218},{131,113,165},{107,128,158},{55,113,119},{35,23,24},{130,67,21},{233,185,129},{255,255,255},{255,255,253},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,253},{211,253,255},{156,176,197},{142,110,125},{165,163,148},{94,153,176},{24,28,67},{86,28,20},{200,146,97},{255,255,232},{255,254,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,254},{255,255,254},{173,230,255},{122,158,181},{157,127,104},{218,195,146},{131,184,221},{20,53,116},{44,15,29},{162,110,63},{255,244,192},{255,253,252},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{254,255,254},{254,255,255},{141,188,244},{102,134,166},{178,153,110},{255,226,172},{165,215,252},{33,94,160},{16,25,40},{123,79,27},{252,210,143},{254,253,250},{255,255,255},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{254,255,254},{248,255,255},{132,152,205},{112,108,145},{194,169,139},{255,252,207},{198,240,254},{73,138,192},{22,35,61},{93,41,0},{225,166,88},{254,253,248},{255,255,255},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{253,254,254},{205,252,255},{133,135,165},{146,107,117},{217,185,161},{255,255,241},{228,252,255},{119,177,216},{31,53,101},{56,8,16},{184,108,59},{253,252,220},{255,255,251},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,254},{252,253,254},{152,225,254},{135,135,141},{189,138,110},{251,216,187},{255,255,255},{255,255,255},{171,217,245},{50,90,152},{20,8,49},{131,67,34},{253,235,175},{255,253,244},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{255,255,254},{250,252,253},{105,177,244},{111,125,127},{182,147,101},{232,204,173},{229,230,232},{232,231,230},{174,203,224},{56,108,161},{0,26,62},{81,49,10},{246,195,120},{254,248,234},{255,255,255},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{255,255,254},{242,252,253},{80,142,208},{11,40,88},{6,3,11},{10,7,4},{9,9,10},{10,9,9},{5,7,9},{0,0,4},{3,0,0},{67,36,1},{211,144,51},{250,238,222},{255,255,255},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{246,255,255},{198,246,253},{107,106,146},{108,91,105},{135,126,120},{144,148,146},{143,142,143},{143,142,143},{141,149,145},{99,129,136},{39,64,90},{33,8,21},{166,76,27},{243,228,192},{255,255,249},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{235,251,255},{138,217,250},{135,102,103},{201,154,127},{251,232,210},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{193,234,249},{79,127,177},{6,7,58},{106,34,14},{233,206,149},{255,253,235},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,254},{224,240,253},{85,163,233},{148,126,96},{225,186,141},{255,240,221},{255,255,255},{255,255,254},{255,255,254},{255,255,255},{223,241,253},{113,160,208},{1,41,103},{45,21,2},{218,167,94},{254,243,211},{255,255,255},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,254},{212,227,244},{69,101,186},{165,140,118},{236,214,172},{255,252,233},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{235,250,254},{147,194,232},{28,87,148},{27,6,0},{187,119,27},{251,223,181},{255,255,255},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,255},{253,255,255},{193,237,246},{116,87,135},{217,182,155},{255,249,228},{255,255,255},{255,255,255},{255,255,253},{255,255,253},{255,255,254},{255,255,255},{196,236,255},{68,136,195},{9,2,20},{122,51,3},{234,200,143},{255,255,251},{255,255,255},{255,255,255},{255,255,254},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,253},{242,255,254},{204,213,231},{156,178,201},{107,152,157},{89,44,56},{154,126,106},{199,180,160},{232,216,200},{252,245,234},{255,255,254},{254,255,254},{229,241,248},{195,208,225},{134,166,192},{48,96,133},{0,0,13},{41,1,0},{136,114,68},{192,176,150},{221,194,190},{255,255,233},{255,255,252},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{255,255,252},{220,255,255},{115,140,194},{36,46,107},{20,34,43},{24,9,7},{34,29,26},{104,69,33},{192,148,100},{247,227,199},{255,255,255},{253,255,255},{185,218,239},{89,125,173},{25,46,88},{14,24,30},{13,13,11},{8,12,13},{28,28,15},{83,39,27},{162,89,78},{255,255,198},{255,255,248},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,252},{255,255,252},{235,255,255},{176,190,221},{138,138,171},{141,139,141},{142,144,143},{138,140,142},{172,152,134},{219,194,167},{250,239,223},{255,255,255},{253,255,255},{215,234,245},{163,181,208},{136,142,163},{143,141,138},{146,146,145},{144,146,147},{139,142,143},{156,135,137},{203,162,155},{255,255,222},{255,255,250},{255,255,255},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,253},{249,255,254},{234,238,245},{225,224,232},{228,226,225},{228,230,229},{225,226,227},{233,228,223},{245,239,231},{253,250,245},{255,255,254},{254,255,254},{244,249,251},{231,235,241},{225,226,230},{229,227,225},{231,231,230},{230,231,230},{226,227,228},{228,223,225},{241,231,228},{255,255,245},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,253},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,253},{255,255,253},{255,255,254},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,255},{255,255,254},{255,255,253},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}},
    {{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254},{255,255,254}}

};

  1. 2019年06月08日 05:22 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Ultra96用PMOD拡張ボード18(動作の確認)

Ultra96用PMOD拡張ボード17(部品の実装)”の続き。

前回は、Ultra96用PMOD拡張ボードに部品を実装した。今回は、Ultra96ボードにUltra96用PMOD拡張ボードを搭載してOV5642 カメラを接続して画像がDisplayPort に表示されるかどうか?を確認してみよう。
なお、今回のUltra96_ext_board Ver.3 はUltra96V2 にも対応するボードだ。前のVer. 2はUltra96V2 では動作しないと思う。

Ultra96にPMOD 拡張ボード、OV5642 カメラを搭載した写真を示す。
cam_displayport_51_190607.jpg

OSコンに基板がかぶってしまっている。基板の下には、レジストが塗布されているので、大丈夫だと思うが、念の為にセロテープでも貼っておくか。。。
奥の穴はUltra96のネジ位置に合わせてあって、延長スペーサでPMOD拡張ボードを固定できるようになっている。今ノギスで基板間の間隔を測ったところ、6.5 mm だった。 6 mm のスペーサで良いだろうかね。。。

基板が沢山増えてしまった。。。

さて、”カメラ画像をDisplayPortに出力する9(アプリを作成、完成)”を参考にして、HD 解像度のディスプレイにカメラ画像を表示してみよう。

Ultra96の電源をON して、 examples/cam_dp ディレクトリに入った。
cd ~/examples/cam_dp

デバイスツリー・オーバレイで、UIO, udmabuf、クロックを設定する。
./lddtovary.sh
cam_displayport_50_190606.png

アプリケーション・ソフトをHD 解像度モードで起動して、q で exit する。
./cam_dp_ov5642 -r 2

ライブ・ビデオを表示する。
./disp_pattern.sh
cam_displayport_49_190606.png

カメラ画像が表示された。写真はピンクっぽいが、実際の画面表示は正しい色だった。
cam_displayport_52_190607.jpg

なお、追加した電源SWも問題なく動作した。

これで、Ultra96_ext_board Ver.3 も問題なく、Ultra96V1 での動作が確認できた。後は、Ultra96V2 での動作を確認したい。
もうすでにUltra96V2 は注文してあるが納期は7月中ということだった。
  1. 2019年06月07日 05:21 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

Ultra96用PMOD拡張ボード17(部品の実装)

Ultra96用PMOD拡張ボード16(タクトスイッチのフットプリントの修正)”の続き。

前回は、タクトスイッチのフットプリント図が間違っていて購入したタクトスイッチが取り付け出来なかったので、タクトスイッチのフットプリントを修正した。しかし、”Ultra96用PMOD拡張ボード15(Ultra96V2用に改版した3)”で出来上がった基板にタクトスイッチを実装するためにフットプリントに合うタクトスイッチをツィッターで教えてもらった。タクトスイッチが実装できるようになったので、今回は部品を実装した。

表面実装用タクトスイッチ”もフットプリントのサイズがギリギリで余裕がなかったので、はんだ付けが難しかった。やはり、パッドが余っているくらいでないと、パッドにはんだごてが当てられずにパッドの加熱が甘くなってしまう。

後はSSOPのレベル変換IC の取り付けが今回手こずってしまった。やはり、はんだごてのコテ先が良くないようだ。白光のFX-600 のT18-D12 1.2D型だと簡単にはんだ付けできた。

Ultra96_ext_board_13_190606.jpg

Ultra96_ext_board_14_190606.jpg
  1. 2019年06月06日 04:16 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

なひたふさんの「Vivadoのプロジェクトをgitで管理する最小限は何か」を参考にしてVivado のプロジェクトをTCLファイルで復元した

Vivado プロジェクトを送る時に最小限のファイルで遅れればとっても良い。そこで、なひたふさんの「Vivadoのプロジェクトをgitで管理する最小限は何か」を参考にして最小限のファイルでVivado プロジェクトを復元してみた。

復元させるVivado 2019.1 プロジェクトは、”Vivado 2018.3 のプロジェクトを Vivado 2019.1 に変換してみた”とする。
vivado2019_1_5_190605.png

File メニューから Project -> Write Tcl... を選択した。

Write Project to Tcl ダイアログが表示された。Copy sources to new project と Recreate Block Designs using Tcl にチェックを入れて、OK ボタンをクリックした。
vivado2019_1_6_190605.png

Write Project to Tcl ダイアログでYes ボタンをクリックして、 cam_dp_183.tcl を表示した。
vivado2019_1_7_190605.png

cam_dp_183.tcl の一部を示す。
vivado2019_1_8_190605.png

現在のディレクトリの下にWork ディレクトリを作成し、cam_dp.xdc と cam_dp_wrapper.v, cam_dp_183.tcl の各ファイルと IP のディレクトリをコピーした。
vivado2019_1_9_190605.png

現在のプロジェクトをクローズしてから、Vivado 2019.1 のTcl Console でコマンドを入力した。
vivado2019_1_10_190605.png

cd /home/masaaki/HDL/Ultra96/cam_dp_191/Work/
source cam_dp_183.tcl

するとエラーになってしまった。
vivado2019_1_11_190605.png

ERROR: [Vivado 12-172] File or Directory '/home/masaaki/HDL/Ultra96/cam_dp_191/Work/cam_dp_183.srcs/sources_1/bd/cam_dp/hdl/cam_dp_wrapper.v' does not exist



cam_dp.xdc と cam_dp_wrapper.v は以前のディレクトリパスの下に置く必要があるようだ。

そこで、Work ディレクトリ下にディレクトリを構築した。
vivado2019_1_12_190605.png

もう一度、source cam_dp_183.tcl を実行するとエラーだった。一旦、cam_dp_183 ディレクトリを削除する必要があるようだ。
vivado2019_1_13_190605.png

cam_dp_183 ディレクトリを削除して、もう一度、source cam_dp_183.tcl を実行したところ、Vivado 2019.1 のプロジェクトが生成された。
vivado2019_1_14_190605.png

IP Catalog を見ると、IP はコピーされていないで、Work ディレクトリ直下のIP のディレクトリを指している。
vivado2019_1_15_190605.png

ちょっと残念。上のディレクトリも一緒に移動する必要あるな。。。
現在のWork ディレクトリの様子を示す。
vivado2019_1_16_190605.png

Work ディレクトリの下の cam_dp_183 ディレクトリの内容を示す。
vivado2019_1_17_190605.png

cam_dp.xdc と cam_dp_wrapper.v は cam_dp_183 ディレクトリの下にコピーされていた。
vivado2019_1_18_190605.png

生成されたVivado 2019.1 プロジェクトを論理合成、インプリメンテーション、ビットストリームの生成を行った。
途中、クリティカル・ワーニングが表示された。
vivado2019_1_19_190605.png

[IP_Flow 19-4965] IP pixel_fifo was packaged with board value 'em.avnet.com:ultra96v1:part0:1.2'. Current project's board value is unset. Please update the project settings to match the packaged IP.


そのまま、OK ボタンをクリックして、進めたところ、成功した。
vivado2019_1_20_190605.png

なお、SDK のディレクトリはコピーされないので、SDKを上げてSDKのディレクトリを生成してからSDK でアプリケーション・プロジェクトを作成後に正規の手順でプリケーション・ソフトのソースコードをコピーしたほうが良さそうだ。
  1. 2019年06月05日 05:36 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Vivado 2018.3 のプロジェクトを Vivado 2019.1 に変換してみた

Vivado 2018.3 の cam_dp_183 プロジェクトをVivado 2019.1 に変換してみた。

まずは、cam_dp_183 をディレクトリごとコピーして、名前を cam_dp_191 に変更した。
vivado2019_1_1_190604.png

Vivado 2019.1 で cam_dp_191/cam_dp_183 プロジェクトを開いて、新しいプロジェクトに変換した。

IP を更新した。自作IP の下の pixel_fifo も更新した。

論理合成、インプリメンテーション、ビットストリームの生成まで成功した。
vivado2019_1_2_190604.png

Project Summary を示す。
vivado2019_1_3_190604.png

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

cam_dp_wrapper_hw_platform_1 が生成された。

とりあえず、今の所問題なく Vivado 2018.3 のプロジェクトをVivado 2019.1 に変換できた。
  1. 2019年06月04日 05:13 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

MIPIボード用PMOD拡張ボードをテストする6(I2Cのテスト2)

MIPIボード用PMOD拡張ボードをテストする5(I2Cのテスト1)”の続き。

前回は、BME280使用 温湿度・気圧センサモジュールキットにヘッダをはんだ付けし、I2C モードに設定して、ブレッドボード上に回路を組んでI2C のテストをし、レジスタが読めることを確認した。今回は、温度、気圧、湿度を表示してみよう。

スイッチサイエンスさんの「BME280搭載 温湿度・気圧センサモジュールの使い方」のスケッチのコードを引用させていただいた。というかほとんどコードをいただいてしまっている。MITライセンスなので大丈夫と思うのだが、スイッチサイエンスさんのコードにライセンスの表示がないので、この引用文で代用したい。

作成したソースコードは前回同様に BME280_temp.c だ。プログラムの流れもスイッチサイエンスさんの「BME280搭載 温湿度・気圧センサモジュールの使い方」を参考にさせていただいた。
PMOD_B4MIPI_B_test_31_190602.png

gcc -o BME280_temp BME280_temp.c
でコンパイルして、
sudo ./BME280_temp
で動作させたところ、温度、気圧、湿度の値を表示することができた。
PMOD_B4MIPI_B_test_32_190602.png

TEMP = 28.740000
DegC PRESS = 1007.970000
hPa HUM : 51.779297



現在は、I2C0 を使用しているが、I2C1 でも同様に温度、気圧、湿度の値を表示することができた。

BME280_temp.c を示す。

// BME280_temp.c
// 2019/06/01 by marsee
//
// Quote part of ultra96_design/src/linux/caminit/src/ov5640.cc::init_ov5640()
// https://github.com/fixstars/ultra96_design
// 
// Quote of SwitchScience Wiki (Special Thanks)
// http://trac.switch-science.com/wiki/BME280
//

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <stdint.h>

int writeReg(int fd, uint8_t addr, uint8_t data);
int readReg(int fd, uint8_t addr, uint8_t *data);
signed long int calibration_T(signed long int adc_T);
unsigned long int calibration_P(signed long int adc_P);
unsigned long int calibration_H(signed long int adc_H);

unsigned long int hum_raw,temp_raw,pres_raw;
signed long int t_fine;

uint16_t dig_T1;
 int16_t dig_T2;
 int16_t dig_T3;
uint16_t dig_P1;
 int16_t dig_P2;
 int16_t dig_P3;
 int16_t dig_P4;
 int16_t dig_P5;
 int16_t dig_P6;
 int16_t dig_P7;
 int16_t dig_P8;
 int16_t dig_P9;
 int8_t  dig_H1;
 int16_t dig_H2;
 int8_t  dig_H3;
 int16_t dig_H4;
 int16_t dig_H5;
 int8_t  dig_H6;
 
int main(){
    int fd;
    uint8_t addr;
    uint8_t datar;
    uint8_t data[32];
    
    fd = open("/dev/i2c-2", O_RDWR); // I2C0
    //fd = open("/dev/i2c-3", O_RDWR); // I2C1
    if(fd < 0){
        fprintf(stderr, "Can't open /dev/i2c-2\n");
        return(-1);
    }
    
    ioctl(fd, I2C_SLAVE, 0x76);
        
    uint8_t osrs_t = 1;             //Temperature oversampling x 1
    uint8_t osrs_p = 1;             //Pressure oversampling x 1
    uint8_t osrs_h = 1;             //Humidity oversampling x 1
    uint8_t mode = 3;               //Normal mode
    uint8_t t_sb = 5;               //Tstandby 1000ms
    uint8_t filter = 0;             //Filter off 
    uint8_t spi3w_en = 0;           //3-wire SPI Disable
    
    uint8_t ctrl_meas_reg = 0x27;
    uint8_t config_reg    = (t_sb << 5) | (filter << 2) | spi3w_en;
    uint8_t ctrl_hum_reg  = osrs_h;

    writeReg(fd, 0xf2, ctrl_hum_reg);
    writeReg(fd, 0xf4, ctrl_meas_reg);
    writeReg(fd, 0xf5, config_reg);
    
    readReg(fd, 0xfc, &datar);
    //printf("0xfc = %x\n", datar);
    readReg(fd, 0xfb, &datar);
    //printf("0xfb = %x\n", datar);
    readReg(fd, 0xfa, &datar);
    //printf("0xfa = %x\n", datar);
    
    for(int i=0, addr=0x88; i<24; i++, addr++){
        readReg(fd, addr, &data[i]);
        //printf("data[%d] = %x\n", i, data[i]);
    }
    readReg(fd, 0xa1, &data[24]);
    //printf("data[24] = %x\n", data[24]);
    for(int i=25, addr=0xE1; i<32; i++, addr++){
        readReg(fd, addr, &data[i]);
        //printf("data[%d] = %x\n", i, data[i]);
    }
    dig_T1 = (data[1] << 8) | data[0];
    dig_T2 = (data[3] << 8) | data[2];
    dig_T3 = (data[5] << 8) | data[4];
    dig_P1 = (data[7] << 8) | data[6];
    dig_P2 = (data[9] << 8) | data[8];
    dig_P3 = (data[11]<< 8) | data[10];
    dig_P4 = (data[13]<< 8) | data[12];
    dig_P5 = (data[15]<< 8) | data[14];
    dig_P6 = (data[17]<< 8) | data[16];
    dig_P7 = (data[19]<< 8) | data[18];
    dig_P8 = (data[21]<< 8) | data[20];
    dig_P9 = (data[23]<< 8) | data[22];
    dig_H1 = data[24];
    dig_H2 = (data[26]<< 8) | data[25];
    dig_H3 = data[27];
    dig_H4 = (data[28]<< 4) | (0x0F & data[29]);
    dig_H5 = (data[30] << 4) | ((data[29] >> 4) & 0x0F);
    dig_H6 = data[31];   
        
    for(int i=0, addr=0xf7; i<8; i++, addr++){
        readReg(fd, addr, &data[i]);
        //printf("data[%d] = %x\n", i, data[i]);
    }
    pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4);
    temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4);
    hum_raw  = (data[6] << 8) | data[7];

    double temp_act = 0.0, press_act = 0.0,hum_act=0.0;
    signed long int temp_cal;
    unsigned long int press_cal,hum_cal;
    
    temp_cal = calibration_T(temp_raw);
    press_cal = calibration_P(pres_raw);
    hum_cal = calibration_H(hum_raw);
    temp_act = (double)temp_cal / 100.0;
    press_act = (double)press_cal / 100.0;
    hum_act = (double)hum_cal / 1024.0;

    printf("TEMP = %f\n", temp_act);
    printf("DegC PRESS = %f\n", press_act);
    printf("hPa HUM : %f\n", hum_act);
    
    return(0);
}

int writeReg(int fd, uint8_t addr, uint8_t data){
    uint8_t dt[2];
    
    dt[0] = addr;
    dt[1] = data;
    write(fd, dt, 2);
    return(0);
}

int readReg(int fd, uint8_t addr, uint8_t *data){
    uint8_t addrt = addr;
    
    write(fd, &addrt, 1);
    read(fd, data, 1);
    return(0);
}

signed long int calibration_T(signed long int adc_T)
{
    
    signed long int var1, var2, T;
    var1 = ((((adc_T >> 3) - ((signed long int)dig_T1<<1))) * ((signed long int)dig_T2)) >> 11;
    var2 = (((((adc_T >> 4) - ((signed long int)dig_T1)) * ((adc_T>>4) - ((signed long int)dig_T1))) >> 12) * ((signed long int)dig_T3)) >> 14;
    
    t_fine = var1 + var2;
    T = (t_fine * 5 + 128) >> 8;
    return T; 
}

unsigned long int calibration_P(signed long int adc_P)
{
    signed long int var1, var2;
    unsigned long int P;
    var1 = (((signed long int)t_fine)>>1) - (signed long int)64000;
    var2 = (((var1>>2) * (var1>>2)) >> 11) * ((signed long int)dig_P6);
    var2 = var2 + ((var1*((signed long int)dig_P5))<<1);
    var2 = (var2>>2)+(((signed long int)dig_P4)<<16);
    var1 = (((dig_P3 * (((var1>>2)*(var1>>2)) >> 13)) >>3) + ((((signed long int)dig_P2) * var1)>>1))>>18;
    var1 = ((((32768+var1))*((signed long int)dig_P1))>>15);
    if (var1 == 0)
    {
        return 0;
    }    
    P = (((unsigned long int)(((signed long int)1048576)-adc_P)-(var2>>12)))*3125;
    if(P<0x80000000)
    {
       P = (P << 1) / ((unsigned long int) var1);   
    }
    else
    {
        P = (P / (unsigned long int)var1) * 2;    
    }
    var1 = (((signed long int)dig_P9) * ((signed long int)(((P>>3) * (P>>3))>>13)))>>12;
    var2 = (((signed long int)(P>>2)) * ((signed long int)dig_P8))>>13;
    P = (unsigned long int)((signed long int)P + ((var1 + var2 + dig_P7) >> 4));
    return P;
}

unsigned long int calibration_H(signed long int adc_H)
{
    signed long int v_x1;
    
    v_x1 = (t_fine - ((signed long int)76800));
    v_x1 = (((((adc_H << 14) -(((signed long int)dig_H4) << 20) - (((signed long int)dig_H5) * v_x1)) + 
              ((signed long int)16384)) >> 15) * (((((((v_x1 * ((signed long int)dig_H6)) >> 10) * 
              (((v_x1 * ((signed long int)dig_H3)) >> 11) + ((signed long int) 32768))) >> 10) + (( signed long int)2097152)) * 
              ((signed long int) dig_H2) + 8192) >> 14));
   v_x1 = (v_x1 - (((((v_x1 >> 15) * (v_x1 >> 15)) >> 7) * ((signed long int)dig_H1)) >> 4));
   v_x1 = (v_x1 < 0 ? 0 : v_x1);
   v_x1 = (v_x1 > 419430400 ? 419430400 : v_x1);
   return (unsigned long int)(v_x1 >> 12);   
}

  1. 2019年06月03日 04:02 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

MIPIボード用PMOD拡張ボードをテストする5(I2Cのテスト1)

MIPIボード用PMOD拡張ボードをテストする4(I2Cのテスト用部品の到着)”の続き。

前回、I2C のテスト用のBME280使用 温湿度・気圧センサモジュールキットなどが到着した。今回は、そのBME280使用 温湿度・気圧センサモジュールキットにヘッダをはんだ付けし、I2C モードに設定して、ブレッドボード上に回路を組んでテストした。
PMOD_B4MIPI_B_test_28_190602.jpg

なお、MIPI ボード用PMOD 拡張ボードの 2 つのPMOD コネクタの内のP1 がGPIO でPL のポートが出ている。P2 コネクタがI2C とSPI でPS のペリフェラルを出してある。今回テストするのは、P2 コネクタのPS ペリフェラルのI2C となっている。
2 系統 PS のI2C をPMOD に出力しているが、今回テストするのは、 I2C0 ( /dev/i2c-2 ) だ。

Ultra96 のDebian を立ち上げて、GitHub のultra96_design/src/linux/caminit/src/ov5640.cc::init_ov5640() を参考にBME280 を制御するソフトウェアを作った。
PMOD_B4MIPI_B_test_26_190601.png

// BME280_temp.c
// 2019/06/01 by marsee
//
// Quote part of ultra96_design/src/linux/caminit/src/ov5640.cc::init_ov5640()
// https://github.com/fixstars/ultra96_design

#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <stdint.h>

int main(){
    int fd;
    uint8_t addr;
    uint8_t data0, data1;
    
    fd = open("/dev/i2c-2", O_RDWR);
    if(fd < 0){
        fprintf(stderr, "Can't open /dev/i2c-2\n");
        return(-1);
    }
    
    ioctl(fd, I2C_SLAVE, 0x76);
    
    addr = 0xfe;
    write(fd, &addr, 1);
    read(fd, &data0, 1);
    printf("0xfe = %x\n", data0);
    
    addr = 0xfd;
    write(fd, &addr, 1);
    read(fd, &data0, 1);
    printf("0xfd = %x\n", data0);
    
    addr = 0xd0;
    write(fd, &addr, 1);
    read(fd, &data0, 1);
    printf("0xd0 = %x\n", data0);
    
    return(0);
}


BME280_temp.c をコンパイルした。
gcc -o BME280_temp BME280_temp.c

sudo ./BME280_temp
で起動したところレジスタの値が取れた。
PMOD_B4MIPI_B_test_27_190601.png

Final Datasheet BME280 Environmental sensor から Table 18: Memory map を引用する。
PMOD_B4MIPI_B_test_30_190602.png

このレジスタマップのデフォルト値と取得した値は合っているので読めているようだ。

I2C の波形を示す。
PMOD_B4MIPI_B_test_29_190602.jpg
  1. 2019年06月02日 05:01 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0

空母いぶき(映画)を見てきた

空母いぶき(映画)を見てきた。私としてはなかなか楽しめた映画だった。
今度はゴジラを見たい。
  1. 2019年06月01日 21:14 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0