FC2カウンター FPGAの部屋 2014年12月
fc2ブログ

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

FPGAの部屋

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

2014年のFPGAの部屋のブログのまとめ(7月~12月)

2014年のFPGAの部屋のブログのまとめ(1月~6月)”の続き。

2014年のFPGAの部屋のブログを振り返ってみた。7月~12月。

7月
・ZYBOにビットマップ・ディスプレイ・コントローラを追加する
Parallella-16ボード用ケース2。ケースがとっても良く出来た。GitHubに公開してあるんだけど、作ってくれた人はいるだろうか?
AXI4 Slave Bus Functional Model のVHDL版2(VHDL 版のAXI4 Slave Bus Functional Model のソースコードがブログに貼ってあります。無保証です。)
AXI4 Slave Bus Functional Model のVerilog HDL版2(Verilog HDL 版のAXI4 Slave Bus Functional Model のソースコードがブログに貼ってあります。無保証です。)
AXI4 Slave Bus Functional Model のVHDL版3(RAMの初期化ファイルを追加)
AXI4 Slave Bus Functional Model のVerilog HDL版3(RAMの初期化ファイルを追加)

8月
ZYBO用ビットマップ・ディスプレイ・コントローラの作製6(実機動作)
明日から仙台に1週間程度滞在します
・Vivado 2104.2でSystemVerilog をやってみた。結局まだ時期尚早だということがわかった。
STAND BY ME ドラえもん(映画)を見てきました。仙台で見ました。
ZYBO用カメラ表示回路の作製1(準備編)。ZedBoard用のカメラをZYBOで使うことにした。
2つの AXI4 Master ポートを持つ XPS 用 IP の書き方(ISE14.7 の XPS)。お仕事で、これで悩んで時間がかかってしまった。
ZYBO用カメラ表示回路の作製6(デバック2、完成)。ZYBOでカメラ画像を表示することができた。
ZYBO用のEmbedded Linux チュートリアル1(IPのアップグレード)。(ZYBO用のLinuxをビルドしようと思う。Digilent社のZYBOのWebページに置いてあるPDFファイルの”Embedded Linux® Hands-on Tutorial for the ZYBO™”をやってみようと思っている。一旦、チュートリアルをやってから、好みの設定にしてみようと思っている。)
ZYBO用のEmbedded Linux チュートリアル5(U-Bootのビルド)

9月
AXI4 Slave Bus Functional Model のバグフィックス
ZYBO用のEmbedded Linux チュートリアル7(Linuxカーネルのビルド)
ZYBO用のEmbedded Linux チュートリアル8(DTB、RAMDISK、Linux起動)
ZYBO用のEmbedded Linux チュートリアル10(myLedのドライバの構築とデバイス・ツリーへの追加)
ZYBO用のEmbedded Linux(root file system をSDカードの第2パーティションへ)。ZedBoardで使ったUbntuのRoot File SystemをZYBO用に使用した。
ZYBO用のEmbedded Linux での u-boot のログ。バグもフィックスできて apt-get もできるようになった。
ZYBO用のEmbedded Linux をブートするSDカードの作り方。まとめ
走った時の3軸加速度を測定しました
ZYBO用の Linaro Ubuntu のPL部にビットマップ・ディスプレイ・コントローラを搭載する1(ブロック・デザイン)
・ZYBO用の Linaro Ubuntu のPL部にビットマップ・ディスプレイ・コントローラを搭載する3(UIOの設定)。、UIO (Userspace I/O) を使用するためにLinux のコンフィギュレーションをチェックして、デバイス・ツリーにUIOを追加した。
ZYBO用の Linaro Ubuntu のPL部にビットマップ・ディスプレイ・コントローラを搭載する5(UIOの設定3)。UIOをCプログラムを書いて実際に使用した。

10月
BeMicro MAX 10 FPGA 評価キットを注文した。中にレギュレーターを内蔵して、単一3.3Vのパッケージがある。
ZYBO用LinuxカーネルにCMA領域を確保1。ビット・マップ・ディスプレイ・コントローラのフレーム・バッファを確保しようとしたら、Linuxが落ちたので、CMA領域を確保した。
ZYBO用の Linaro Ubuntu のPL部にビットマップ・ディスプレイ・コントローラを搭載する8(ZYBOで動作確認2)。完成。
ZYBO用のLinaro Ubuntu にOpenCV-2.4.6.1 をインストール
ZYBOのLinaro Ubuntu のIPアドレスを固定する
・ZYBOのLinaro Ubuntu のXウインドウの表示をパソコンで行う(Xmingを使用)。WindowsのXmingを使用して、ZYBO LinuxのXウインドウをWindows 7 で表示した。
BeMicro MAX 10 FPGA 評価キットが来ました
・レナ像を使用してOpenCVで顔検出をやってみた(ZYBO Linaro Ubuntu)
BeMicro MAX 10 の Full featured Reference Design をやってみた1(コンパイル)。久しぶりに Quartus II を使った。
Altera Wiki , BeMicro Max 10 の Finger Temperature Tutorial をやってみた2(Qsys)。Qsysも使ってみた。
ZYBO用の Linaro Ubuntu のバージョンを 12.11 から14.04 LTS にアップグレード2
2014年10月23日の日記。Alteraツールの感想。2月中旬のVivado and ZYBO Linux勉強会の概要。
ZYBO用の Linaro Ubuntu 14.04 LTS で OpenCV の顔検出ができた
facedetect でいろいろな定義ファイルを試してみた1
Intel Edison Breakout Board Kitが来ました。そう言えば、あまり使ってないな~。

11月
Edison のファームウェアの更新
Edison を無線LANに接続
PocketDuinoが来ました。おもちゃがありすぎて、全然使っていない。
ZYBO用の Linaro Ubuntu のPL部にカメラ・コントローラを搭載する1(準備編)
いわい将門ハーフマラソン、映画『トワイライト ささらさや』を見てきました。いわい将門ハーフマラソンは腰痛で棄権しました。
ZYBOのUbuntuで使用するエディタを gvim にしました
ホンダ ライフ GF-JB1。息子の車として、購入しましたが、息子が乗らないので、私が乗っています。エンジンは最高に回りが良いし、足回りも良い感じです。乗っていて楽しいです。ただ、ハンドルのパワーステがダメなのが残念です。
ZYBO用の Linaro Ubuntu のPL部にカメラ・コントローラを搭載する10(デバック2)。ベアメタルアプリではカメラ画像を表示できた。
ZYBO用の Linaro Ubuntu のPL部にカメラ・コントローラを搭載する11(Linuxで確認)。Linuxでもカメラ画像を表示できた。
つくばマラソン2014。10kmにでて、やはり腰痛のため3.5km地点で棄権しました。
Maker Faire Tokyo 2014 に行ってきました。今年は展示物作ってないので、見学に行きました。
ZYBOのUbuntu上でカメラ画像をBMPファイルに変換できた
ハードディスクが壊れちゃいました。とっても焦った。データはほとんど修復できたので、良かった。
ZYBO用カメラ画像をOpenCVで顔認証した。これがやってみたかった。とりあえず、ファイル経由だけど、カメラ画像を顔認証できた。
ZYBO用Ubuntu Linuxの時計のずれ2(解決編)

12月
Vivado のライセンス。Activation Based Licenses では、Vivado HLS Evaluation License のライセンス期限が365日になっていました。つまり1年間使えるみたいですね。使わない手はないと思います。
VirtualBox上のUbuntu14.04LTSにVivado 2014.4 をインストールし起動する時の覚書
ZYBO用Ubuntu Linux のカメラで撮った画像にラプラシアンフィルタをかける
ZYBOのUbuntu14.04LTSにOpenCV-2.4.10をインストール
OpenCVのエッジ画像フィルタのサンプルプログラムを試してみた
OpenCVのいろいろなサンプルプログラムを試してみた
東北大学混声合唱団の定期演奏会を聞いてました。こうこれで定期演奏会を聞きに仙台に行くのも最後です。近くの旅館の天龍閣に泊まりました。
Synthesijerを試してみる1(VHDLファイルを出力)。Synthesijer を試してみることにした。
Synthesijerを試してみる4(実機でテスト)。問題なく動作した。
カメラで撮影した画像をBMPファイルにしてOpenCV で顔認証するソフトウェアを作った
Synthesijer でラプラシアンフィルタを作ってみた。24クロック掛かるようだった。

今年の後半はLinuxをかなりやっていたが、まだまだわからないことばかりだ。。。
  1. 2014年12月30日 06:48 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

映画『ホビット 決戦のゆくえ』を見てきました

映画『ホビット 決戦のゆくえ』を見てきました。
前作も見たし、ロード・オブ・ザ・リングも全て見たので、これでコンプリートですね。なかなか面白かったですが、もうこのシリーズは見なくても良いかなと思います。戦闘シーンが凄かったですが、もう見飽きた感が。。。
  1. 2014年12月28日 20:58 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

2014年のFPGAの部屋のブログのまとめ(1月~6月)

2014年のFPGAの部屋のブログを振り返ってみた。まずは1月~6月。

1月
筑波山に登った
・Vivado 2013.4だった。
・Zynq勉強会の資料を作製した。
・IP Integrator のやり方を試した。
・AXI VMDAを使ってプロジェクトを作っている。(今もうまくAXI VDMAを使えていない)

2月
つくば健康マラソンで、5km に出て、26分33秒で走れた。この時がピークだった。
・AXI VMDAも続けてやっている。
・Vivado HLSのAXI Master でラプラシアンフィルタを実装した。Vivado 2013.4 での結果はおかしかったが、Vivado 2014になって修正された。
ZYBOが届いた。(TEDさんが、Digilent社の代理店をやめたのが悲しい)
Zynq勉強会を開催した。
・ZYBOのLEDテストプロジェクト

3月
・ZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラを作った。
・FPGAエクストリーム・コンピューティング 第5回で発表した。難しいくなりすぎたかも?難しいというか?1年半を40分に縮めてご紹介したので、わかっている人しかわからない話になったかも?しれない?5回シリーズ位で説明すべき話と思う。
ZYBO用キャラクタ・ディスプレイ・コントローラ2(VGAポート専用)。HD解像度も行けたんだった。
2人の娘と伊豆に行ってきました。楽しかった。。。
ZynqのAXI_ACPポートとAXI_HPポートの性能の違い1(AXI_ACPポート)
介護用住宅改修。おやじが病院から帰ってくるので、手すりとかを付けた。

4月
Ascend HW-01E docomoを購入しました。今もこのスマホを使っています。維持費が安いので助かっています。
・Yocto ProjectのZedBoard用Linuxをビルドしてみた。成功したが動かなかった。ブートのさせ方がおかしいのかもしれない?もう一度確かめたいと思っている。
・ZYBO用のLEDテスト・プロジェクトを作ってGithub にアップロードした。
・PocketDuino Alcohol sensor kitを購入しました。届いたがまだ使っていない。
かすみがうらマラソンの5kmを走ってきました
・Lubuntu14.04 にVivado 2014.1 をインストールすることができた。まだ正式対応になっていない前だったので苦労しました。
Vivado HLS 2014.1でラプラシアン・フィルタ関数をaxi masterモジュールにする2(実機でテスト)。ソフトの結果と大きな違いは見られなくなった。
・ZYBO Base System Design

5月
・ZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラ
7シリーズのMMCM (Mixed Mode Clock Manager)
・ZYBOでXillinuxを起動してみる。Ubuntuのディスクトップが表示された。
ZedBoard用のUbuntu Linuxをビルド
ZedBoard用のUbuntu Linuxをビルド7(rootfsの書き込みと実機動作)でUbuntuディスクトップが表示できた。
ZedBaord用UbuntuにOpenCV2.4.6.1をインストール
ZYBOにOpenCV 2.4.6.1をインストール
レナ像を使用してOpenCVで顔検出をやってみた
Zynqチップにヒートシンクを付けた

6月
VivadoでZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラ IP3(単体シミュレーション)。Vivado Simulatorの機能を確かめてみた。
Vivado HLS 2014.1でラプラシアン・フィルタ関数をaxi masterモジュールにする5(Cソースのフィルタ処理をパイプライン化)
Vivado HLS 2014.1でラプラシアン・フィルタ関数をaxi masterモジュールにする8(パイプライン化ソースを実機テスト3)
Vivado 2014.2 が出ました
Parallella-16 ボードが届きました
Parallella-16でUbuntuを動作させる
・VivadoでZYBOのAXI4 Slave キャラクタ・ディスプレイ・コントローラ
Vivado 2014.2 で IP の更新のやり方を試してみた
  1. 2014年12月28日 13:22 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Synthesijer でラプラシアンフィルタを作ってみた

Synthesijer もひと通り、やってみたので、今度は”ZYBO用Ubuntu Linux のカメラで撮った画像にラプラシアンフィルタをかける”で使用した laplacian_filter.c のラプラシアンフィルタ部分のみのコードを Synthesijer でコンパイルすることにした。

ほとんど C のコードと同じだが、Java のコードに変更した laplacian_filter.java を下に示す。

// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1  8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
public class laplacian_filter{
    public int lap_filter(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2){
        int y;

        y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
        if (y<0)
            y = 0;
        else if (y>255)
            y = 255;
        return(y);
    }
}


これを Make ファイルを修正して make した。Makefile の内の関係ある部分を下に示す。

SYNTHESIJER ?= ../../bin

SOURCES = laplacian_filter.java
VHDL_SOURCES = $(SOURCES:.java=.vhd)
VERILOG_SOURCES = $(SOURCES:.java=.v)

all: $(SOURCES)
    java -cp $(SYNTHESIJER) synthesijer.Main --verilog --vhdl $(SOURCES)


実行後に、laplacian_filter.vhd と laplacian_filter.v ファイルができた。

VHDLのテストベンチ (sim.vhd) を作製して、laplacian_filter.vhd をテストした。
GHDL + GTKWave では面倒なので、ModelSim AE 10.1e を使用した。
図 1 にシミュレーション結果を示す。
Synthesijer_15_141227.png
図 1 laplacian_filter.vhd のシミュレーション結果1 - 1

プロトコルを説明する。
lap_filter_req を 1 クロック間 1 にアサートした次のクロックで、lap_filter_busy が 1 にアサートされて計算中を示す。
lap_filter_busy が 0 にディアサートされた時が計算が終了した時で、この時には、lap_filter_return にラプラシアンフィルタの値が確定されている。
lap_filter_busy が 1 にアサートされた時から 0 にディアサートされるまでの幅は 240 ns だった。クロックは100MHz, 10 ns なので、ラプラシアンフィルタの計算に 24 クロックかかっている。
図 2 を見ると、unary_expr_0010 ~ binary_expr_0018 まで 1 クロックごとに 演算しているのがわかる。
Synthesijer_16_141227.png
図 2 laplacian_filter.vhd のシミュレーション結果1 - 2

lap_filter_req の間隔を狭めると (for i in 0 to 10 loop)、正しい値が出力できなくなる。その様子を図 3 に示す。
Synthesijer_17_141227.png
図 3 laplacian_filter.vhd のシミュレーション結果2

図 1 と図 2 のシミュレーション結果の sim.vhd を下に示す。

-- sim.vhd
-- Testbench for laplacian_filter.vhd 
-- 2014/12/27 by marsee

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity sim is
end sim;

architecture testbench of sim is
component laplacian_filter
  port (
    clk : in std_logic;
    reset : in std_logic;
    lap_filter_x0y0 : in signed(32-1 downto 0);
    lap_filter_x1y0 : in signed(32-1 downto 0);
    lap_filter_x2y0 : in signed(32-1 downto 0);
    lap_filter_x0y1 : in signed(32-1 downto 0);
    lap_filter_x1y1 : in signed(32-1 downto 0);
    lap_filter_x2y1 : in signed(32-1 downto 0);
    lap_filter_x0y2 : in signed(32-1 downto 0);
    lap_filter_x1y2 : in signed(32-1 downto 0);
    lap_filter_x2y2 : in signed(32-1 downto 0);
    lap_filter_req : in std_logic;
    lap_filter_busy : out std_logic;
    lap_filter_return : out signed(32-1 downto 0)
  );
end component;

constant clock_period : time := 10 ns;
constant delay : time := 1 ns;

signal clk : std_logic := '0';
signal reset : std_logic;
signal lap_filter_x0y0 : signed(32-1 downto 0);
signal lap_filter_x1y0 : signed(32-1 downto 0);
signal lap_filter_x2y0 : signed(32-1 downto 0);
signal lap_filter_x0y1 : signed(32-1 downto 0);
signal lap_filter_x1y1 : signed(32-1 downto 0);
signal lap_filter_x2y1 : signed(32-1 downto 0);
signal lap_filter_x0y2 : signed(32-1 downto 0);
signal lap_filter_x1y2 : signed(32-1 downto 0);
signal lap_filter_x2y2 : signed(32-1 downto 0);
signal lap_filter_req : std_logic;
signal lap_filter_busy : std_logic;
signal lap_filter_return : signed(32-1 downto 0);

begin
    clk <= not clk after clock_period/2; -- clk = 100MHz, 10 ns

    uut : laplacian_filter port map (
        clk                    => clk,
        reset                => reset,
        lap_filter_x0y0        => lap_filter_x0y0,
        lap_filter_x1y0        => lap_filter_x1y0,
        lap_filter_x2y0     => lap_filter_x2y0,
        lap_filter_x0y1     => lap_filter_x0y1,
        lap_filter_x1y1     => lap_filter_x1y1,
        lap_filter_x2y1     => lap_filter_x2y1,
        lap_filter_x0y2     => lap_filter_x0y2,
        lap_filter_x1y2     => lap_filter_x1y2,
        lap_filter_x2y2     => lap_filter_x2y2,
        lap_filter_req        => lap_filter_req,
        lap_filter_busy        => lap_filter_busy,
        lap_filter_return    => lap_filter_return
    );

    stimulus : process begin
        reset <= '1';
        lap_filter_x0y0 <= to_signed(0, 32);
        lap_filter_x1y0 <= to_signed(0, 32);
        lap_filter_x2y0 <= to_signed(0, 32);
        lap_filter_x0y1 <= to_signed(0, 32);
        lap_filter_x1y1 <= to_signed(0, 32);
        lap_filter_x2y1 <= to_signed(0, 32);
        lap_filter_x0y2 <= to_signed(0, 32);
        lap_filter_x1y2 <= to_signed(0, 32);
        lap_filter_x2y2 <= to_signed(0, 32);
        lap_filter_req <= '0';

        wait for 100 ns;
        reset <= '0';

        wait for 50 ns;

        lap_filter_x0y0 <= to_signed(127, 32);
        lap_filter_x1y0 <= to_signed(127, 32);
        lap_filter_x2y0 <= to_signed(127, 32);
        lap_filter_x0y1 <= to_signed(127, 32);
        lap_filter_x1y1 <= to_signed(127, 32);
        lap_filter_x2y1 <= to_signed(127, 32);
        lap_filter_x0y2 <= to_signed(0, 32);
        lap_filter_x1y2 <= to_signed(0, 32);
        lap_filter_x2y2 <= to_signed(0, 32);

        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '1';
        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '0';

        for i in 0 to 22 loop
            wait until clk'event and clk='1';
            wait for delay;
        end loop;

        lap_filter_x0y0 <= to_signed(127, 32);
        lap_filter_x1y0 <= to_signed(127, 32);
        lap_filter_x2y0 <= to_signed(127, 32);
        lap_filter_x0y1 <= to_signed(127, 32);
        lap_filter_x1y1 <= to_signed(81, 32);
        lap_filter_x2y1 <= to_signed(127, 32);
        lap_filter_x0y2 <= to_signed(0, 32);
        lap_filter_x1y2 <= to_signed(0, 32);
        lap_filter_x2y2 <= to_signed(0, 32);

        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '1';
        wait until clk'event and clk='1';
        wait for delay;
        lap_filter_req <= '0';

        wait for 1 us;
        
        assert (false) report "Simulation End!" severity failure;
    end process;
end testbench;

  1. 2014年12月27日 19:47 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:0

Cygwin/X の設定

Cygwin/X のインストール”の続き。

Cygwin/X の xterm はデフォルトだとフォントが小さい。大きさを変えられるが、調度良いMedium だと日本語がトーフになってします。
フォントがデフォルトのxterm 画面。
CygwinX_4_141226.png

フォントがMedium のxterm 画面。
CygwinX_5_141226.png

そこで、mintty を使うことにした。
Synthesijer_11_141226.png

フォントがちょうど良い。

Cygwin/X のファイルマネージャーは、mc がある。
CygwinX_6_141226.png

もうちょっと良さそうjなファイルマネージャーは無いものか?知っている方教えて下さい。

でも、Windowsのエクスプローラでも良いかな?と思い直してきた。
  1. 2014年12月26日 07:20 |
  2. Linux
  3. | トラックバック:0
  4. | コメント:0

”WindowsでSynthesijerのsample/benchを試す”を試してみた

最初にSynthesijer の関連資料まとめのページを紹介する。

Synthesijer で1つやってみたいことがある。

それは、いつものラプラシアンフィルタを実装してみたいということだ。Synthesijer にはAXI Master インターフェースを生成する機能は無いので、私の汎用AXI Master Module を使って制御してみたいという希望がある。

今までの結果からして、Sythesijer での実行はかなりクロックを消費してしまうので、ラプラシアンフィルタの演算を1クロックで行える形にHDLにしてくれるかどうかが最大の関心事だ。それがダメでも、消費クロック数分の演算器を並べてもよい。

Javeはあまり書いたことがないので、懸念材料とはなっている。Javaを見てはいるし、Androidのアプリも少しは書いたことがあるのだが、参考書のコールバック・ルーチンを少し変えたくらいなのだ。そこで、”やさしいJava”という参考書を買ったので、勉強しようと思っている。(やることは多すぎるのだが。。。やりたいことは多すぎて時間はとっても足りない。そう今もSynthesijer 、OpenCV のMatの勉強、Vivado HLS のAXI Steramの構築、etc.. を並列に考えている。そうPythonの勉強もあった)

さてその第1段階として、”WindowsでSynthesijerのsample/benchを試す”をやってみることにした。

Cygwin/X のインストール”で、Cygwin/X をインストールしたので、それ上で行う。

GHDL と GTKWaveのインストールは説明通りに行った。

cygwin上で環境変数SYNTHESIJERを設定するが、最初は絶対パスで設定していたが、やはりうまく行かなかった。やはり相対パスで指定する必要がある。現在は.bashrc に下のように記述してある。
export SYNTHESIJER="../../synthesijer-20141211.jar"
Synthesijer_10_141226.png

ディレクトリ構造は、/home/Masaaki の下に、syntheijer ディレクトリを作製して、その下に、lib やsynthesijer-20141211.jar, synthesijer_samples_20141124 を置いている。lib も作った。
Synthesijer_9_141226.png

~/synthesijer/synthesijer_samples_20141124/bench で make した。
Synthesijer_11_141226.png

make ghdl32 した。
Synthesijer_12_141226.png

ghdl -r primesim_top --wave=primesim_top.ghw を行った。時間が掛かった。
Synthesijer_13_141226.png

gtkwave primesim_top.ghw で、GTKWave を立ち上げる。これも時間がかかる。
Synthesijer_14_141226.png
  1. 2014年12月26日 05:52 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:0

カメラで撮影した画像をBMPファイルにしてOpenCV で顔認証するソフトウェアを作った

カメラで撮影した画像をそのまま顔認証するソフトウェアを作るのが目標の1つでもあるのだが、Matのフォーマットが良くわかっていないので、勉強しようと思っている。
今回は、その前段階としてカメラで撮影した画像をBMPファイルに変換してから、そのBMPファイルをOpenCVで顔認証するソフトウェアを作った。

カメラ画像をBMPファイルにするソフトウェアは、”ZYBOのUbuntu上でカメラ画像をBMPファイルに変換できた”で作った disp2bmp.c だ。そのBMPファイルを”ZYBO用カメラ画像をOpenCVで顔認証した”で顔認証したので、その2つをつなげたソフトウェアを作った。名前は長いのだが、disp2bmp2facedetect.cpp とした。

disp2bmp2facedetect.cpp は、カメラの画像を temp0.bmp という名前でBMPファイルにする。その次に起動した時は temp0.bmp には書き込まずに、temp1.bmp という名前でカメラの画像をBMPファイルに書き込む。このように、名前の番号を増やしてBMPファイルを作っていく。
ZYBO_OpenCV_79_141224.png

disp2bmp2facedetect.cpp のコンパイルも通って、実行することができた。コマンドは下に示すように、cascade や scale を引数として書く。
./disp2bmp2facedetect --cascade="/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml" --scale=1.3

今回のC++のコードは、2つのソフトウェアをつなげただけで、見栄えが悪いし、facedetect.cpp のライセンスもわからないので、公表しない。

これで、カメラ画像を残しながら、顔認証することができる。
次は、Matのフォーマットを解析して、BMPファイルを介さずに、カメラデータで顔認証をしてみたい。
  1. 2014年12月24日 04:52 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

ベイマックス(映画)を見てきました

ベイマックス(映画)を見てきました。子守ロボットの話かと思ったら違っていました。予告編と見た印象とは全く違ってましたね。これでは誤解するんじゃないでしょうか?ロボット好きの人に見てほしいと思います。
私も、あの小さいロボットの集合体を作ってみたいと思いました。いいアイデアだと思います。そのままでは作れないので、ちょっと形を変えて、プロトタイプを作ってみたいと思いました。構造を考えようと思っています。刺激を受けたアニメでした。
  1. 2014年12月23日 13:28 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Cygwin/X のインストール

Windows で Linuxの機能を提供するソフトウェア Cygwin の内の Xサーバー同梱版の Cygwin64/X をインストールした。

Cygwin/X のページから、setup-x86_64.exe をダウンロードしてインストールした。
Cygwin Setup 画面では、Devel と X11 をすべてインストールした。
CygwinX_1_141223.png

たくさんインストールしてしまったので、Windows 7 のすべてのプログラムから Cygwin-X を開くとたくさん出てくるが、その内の Openbox を選択すれば良いようだ。
CygwinX_2_141223.png

Openbox のウインドウ内で右クリック、右クリックメニューから Terminals -> Xterm を開くとターミナルが開く。

そこで、ls をしても種類別に色分けされないので、.bashrc に

alias ls='ls --color=auto'

を追加した。(jujurou さん、ありがとうございました)

vim も行番号を表示して、シンタックスの色分けを行うために、.vimrc を作製して

set number
syntax on

を書いた。

更に、”Cygwinのインストールとapt-cygのインストール”を参照して、apt-cyg のインストールを行った。
これは、Debian の apt-get と同様のコマンドで、Cygwin はsetup.exe を起動しないと追加インストールが出来なかったのだが、コマンドラインから追加インストールを行うコマンドだ。
CygwinX_3_141223.png
  1. 2014年12月23日 13:18 |
  2. Linux
  3. | トラックバック:0
  4. | コメント:0

Cygwin で nvc (VHDL compiler and simulator) を試してみた2

Writing a VHDL compiler”を参考にして、counter.vhd と top.vhd を作ってやってみた。
(注)いろいろと試行錯誤しているので、お見苦しい点がありますが、ご了承ください。

counter.vhd を作って、
nvc -a counter.vhd
コマンドを実行すると work ディレクトリが出来て、その下に _index _NVC_LIB WORK.COUNTER WORK.COUNTER-BEHAV ファイルができた。
nvc_12_141222.png

top.vhd を作って、
nvc -a top.vhd
コマンドを実行すると、work ディレクトリに WORK.TOP WORK.TOP-TEST が増えていた。
nvc_13_141222.png

nvc -e top
コマンドを実行すると、work ディレクトリに _WORK.TOP.elab.bc  _WORK.TOP.elab.deps.txt _WORK.TOP.elab.netdb _WORK.TOP.final.bc が生成された。
nvc_14_141222.png

nvc -r --stop-time=50ns top
コマンドを実行すると、コアダンプしました。orz

nvc -r -c top
show signals

でもコアダンプです。
nvc_15_141222.png
  1. 2014年12月22日 21:33 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Cygwin で nvc (VHDL compiler and simulator) を試してみた1

hiyuh さんに教えてもらった nvc (VHDL compiler and simulator) を Cygwin にインストールして、試してみることにした。

・LLVM を Cygwin にインストールした。
nvc_3_141222.png

・GitHub から nvc を clone する。
git clone https://github.com/nickg/nvc.git

nvc というディレクトリができた。
nvc_1_141222.png

・GitHub のReadme.md に書いてあるインストール・コマンドを入力した。
cd nvc
./autogen.sh

nvc_2_141222.png

./tools/fetch-ieee.sh を実行するとエラー。curl をインストールする必要があるようだ。
nvc_4_141222.png

・Cygwin で curl をインストールした。
nvc_5_141222.png

もう一度、./tools/fetch-ieee.sh を実行した。今度は成功。
nvc_6_141222.png

・続けでコマンドを実行した。
mkdir build && cd build
../configure

nvc_7_141222.png

make
nvc_8_141222.png

致命的なエラーが出ちゃいました。

・src/rt/shell.c の 39, 43 行目をコメントアウトした。
nvc_10_141222.png

・もう一度、make を行うと警告はあったが、通った。
nvc_9_141222.png

make install
nvc_11_141222.png

なんとか通ったみたいだけど、大丈夫だろうか?
  1. 2014年12月22日 05:20 |
  2. シミュレーション
  3. | トラックバック:0
  4. | コメント:0

Synthesijerを試してみる4(実機でテスト)

Test.java の上の Top.java があることがわかった。SoureForge の quickstart に一式があった。これを使用して、今回は実機で動作させてみようと思う。
使用するFPGAボードはZYBO だ。思えば、ZYBO はPLだけ、つまりFPGA部分だけで動作させたことがない。つまり、いつもハードウェアをエクスポートして、SDKでPL部をコンフィギュレーションしていた。今回はPSのクロックをあてに出来ないので、PL部へ外部から供給されたクロックを使用する。ZYBOには、イーサーネットのPHYから供給されている125MHzのクロックがあるので、これを使用する。
reset 入力はBTN0 を使用して、flag_return はLED1 を使用する。

java ファイルは、make.bat を作って、VHDL と Verilog HDL へ変換した。make.bat を示す。

java -cp C:\Users\Masaaki\Documents\Synthesijer\synthesijer-20141211.jar synthesijer.Main --vhdl --verilog^
                   Test.java ^
                   Top.java


ZYBO用のVivado プロジェクトを作製した。quickstart にあった sim.vhd もVivado プロジェクトに入れた。シミュレーションもしてみたが、やはり、5000001 カウントは遠い。なかなかflag_return が変化しないので、止めた。

論理合成、インプリメント、ビットストリームの生成を行った。
その際に、Test.xdc ファイルを作製した。Test.xdc ファイルを下に示す。

set_property PACKAGE_PIN L16 [get_ports clk]
set_property IOSTANDARD LVCMOS33 [get_ports clk]
set_property PACKAGE_PIN R18 [get_ports reset]
set_property IOSTANDARD LVCMOS33 [get_ports reset]
set_property PACKAGE_PIN M14 [get_ports flag_return]
set_property IOSTANDARD LVCMOS33 [get_ports flag_return]


ここからが初めて使用するVivado の機能(Vivado Logic Simulator では使用しているが、それを使用しないで、FPGAのコンフィギュレーションのみは、今回初めて)なのだが、Flow Navigator から Open Target をクリックして、Program Deviceをクリックしたら問題なくZynq のPL のみのコンフィギュレーションが成功した。
Synthesijer_8_141220.png

LED0 も正常に点滅している。点滅周波数は、

125MHz / (5000001カウント * 7クロック * 2状態) ≒ 1.8 Hz

となるはずだ。

10秒間のLED0 の点滅回数を数えてみると、16回となった。少しズレが大きい気もするがだいたい合っている気がする。
  1. 2014年12月21日 05:44 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:0

Synthesijerを試してみる3(Test2.java)

Lチカする java ソフトウェア Test.java だが、私は違う書き方で書きたいので書いてみた。それをTest2.java とする。
Test2.java を下に示す。

public class Test2{
  public boolean flag;
  private int count;

  public void run(){
    while(true){
      if (count <= 10){
        count++;
      } else {
        count = 0;
        flag = !flag;
      }
    }
  }
}


これを、Synthesijer でコンパイルするために、Synthesijer の make.bat を参考にして私も make.bat を作製した。なお、Cygwinで Makefile を make してみたが、java コマンドを実行した所でエラーになってしまった。java のエラー・メッセージが日本語化けでわからないので、諦めて、Windows上でバッチファイルでコンパイルすることにした。make.bat を下に示す。

java -cp C:\Users\Masaaki\Documents\Synthesijer\synthesijer-20141211.jar synthesijer.Main --vhdl --verilog^
                   Test2.java 

make.bat を実行すると、Test2.vhd と Test2.v ができる。
テストベンチ Test2_tb.v は、前回の Test_tb.v と殆ど同じだ。
シミュレーションの結果を下の図に示す。
Synthesijer_7_141220.png

このソフトウェアだと、flag_out の周期は 1.92 usec となって、前回の 1.6 usec よりも長くなった。
前回は count を一つカウントアップするまでに7ステートだったが、今回は8ステートかかっているようだ。多分だが、こちらは、count++ するのに条件をつけているので、1クロック余計に必要としているのだろう?
この辺りの事情を汲んで java コードを書いたほうが良いかもしれない?

Test2.vhd を下に示す。

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity Test2 is
  port (
    clk : in std_logic;
    reset : in std_logic;
    flag_in : in std_logic;
    flag_we : in std_logic;
    flag_out : out std_logic;
    run_req : in std_logic;
    run_busy : out std_logic
  );
end Test2;

architecture RTL of Test2 is


  signal clk_sig : std_logic;
  signal reset_sig : std_logic;
  signal flag_in_sig : std_logic;
  signal flag_we_sig : std_logic;
  signal flag_out_sig : std_logic;
  signal run_req_sig : std_logic;
  signal run_busy_sig : std_logic := '1';

  signal class_flag_0000 : std_logic := '0';
  signal class_flag_0000_mux : std_logic;
  signal tmp_0001 : std_logic;
  signal class_count_0001 : signed(32-1 downto 0) := (others => '0');
  signal binary_expr_00002 : std_logic := '0';
  signal unary_expr_00003 : signed(32-1 downto 0) := (others => '0');
  signal unary_expr_00004 : std_logic := '0';
  signal run_req_flag : std_logic;
  signal run_req_local : std_logic := '0';
  signal tmp_0002 : std_logic;
  type Type_run_method is (
    run_method_IDLE,
    run_method_S_0000,
    run_method_S_0001,
    run_method_S_0002,
    run_method_S_0003,
    run_method_S_0004,
    run_method_S_0005,
    run_method_S_0006,
    run_method_S_0007,
    run_method_S_0008,
    run_method_S_0009,
    run_method_S_0010,
    run_method_S_0012,
    run_method_S_0013,
    run_method_S_0014,
    run_method_S_0015  
  );
  signal run_method : Type_run_method := run_method_IDLE;
  signal run_method_delay : signed(32-1 downto 0) := (others => '0');
  signal tmp_0003 : std_logic;
  signal tmp_0004 : std_logic;
  signal tmp_0005 : std_logic;
  signal tmp_0006 : std_logic;
  signal tmp_0007 : std_logic;
  signal tmp_0008 : signed(32-1 downto 0);
  signal tmp_0009 : std_logic;

begin

  clk_sig <= clk;
  reset_sig <= reset;
  flag_in_sig <= flag_in;
  flag_we_sig <= flag_we;
  flag_out <= flag_out_sig;
  flag_out_sig <= class_flag_0000;

  run_req_sig <= run_req;
  run_busy <= run_busy_sig;
  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        run_busy_sig <= '1';
      else
        if run_method = run_method_S_0001 then
          run_busy_sig <= run_req_flag;
        end if;
      end if;
    end if;
  end process;


  -- expressions
  tmp_0001 <= flag_in_sig when flag_we_sig = '1' else class_flag_0000;
  tmp_0002 <= run_req_local or run_req_sig;
  tmp_0003 <= '1' and '1';
  tmp_0004 <= '1' and '0';
  tmp_0005 <= '1' when binary_expr_00002 = '1' else '0';
  tmp_0006 <= '1' when binary_expr_00002 = '0' else '0';
  tmp_0007 <= '1' when class_count_0001 <= X"0000000a" else '0';
  tmp_0008 <= class_count_0001 + X"00000001";
  tmp_0009 <= not class_flag_0000;

  -- sequencers
  process (clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        run_method <= run_method_IDLE;
        run_method_delay <= (others => '0');
      else
        case (run_method) is
          when run_method_IDLE => 
            run_method <= run_method_S_0000;
          when run_method_S_0000 => 
            run_method <= run_method_S_0001;
            run_method <= run_method_S_0001;
          when run_method_S_0001 => 
            if run_req_flag = '1' then
              run_method <= run_method_S_0002;
            end if;
          when run_method_S_0002 => 
            if tmp_0003 = '1' then
              run_method <= run_method_S_0004;
            elsif tmp_0004 = '1' then
              run_method <= run_method_S_0003;
            end if;
          when run_method_S_0003 => 
            run_method <= run_method_S_0015;
          when run_method_S_0004 => 
            run_method <= run_method_S_0005;
          when run_method_S_0005 => 
            if tmp_0005 = '1' then
              run_method <= run_method_S_0007;
            elsif tmp_0006 = '1' then
              run_method <= run_method_S_0010;
            end if;
          when run_method_S_0006 => 
            run_method <= run_method_S_0014;
          when run_method_S_0007 => 
            run_method <= run_method_S_0008;
          when run_method_S_0008 => 
            run_method <= run_method_S_0009;
          when run_method_S_0009 => 
            run_method <= run_method_S_0006;
          when run_method_S_0010 => 
            run_method <= run_method_S_0012;
          when run_method_S_0012 => 
            run_method <= run_method_S_0013;
          when run_method_S_0013 => 
            run_method <= run_method_S_0006;
          when run_method_S_0014 => 
            run_method <= run_method_S_0002;
          when run_method_S_0015 => 
            run_method <= run_method_S_0000;
          when others => null;
        end case;
      end if;
    end if;
  end process;


  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        class_flag_0000 <= '0';
      else
        if run_method = run_method_S_0012 then
          class_flag_0000 <= unary_expr_00004;
        else
          class_flag_0000 <= class_flag_0000_mux;
        end if;
      end if;
    end if;
  end process;

  class_flag_0000_mux <= tmp_0001;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        class_count_0001 <= (others => '0');
      else
        if run_method = run_method_S_0008 then
          class_count_0001 <= unary_expr_00003;
        elsif run_method = run_method_S_0010 then
          class_count_0001 <= X"00000000";
        end if;
      end if;
    end if;
  end process;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        binary_expr_00002 <= '0';
      else
        if run_method = run_method_S_0004 then
          binary_expr_00002 <= tmp_0007;
        end if;
      end if;
    end if;
  end process;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        unary_expr_00003 <= (others => '0');
      else
        if run_method = run_method_S_0007 then
          unary_expr_00003 <= tmp_0008;
        end if;
      end if;
    end if;
  end process;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        unary_expr_00004 <= '0';
      else
        if run_method = run_method_S_0010 then
          unary_expr_00004 <= tmp_0009;
        end if;
      end if;
    end if;
  end process;

  run_req_flag <= tmp_0002;



end RTL;

  1. 2014年12月20日 21:17 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:0

Synthesijerを試してみる2(VHDLファイルをシミュレーション)

Synthesijerを試してみる1(VHDLファイルを出力)”の続き。

今回はテストベンチ (Test_tb.v) を書いて、シミュレーションを行った。シミュレーション環境はVivado 2014.4のVivado Simulatorで行った。何故かと言うと、混在シミュレーションができるシミュレータが少ないからだ。ZYBOボードの xc7z010clg400-1 でプロジェクトを作製した。

シミュレータを行ったが、カウント数が多いので、シミュレーションが大変ということで、ループカウントを10 に変更した。変更したJava のコードを下に示す。

public class Test{
  public boolean flag;
  private int count;

  public void run(){
    while(true){
      count++;
      if(count > 10){
      //if(count > 5000000){
           count = 0;
           flag = !flag;
      }
    }
  }
}


これでシミュレーションを行った。Vivado Simulator の画面を下に示す。
Synthesijer_6_141218.png

上の図から flag_out の周期は 1.6 usec となった。flag_out の値が反転するのは半分の 800 nsec である。それをカウント値の11カウントで割ると、

800 /11 ≒ 72.7 nsec

となる。現在の動作クロックは 100MHz で 10 nsec なので、1カウント分の平均的なクロック数は

72.7 / 10 = 7.27 クロック

となった。どうやら run_method_S_0011 の時に、flag_out が変化するようだ。ステートを遷移して行って判定を行いながら結果を出力しているのか?ユーザーズ・マニュアルが欲しいと思った。

下にテストベンチのTest_tb.v を示す。

`default_nettype none

`timescale 1ns / 100ps

// Test_tb.v
// 2014/12/17
//

module Test_tb;
    parameter DELAY = 1;

    wire    clk;
    wire    reset;
    reg        flag_in;
    reg        flag_we;
    wire    flag_out;
    reg        run_req;
    wire    run_busy;

    Test uut_Test (
        .clk(clk),
        .reset(reset),
        .flag_in(flag_in),
        .flag_we(flag_we),
        .flag_out(flag_out),
        .run_req(run_req),
        .run_busy(run_busy)
    );

    initial begin
        // Initialize Inputs
        flag_in <= 1'b0;
        flag_we <= 1'b0;
        run_req <= 1'b1;
    end

    // clk_gen のインスタンス(clk)
    clk_gen #(
        .CLK_PERIOD(10),    // 10nsec, 100MHz
        .CLK_DUTY_CYCLE(0.5),
        .CLK_OFFSET(0),
        .START_STATE(1'b0)
    ) ACLKi (
        .clk_out(clk)
    );

    // reset_gen のインスタンス
    reset_gen #(
        .RESET_STATE(1'b1),
        .RESET_TIME(100)    // 100nsec
    ) RESET_ARESETN (
        .reset_out(reset),
        .init_done()
    );
endmodule

module clk_gen #(
    parameter         CLK_PERIOD = 100,
    parameter real    CLK_DUTY_CYCLE = 0.5,
    parameter        CLK_OFFSET = 0,
    parameter        START_STATE    = 1'b0 )
(
    output    reg        clk_out
);
    begin
        initial begin
            #CLK_OFFSET;
            forever
            begin
                clk_out = START_STATE;
                #(CLK_PERIOD-(CLK_PERIOD*CLK_DUTY_CYCLE)) clk_out = ~START_STATE;
                #(CLK_PERIOD*CLK_DUTY_CYCLE);
            end
        end
    end
endmodule

module reset_gen #(
    parameter    RESET_STATE = 1'b1,
    parameter    RESET_TIME = 100 )
(
    output    reg        reset_out,
    output    reg        init_done
);
    begin
        initial begin
            reset_out = RESET_STATE;
            init_done = 1'b0;
            #RESET_TIME;
            reset_out = ~RESET_STATE;
            init_done = 1'b1;
        end
    end

endmodule

`default_nettype wire

  1. 2014年12月19日 04:39 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:5

Synthesijerを試してみる1(VHDLファイルを出力)

Synthesijer を試してみることにした。まずはLチカからか。
Synthesijer はjava ベースの高位合成ツールだ。わらさぼで作られている。java はあまり分からないがサンプルをやってみようと思う。
Vivado HLSとくらべて、どんなHDLコードが出力されるのかを見てみたい。
環境がよくわからないんだけど、Linuxは問題無いとして、Windowsでも行けるのだろうか?(javaだからjava が動けばどれでもよいんですね?)
とりあえず、Windowsでやってみようと思う。

sourceforge のSynthesijer からsynthesijer-20141211.jar をダウンロードした。

Synthesijer のページから Writing 1st Program を Test.jave をコピー&ペーストして、作製した。Test.java を引用する。

public class Test{
  public boolean flag;
  private int count;

  public void run(){
    while(true){
      count++;
      if(count > 5000000){
    count = 0;
    flag = !flag;
      }
    }
  }
}


・Synthesijer フォルダを作製して、synthesijer-20141211.jar と Test.java を入れて

java -cp synthesijer-20141211.jar synthesijer.Main Test.java

コマンドを実行すると Test.vhd ファイルを出力した。
Synthesijer_1_141217.png

・現在使用している java のバージョンは 1.7.0_17 だ。無事に実行できた。
Synthesijer_2_141217.png

・Synthesijer フォルダを見ると、いろいろな中間ファイルが生成されていた。Test.vhd も生成されていた。
Synthesijer_3_141217.png

・Test.vhd を見ると、clk, reset, flag_in, flag_we, flag_out, run_req, run_busy のポートが生成されている。出力ポートは flag_out, run_busy で、後は入力ポートだ。
ステートは、run_method_IDLE から run_method_S_0014 までの16ステートある。
どうやら、tmp_0007 で class_count_0001 を +1 して、tmp_0008 で、class_count_0001 が 0x4C4B40 (5000000) 以上になった時を判定しているようだ。

・Test.vhd を下に示す。

ibrary IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity Test is
  port (
    clk : in std_logic;
    reset : in std_logic;
    flag_in : in std_logic;
    flag_we : in std_logic;
    flag_out : out std_logic;
    run_req : in std_logic;
    run_busy : out std_logic
  );
end Test;

architecture RTL of Test is


  signal clk_sig : std_logic;
  signal reset_sig : std_logic;
  signal flag_in_sig : std_logic;
  signal flag_we_sig : std_logic;
  signal flag_out_sig : std_logic;
  signal run_req_sig : std_logic;
  signal run_busy_sig : std_logic := '1';

  signal class_flag_0000 : std_logic := '0';
  signal class_flag_0000_mux : std_logic;
  signal tmp_0001 : std_logic;
  signal class_count_0001 : signed(32-1 downto 0) := (others => '0');
  signal unary_expr_00002 : signed(32-1 downto 0) := (others => '0');
  signal binary_expr_00003 : std_logic := '0';
  signal unary_expr_00004 : std_logic := '0';
  signal run_req_flag : std_logic;
  signal run_req_local : std_logic := '0';
  signal tmp_0002 : std_logic;
  type Type_run_method is (
    run_method_IDLE,
    run_method_S_0000,
    run_method_S_0001,
    run_method_S_0002,
    run_method_S_0003,
    run_method_S_0004,
    run_method_S_0005,
    run_method_S_0006,
    run_method_S_0007,
    run_method_S_0008,
    run_method_S_0009,
    run_method_S_0011,
    run_method_S_0012,
    run_method_S_0013,
    run_method_S_0014  
  );
  signal run_method : Type_run_method := run_method_IDLE;
  signal run_method_delay : signed(32-1 downto 0) := (others => '0');
  signal tmp_0003 : std_logic;
  signal tmp_0004 : std_logic;
  signal tmp_0005 : std_logic;
  signal tmp_0006 : std_logic;
  signal tmp_0007 : signed(32-1 downto 0);
  signal tmp_0008 : std_logic;
  signal tmp_0009 : std_logic;

begin

  clk_sig <= clk;
  reset_sig <= reset;
  flag_in_sig <= flag_in;
  flag_we_sig <= flag_we;
  flag_out <= flag_out_sig;
  flag_out_sig <= class_flag_0000;

  run_req_sig <= run_req;
  run_busy <= run_busy_sig;
  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        run_busy_sig <= '1';
      else
        if run_method = run_method_S_0001 then
          run_busy_sig <= run_req_flag;
        end if;
      end if;
    end if;
  end process;


  -- expressions
  tmp_0001 <= flag_in_sig when flag_we_sig = '1' else class_flag_0000;
  tmp_0002 <= run_req_local or run_req_sig;
  tmp_0003 <= '1' and '1';
  tmp_0004 <= '1' and '0';
  tmp_0005 <= '1' when binary_expr_00003 = '1' else '0';
  tmp_0006 <= '1' when binary_expr_00003 = '0' else '0';
  tmp_0007 <= class_count_0001 + X"00000001";
  tmp_0008 <= '1' when class_count_0001 > X"004c4b40" else '0';
  tmp_0009 <= not class_flag_0000;

  -- sequencers
  process (clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        run_method <= run_method_IDLE;
        run_method_delay <= (others => '0');
      else
        case (run_method) is
          when run_method_IDLE => 
            run_method <= run_method_S_0000;
          when run_method_S_0000 => 
            run_method <= run_method_S_0001;
            run_method <= run_method_S_0001;
          when run_method_S_0001 => 
            if run_req_flag = '1' then
              run_method <= run_method_S_0002;
            end if;
          when run_method_S_0002 => 
            if tmp_0003 = '1' then
              run_method <= run_method_S_0004;
            elsif tmp_0004 = '1' then
              run_method <= run_method_S_0003;
            end if;
          when run_method_S_0003 => 
            run_method <= run_method_S_0014;
          when run_method_S_0004 => 
            run_method <= run_method_S_0005;
          when run_method_S_0005 => 
            run_method <= run_method_S_0006;
          when run_method_S_0006 => 
            run_method <= run_method_S_0007;
          when run_method_S_0007 => 
            if tmp_0005 = '1' then
              run_method <= run_method_S_0009;
            elsif tmp_0006 = '1' then
              run_method <= run_method_S_0008;
            end if;
          when run_method_S_0008 => 
            run_method <= run_method_S_0013;
          when run_method_S_0009 => 
            run_method <= run_method_S_0011;
          when run_method_S_0011 => 
            run_method <= run_method_S_0012;
          when run_method_S_0012 => 
            run_method <= run_method_S_0008;
          when run_method_S_0013 => 
            run_method <= run_method_S_0002;
          when run_method_S_0014 => 
            run_method <= run_method_S_0000;
          when others => null;
        end case;
      end if;
    end if;
  end process;


  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        class_flag_0000 <= '0';
      else
        if run_method = run_method_S_0011 then
          class_flag_0000 <= unary_expr_00004;
        else
          class_flag_0000 <= class_flag_0000_mux;
        end if;
      end if;
    end if;
  end process;

  class_flag_0000_mux <= tmp_0001;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        class_count_0001 <= (others => '0');
      else
        if run_method = run_method_S_0005 then
          class_count_0001 <= unary_expr_00002;
        elsif run_method = run_method_S_0009 then
          class_count_0001 <= X"00000000";
        end if;
      end if;
    end if;
  end process;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        unary_expr_00002 <= (others => '0');
      else
        if run_method = run_method_S_0004 then
          unary_expr_00002 <= tmp_0007;
        end if;
      end if;
    end if;
  end process;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        binary_expr_00003 <= '0';
      else
        if run_method = run_method_S_0006 then
          binary_expr_00003 <= tmp_0008;
        end if;
      end if;
    end if;
  end process;

  process(clk)
  begin
    if clk'event and clk = '1' then
      if reset = '1' then
        unary_expr_00004 <= '0';
      else
        if run_method = run_method_S_0009 then
          unary_expr_00004 <= tmp_0009;
        end if;
      end if;
    end if;
  end process;

  run_req_flag <= tmp_0002;



end RTL;

  1. 2014年12月17日 05:54 |
  2. Synthesijer
  3. | トラックバック:0
  4. | コメント:0

東北大学混声合唱団の定期演奏会を聞いてました

12月13日(土)、14日(日)と娘の所属する東北大学混声合唱団の定期演奏会を聞きに仙台まで車で行ってきました。

今回は奥さんと私の妹と3人で車で行ってきました。下の娘も行く予定だったのですが、土曜日が高校の授業になってしまったので、行けなくなりました。残念。。。
13日は、6時30分ころ家を出発して矢板から東北道へ、結構車が少なかったので、順調に仙台に到着しました。
仙台に到着したら、美味しい牛たんの店に行こうということになりました。奥さんがネットで検索したら、一隆が良いとのことでいきました。 牛たんを1.5人前に増量してもらって食べましたが、私は歯のかみ合わせが悪いので、厚めの牛たんは噛み切れません。あまり向かないようです。牛テールスープはとっても美味しかったです。家に送ってもらいました。

雪が降るなか、東北大学の萩ホールに行って東北大学混声合唱団の定期演奏会を見ました。14時30分開場、15時開演です。
ステージは3部構成で、今年は第3部(フランス語です)もとっても聴きやすく、素晴らしい合唱でした。聴き応えがありましたよ。元オフコースの小田和正さんが混声合唱団OBということで、贈られたお花が飾ってありました。
演奏会終了時に合唱団がエントランスで歌ってくれるサプライズもあって良かったです。娘にも会えました。
sendai_1_141215.jpg

今日は娘のアパートに泊まるのではなく、近くの旅館の天龍閣に泊まりました。夕食がとっても豪華でしたよ。岩盤浴もやって来ましたが、サウナのような感じでマットを敷いて熱い岩盤の上で寝ているんですね。熱いので汗びっしょりになったので、早々に退散しました。宿泊費は1万800円でなかなか良かったです。日本の旅館という感じですね。

14日は朝から歩いてすぐ近くの瑞鳳殿へ行ってきました。小さな日光の東照宮の様な感じで色が鮮やかです。
sendai_2_141215.jpg

娘が起きたようなので、娘のアパートに行ってきました。娘と一緒にお買い物へ行きました。娘にプレゼントというか服を買ってあげました。お昼には、パルコの9Fの東京純豆腐でスンドゥブを食べてきました。私は辛くない牛すじスンドゥブでしたがおいしかったですよ。。。
仙台はとっても寒かったです。気温は1度くらいでした。震え上がってました。

名残惜しかったですが、娘と別れて東北道へ。途中、かなり雪が降ってきて積もりそうでしたが、道に雪が乗っている状況にはならなかったので良かったです。タイヤはスタッドレスタイヤを履いてので、雪が道路に積もっていてもスピードを落とせば大丈夫だと思いますが。。。5時間程度で帰ってきました。奥さんにも運転してもらったので、助かりました。

娘も4年生なので最後の定期演奏会です。4回全部行って聞いていますが、どれも素晴らしかったですね。練習は大変なようですけど。。。大学院の前期課程に入学するので、後2年間大学生活が続きますが、大学生活を楽しんで欲しいですね。
  1. 2014年12月15日 05:18 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0

Vivado 2014.4 でLED4ビットのAXI4 Lite Slave IPをウィザードで作る1(仕様)

今回は、2月中旬に行うVivado and ZYBO Linux勉強会に向けて、ライブ・コーティング(参加者と一緒にその場で、自分でやりながら、参加者にも同時にやってもらう)する LED4bitのAXI4 Lite Slave IPを作っていこうと思う。 前回は、XPSでAXI4 Lite Slaveバス・プロトコルまですべて自作だったが、今回は、Vivado 2014.4 で AXI4 Peripheral ウィザード機能で作っていこうと思う。 なお、2日目にu-boot や Digilent Linuxカーネルのコンパイルを行うため、VirtualBox上にインストールしたUbuntu上にVivado 2014.4をインストールしてライブ・コーティングを行う。
ライブ・コーティングではIP Integratorを使用してIPベースでの構築を行う。LEDを制御するAXI4 Lite SlaveのカスタムIPを作るわけだ。しかし、自作カスタムIPが間違っている場合もある。その時のために、その修正方法を学ぶという意味で、わざと間違えたHDLコードを入れておいて、エラーが出てからエラーのあるIP を修正し、正しくコンパイルを行うという手順でやってみようと思う。つまりIP の修正方法も学ぶという意味だ。通常のセミナでは、正しいHDLコードしか提供されていないと思うのだが、やはり間違っていた時の修正方法も学べたほうが良いと思う。普通は自作したIPは修正する必要が有ることが殆どだろう?

仕様としてはZedBoardからZYBOになって、LEDが4個になったのが違うだけだ。以前に、GitHubに上げてあるVivado_ZYBO_LED_test2 と同じ動作になるが、IP Packager のAXI4 Peripheral ウィザード機能でAXI4 Lite Slave プロトコルを自動生成するところが異なる。

下に仕様を示す。
4つのLEDを制御するIOポートを用意して、値を設定するレジスタを用意する。更に、コマンド・レジスタを用意する。そこには、LEDを+1するコマンド・ビットを用意する。+1する時のクロックのカウント値を決めるレジスタと、LEDの点灯値を表示するレジスタも必要だ。よってレジスタ構成は次の通りになる。

オフセット0:コマンド・レジスタ(R/W)
 ビット0:1 - LEDの値を+1する 0 - LEDの値はそのまま (デフォルト値は0)
 ビット31~1:リザーブ
オフセット4:LED値のロード・レジスタ(R/W)
 ビット7~0:8ビット分のLEDの値
 ビット31~8:リザーブ(Read時はすべて0)
オフセット8:現在のLEDの値のReadレジスタ(Read Only)
 ビット7~0:8ビット分の現在のLEDの値
 ビット31~8:すべて0
(2014/12/16:AXI Lite Slave ウイザードだど実装が難しいので削除)
オフセットC:LED値を+1する時のカウント値(R/W)但し、動作クロックは100MHzとする
 ビット31~0:LED値を+1する時のカウント値


IP Packager のAXI4 Peripheral ウィザード機能でAXI4 Lite Slaveを作ると生成されるレジスタの値は4個になるので、ちょうどデフォルト値でOKとなる。
  1. 2014年12月12日 04:38 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

IP Packager で AXI4 peripheral を作成すると、Internal Exception が発生する

VirtualBoxに Ubuntu 14.04LTS をインストールして Vivado 2014.4 を使用している。
その環境で、IP Packager を使ってIPを作る時のダイアログでAXI4 peripheral を選ぶと、Vivado で Internal Errorが発生した。

Internal Exception に至るまでの手順を示す。

・Vivado の Tools メニューからCreate and Package IP ... をクリックした。
ZYBO_EM_Linux_16_140828.png

・Create and Package New IP ダイアログをが開いた。Next > ボタンをクリックした。
ZYBO_EM_Linux_17_140828.png

・Create a new AXI4 peripheral のラジオボタンをクリックして、Next > ボタンをクリックした。
ZYBO_EM_Linux_18_140828.png

そうすると、Internal Exception のダイアログが出た。
Vivado_internal_error_1_141211.png

ツィッターに呟くと、nabesan_tofu さんが、” そのバグ、vender名を空でなく何か入れると回避できる、ってどこかで見た気がします”とメンションをくれた。ありがとうございます。
調べてみると、”AR# 60477 2014.1 Vivado IP フロー - IP パッケージャーで AXI4 ペリフェラルを作成すると、内部例外エラーが発生する”がありました。やはり vender 名を入れておけとのことだった。
実際に確認してみよう。

・Flow Navigator のProject Manager -> Project Settings をクリックした。
ZYBO_EM_Linux_13_140828.png

・IPをクリックして、Packager タブをクリックした。vendor は none だった。
Vivado_internal_error_2_141211.png

・vendor を marsee に変更した。
Vivado_internal_error_3_141211.png

・Peripheral Detals まで行けました。
Vivado_internal_error_4_141211.png

問題解決です。nabesan_tofu さん、ありがとうございました。
  1. 2014年12月11日 11:17 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Interface誌2013年7月号のOpenCVのサンプルプログラム1

Interface誌2013年7月号のOpenCVのサンプルプログラムはとってもよく出来ていると思うので、やってみたいと思う。(引用は必ず記載するようにしているが問題があったら教えて下さい)
記事の内容には言及しない。記事はInterface誌2013年7月号で見て欲しいが、残念ながらCQ出版社のWebショップでも売り切れのようだ。かろうじてアマゾンの中古雑誌がある。

最初は、Interface誌2013年7月号のOpenCVのP48、「基本処理その3…ヒストグラムによる輝度調整」の demhist.cpp を g++_opencv でコンパイルして、実行してみた。当然、ZYBO上のUbuntu にインストールしたOpenCV-2.4.10 でコンパイルしている。
ZYBO_OpenCV_78_141211.jpg

スライダーで明るさとコントラストを変更することができる。
明るさを落とすとヒストグラムが左に偏るし、明るくするとヒストグラムが右に偏る。
コントラストを上げるとヒストグラムが左端と右端に偏る。
コントラストを下げると、ヒストグラムが真ん中に偏る。
やはりスライダーで調整つできると面白い。ぜひやってみてください。
  1. 2014年12月11日 05:48 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

OpenCVのいろいろなサンプルプログラムを試してみた2

今度は、OpenCV 1.0 のサンプルプログラムを幾つか試してみた。

ハフ変換による直線検出 cvHoughLines2
ZYBO_OpenCV_73_141210.jpg

ハフ変換による円検出 cvHoughCircles
ZYBO_OpenCV_74_141210.jpg

輪郭の検出と描画 cvFindContours
ZYBO_OpenCV_75_141210.jpg

画像のアフィン変換(1) cvGetAffineTransform + cvWarpAffine
ZYBO_OpenCV_76_141210.jpg

平滑化 cvSmooth
ZYBO_OpenCV_77_141210.jpg

平滑化はだいぶ時間が掛かった。一度の4種類のフィルタの結果が確かめられるのは良いが、平滑化の度合いを変更できるスライダーを付けてみたい。
  1. 2014年12月10日 04:25 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

OpenCVのいろいろなサンプルプログラムを試してみた

前回の続きで、いろいろなOpenCV のサンプルプログラムを試してみた。(ZYBOボードにインストールしたOpenCV-2.4.10 上でやっています)
サンプルプログラムの中には、コンパイルでエラーが出るもの、実行時にエラーが出るものがあった。OpenCV-2.4.10 を使用してコンパイルした。

コーナー検出(EigenValue,Harris,FAST)
ZYBO_OpenCV_67_141209.jpg
ZYBO_OpenCV_68_141209.jpg

う~ん。窓枠をもっと検出して欲しかった気がする。(画像は640X475ピクセル)

画像の二値化
ZYBO_OpenCV_69_141209.jpg

画像のカラーヒストグラムの描画
レナ像のカラーヒストグラム。やはり赤が強い気がする。
ZYBO_OpenCV_70_141209.jpg

k-meansクラスタリングによる画像分割,減色
ZYBO_OpenCV_71_141209.jpg

モルフォロジー変換
ZYBO_OpenCV_72_141209.jpg
  1. 2014年12月09日 04:51 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

OpenCVのエッジ画像フィルタのサンプルプログラムを試してみた

OpenCVのエッジ画像フィルタのサンプルプログラムを試してみた。

最初にCQ出版社のInterface 誌の2013年7月号の”第5章 オープンソースで簡単に試せる! USBカメラにピッタリ! 定番 画像処理ライブラリOpenCVの準備サンプルプログラム”から、edge.cpp を試してみた。edge.cpp はcanny フィルタの結果のみを表示するが、原画像も表示するようにプログラムを書き換えた。下にレナ像を表示してみた結果を示す。
ZYBO_OpenCV_62_141207.jpg

Canny threshold のスライダーをスライドさせるとフィルタ画像が変化する。28の場合。
ZYBO_OpenCV_63_141207.jpg

56の場合。
ZYBO_OpenCV_64_141207.jpg

100の場合。
ZYBO_OpenCV_65_141207.jpg

次に、OpenCV.jp のエッジ検出(Sobel,Laplacian,Canny) フィルタを試してみる。C++ バージョンを edge_filters.cpp という名前でセーブして、g++_opencv edge_filters.cpp コマンドでコンパイルした。結果を下に示す。
ZYBO_OpenCV_66_141208.jpg

短いコードで、お手軽にフィルタを試してみることができて、OpenCVやっていると楽しい。
  1. 2014年12月08日 04:28 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

OpenCV のコンパイル・スクリプト

OpenCV の C , C++ のプログラムをコンパイルするためのコンパイル・スクリプトを作った。

gcc_opencv と g++_opencv だ。この2つは、opencv-2.4.10/samples/c ディレクトリの build_all.sh を参考にしている。~/OpenCV/bin ディレクトリに2つとも入れてある。
ZYBO_OpenCV_61_141207.png

gcc_opencv を下に示す。

#!/bin/sh

if [ $# -eq 1 ] ; then
    gcc -ggdb `pkg-config --cflags opencv` -o `basename $1 .c` $1 `pkg-config --libs opencv`;
else
    echo "gcc_opencv < C file name >"
fi


g++_opencv を下に示す。

#!/bin/sh

if [ $# -eq 1 ] ; then
    g++ -ggdb `pkg-config --cflags opencv` -o `basename $1 .cpp` $1 `pkg-config --libs opencv`;
else
    echo "g++_opencv < C++ file name >"
fi

gcc_opencv と g++_opencv コマンドを実行形式に変更する。

chmod +x gcc_opencv
chmod +x g++_opencv


ホーム・ディレクトリの .bashrc の最後の行に以下の行を追加した。

export PATH=$PATH:~/OpenCV/bin


上のパスを反映させるために、source .bashrc コマンドを実行した。
これで、現在のターミナルでもパスが通るので、gcc_opencv と g++_opencv コマンドでコンパイルができるようになった。
  1. 2014年12月07日 21:14 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

ZYBOのUbuntu14.04LTSにOpenCV-2.4.10をインストール

Ubuntu12.10 から14.04LTSにアップグレードしたZYBOのUbuntu で、12.10時代にインストールした OpenCV-2.4.6.1 でアプリケーションをコンパイルしようとしたが、インストールできなかった。
OpenCV-2.4.6.1 の samples/c ディレクトリのサンプルプログラムもコンパイルできなかった。そこで、もう一度 OpenCV-2.4.6.1 をインストールしようとして、make したが途中でエラーで落ちてしまう。
これは、OpenCV のバージョンが古いんだろう?ということで、OpenCV-2.4.10 をダウンロードしてインストールした。
参考にした記事は、”ZYBO用のLinaro Ubuntu にOpenCV-2.4.6.1 をインストール”だ。

・まず、opencv-2.4.10.zip を、SourceForge からダウンロードした。
wget http://sourceforge.net/projects/opencvlibrary/files/opencv-unix/2.4.10/opencv-2.4.10.zip

・OpenCV ディレクトリを作製して、その下に、opencv-2.4.10.zip を移動した。
mkdir OpenCV
mv opencv-2.4.10.zip OpenCV
cd OpenCV


・opencv-2.4.10.zip を解凍した。
unzip opencv-2.4.10.zip

・opencv-2.4.10 ディレクトリができた。
ZYBO_OpenCV_59_141207.png

・opencv-2.4.10 ディレクトリに行って、build ディレクトリを作製した。
mkdir build

・build ディレクトリに行った。
cd build

・そこで、OpenCV をインストールするためのコマンドを発行した。
cmake ..
make

ZYBO_OpenCV_57_141206.png

sudo make install
sudo ldconfig

ZYBO_OpenCV_58_141206.png

これで、ZYBOのUbuntu 14.04 LTS に、OpenCV-2.4.10 をインストールすることができた。ビルドは成功した。

いつものように、samples/c のOpenCV のサンプルプログラムもすべてビルドできた。
./build_all.sh

顔認証アプリケーションを起動してみた。今回は、顔認証と目の認証を2つ同時に行うやり方だ。サンプルプログラムの中の facedetect.cmd に書いてあった。2つ目のプロファイル?は、--nested-cascade を付ければ良いらしい。
./facedetect --cascade="/usr/local/share/OpenCV/haarcascades/haarcascade_frontalface_alt.xml" --nested-cascade="/usr/local/share/OpenCV/haarcascades/haarcascade_eye.xml" --scale=1.3 lena.jpg
ZYBO_OpenCV_60_141207.png
  1. 2014年12月07日 04:46 |
  2. OpenCV
  3. | トラックバック:0
  4. | コメント:0

TeraTermでXmingのウインドウを開く

ZYBOのLinaro Ubuntu のXウインドウの表示をパソコンで行う(Xmingを使用)”で、XウインドウをWindowsパソコンで開くことができた。
その時に使用したターミナルソフトは Putty だった。Puttyは使っていると落ちることもあったので、TeraTermでできないか?検索したところ、”開発ツール/XmingをTeraTermで使用する”を見つけた。

それによると、TeraTermの設定メニューから SSH 転送を選んだ。
その後、SSHポート転送のダイアログで、”Xクライントアプリケーションの転送 リモートの(X)アプリケーションをローカルのXサーバーの表示する”にチェックを入れて、OKボタンをクリックする。これで、Tera TermからXウインドウを使用するソフトウェアが GUI 付きで立ち上がる。

試しに gedit cam_on.c コマンドで cam_on.c を gedit でXウインドウで表示してみた。
TeraTerm_Xming_1_141206.png

まだあまり使っていないが、Putty よりも TeraTerm の方がXウインドウが落ちない気がする?
  1. 2014年12月06日 21:13 |
  2. Linux
  3. | トラックバック:0
  4. | コメント:0

ZYBO用Ubuntu Linux のカメラで撮った画像にラプラシアンフィルタをかける

ZYBO用のUbuntu Linux 上でカメラ画像を取得することができたので、そのカメラ画像にラプラシアンフィルタをかけることにした。

ラプラシアンフィルタは、以前ZedBoard でラプラシアンフィルタをかけたことがあるので、それをベースに使用して、UIO版に書き換えた。しかし、一部 float を使用していたり、ラプラシアンフィルタ関数が間違っていたりしたので、Vivado HLSで作ったコードに書き換えた。
Cソフトウェアの名前は、laplacian_filter.c とした。これをコンパイルして、実行してみた。

最初にカメラ画像を表示するために、./cam_disp_uio コマンドを入力する。
次に、カメラ画像をキャプチャするために、./cam_capture コマンドを入力する。
./laplacian_filter コマンドを入力する。
ZYBO_Cam_Linux_74_141205.png

処理時間は 449 ms だった。ZedBoard では、391 ms だったので、ZedBoard のARMプロセッサのクロックが 667 MHz、ZYBOのARMプロセッサのクロックが 650 MHz の違いはあるが、ラプラシアンフィルタの処理時間は遅くなっている。

ラプラシアンフィルタ処理後の画像を下に示す。
ZYBO_Cam_Linux_75_141205.jpg

元のカメラ画像を示す。
ZYBO_Cam_Linux_76_141205.jpg

laplacian_filter.c とラプラシアンフィルタ画像表示モードからカメラ画像への復帰用のソフトウェア return_cam.c を貼っておく。
最初に laplacian_filter.c から下に示す。
(2015/07/02: laplacian_filter.c が間違っていたので、修正しました。最初のラインを読むときに1ライン同じものを読んでしまってました)
2015/07/12:修正 時間計測にバグがあったので、修正しました。miyox さん、ありがとうございました)

// laplacian_filter.c
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/09/16
// 2014/12/04 : ZYBO用Ubuntu Linux のUIO用に変更

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>

#define HORIZONTAL_PIXEL_WIDTH    800
#define VERTICAL_PIXEL_WIDTH    600
#define ALL_PIXEL_VALUE    (HORIZONTAL_PIXEL_WIDTH*VERTICAL_PIXEL_WIDTH)

#define CMA_START_ADDRESS           0x17800000
#define VIDEO_BUFFER_START_ADDRESS  0x18000000  // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS    0x18200000  // 800*600*4 = 0x1d4c00

int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2);
int conv_rgb2y(int rgb);
int chkhex(char *str);

int main()
{
    volatile unsigned int *fb_addr, *next_frame_addr;
    int lap_fil_val;
    int x, y;
    struct timeval start_time, temp1, temp2, end_time;
    unsigned int line_buf[3][HORIZONTAL_PIXEL_WIDTH];
    int a, b;
    int fl, sl, tl;
    int fd0, fd3;
    volatile unsigned *bmdc_axi_lites;
    volatile unsigned int *frame_buffer;

    gettimeofday(&start_time, NULL);    // プログラム起動時の時刻を記録

    // frame_buffer にマップする
    fd3 = open("/dev/uio3", O_RDWR); // Frame Buffer
    if (fd3 < 1){
        fprintf(stderr, "/dev/uio3 open error\n");
        exit(-1);
    }
    frame_buffer = (volatile unsigned *)mmap(NULL, 0x1000000, PROT_READ|PROT_WRITE, MAP_SHARED, fd3, 0);
    if (!frame_buffer){
        fprintf(stderr, "frame_buffer mmap error\n");
        exit(-1);
    }
    fb_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(VIDEO_BUFFER_START_ADDRESS-CMA_START_ADDRESS));

    // ラプラシアンフィルタの結果を入れておくフレーム・バッファ
    next_frame_addr = (volatile unsigned int *)((unsigned int)frame_buffer + (unsigned int)(LAPLACIAN_FILTER_ADDRESS-CMA_START_ADDRESS));

    // RGB値をY(輝度成分)のみに変換し、ラプラシアンフィルタを掛けた。
    for (y=0; y<VERTICAL_PIXEL_WIDTH; y++){
        for (x=0; x<HORIZONTAL_PIXEL_WIDTH; x++){
            if (y==0 || y==VERTICAL_PIXEL_WIDTH-1){ // 縦の境界の時の値は0とする
                lap_fil_val = 0;
            }else if (x==0 || x==HORIZONTAL_PIXEL_WIDTH-1){ // 横の境界の時も値は0とする
                lap_fil_val = 0;
            }else{
                if (y == 1 && x == 1){ // 最初のラインの最初のピクセルでは2ライン分の画素を読み出す
                    for (a=0; a<2; a++){ // 2ライン分
                        for (b=0; b<HORIZONTAL_PIXEL_WIDTH; b++){ // ライン
                            line_buf[a][b] = fb_addr[(a*HORIZONTAL_PIXEL_WIDTH)+b];
                            line_buf[a][b] = conv_rgb2y(line_buf[a][b]);
                        }
                    }
                }
                if (x == 1) {    // ラインの最初なので、2つのピクセルを読み込む
                    for (b=0; b<2; b++){ // ライン
                        line_buf[(y+1)%3][b] = fb_addr[((y+1)*HORIZONTAL_PIXEL_WIDTH)+b];
                        // (y+1)%3 は、使用済みのラインがに読み込む、y=2 の時 line[0], y=3の時 line[1], y=4の時 line[2]
                        line_buf[(y+1)%3][b] = conv_rgb2y(line_buf[(y+1)%3][b]);
                    }
                }
                
                // 1つのピクセルを読み込みながらラプラシアン・フィルタを実行する
                line_buf[(y+1)%3][x+1] = fb_addr[((y+1)*HORIZONTAL_PIXEL_WIDTH)+x];
                // (y+1)%3 は、使用済みのラインがに読み込む、y=2 の時 line[0], y=3の時 line[1], y=4の時 line[2]
                line_buf[(y+1)%3][x+1] = conv_rgb2y(line_buf[(y+1)%3][x+1]);
                
                fl = (y-1)%3;    // 最初のライン, y=1 012, y=2 120, y=3 201, y=4 012
                sl = y%3;        // 2番めのライン
                tl = (y+1)%3;    // 3番目のライン
                lap_fil_val = laplacian_fil(line_buf[fl][x-1], line_buf[fl][x], line_buf[fl][x+1], line_buf[sl][x-1], line_buf[sl][x], line_buf[sl][x+1], line_buf[tl][x-1], line_buf[tl][x], line_buf[tl][x+1]);
            }
            // ラプラシアンフィルタ・データの書き込み
            next_frame_addr[(y*HORIZONTAL_PIXEL_WIDTH)+x] = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val ;
            // printf("x = %d  y = %d", x, y);
        }
     }

    munmap((void *)frame_buffer, 0x1000000);
 
   // ラプラシアンフィルタ表示画面に切り替え
    // Bitmap Display Controller AXI4 Lite Slave (UIO0)
    fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 open error\n");
        exit(-1);
    }
    bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (!bmdc_axi_lites){
        fprintf(stderr, "bmdc_axi_lites mmap error\n");
        exit(-1);
    }
    bmdc_axi_lites[0] = (unsigned int)LAPLACIAN_FILTER_ADDRESS; // Bitmap Display Controller start (ラプラシアンフィルタ表示画面のアドレス)
    munmap((void *)bmdc_axi_lites, 0x10000);
    
    gettimeofday(&end_time, NULL);
    if (end_time.tv_usec < start_time.tv_usec) {
        printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec - 11000000 + end_time.tv_usec - start_time.tv_usec);
    }
    else {
        printf("total time = %ld.%06ld sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
    }
    return(0);
}

// RGBからYへの変換
// RGBのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 輝度信号Yのみに変換する。変換式は、Y =  0.299R + 0.587G + 0.114B
// "YUVフォーマット及び YUV<->RGB変換"を参考にした。http://vision.kuee.kyoto-u.ac.jp/~hiroaki/firewire/yuv.html
// 2013/09/27 : float を止めて、すべてint にした
int conv_rgb2y(int rgb){
    int r, g, b, y_f;
    int y;

    b = rgb & 0xff;
    g = (rgb>>8) & 0xff;
    r = (rgb>>16) & 0xff;

    y_f = 77*r + 150*g + 29*b; //y_f = 0.299*r + 0.587*g + 0.114*b;の係数に256倍した
    y = y_f >> 8// 256で割る

    return(y);
}

// ラプラシアンフィルタ
// x0y0 x1y0 x2y0 -1 -1 -1
// x0y1 x1y1 x2y1 -1  8 -1
// x0y2 x1y2 x2y2 -1 -1 -1
int laplacian_fil(int x0y0, int x1y0, int x2y0, int x0y1, int x1y1, int x2y1, int x0y2, int x1y2, int x2y2)
{
    int y;

    y = -x0y0 -x1y0 -x2y0 -x0y1 +8*x1y1 -x2y1 -x0y2 -x1y2 -x2y2;
    if (y<0)
        y = 0;
    else if (y>255)
        y = 255;
    return(y);
}

// 文字列が16進数かを調べる
int chkhex(char *str){
    while (*str != '\0'){
        if (!isxdigit(*str))
            return 0;
        str++;
    }
    return 1;
}


return_cam.c を下に示す。

//
// return_cam.c
// Created on: 2014/12/05
//      Author: Masaaki
//

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <sys/mman.h>
#include <fcntl.h>

#define CMA_START_ADDRESS           0x17800000
#define VIDEO_BUFFER_START_ADDRESS  0x18000000  // Limit 0x18800000, 800*600*4 = 2MBytes * 2
#define LAPLACIAN_FILTER_ADDRESS    0x18200000  // 800*600*4 = 0x1d4c00

int main(){
    int fd0;
    volatile unsigned *bmdc_axi_lites;

    // Bitmap Display Controller AXI4 Lite Slave (UIO0)
    fd0 = open("/dev/uio0", O_RDWR); // bitmap_display_controller axi4 lite
    if (fd0 < 1){
        fprintf(stderr, "/dev/uio0 open error\n");
        exit(-1);
    }
    bmdc_axi_lites = (volatile unsigned *)mmap(NULL, 0x10000, PROT_READ|PROT_WRITE, MAP_SHARED, fd0, 0);
    if (!bmdc_axi_lites){
        fprintf(stderr, "bmdc_axi_lites mmap error\n");
        exit(-1);
    }
    bmdc_axi_lites[0] = (unsigned int)VIDEO_BUFFER_START_ADDRESS; // Bitmap Display Controller start, camera display

    munmap((void *)bmdc_axi_lites, 0x10000);
}

  1. 2014年12月05日 04:17 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

Vivado and ZYBO Linux 勉強会

ZYBOボードを使用した Vivado and ZYBO Linux 勉強会 を内部的にやる予定です。開催時期は2月中旬にしようと思っています。

VirtualBox(VMWAREでもOK)上にUbuntu14.04LTSをインストールしたノートパソコンを持ってきてもらって、しかも Ubuntu 上に予めVivado 2014.4 WebPACK をインストールしてきてもらうというハードルの高い勉強会です。
今のところ、その事前準備のやり方をまとめています。まだ、本体の準備にも入れていませんが、今までブログでやって来たことをまとめるだけなので、(多分?)そっちは問題ないかな?と思っています。使うツールの数も多いし、大変かもしれません?
ただ、今度の勉強会は、1日目はハード、2日目はソフトと分かれているので、どっちをやっているのかわからなくなるということはないでしょう?多分???
FPGAの部屋のブログでも勉強会の準備をしながら、その内容をブログに書くということがあります。

Vivado and ZYBO Linux 勉強会 基本方針

1日目
午前
・Zynq-7000の概要
・Vivadoツールの概要

午後
・LEDテストプロジェクトをライブコーディング(VivadoのウィザードでAXIカスタムIPを作る)
IPをわざと間違えておいて、IPの修正方法を実習する

2日目
午前・午後 ハンズオン
・ハードウェアは、1日目のVivadoプロジェクトを使用する
・ZYBO用u-bootのビルド
・SDKでBoot.bin を作製
・ZYBO用Linuxカーネルのビルド
・デバイス・ツリーのコンパイル
・Micro SDカードのフォーマット
・UbuntuのROOT File Systemのコピー
・FAT32パーティションへ必要なファイルをコピー
・ZYBOにSDカードを挿してLinuxをブート
・ユーザーでログイン
・LEDをカウントアップするソフトウェアを実行(UIOの実習)
・SSHのインストール
・XmingでXウインドウをWindowsで操作
・OpenCVインストール
・サンプル・プロジェクトのコンパイル
・顔認識アプリの実行

”SSHのインストール”からはルーターが必要になるし、時間も足りなくなりそうなので、”LEDをカウントアップするソフトウェアを実行(UIOの実習)”までなかな?と思っています。
VivadoはネイティブLinuxノートパソコンか、VirtualBoxへインストールしたLinuxでやろうかと思っています。そうでないと、ARM用のGCCがインストールされないようなので。
Vivado をWindowsで使いたい方は、Menter社 のSourcery CodeBench Lite Editionを使う方法もあります。
この辺りは現在検討中です。
VivadoツールとLinux環境は予めインストールをお願いする予定です。

  1. 2014年12月04日 06:40 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

VirtualBox上のUbuntu14.04LTSにVivado 2014.4 をインストールし起動する時の覚書

VirtualBox上のUbuntu14.04LTSにVivado 2014.4 をインストールし起動する時の覚書です。

Xilinxのダウンロードのページから” Vivado 2014.4 のフル イメージ (すべての OS) (TAR/GZIP - 7.32GB)”をダウンロードしてインストールしたのだが、最初に xsetup と関連するファイルが Xパーミッションが入っていないので、入れた。(アバウトですみません。やってみれば分かります)(:Linuxでインストールする時は特に、” Linux 64 用 Vivado 2014.4 WebInstall (BIN - 74.54MB)”をダウンロードして、WebInstall するのが間違いないと思う)

Vivado のWebPACKがインストールされて、Activation Base License を取得できたのだが、LXDEのランチャーにはVivado が登録されていないし、LX Terminal から、vivado とコマンド入力しても起動しない。

どうやら、setting64.sh を動かせば良さそうだということがわかった。
gedit .bashrc コマンドで、.bashrc を編集して、bash の起動時に setting64s.sh を起動する。追加したコマンドを示す。

source /opt/Xilinx/Vivado/2014.4/settings64.sh


SDK_install_27_141202.png

source .bashrc で .bashrc の内容を反映させる。
SDK_install_28_141202.png

これで、vivado コマンドで Vivado が起動するようになった。
SDK_install_30_141202.png

しかし、SDKを起動するとアプリケーションを作ってもコンパイルエラーになってしまう。
エラーの内容は、

/bin/sh: 1: arm-xilinx-eabi-gcc: not found

だった。
これで、検索すると、”SDK can't find arm-xilinx-eabi-gcc”がヒットした。それによると、 ia32-libs をインストールすれば良いとの事だったが、apt-get install でインストールすると古いとのこと、今は、lib32z1 ということなので、これをインストールした。
sudo apt-get install lib32z1

もう一度、SDK (xsdk) を立ちあげて、ビルドするとエラーが解消され、コンパイルが正常終了した。

Ubuntu_SDK_install_141203.png 

やった~。けど、結構時間がかかってしまった。
  1. 2014年12月02日 20:59 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Vivado のライセンス

Vivado のライセンスですが、いつの間にか、Certificate Based Licenses と Activation Based Licenses に分かれているようです。Xilinxのライセンス取得ページから行くと分かりますし、”Vivado Design Suite ユーザー ガイド リ リース ノー ト 、 インス ト ールおよびライセンス UG973 (v2014.4) 2014 年 11 月 19 日”の34ページの第5章 ラ イセンスの取得および管理 に書いてあります。

Certificate Based Licensesは、以前のようにメールでライセンス・ファイルを貰って、ライセンス・マネージャーでライセンスを読み込むもので、Activation Based Licenses はライセンス・マネージャーから直接ライセンスを取得することができます。Xilinxのライセンスの取得ページに飛んで、ライセンスを発行してもらったら、ライセンス・マネージャーがライセンスを取得しています。

このActivation Based Licenses では、Vivado HLS Evaluation License のライセンス期限が365日になっていました。つまり1年間使えるみたいですね。使わない手はないと思います。
Vivado HLSはVivado の高位合成ツールで、C やC++、SystemC で書いたソフトウェアをHDLのIPにすることができます。
  1. 2014年12月02日 04:36 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0