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

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

FPGAの部屋

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

並列ステレオカメラによる距離の測定8(Ubuntuで動作するアプリケーションを作る1)

並列ステレオカメラによる距離の測定7(ZYBO 0 のハードウェア6)完成2”の続き。

前回、Linuxを起動しなくても問題ないように standalone で動作するラプラシアンフィルタのアプリケーションを作製したが、やはり今後のためにもZYBO 上のUbuntu 14.04 LTS で動作するアプリケーションを作製しようと思う。
そのためには、最初にSDK でBOOT.bin を作製し、パソコンのVirtualBox 上のUbuntu 14.04 LTS で devicetree を作製しMicro SD カードにコピーする必要がある。

SDKで FSBL を作製した。
StereoCam_107_151128.png

Project Exploer 上でFSBL を右クリックし、右クリックメニューからCreate Boot Image を選択した。

Creater Zynq Boot Image ダイアログが開いた。u-boot.elf を追加してから、Create Image ボタンをクリックした。
StereoCam_108_151128.png

BOOT.bin ができた。
StereoCam_109_151128.png

次に devicetree.dtb を作る。

パソコンでUbuntu 14.04 LTS を起動した。

ZYBOにHDLで書いたラプラシアンフィルタを実装する9(devicetreeの生成、/sys, /devディレクトリ)”で作った driver_hls_hdl_lap_fil をコピーして、貼り付け、名前を drivers_ZYBO_0 に変更した。

zynq-zybo.dts を編集して、Address Editor に表示される通りに
StereoCam_96_151124.png

UIO のエントリを追加した。
StereoCam_110_151128.png

mt9d111_axi_iic@0x41600000 {
compatible = "generic-uio";
reg = < 0x41600000 0x10000>;
};
axi_vdma_0@43000000 {
compatible = "generic-uio";
reg = < 0x43000000 0x10000 >;
};
axis_switch_0@0x43c10000 {
compatible = "generic-uio";
reg = < 0x43c10000 0x10000 >;
};
axis_switch_1@0x43c20000 {
compatible = "generic-uio";
reg = < 0x43c20000 0x10000 >;
};
lap_filter_axis_0@0x43c30000 {
compatible = "generic-uio";
reg = < 0x43c30000 0x10000>;
};
mt9d111_inf_axis_0@0x43C40000 {
compatible = "generic-uio";
reg = < 0x43C40000 0x10000>;
};
bitmap_disp_cntrler_axi_master_0@0x43c00000 {
compatible = "generic-uio";
reg = < 0x43c00000 0x10000>;
};
bitmap_disp_cntrler_axi_master_1@0x43c50000 {
compatible = "generic-uio";
reg = < 0x43c50000 0x10000>;
};
axi_gpio_0@0x41200000 {
compatible = "generic-uio";
reg = < 0x41200000 0x10000>;
};
frame_buffer_bmdc@0x17800000 {
compatible = "generic-uio";
reg = < 0x17800000 0x1000000>;
};


zynq-zybo.dts をセーブして閉じた。

LX Terminal で drivers_ZYBO_0 ディレクトリに入った。

../Linux-Digilent-Dev/scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb zynq-zybo.dts コマンドで、zynq-zybo.dts を dtc でコンパイルして、devicetree.dtb を生成した。
StereoCam_111_151128.png

Micro SD カードに BOOT.bin と devicetree.dtb をコピーした。
StereoCam_112_151128.png

Micro SD カードをZYBO の Micro SD カード・フォルダに戻して、ZYBO をMicro SDカードブートの設定に変更した後で、電源をON した。

起動後、ターミナル・ソフト (Tera Term) で、/sys/devices/amba.0 の下を見て、devicetree に設定したデバイスが uio いくつに対応したのかを確認した。
StereoCam_115_151128.png

StereoCam_113_151128.png
StereoCam_114_151128.png

UIO の番号順は、zynq-zybo.dts に書いた順番通りだった。
  1. 2015年11月29日 05:54 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2015.4を試してみる(AXI4-Stream版ラプラシアンフィルタ IPを使用した)

皆さんがフリーで使えるVivado HLS 2015.4 が出たので、AXI4-Stream版ラプラシアンフィルタ IP で試してみることにした。

なお、私のブログのVivado HLS カテゴリを良かったら参考にして欲しい。

以前、”Vivado HLS 2014.4 vs Vivado HLS 2015.1 vs Vivado HLS 2015.3(AXI4-Stream版ラプラシアンフィルタ IPの比較)”という記事で、Vivado HLS 2014.4 vs Vivado HLS 2015.1 vs Vivado HLS 2015.3 を比べたことがあった。これらと比較しても良いのだが、AXI4-Stream版ラプラシアンフィルタ IP が青のみ出力されてしまっていた関係で修正が入っているので、修正後のCソースコードでやってみることにした。

クロック周期 10 ns
クロック周期 10 ns で Vivado HLS 2015.4 を用いて高位合成を行った結果を示す。
Vivado_HLS_2015_4_1_151127.png
Timing の Estimated は 7.71 ns だった。FF は 413 個、LUT は 463 個使用している。

Analysis の結果を示す。処理は C8 までだ。
Vivado_HLS_2015_4_2_151127.png

クロック周期 9 ns
クロック周期 9 ns で Vivado HLS 2015.4 を用いて高位合成を行った結果を示す。
Vivado_HLS_2015_4_3_151127.png
Timing の Estimated は 7.71 ns だった。FF は 413 個、LUT は 463 個使用している。これはクロック周期が 10 ns の時と同じだ。

Analysis の結果を示す。処理は C8 までだ。
Vivado_HLS_2015_4_4_151127.png

クロック周期 8 ns
クロック周期 8 ns で Vivado HLS 2015.4 を用いて高位合成を行った結果を示す。
Vivado_HLS_2015_4_5_151127.png
Timing の Estimated は 6.91 ns だった。FF は 446 個、LUT は 463 個使用している。FF の使用数が増えた。

Analysis の結果を示す。処理は C9 までだ。これも前より伸びた。
Vivado_HLS_2015_4_6_151127.png

クロック周期 7 ns
クロック周期 7 ns で Vivado HLS 2015.4 を用いて高位合成を行った結果を示す。
Vivado_HLS_2015_4_7_151127.png
Timing の Estimated は 6.88 ns だった。FF は 527 個、LUT は 473 個使用している。FF も LUT も使用数が増えた。

Analysis の結果を示す。処理は C10 までだ。これも前より伸びた。
Vivado_HLS_2015_4_8_151127.png

クロック周期 6 ns
クロック周期 6 ns で Vivado HLS 2015.4 を用いて高位合成を行った結果を示す。
Vivado_HLS_2015_4_9_151127.png
Timing の Estimated は 6.88 ns だった。FF は 515 個、LUT は 483 個使用している。FF の使用数は前より減ったが、 LUT は使用数が増えた。

Analysis の結果を示す。処理は C12 までだ。これは前より伸びた。
Vivado_HLS_2015_4_10_151127.png

クロック周期 2.5 ns
限界を見るために、クロック周期 2.5 ns で Vivado HLS 2015.4 を用いて高位合成を行った結果を示す。
Vivado_HLS_2015_4_11_151127.png
Timing の Estimated は 6.88 ns だった。FF は 1384 個、LUT は 632 個使用している。FF の使用数は前より大幅に増えた。 LUT も使用数が増えた。
やはり、6.88 ns が限界のようだ。

Analysis の結果を示す。処理は C24 までだ。これは前より大幅に増えた。
Vivado_HLS_2015_4_12_151127.png

おまけとして、クロック周期が 40 ns の時をやってみた。

クロック周期 40 ns
クロック周期 40 ns で Vivado HLS 2015.4 を用いて高位合成を行った結果を示す。
Vivado_HLS_2015_4_13_151127.png
Timing の Estimated は 27.9 ns だった。FF は 228 個、LUT は 457 個使用している。

Analysis の結果を示す。処理は C4 までだ。
Vivado_HLS_2015_4_14_151127.png

このように、クロック周期を小さくすると、(クロック周波数を高くすると) FF の数が増えていって、1処理あたりのクロック数が増えて行く。これは、演算などの処理を細かく細分化してクロックごとに処理するからだ。つまりレイテンシが増えるが、完全にパイプライン化されていれば、スループットはどれも同じになるはずだ。

ソースコードにクロックの概念が無いので、クロックのパラメータによって、処理の段数を変えて、動作周波数を伸ばすことができるのは、高位合成の利点だと思う。
Vivado HLS は良く出来ていると思う。この機能はとてもありがたい。
  1. 2015年11月27日 05:02 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

Vivado 2015.4 が出ました

Vivado 2015.4 が出ました。
今回のバージョンは、特別な記念すべきバージョンです。”Vivado Design Suite ユーザー ガイド リ リース ノー ト 、 インス ト ールおよびライセンス UG973 (v2015.4) 2015 年 11 月 18 日”から引用します。

Vivado® Design Suite 2015.4 リ リ ースか ら、高位合成ツールであ る Vivado HLS が無償で提供 される よ う にな り 、Vivado のすべてのエデ ィ シ ョ ンに含まれる よ う にな り ま し た。 この変更を示すため、 エデ ィ シ ョ ンの名前は Vivado Design Suite HLx Edition に変更 されています。HLx Edition には、HL System Edition、HL Design Edition、および HL WebPACK™ Edition があ り ます。 これ らのエデ ィ シ ョ ンでは、 All Programmable FPGA、 SoC、 および再利用可能なプ ラ ッ ト フ ォーム を高い生産性で設計する ための新しい手法が イ ネーブルになっています。 すべての HLx エデ ィ シ ョ ンには Vivado 高位合成 (HLS)、 Vivado IP イ ンテグ レーター、 LogicCore IP サブシステム、 および Vivado インプ リ メ ンテーシ ョ ン ツール ス イー ト すべてが含まれてお り 、 生産性が高 く 、 高度な C および IP ベースのデザイ ン フ ローを即座に導入でき る よ う になっています。


つまり、無料の WebPACK でもVivado HLS がつかえるようになりました。凄いです~~~。Xilinxさん、太っ腹ですね。。。
しかも今回のバージョンは、Spartan3, Spartan6, Virtex4, Virtex5, Virtex6 もVivado HLS が使えるそうです。Vivado HLSのParts のFamilyの選択肢にそれらのFPGAを選ぶ項目がありました。それらのFPGAはVivado では使えないと思いますが、Vivado HLS ではXPS用のPcore IP としてIP をエクスポートすることもできるので、XPS のIP としての使用が可能になると思います。

高位合成ツールのVivado HLS が無料で使えるようになったということで、高位合成が一般的に普及するかもしれませんね?
とっても良いことだと思います。
私もVivado HLS 勉強会資料としてスライド650枚分の資料を作ってあるので、それをVivado HLS 2015.4 対応にして、そのうちに勉強会でもやってみたいです。。。
  1. 2015年11月26日 05:16 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

並列ステレオカメラによる距離の測定7(ZYBO 0 のハードウェア6)完成2

並列ステレオカメラによる距離の測定6(ZYBO 0 のハードウェア5)完成”の続き。

前回はZYBO でUbuntu を起動して、そこからカメラ出力かラプラシアンフィルタ出力かを選択できるようにしようということで終わったが、ベアメタル・アプリとしてスイッチでカメラ出力とラプラシアンフィルタ出力を切り替えても良いのじゃないか?ということで、スライドSWの 0 番めが 0 だったらカメラ出力、1 だったらラプラシアンフィルタ出力にすることにした。

まずは、ブロックデザインで、AXI GPIO をAdd IP した。

axi_gpio をダブル・クリックして、設定を行った。
All Inputs のチェックボックスをチェックして、GPIO Width を 1 に設定した。
StereoCam_94_151124.png

Run Connection Automatin をクリックして、AXI4 Lite Slave バスとGPIO のポートを自動的に接続した。GPIO ポートは sw という名前に変更した。
StereoCam_95_151124.png

Address Editor の設定を示す。 axi_gpio_0 は 0x41200000 にマップされた。
StereoCam_96_151124.png

ブロックデザインをセーブした。
StereoCam_97_151124.png

Flow Navigator -> Synthesis -> Run Synthesis をクリックして、論理合成を行った。
StereoCam_97_151124.png

論理合成が成功した。
Synthesised Desgin を開いて、Layout メニューから I/O Planning を選択した。
Package ビューが開いた。
sw_tri_i[0] をG15 に割り当てて、IO Std はLVCMOS33 に設定した。
StereoCam_98_151124.png

Flow Navigator -> Program and Debug -> Generate Bitstream をクリックして、インプリメント、ビットストリームの生成を行った。
ビットストリームの生成まで成功した。
StereoCam_99_151124.png

Project Summary を示す。 LUT が 1% 増えている。
StereoCam_100_151124.png

ハードウェアをエクスポートして、SDKを立ち上げよう。

File メニューから Exprot -> Export Hardware... を選択した。

Export Hardware ダイアログが表示される。Include bitstream にチェックを入れて、OKボタンをクリックした。

File メニューから Launch SDKを選択した。

SDKが立ち上がった。

SDK の File メニューからNew -> Application Project を選択する。

Project name に cam_lap_disp と入力した。Next > ボタンをクリックした。OS Platform は取りあえず、ベアメタル・アプリケーションとするので、デフォルトの standalone に設定した。
Board Support Package は Create New のラジオボタンをチェックして、BSPを新しく生成する。
BSPを新しく生成すると gpio のベアメタル・ドライバを参照することができる。
StereoCam_101_151124.png

SDK使ったベアメタルアプリケーションのXilinx IPのドライバは、Vivadoでハードウェアをエクスポートした後に作ったBSPのps7_cortex9_? -> libsrc -> Xilinx IP名にある。
今回は gpio_v4_0 -> src にドライバのソースがある。
StereoCam_102_151125.png

gpio のドライバを使用して、gpio を制御するが、制御方法は”ZedBoard Linux のフレームバッファにカメラ画像を表示8(カメラ画像表示成功)”を参考にした。

cam_lap_disp.c を新しく生成して、Cソースコードを書いて、オート・ビルドした。
StereoCam_103_151125.png

Xilinx Tools メニューからProgram FPGA を選択して、ZYBO のコンフィギュレーションを行った。

cam_lap_disp.elf を右クリックし、右クリックメニューから Run AS -> Launch on Hardware (GDB) を選択して、ソフトウェアを起動すると、スライドSWの 0 番めが 0 の時がカメラ出力、1 の時がラプラシアンフィルタ出力された。成功だ。

最後に cam_lap_disp.c を貼っておく。
// cam_lap_disp.c
// 2015/11/25 by marsee
//
// Refered to Xilinx\SDK\2015.1\data\embeddedsw\XilinxProcessorIPLib\drivers\axivdma_v5_1\doc\html\api
// Refered to https://github.com/elitezhe/Atyls-VDMA-one-in-one-out/blob/master/SDK/colorbar/src/helloworld.c
// Refered to http://www.xilinx.com/support/documentation/ip_documentation/axi_vdma/v6_2/pg020_axi_vdma.pdf
// Refered to http://forums.xilinx.com/t5/Embedded-Processor-System-Design/Axi-VDMA-on-Digilent-Atlys/td-p/297019/page/2
//
// if sw0 is 0 level then normal camera out else laplacian filter out
//

#include <stdio.h>
#include <stdlib.h>
#include "xaxivdma.h"
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#include "xgpio.h"
#include "xlap_filter_axis.h"

#define NUMBER_OF_WRITE_FRAMES    3 // Note: If not at least 3 or more, the image is not displayed in succession.

#define HORIZONTAL_PIXELS    800
#define VERTICAL_LINES        600
#define PIXEL_NUM_OF_BYTES    4

#define FRAME_BUFFER_ADDRESS 0x10000000

static XAxiVdma_DmaSetup Vdma0_WriteCfg;

void camera_out(XLap_filter_axis Xlap_fil_axis);
void lap_fil_out(XLap_filter_axis Xlap_fil_axis);

void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
    mt9d111_i2c_axi_lites[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    mt9d111_i2c_axi_lites[64] = 0x1; // enable i2c
}

void cam_i2x_write_sync(void) {
    // unsigned c;

    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}

void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe);   // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    mt9d111_i2c_axi_lites[66] = write_addr;
    mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff;         // first data
    mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff);        // second data
    cam_i2x_write_sync();
}

int main(){
    // malloc frame buffer
    // unsigned int *frame_buffer = (unsigned int *)malloc(HORIZONTAL_PIXELS * VERTICAL_LINES * PIXEL_NUM_OF_BYTES * NUMBER_OF_WRITE_FRAMES);

    // AXI VDMA Initialization sequence
    XAxiVdma_Config *XAxiVdma0_Config;
    XAxiVdma XAxiVdma0;
    int XAxiVdma0_Status;
    static XGpio GPIOInstance_Ptr;
    int XGpio_Status;
    XLap_filter_axis Xlap_fil_axis;
    XLap_filter_axis_Config *Xlap_fil_axisPtr;
    int sw0_status, sw0_status_old;

    XAxiVdma0_Config = XAxiVdma_LookupConfig(XPAR_CAMERA_INTERFACE_AXI_VDMA_0_DEVICE_ID); // Look up the hardware configuration for a device instance
    if (XAxiVdma0_Config == NULL){
        fprintf(stderr, "No AXI VDMA found\n");
        return(-1);
    }

    XAxiVdma0_Status = XAxiVdma_CfgInitialize(&XAxiVdma0, XAxiVdma0_Config, XAxiVdma0_Config->BaseAddress); // Initialize the driver with hardware configuration
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_CfgInitialize() failed\n");
        return(-1);
    }

    XAxiVdma_Reset(&XAxiVdma0, XAXIVDMA_WRITE);
    while(XAxiVdma_ResetNotDone(&XAxiVdma0, XAXIVDMA_WRITE)) ;

    XAxiVdma0_Status = XAxiVdma_SetFrmStore(&XAxiVdma0, NUMBER_OF_WRITE_FRAMES, XAXIVDMA_WRITE); // Set the number of frame store buffers to use.

    Vdma0_WriteCfg.VertSizeInput = VERTICAL_LINES;
    Vdma0_WriteCfg.HoriSizeInput = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES;
    Vdma0_WriteCfg.Stride = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES; // Indicates the number of address bytes between the first pixels of each video line.
    Vdma0_WriteCfg.FrameDelay = 0; // Indicates the minimum number of frame buffers the Genlock slave is to be behind the locked master. This field is only used if the channel is enabled for Genlock Slave operations. This field has no meaning in other Genlock modes.
    Vdma0_WriteCfg.EnableCircularBuf = 1; // Indicates frame buffer Circular mode or frame buffer Park mode.  1 = Circular Mode Engine continuously circles through frame buffers.
    Vdma0_WriteCfg.EnableSync = 0; // Enables Genlock or Dynamic Genlock Synchronization. 0 = Genlock or Dynamic Genlock Synchronization disabled.
    Vdma0_WriteCfg.PointNum = 0; // No Gen-Lock
    Vdma0_WriteCfg.EnableFrameCounter = 0; // Endless transfers
    Vdma0_WriteCfg.FixedFrameStoreAddr = 0; // We are not doing parking

    XAxiVdma0_Status = XAxiVdma_DmaConfig(&XAxiVdma0, XAXIVDMA_WRITE, &Vdma0_WriteCfg);
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_DmaConfig() failed\n");
        return(-1);
    }

    // Frame buffer address set
    unsigned int frame_addr = (unsigned int)FRAME_BUFFER_ADDRESS;
    int i;
    for (i=0; i<NUMBER_OF_WRITE_FRAMES; i++){
        Vdma0_WriteCfg.FrameStoreStartAddr[i] = frame_addr;
        frame_addr += HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES * VERTICAL_LINES;
    }

    XAxiVdma0_Status = XAxiVdma_DmaSetBufferAddr(&XAxiVdma0, XAXIVDMA_WRITE, Vdma0_WriteCfg.FrameStoreStartAddr);
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_DmaSetBufferAddr() failed\n");
        return(-1);
    }

    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers

    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers

    // VDMA start
    XAxiVdma0_Status = XAxiVdma_DmaStart(&XAxiVdma0, XAXIVDMA_WRITE);
    if (XAxiVdma0_Status != XST_SUCCESS){
        fprintf(stderr, "XAxiVdma_DmaStart() failed\n");
        return(-1);
    }

    // mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
    volatile unsigned int *bmdc0_axi_lites;
    volatile unsigned int *bmdc1_axi_lites;
    volatile unsigned int *mt9d111_axi_lites;
    volatile unsigned int *mt9d111_i2c_axi_lites;

    bmdc0_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_BASEADDR;
    bmdc1_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_1_BASEADDR;
    mt9d111_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_MT9D111_INF_AXIS_0_BASEADDR;
    mt9d111_i2c_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_AXI_IIC_0_BASEADDR;

    bmdc0_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 0 start
    bmdc1_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 1 start
    mt9d111_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)

    // CMOS Camera initialize, MT9D111
    cam_i2c_init(mt9d111_i2c_axi_lites);

    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0xf0, 0x1);      // Changed regster map to IFP page 1
    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x97, 0x20);        // RGB Mode, RGB565

    mt9d111_axi_lites[1] = 0; // One_shot_mode is disabled

    // AXI GPIO Initialization
    XGpio_Status = XGpio_Initialize(&GPIOInstance_Ptr,XPAR_AXI_GPIO_0_DEVICE_ID);
    if(XST_SUCCESS != XGpio_Status)
        print("GPIO INIT FAILED\n\r");
    // AXI GPIO Set the Direction(input setting)
    XGpio_SetDataDirection(&GPIOInstance_Ptr, 1, 1);

    // Look Up the device configuration
    Xlap_fil_axisPtr = XLap_filter_axis_LookupConfig(0);
    if (!Xlap_fil_axisPtr){
        fprintf(stderr, "XLap_filter_axis configuration failed.\n");
        return(-1);
    }

    // Initialize the Device
    int Xlap_status = XLap_filter_axis_CfgInitialize(&Xlap_fil_axis, Xlap_fil_axisPtr);
    if (Xlap_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XLap_filter_axis\n");
        return(-1);
    }

    sw0_status_old = XGpio_DiscreteRead(&GPIOInstance_Ptr, 1) & 1;
    usleep(5000); // wait 5ms

    while(1){
        sw0_status = XGpio_DiscreteRead(&GPIOInstance_Ptr, 1) & 1;
        if (sw0_status_old != sw0_status){ // sw0 status changed
            if (sw0_status == 0) // camera output
                camera_out(Xlap_fil_axis);
            else // laplacian filter output
                lap_fil_out(Xlap_fil_axis);
            sw0_status_old = sw0_status;
        }
        usleep(5000); // wait 5ms
    }

    return(0);
}

void camera_out(XLap_filter_axis Xlap_fil_axis){
    // axis_switch_1, 1to2 ,Select M00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers

    // laplacian filter AXIS AutoRestart disable
    XLap_filter_axis_DisableAutoRestart(&Xlap_fil_axis);

    // axis_switch_0, 2to1, Select S00_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers
}

void lap_fil_out(XLap_filter_axis Xlap_fil_axis){
    // axis_switch_1, 1to2 ,Select M01_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x80000000); // disable
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers

    // laplacian filter AXIS Start
    XLap_filter_axis_Start(&Xlap_fil_axis);
    XLap_filter_axis_EnableAutoRestart(&Xlap_fil_axis);

    // axis_switch_0, 2to1, Select S01_AXIS
    // Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x1);
    Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers
}

  1. 2015年11月25日 05:12 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

並列ステレオカメラによる距離の測定6(ZYBO 0 のハードウェア5)完成

”並列ステレオカメラによる距離の測定5(ZYBO 0 のハードウェア4)”の続き。

HDMI 出力が安定しない原因はBUFR でOSERDES で使用する5倍のピクセルクロックから5分周してピクセルクロックを作製する時に制約を掛けていないためだった。(”BUFR でクロックを分周する場合は制約を追加する必要がある(ビットマップ・ディスプレイ・コントローラ IP のHDMI 出力)”参照)
その後、ビットマップ・ディスプレイ・コントローラIP に制約を入れて問題なく動作した。(”プロジェクトにインスタンスされているIPに制約を追加する”参照)

今回は、カメラ画像出力はできたのだが、タイミング違反が出ていたので、それを解消してから、ラプラシアンフィルタ出力するようにソフトウェアを追加する。

今回の lap_fil_on.c と cam_return.c のソースコードは、”AXI4-Stream版ラプラシアンフィルタIPのカメラ表示システム10(ラプラシアンフィルタ処理)”のCソースコードをそのまま使用している。

最初にタイミング違反を解消しよう。

現在のVivado 2015.3 の表示を示す。
StereoCam_79_151122.png
タイミング違反が出ている。

Flow Navigator -> Implemented Design -> Report Timing Summary をクリックして、タイミング違反を観察する。
StereoCam_80_151122.png
ビットマップ・ディスプレイ・コントローラIP 1 の pixclk と clk_fpga_0 のクロック間のタイミング違反だった。この間のタイミング解析を止めさせれば問題ない。

Flow Navigator -> Implemented Design -> Edit Timing Constraints をクリックして、ビットマップ・ディスプレイ・コントローラIP 1 の pixclk と clk_fpga_0 のクロック間を False Path に指定した。
StereoCam_82_151122.png

set_false_path -from [get_clocks ZYBO_0_i/bitmap_disp_cntrler_axi_master_1/inst/dvi_disp_i/pixclk] -to [get_clocks clk_fpga_0]
set_false_path -from [get_clocks clk_fpga_0] -to [get_clocks ZYBO_0_i/bitmap_disp_cntrler_axi_master_1/inst/dvi_disp_i/pixclk]


Timing タブのRerun を実行すると、False Path を設定した時のタイミングが見える。(たぶん)
StereoCam_83_151122.png

Timing タブのRerun を実行すると、タイミング違反が解消されるようだ。
StereoCam_84_151122.png

もう一度、論理合成、インプリメント、ビットストリームの生成を行った。予想通り、タイミング違反は解消されていた。
StereoCam_85_151123.png

Project Summary を示す。
StereoCam_86_151123.png

ハードウェアをビットストリームごとエクスポートして、SDKを立ち上げた。

cam_disp_elf を再度実行してみたが、HDMI 出力は問題なかった。
StereoCam_87_151123.png

SDK の File メニューからNew -> Application Project を選択する。

Project name に lap_fil_on と入力した。Next > ボタンをクリックした。OS Platform は取りあえず、ベアメタル・アプリケーションとするので、デフォルトの standalone に設定した。Next > ボタンをクリックする。
StereoCam_88_151123.png

Templates で Empty Application を選択して、Finish ボタンをクリックした。
StereoCam_89_151123.png

lap_fil_on プロジェクトの src フォルダに lap_fil_on.c を新規作成して、既存の lap_fil_on.c のソースコードをコピーした。
StereoCam_90_151123.png

lap_fil_on.elf を右クリックし、右クリックメニューから Run AS -> Launch on Hardware (GDB) を選択するとラプラシアンフィルタ処理画像が表示された。
StereoCam_93_151123.jpg

元画像はこれだ。
StereoCam_94_151123.jpg

次に、cam_return Application Project を作製した。BSP は lap_fil_on_bsp を使用した。
StereoCam_91_151123.png

cam_return プロジェクトの src フォルダに cam_return.c を新規作成して、既存の cam_return.c のソースコードをコピーした。
StereoCam_92_151123.png

cam_return.elf を右クリックし、右クリックメニューから Run AS -> Launch on Hardware (GDB) を選択するとカメラ画像に戻った。

これで、たぶん 5 fps ととてもフレームレートが遅いのだが、一応、ZYBO_0 として使用できるプロジェクトができたと思う。
次は、これをUbuntu 14.04 LTS で動作させるためのソフトウェアを書くことにしよう。
  1. 2015年11月23日 05:47 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

プロジェクトにインスタンスされているIPに制約を追加する

BUFR でクロックを分周する場合は制約を追加する必要がある(ビットマップ・ディスプレイ・コントローラ IP のHDMI 出力)”で BUFR でOSERDES のDDR モードのシリアルクロックを 1/5 にしてピクセルクロックとしているの時のタイミング制約を追加すれば、XGA解像度でもHDMI 表示がうまくいくことが分かった。

今回は、IP にその制約を追加すれば、XGA解像度でもHDMI 表示がうまくいくことを確かめる。

ZYBO_0_153 プロジェクトで bitmap_disp_cntrler_axi_master_1 を右クリックし、右クリックメニューから Edit in IP Packager を選択する。
StereoCam_50_151122.png

Edit in IP Packager ダイアログが開いた。OKボタンをクリックする。
StereoCam_68_151122.png

bitmap_disp_cntrler_axi_master_v1_project が別画面で開く。
StereoCam_51_151121.png

制約を行うために論理合成を行った。Synthesized Design を開き、Edit Timing Constraints をクリックした。

Edit Timing Constraints ウインドウで、Create Generated Clock を選択して、Duble click to create a Create Generated Clock constraint をダブル・クリックした。
StereoCam_52_151121.png

Create Generated Clock ダイアログが開いた。
Master pin (sourece) の右の … ボタンをクリックした。
StereoCam_53_151121.png

Specify Master Pin ダイアログが開いた。
Options に *pclkx5_buf* と入力して、Find ボタンをクリックした。
Result の dvi_disp_i/hdmi_tx_i/pclkx5_buf を選択し、右矢印をクリックして、Selected ペインに入力した。
StereoCam_54_151121.png

Create Generated Clock ダイアログに戻ると、Master pin (source) に入力されていた。
Derive from Source Clock Waveform の By clock frequency のラジオボタンにチェックが入っていることを確認して、Divide source clock freqency by を 5 に設定した。
Source object の右の … ボタンをクリックした。
StereoCam_55_151121.png

Specify Master Pin ダイアログが開いた。
Options に *pixclk* と入力して、Find ボタンをクリックした。
Result の dvi_disp_i/pixclk を選択し、右矢印をクリックして、Selected ペインに入力した。
StereoCam_56_151121.png

Create Generated Clock ダイアログに戻ると、Source object に入力されていた。
StereoCam_57_151121.png

OK ボタンをクリックすると制約が入力される。

Save ボタンをクリックして制約をセーブする。
StereoCam_59_151121.png

Out of Data Design ダイアログが表示された。OKボタンをクリックした。
StereoCam_60_151121.png

Save Constraints ダイアログが表示された。File name に bmdc_axim_clock と入力した。
StereoCam_61_151121.png

制約が bmdc_axim_clock.xdc にセーブされた。
StereoCam_62_151121.png

Package IP のFile Groups をクリックして、Merge change from File Groups Wizard をクリックしたが、bmdc_axim_clock.xdc は入らなかった。
StereoCam_63_151121.png

なぜだろうと思って調べてみると、bmdc_axim_clock.xdc は、Z:\ZYBO_0_153\ZYBO_0_153.tmp\bitmap_disp_cntrler_axi_master_v1_0_project\bitmap_disp_cntrler_axi_master_v1_0_project.srcs\constrs_1\new フォルダの下にあるので、グループにできないようだ。
StereoCam_64_151121.png

そこで、この bmdc_axim_clock.xdc をコピーして、Z:\ZYBO_0_153\BMDispCaL\sources フォルダにペーストした。
StereoCam_65_151121.png

現在の bitmap_disp_cntrler_axi_master_v1_project をセーブしないで終了した。
StereoCam_66_151122.png

StereoCam_67_151122.png

もう一度、bitmap_disp_cntrler_axi_master_v1_project を Edit in IP Packager で開いて、 bmdc_axim_clock.xdc を Add Source した。
StereoCam_69_151122.png

右上のPackage IP タブをクリックして、File Groups をクリックし、Merge changes from File Groups Wizard をクリックする。
StereoCam_70_151122.png

すると、Standard -> Synthesis に bmdc_axim_clock.xdc が入った。
StereoCam_71_151122.png

Review and Package をクリックし、Re-Package IP ボタンをクリックして、IPを再度パッケージ化する。
StereoCam_72_151122.png

bitmap_disp_cntrler_axi_master_v1_project をクローズするというダイアログが出てくるので、プロジェクトをクローズする。

ZYBO_0_153 プロジェクトに戻る。
Block Design ウインドウの Refresh IP Catalog をクリックする。
StereoCam_73_151122.png

下のIP Status のUpgrade Selected ボタンをクリックする。
StereoCam_74_151122.png

Upgrede Ip ダイアログが表示された。
StereoCam_75_151122.png

IP Status のRerun をクリックする。
StereoCam_76_151122.png

IPのアップグレードが完了した。
StereoCam_77_151122.png

Flow Navigatgor -> Generate Bitstream をクリックして、ビットストリームを生成した。
StereoCam_78_151122.png

タイミングのエラーは出ているが、ビットストリームが生成された。

ハードウェアをエクスポートして、SDKを立ちあげて、XGA解像度のHDMI を出力させてみたが、乱れていなかった。成功だけれども、手順が面倒だ。
特にIPパケ-ジャーでIPを修正するときに、テンポラリにプロジェクトを生成しているので、新たに生成したファイルがIPのファイル・グループにそのままでは Add できない。
  1. 2015年11月22日 08:13 |
  2. IP
  3. | トラックバック:0
  4. | コメント:0

BUFR でクロックを分周する場合は制約を追加する必要がある(ビットマップ・ディスプレイ・コントローラ IP のHDMI 出力)

Zynq のビットマップ・ディスプレイ・コントローラのHDMI 出力では、VGA, SVGAは安定して出力できるが、XGA以上になると時々プチプチ切れる現象が続いていた。(”ZYBOにビットマップ・ディスプレイ・コントローラを追加する1(仕様)”参照)

並列ステレオカメラによる距離の測定5(ZYBO 0 のハードウェア4)”でもHDMI 出力のXGA 画像が時々消えてしまっていた。

Digilent 社のDigilentInc/vivado-library を Download ZIP して見ていた時に、ip\rgb2dvi_v1_2\src を見ていたら制約のXDCファイルがある。制約を見るとHDMI の周波数がピクセルクロックの5倍のSerDes 用クロックは、ピクセルクロックのクロック周波数の 5 倍の周波数であるという記述だった。

もしかしてこの記述が重要なのか?と思い、自分のMMCM の制約として付けてみることにした。取りあえずは、ビットマップ・ディスプレイ・コントローラ IPの制約ではなく、プロジェクト全体への制約として付加することにする。

MMCM回りのVHDL記述を下に示す。

MMCM_BASE_PIXEL : MMCME2_BASE generic map (
BANDWIDTH => "OPTIMIZED",
    CLKOUT4_CASCADE     => FALSE,
    STARTUP_WAIT        => FALSE,
    CLKFBOUT_MULT_F => MMCM_CLKFBOUT_MULT,
CLKIN1_PERIOD => MMCM_CLKIN_PERIOD,
CLKOUT0_DIVIDE_F => MMCM_CLKOUT0_DIVIDE,
DIVCLK_DIVIDE => 1
) port map (
CLKFBOUT => mmc_fb_out,
CLKOUT0 => pixel_clkx5,
LOCKED => mmcm_locked,
CLKFBIN => mmc_fb_in,
CLKIN1 => clk25,
PWRDWN => '0',
RST => '0'
);
mmcm_locked_n <= not mmcm_locked;
mmc_fb_in <= mmc_fb_out;
-- BUF_FB : BUFG port map(
-- I => mmc_fb_out,
-- O => mmc_fb_in
-- );
BUFIO_pixel_clkx5 : BUFIO port map (
O => pclkx5_buf,
I => pixel_clkx5
);
BUFR_pixel_clk_io : BUFR generic map(
BUFR_DIVIDE => "5",
SIM_DEVICE => "7SERIES"
) port map (
O => pclk_buf,
CE  => '1',
CLR => mmcm_locked_n,
I => pixel_clkx5
);
CLK_OUT_BUFG : bufg port map (
O => pclk_buf_out,
I => pclk_buf
);
pclk_out <= pclk_buf_out;
pclk_locked <= mmcm_locked;


上のVHDL ソースコードで pclkx5_buf がOSERDESE2 用の出力データシフト用クロックだ。OSERDESE2 のモードはDDR となっている。ピクセルクロックはBUFR で 5 分周されたpclk_buf_out だ。(BUFRに関しては、”AR# 465057 シリーズ FPGA デザイン アシスタント - クロック バッファーの使用”を参照)

そこで、Flow Navigator のImplementation -> Implemented Desgin をクリックして、Implemented Desgin 画面を起動した。

Flow Navigator のImplementation -> Implemented Desgin -> Edit Timing Constraints をクリックしてタイミング制約を編集した。
もうすでに入っているが、Create Generate Clock に pclkx5_buf クロックを元に1/5 してpixclk を作っているという制約が入っている。
StereoCam_48_151121.png

StereoCam_49_151121.png

制約の記述を示す。

create_generated_clock -source [get_pins ZYBO_0_i/bitmap_disp_cntrler_axi_master_1/inst/dvi_disp_i/hdmi_tx_i/pclkx5_buf] -divide_by 5 [get_pins ZYBO_0_i/bitmap_disp_cntrler_axi_master_0/inst/dvi_disp_i/pixclk]


これで、”並列ステレオカメラによる距離の測定5(ZYBO 0 のハードウェア4)”をもう一度、論理合成、インプリメント、ビットストリームの生成を行ったところ、XGA 解像度のHMDI 出力が安定した。

通常は、MMCMやPLL で異なる周波数のクロックを出力しても自動的に新しいクロックの制約を自動生成してくれると思うのだが、BUFR に関してはやってくれないのかもしれない?
ビットマップ・ディスプレイ・コントローラ IP の制約として一緒にIP したほうが良いと思う。
  1. 2015年11月21日 05:51 |
  2. 制約
  3. | トラックバック:0
  4. | コメント:0

Xilinx Announces the Spartan-7 FPGA Family

Spartan-7 が出るそうです。びっくりしました。

Xilinx Announces the Spartan-7 FPGA Family

  1. 2015年11月20日 05:15 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

並列ステレオカメラによる距離の測定5(ZYBO 0 のハードウェア4)

並列ステレオカメラによる距離の測定4(ZYBO 0 のハードウェア3)”の続き。

前回はタイミング違反を修正して、再度ビットストリームを生成し、SDKを立ち上げた。
今回は、SDK上でアプリケーション・プロジェクトを作製して、ソフトウェアを作り、ZYBO上で動かしてみよう。

SDK の File メニューからNew -> Application Project を選択する。

Project name に cam_disp と入力した。Next > ボタンをクリックした。OS Platform は取りあえず、ベアメタル・アプリケーションとするので、デフォルトの standalone に設定した。
StereoCam_37_151118.png

Available Templates から Empty Application を選択する。Finish ボタンをクリックした。
StereoCam_38_151118.png

今、使用しているVivado のバージョンは 2015.3 だが、2015.1 の時の Templates から明らかに項目が増えている。OpenAMP 関連の項目や、MPSoC 関連の項目が増えているようだ。Vivado 2015.1 の時のAvailable Templates 画面を下に示す。
V_ZYBO_CAMD_151_63_150612.png

cam_disp Application Project と cam_disp_bsp Board Support Package が生成された。
StereoCam_39_151118.png

次に、カメラ画像を表示されるソフトウェア cam_disp_aixs.c を作る。

cam_disp Application Project の src フォルダから 右クリックし、右クリックメニューから New -> Source File を選択した。
StereoCam_40_151119.png

New Source File ダイアログで Source file に cam_disp_axis.c を入力して、Finish ボタンをクリックした。
StereoCam_41_151119.png

cam_disp_axis.c は、”AXI4-Stream版ラプラシアンフィルタIPのカメラ表示システム9(カメラ画像表示は完成)”のCソースコードを元に、bitmap_disp_cntrler_axi_master_1 の処理を追加した。
StereoCam_42_151119.png
セーブするとビルドされ、elf ファイルが自動的に生成された。

SDK のXilinx Tools -> Program FPGA を選択した。

Program FPGA ダイアログが表示され、Program ボタンをクリックした。
StereoCam_43_151119.png

Zynq へのFPGA コンフィギュレーション・データのダウンロードが成功した。
StereoCam_44_151119.png

cam_disp.elf バイナリを起動する。

cam_disp.elf を右クリックし、右クリックメニューから Run AS -> Launch on Hardware (GDB) を選択した。
StereoCam_45_151119.png

VGAポートにカメラ画像が表示されたが、フレームレートが遅すぎる。
フレームレートは15fps / 3 = 5 fps 程度と思われる。これは、AXI VDMAで 3 画面分のフレームバッファを取っているけれども私の作ったビットマップ・ディスプレイ・コントローラのフレームバッファが1フレームであるので、15 fps のカメラ画像の更新頻度が 1/3 になってしまうためである。
StereoCam_46_151119.jpg

HDMIポートにもXGA画像が表示されているが、予想通り、時々消えてしまう。
StereoCam_47_151119.jpg

フレームレートが遅いのが我慢出来ないので、ビットマップ・ディスプレイ・コントローラのAXI4 Stream 版を作って、AXI VDMAからもらったカメラ画像のAXI4 Stream を使って表示ししてみたい。それに、HDMI へのXGA 出力はDigilent 社から配っている rgb2dvi IPを使用したい。

最後に、cam_disp_axis.c を貼っておく。

// cam_disp_axis.c
// 2015/11/19 by marsee
//
// Refered to Xilinx\SDK\2015.1\data\embeddedsw\XilinxProcessorIPLib\drivers\axivdma_v5_1\doc\html\api
// Refered to https://github.com/elitezhe/Atyls-VDMA-one-in-one-out/blob/master/SDK/colorbar/src/helloworld.c
// Refered to http://www.xilinx.com/support/documentation/ip_documentation/axi_vdma/v6_2/pg020_axi_vdma.pdf
// Refered to http://forums.xilinx.com/t5/Embedded-Processor-System-Design/Axi-VDMA-on-Digilent-Atlys/td-p/297019/page/2
//
// normal camera out
//
#include <stdio.h>
#include <stdlib.h>
#include "xaxivdma.h"
#include "xil_io.h"
#include "xparameters.h"
#include "sleep.h"
#define NUMBER_OF_WRITE_FRAMES 3 // Note: If not at least 3 or more, the image is not displayed in succession.
#define HORIZONTAL_PIXELS 800
#define VERTICAL_LINES 600
#define PIXEL_NUM_OF_BYTES 4
#define FRAME_BUFFER_ADDRESS 0x10000000
static XAxiVdma_DmaSetup Vdma0_WriteCfg;
void cam_i2c_init(volatile unsigned *mt9d111_i2c_axi_lites) {
    mt9d111_i2c_axi_lites[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    mt9d111_i2c_axi_lites[64] = 0x1; // enable i2c
}
void cam_i2x_write_sync(void) {
    // unsigned c;
    // c = *cam_i2c_rx_fifo;
    // while ((c & 0x84) != 0x80)
        // c = *cam_i2c_rx_fifo; // No Bus Busy and TX_FIFO_Empty = 1
    usleep(1000);
}
void cam_i2c_write(volatile unsigned *mt9d111_i2c_axi_lites, unsigned int device_addr, unsigned int write_addr, unsigned int write_data){
    mt9d111_i2c_axi_lites[66] = 0x100 | (device_addr & 0xfe);   // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    mt9d111_i2c_axi_lites[66] = write_addr;
    mt9d111_i2c_axi_lites[66] = (write_data >> 8)|0xff;         // first data
    mt9d111_i2c_axi_lites[66] = 0x200 | (write_data & 0xff);        // second data
    cam_i2x_write_sync();
}
int main(){
// malloc frame buffer
// unsigned int *frame_buffer = (unsigned int *)malloc(HORIZONTAL_PIXELS * VERTICAL_LINES * PIXEL_NUM_OF_BYTES * NUMBER_OF_WRITE_FRAMES);
// AXI VDMA Initialization sequence
XAxiVdma_Config *XAxiVdma0_Config;
XAxiVdma XAxiVdma0;
int XAxiVdma0_Status;
XAxiVdma0_Config = XAxiVdma_LookupConfig(XPAR_CAMERA_INTERFACE_AXI_VDMA_0_DEVICE_ID); // Look up the hardware configuration for a device instance
if (XAxiVdma0_Config == NULL){
fprintf(stderr, "No AXI VDMA found\n");
return(-1);
}
XAxiVdma0_Status = XAxiVdma_CfgInitialize(&XAxiVdma0, XAxiVdma0_Config, XAxiVdma0_Config->BaseAddress); // Initialize the driver with hardware configuration
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_CfgInitialize() failed\n");
return(-1);
}
XAxiVdma_Reset(&XAxiVdma0, XAXIVDMA_WRITE);
while(XAxiVdma_ResetNotDone(&XAxiVdma0, XAXIVDMA_WRITE)) ;
XAxiVdma0_Status = XAxiVdma_SetFrmStore(&XAxiVdma0, NUMBER_OF_WRITE_FRAMES, XAXIVDMA_WRITE); // Set the number of frame store buffers to use.
Vdma0_WriteCfg.VertSizeInput = VERTICAL_LINES;
Vdma0_WriteCfg.HoriSizeInput = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES;
Vdma0_WriteCfg.Stride = HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES; // Indicates the number of address bytes between the first pixels of each video line.
Vdma0_WriteCfg.FrameDelay = 0; // Indicates the minimum number of frame buffers the Genlock slave is to be behind the locked master. This field is only used if the channel is enabled for Genlock Slave operations. This field has no meaning in other Genlock modes.
Vdma0_WriteCfg.EnableCircularBuf = 1; // Indicates frame buffer Circular mode or frame buffer Park mode.  1 = Circular Mode Engine continuously circles through frame buffers.
Vdma0_WriteCfg.EnableSync = 0; // Enables Genlock or Dynamic Genlock Synchronization. 0 = Genlock or Dynamic Genlock Synchronization disabled.
Vdma0_WriteCfg.PointNum = 0; // No Gen-Lock
Vdma0_WriteCfg.EnableFrameCounter = 0; // Endless transfers
Vdma0_WriteCfg.FixedFrameStoreAddr = 0; // We are not doing parking
XAxiVdma0_Status = XAxiVdma_DmaConfig(&XAxiVdma0, XAXIVDMA_WRITE, &Vdma0_WriteCfg);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaConfig() failed\n");
return(-1);
}
// Frame buffer address set
unsigned int frame_addr = (unsigned int)FRAME_BUFFER_ADDRESS;
int i;
for (i=0; i<NUMBER_OF_WRITE_FRAMES; i++){
Vdma0_WriteCfg.FrameStoreStartAddr[i] = frame_addr;
frame_addr += HORIZONTAL_PIXELS * PIXEL_NUM_OF_BYTES * VERTICAL_LINES;
}
XAxiVdma0_Status = XAxiVdma_DmaSetBufferAddr(&XAxiVdma0, XAXIVDMA_WRITE, Vdma0_WriteCfg.FrameStoreStartAddr);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaSetBufferAddr() failed\n");
return(-1);
}
// axis_switch_1, 1to2 ,Select M00_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x40), 0x0);
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR+0x44), 0x80000000); // disable
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_1_BASEADDR), 0x2); // Commit registers
// axis_switch_0, 2to1, Select S00_AXIS
// Refer to http://marsee101.blog19.fc2.com/blog-entry-3177.html
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR+0x40), 0x0);
Xil_Out32((XPAR_CAMERA_INTERFACE_AXIS_SWITCH_0_BASEADDR), 0x2); // Commit registers
// VDMA start
XAxiVdma0_Status = XAxiVdma_DmaStart(&XAxiVdma0, XAXIVDMA_WRITE);
if (XAxiVdma0_Status != XST_SUCCESS){
fprintf(stderr, "XAxiVdma_DmaStart() failed\n");
return(-1);
}
// mt9d111_inf_axis_0, axi_iic_0, bitmap_disp_cntrler_axi_master_0
    volatile unsigned int *bmdc0_axi_lites;
    volatile unsigned int *bmdc1_axi_lites;
    volatile unsigned int *mt9d111_axi_lites;
    volatile unsigned int *mt9d111_i2c_axi_lites;
    bmdc0_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_0_BASEADDR;
    bmdc1_axi_lites = (volatile unsigned *)XPAR_BITMAP_DISP_CNTRLER_AXI_MASTER_1_BASEADDR;
    mt9d111_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_MT9D111_INF_AXIS_0_BASEADDR;
    mt9d111_i2c_axi_lites = (volatile unsigned *)XPAR_CAMERA_INTERFACE_AXI_IIC_0_BASEADDR;
    bmdc0_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 0 start
    bmdc1_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Bitmap Display Controller 1 start
    mt9d111_axi_lites[0] = (volatile unsigned int)FRAME_BUFFER_ADDRESS; // Camera Interface start (Address is dummy)
    // CMOS Camera initialize, MT9D111
    cam_i2c_init(mt9d111_i2c_axi_lites);
    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0xf0, 0x1);      // Changed regster map to IFP page 1
    cam_i2c_write(mt9d111_i2c_axi_lites, 0xba, 0x97, 0x20); // RGB Mode, RGB565
    mt9d111_axi_lites[1] = 0; // One_shot_mode is disabled
return(0);
}

  1. 2015年11月19日 05:23 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

並列ステレオカメラによる距離の測定4(ZYBO 0 のハードウェア3)

並列ステレオカメラによる距離の測定3(ZYBO 0 のハードウェア2)”の続き。

前回は、bitmap_disp_cntrler_axi_master_1 をブロックデザインに追加し、制約ファイルをコピーして論理合成、インプリメント、ビットストリームの生成を行ったが、タイミング違反が出てしまった。
今回は、タイミング違反を確認して、タイミング違反がInter-Clock Path だったら、False Path を設定して、もう一度、インプリメント、ビットストリームの生成を行う。

まずは、Vivado 2015.3 の左端、Flow Navigator のImplementation -> Implemented Desgin をクリックして、Implemented Desgin 画面を起動する。

Flow Navigator のImplementation -> Implemented Desgin -> Report Timing Summary をクリックしてタイミング・レポートを出した。
StereoCam_30_151117.png

Inter-Clock Paths の BUFR_pixel_clk_io_0 、BUFR_pixel_clk_io_0_1 と clk_fpga_0 の間にタイミング違反があるとのことだ。
StereoCam_30_151117.png

このクロックは独立していて、依存関係は無いはずなので、Flow Navigator のImplementation -> Implemented Desgin -> Edit Timing Constraints をクリックしてタイミング制約を編集した。

Edit Timing Constraints ウインドウのException -> Set False Path を選択して、4つの制約を追加した。
StereoCam_31_151118.png

セーブはZYBO_0.xdc にセーブした。
StereoCam_32_151118.png

下に新たに作製した制約を貼っておく。

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


これで、もう一度、論理合成、インプリメント、ビットストリームの生成を行った。下の図は現在、論理合成中のVivado 2015.3 を示す。
StereoCam_33_151118.png

ビットストリームの生成まで終了した。
StereoCam_34_151118.png

Summary を表示した。タイミング違反は無くなった。
StereoCam_34_151118.png

ハードウェアをエクスポートして、SDKを立ち上げよう。

File メニューから Exprot -> Export Hardware... を選択した。

Export Hardware ダイアログが表示される。Include bitstream にチェックを入れて、OKボタンをクリックした。

File メニューから Launch SDKを選択した。

SDKが立ち上がった。bitmap_disp_cntrler_axi_master_1 も入っていた。
StereoCam_36_151118.png
  1. 2015年11月18日 04:35 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

並列ステレオカメラによる距離の測定3(ZYBO 0 のハードウェア2)

並列ステレオカメラによる距離の測定2(ZYBO 0 のハードウェア1)”の続き。

前回は、V_ZYBO_CAMDS_151 のブロックデザインを今回のプロジェクトZYBO_0 に移植した。
今回は、ZYBO_0 にXGA 解像度のビットマップ・ディスプレイ・コントローラを追加して、HDMIポートに接続する。

最初に、bitmap_disp_cntrler_axi_master_1 をブロックデザインに追加した。
StereoCam_15_151116.png

bitmap_disp_cntrler_axi_master_1 をダブル・クリックして、Resolution を XGA に変更した。
StereoCam_16_151117.png

FCLK_CLK1 (25MHz)をbitmap_disp_cntrler_axi_master_1 の clk25 に接続した。
StereoCam_17_151117.png

Run Connection Automatin をクリックすると、ダイアログが表示された。
bitmap_disp_cntrler_axi_master_1 のM_AXI をS_AXI_HP2 に接続した。
StereoCam_18_151117.png

bitmap_disp_cntrler_axi_master_1 の s_axi_lite は M_AXI_GP0 に接続した。
StereoCam_19_151117.png

bitmap_disp_cntrler_axi_master_1 の M_AXI と s_axi_lite が接続されたが、ARESETN が接続されていない。
StereoCam_20_151117.png

ARESETN を接続した。
StereoCam_21_151117.png

HDMI ポートと bitmap_disp_cntrler_axi_master_0 との接続を切って、bitmap_disp_cntrler_axi_master_1 に接続した。
StereoCam_22_151117.png

レイアウトを再生成した。
StereoCam_23_151117.png

Address Editor を下に示す。
StereoCam_27_151117.png

ブロックデザインのウインドウのフロートを解除して、ブロックデザインをセーブした。
StereoCam_24_151117.png

Source ウインドウで、ZYBO_0 ブロックデザインを右クリックし、右クリックメニューから、Create HDL Wapper... を選択して、トップのZYBO_0_wapper.v を生成した。
StereoCam_25_151117.png

Source ウインドウで Add Source して、ZYB_0.xdc を生成し、V_ZYBO_CAMDS_151 の制約をコピーした。
StereoCam_26_151117.png

論理合成、インプリメント、ビットストリームの生成を行った。
StereoCam_28_151117.png

タイミングエラーが出ている。

Project Summary を示す。
StereoCam_29_151117.png
  1. 2015年11月17日 04:57 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

並列ステレオカメラによる距離の測定2(ZYBO 0 のハードウェア1)

並列ステレオカメラによる距離の測定1(ブロック図)”の続き。

前回は、並列ステレオカメラによる距離の測定のためのブロック図を示した。
今回は、ステレオカメラによる距離の測定装置のブロック図のZYBO 0 のハードウェアを作っていくことにする。
今回作製するブロックデザインは、”AXI4-Stream版ラプラシアンフィルタIPのカメラ表示システム4(ブロックデザイン2)”で大体出来上がっている。これに、bitmap_disp_cntrler_axi_master を追加して、XGA解像度でHDMI を出力させれば完成する。元からある bitmap_disp_cntrler_axi_master_0 はHDMI ポート出力をオープンにする。

ZYBO 0 用に新しいプロジェクトを作って、ブロックデザインをV_ZYBO_CAMDS_151 と同じように生成したい。このような場合に、”Vivado プロジェクトを配布する方法”の2番めの方法、”tcl スクリプトでプロジェクトやブロックデザインを生成する方法”でブロックデザインをコピーしよう。

まずは、V_ZYBO_CAMDS_151 は、Vivado 2015.1で生成されているので、Vivado 2015.3にプロジェクトを変換する。(TCLスクリプトは違うバージョンでは動かなかった)

V_ZYBO_CAMDS_151 は残しておきたいので、フォルダごとコピー&ペーストして、名前をV_ZYBO_CAMDS_153 に変更しておく。

Vivado 2015.3 を立ちあげて、V_ZYBO_CAMDS_151 プロジェクトを読み込んだ。

Older Project Version ダイアログが開いた。
Automatically upgrade to the current version のラジオボタンにチェックが入っていることを確認してOKボタンをクリックした。
StereoCam_9_151116.png 

Project Upgrade ダイアログが開いた。
Report IP Status ボタンをクリックした。
StereoCam_10_151116.png 

IP Status が開いた。Upgrade Selected ボタンをクリックした。
StereoCam_11_151116.png 

その後、Rerun をクリックするとアップグレードが反映された。
StereoCam_12_151116.png 


これで、File メニューから Export -> Export Block Design... を選択すると、Export Block Design ダイアログが開く。
Tcl file を指定して OK ボタンをクリックするという方法で、V_ZYBO_CAMDS.tcl が生成された。

さて、新しく ZYBO_0_153 プロジェクトを作製しよう。使用するVivado のバージョンはもちろん 2015.3 だ。
ZYBO 用に新しく ZYBO_0_153 プロジェクトを作製したところを下の図に示す。
StereoCam_3_151116.png

V_ZYBO_CAMDS_151 のIP のフォルダを ZYBO_0_153 フォルダにコピーした。具体的なフォルダ名は、BMDispCaL、cam_inf_d111_axis_151、lap_filter_axis_144 だ。


IP Catalog ウインドウを立ちあげて、右クリックし右クリックメニューからIP Settings... 選択して、Project Setting ダイアログのIP -> Repository Manager から先ほどコピーしたIP を指定した。
StereoCam_5_151116.png

OKボタンをクリックし、IP Catalog に登録すると、3つのIP が登録されているのが分かる。
StereoCam_6_151116.png

次に、ブロックデザインを生成するスクリプトV_ZYBO_CAMDS.tcl をコピーする。
V_ZYBO_CAMDS.tcl をエディタで開いて、”# CHANGE DESIGN NAME HERE”と書いてあったデザイン名の指定を”set design_name ZYBO_0”に変更した。
StereoCam_7_151116.png 

下のタブからTcl Console をクリックして、source z:/ZYBO_0_153/V_ZYBO_CAMDS.tcl コマンドを入力する。
StereoCam_8_151116.png

すると、ブロックデザインを構築していく。
StereoCam_13_151116.png 

ブロックデザインの構築が終了した。
StereoCam_14_151116.png 

最後に、ブロックデザインをセーブした。
  1. 2015年11月16日 20:58 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

FPGAの部屋のまとめサイトの更新(2015年11月15日)

FPGAの部屋のまとめサイトを更新しました。

DE0-Nano-SoCボードSynverll を追加して、今日までの記事を各カテゴリに追加しました。
  1. 2015年11月15日 08:46 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

並列ステレオカメラによる距離の測定1(ブロック図)

次の目標(並列ステレオカメラによる距離の測定)”の続き。

今回はステレオカメラによる距離の測定装置のブロック図を書いてみた。下にブロック図を示す。
StereoCam_1_151114.png

ZYBO 0 のCamera Processing Unit がSVGA のカメラからの画像をラプラシアンフィルタ処理をした画像かそのままのカメラ画像かを選択してDDR3 SDRAMに書き込む。その画像をBitmap Display Controller がDDR3 SDRAMから読みだしてVGAポートでSVGA でDisplay に出力する。ZYBO 0 のBitmap Display Controller からは、XGA出力のHDMI画像が出力されて、ZYBO 1 の dvi2rgb IP に渡される。(なぜXGA かというとSVGA では dvi2rgb IP が上手く受け取ることが出来なかった)
ZYBO 1 の dvi2rgb で受けられたHDMI の信号は、rgb から AXI4 Stream に変換されて、AXI VDMA で DDR3 SDRAM に保存される。
ZYBO 1 のSVGA のカメラから Camera Processing Unit でラプラシアンフィルタ処理をした画像かそのままのカメラ画像かを選択してDDR3 SDRAMに書き込む。
Depth Processing Unit では、ZYBO 0 のカメラ画像と ZYBO 1 のカメラ画像を比較して深度情報を色に変換してフレームバッファに書き込む。
ZYBO 1 のBitmap Display Controller は、ZYBO 0 または ZYBO 1 のカメラ画像と深度情報をDMA してアルファブレンドして、Display に出力する。

Camera Processing Unit の内部を示す。
StereoCam_2_151114.png

AXI4-Stream版ラプラシアンフィルタIPのカメラ表示システム1(構想編)”はAXI4 Stream を2分岐出来ないので、間にAXI4 Stream Switcher を入れてある。AXI4-Stream版ラプラシアンフィルタIPのカメラ表示システムでも後で気がついて入れてある。
CMOS Camera からの画像はCamera - AXI4-Stream Output でAXI4 Stream に変換され、AXI4 Stream に変換される。画像のAXI4 Stream はAXI4 Stream Switcher でスイッチされ、ラプラシアンフィルタ処理を行うストリームとカメラ画像が直接流れるAXI4 Stream が次のAXI4 Stream Switcher でスイッチされる。そのAXI4 Stream は、AXI VDMA でAXI4 Master アクセスに変換されて、DDR3 SDRAMに書かれる。

大体、IP は今までのFPGAの部屋のブログに書いてある通りに出来ているので、Depth Processing Unit と アルファブレンドのBitmap Display Controller を作れば良いことになる。
Depth Processing Unit は、最初は作らないで、ARMプロセッサを使って、深度情報をフレームバッファに書き込むようにしようと思っている。そのソフトウェアを元に、Vivado HLS でハードウェアに変換することを考えている。

但し、ZYBO 1 のメモリ帯域が心配だ。AXI4 Master のラインは7本もある。まだ、メモリ帯域の概算もしていないが、メモリ帯域の考察によっては、アルファブレンドする深度情報をBRAMに入れる必要があるかもしれない?もしくは、DDR3 SDRAMに入れるにしても帯域を落とすとか?
深度情報はブロック単位にしようと思っているので、やろうと思えばメモリ量は抑えることができる。

なお、dvi2rgb IP はDigilent 社から配布されているIP だ。”ZYBOのHDMI入力を使用する(概要)”を参照ください。
  1. 2015年11月14日 06:47 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

次の目標(並列ステレオカメラによる距離の測定)

昨日で、ZYBOにHDLで書いたラプラシアンフィルタを実装するのは終了した。

次のお題だが、こういうのを考えている。

ZYBOを2台使用し、それぞれにカメラを搭載して、1台のカメラの画像をラプラシアンフィルタ変換を行い、HDMIでもう一台に送信する。

もう1台のZYBOでのHDMI信号を受けて、自分のカメラの画像のラプラシアンフィルタ変換画像と比較して、距離を計算する。

距離は色としてラプラシアンフィルタ画像にアルファブレンドする。

つまり、ステレオカメラからの距離によって、色が変化する画像をやってみたい。
ステレオカメラはZYBOに1台ずつ付けたカメラを2台のZYBOを使ってステレオカメラとする。

いまブロック図を書いている。頭の中でどんな回路構成にするかを考えながらブロック図を書いているが、ZYBOのZynq-7010だとFPGA部分のリソースが足りなくなるかもしれない?その場合はフレームレートは相当遅くなるだろうが、ARMプロセッサに一部の処理を担当して貰う必要があるかもしれない?
ARMプロセッサにはLinuxを入れて、制御したいと考えている。
  1. 2015年11月13日 05:19 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

ZYBOにHDLで書いたラプラシアンフィルタを実装する11(バグはあるけど完成)

ZYBOにHDLで書いたラプラシアンフィルタを実装する10(UIOの最大数を10に変更する)”の続き。

前回はUIOの最大数を 10 にしたつもりだったが、もしかしたらUIOのアドレス領域を 10 に増やしただけかもしれない?
原因は、/dev/uio5 のパーミッションが 600 だったことだった。パーミッションを 666 にしておけば、uImage も Vivado HLS で出力したドライバもそのまま動作した。

./lap_fil_hdl_1shot は相変わらず動作しないが、ls -l /dev/uio* で見ると、/dev/uio5 のパーミッションが 600 になっている。これでは root 以外は動作しないので、sudo chmod 666 /dev/uio5 でパーミッションを変更したら、uio5 がオープンできて、HDLで作ったラプラシアンフィルタ処理が上手く行く様になった。
lap_fil_HDL_axim_144_151112.png

そう言えば、rc.local に uio のパーミッション変更コマンドを書いてあって、Ubuntu をブートした時に実行するようにしていたんだった。(”ZYBO用の Linaro Ubuntu のPL部にビットマップ・ディスプレイ・コントローラを搭載する5(UIOの設定3)”参照)

/dev/uio5 のパーミッション変更も rc.local に書いておいた。
lap_fil_HDL_axim_145_151112.png

これで、電源ON の起動時から HDL で書いたラプラシアンフィルタ処理をすることができるようになった。
バグはあるのだが、これで取りあえず完成とする。
lap_fil_HDL_axim_134_151108.jpg
  1. 2015年11月12日 04:11 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

ZYBOにHDLで書いたラプラシアンフィルタを実装する10(UIOの最大数を10に変更する)

ZYBOにHDLで書いたラプラシアンフィルタを実装する9(制御ソフトウェアを作製して実機確認)”の続き。

(2015/11/12:追記)原因は、/dev/uio5 のパーミッションが 600 だったことだった。パーミッションを 666 にしておけば、uImage も Vivado HLS で出力したドライバもそのまま動作した。詳細は”ZYBOにHDLで書いたラプラシアンフィルタを実装する11(バグはあるけど完成)”を参照のこと。

前回は、lap_fil_hdl_axim の uio5 をオープンできなくてアプリケーションがエラーになってしまった。lap_fil_hdl_axim の uio4 にすればオープンすることができる。つまり uio が 0 ~ 4 までの5個に制限されているのじゃないかという結論に至った。

Twitter で 石原ひでみさんに教えてもらったのだが、標準は5個までで、MAX値はinclude/linux/uio_driver.h のMAX_UIO_MAPS、MAX_UIO_PORT_REGIONS で決められているということだったので、早速、値を変更して uImage を再度ビルドしてみることにした。

uio_driver.h はinclude/linux にあった。
lap_fil_HDL_axim_131_151108.png

uio_driver.h を開くとMAX_UIO_MAPS、MAX_UIO_PORT_REGIONS があった。両方共 5 だった。
lap_fil_HDL_axim_132_151108.png

MAX_UIO_MAPS、MAX_UIO_PORT_REGIONS を両方共 10 にした。
lap_fil_HDL_axim_133_151108.png

ZYBO/Digilent_Linux_Tutrial/Linux-Digilent-Dev ディレクトリで、
make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- xilinx_zynq_defconfig コマンドでZYBO 用の設定値を反映するため、デフォルト・コンフィギュレーションを行った。(ここを参照
lap_fil_HDL_axim_137_151108.png

make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- コマンドでLinux カーネルをビルドした。(ここを参照)(フルビルド時のログ)
lap_fil_HDL_axim_138_151108.png

Linux-Digilent-Dev/arch/arm/boot ディレクトリに zImage が生成された。
lap_fil_HDL_axim_139_151108.png

make ARCH=arm CROSS_COMPILE=arm-xilinx-linux-gnueabi- UIMAGE_LOADADDR=0x8000 uImage コマンドでを実行して、uImage を作製した。なお、u-boot-Digilent-Dev/tools ディレクトリへのリンクはすでに貼ってある。(ここを参照
lap_fil_HDL_axim_140_151108.png

Linux-Digilent-Dev/arch/arm/boot ディレクトリに uImage が作成された。
lap_fil_HDL_axim_141_151108.png

uImage を ZYBO 用の MicroSD カードの uImage と入れ替えて、ZYBO に挿入して電源ONを行った。

devicetree も 以前の lap_fil_hdl_axim が uio5 にマップされる状態に戻した。

その上で ./lap_fil_hls_1shot を起動してみたが、やはり、XST_OPEN_DEVICE_FAILED の 3 のエラーだった。
lap_fil_HDL_axim_142_151108.png

なお、ZYBO 用 Linux のビルドは 2 回やっている。uio_driver.h の一部変更ビルドとそれが上手く行かないため、make clean してフルビルドした。

Vivado HLS が出力したドライバ・ソフトウェア にも UIO の最大値が定義されていた。
xlap_fil_hdl_axim_linux.c の MAX_UIO_MAPS が 5 だったため、10 に変更して lap_fil_hls_1shot をリビルドしてみたが、結果は変わらなかった。
lap_fil_HDL_axim_143_151111.png
  1. 2015年11月11日 04:57 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

ZYBOにHDLで書いたラプラシアンフィルタを実装する9(制御ソフトウェアを作製して実機確認)

ZYBOにHDLで書いたラプラシアンフィルタを実装する9(devicetreeの生成、/sys, /devディレクトリ)”の続き。

前回は、devicetree.dtb を生成して、Micro SDカードに、BOOT.bin と devicetree.dtb を書き込んで、ZYBOに挿入してUbuntu をブートし、/sys ディレクトリと /dev ディレクトリを観察した。
今回は、制御ソフトウェアを作製してZYBO でHDLで書いたラプラシアンフィルタを動作させる。

ドライバ・ソフトウェアだが、本来はVivado HLS で書いたAXI4 Lite Slave モジュールを頂いているので、それ用のドライバ・ソフトウェアがあるはずなのだが、昔に作ったので、そのVivado HLS のプロジェクトが無くなったか?もしくは削除してしまっていてわからない?
そこで、もう一度Vivado HLS 2015.3 でラプラシアンフィルタのCソースコードを使ってIP 化してドライバ・ソフトウェアを生成することにした。

Vivado HLS 2015.3 で、lap_fil_hdl_axim() というTop Function のCソースコードをIP化して、xlap_fil_hdl_axim.h をHDLで書いたラプラシアンフィルタの lap_filter_axim_LiteS_if.v のアドレス・オフセットに合うように書き換えた。
なお、Cソースコードのディレクティブを変更してある。変更は、cam_addr ポートのインターフェースを ap_hs に、lap_addr ポートのインターフェースを ap_vld に変更した。
下にそのVivado HLS 2015.3 のプロジェクトを示す。
lap_fil_HDL_axim_122_151108.png

ZYBO の電源を入れてUbuntu 14.04 を起動する。
BOOT.bin も devicetree.dtb も問題なく起動できた。

home/linaro/Apps の下に、lap_fil_hdl_1shot ディレクトリを作製した。

ドライバ・ソフトウェアはWindows のパソコン上にあるので、WinSCP でZYBO に接続して、ドライバ・ソフトウェアをZYBO のlap_fil_hdl_1shot ディレクトリにアップロードした。
lap_fil_HDL_axim_123_151108.png

ドライバ・ソフトウェアをZYBO のlap_fil_hdl_1shot ディレクトリにアップロードできた。
lap_fil_HDL_axim_124_151108.png

次に、lap_fil_hls_1shot.c をコピー&ペーストして、修正して lap_fil_hdl_1shot.c を作製した。
lap_fil_HDL_axim_125_151108.png

簡単な Makefile を作製した。
lap_fil_HDL_axim_126_151108.png

make を行った。バイナリ(lap_fil_hdl_1shot)ができた。
cam_disp_uio と lap_fil_hls_1shot をこのディレクトリにコピーした。
lap_fil_HDL_axim_127_151108.png

./cam_disp_uio を実行して、カメラをディスプレイに表示した後で、 ./lap_fil_hdl_1shot を実行したが、エラーになってしまった。
./lap_fil_hls_1shot は通常に実行することができる。
lap_fil_HDL_axim_128_151108.png

試しに、Vivado HLS のラプラシアンフィルタのUIO エントリをコメント・アウトしたデバイスツリーを作ってコンパイルしてやってみた。
lap_fil_HDL_axim_129_151108.png

これだと、lap_fil_hdl_1shot が動作した。
どうやら、UIO で制御できるデバイスはデフォルトでは5個までのようだ。
lap_fil_HDL_axim_130_151108.png
動作時間は 10.05 ms 程度で一番速い。

ラプラシアンフィルタ処理はまだバグが残っている。最初のラプラシアンフィルタ処理は正しいようだが、2番めは上のエッジだけ、3番目は下のエッジだけになる。4番目は最初のラプラシアンフィルタ処理に戻る。

最初のラプラシアンフィルタ処理結果
lap_fil_HDL_axim_134_151108.jpg

2番め
lap_fil_HDL_axim_135_151108.jpg

3番目
lap_fil_HDL_axim_136_151108.jpg

バグが残っているが、動作確認はできるので、良しとすることにしよう。何処か完全に終了していない部分があるのだと思う。

次は、Linuxカーネルを修正してUIOを10 個までエントリできるようにしてみたい。
  1. 2015年11月09日 05:28 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

フリーの3D Cad 勉強会

今度、職場でフリーの3D Cadの勉強会をすることになりました。5人程度の参加人数です。

フリーの3D CadはFreeCad を使用します。
日本語のマニュアルがあるので、それを参照しながら、FreeCAD - 初心者向けチュートリアルをやっていこうかな?と思っています。

職場の工作室に 3Dプリンタ5台とレーザー加工機1台が入ったので、3Dプリンタを使わせてもらいます。
自分が作ったモデルを3Dプリントしようと思っています。

基板のケースや機構部品の加工ができそうです。
レーザー加工機のパラメータも大体の値は教えてもらったので、微調整すれば良さそうです。
  1. 2015年11月07日 08:34 |
  2. Make
  3. | トラックバック:0
  4. | コメント:0

フリーの高位合成ツール Synverll を試してみる3

フリーの高位合成ツール Synverll を試してみる2”の続き。

前回、不具合があって評価を中止していたが、11月5日にひでみさんが、”信号のつなぎ目を修正”で修正してくれたので、再度評価してみることにした。(ひでみさん、ありがとうございました)

VirtualBox 上の Ubuntu 14.04 LTS 上の synverll ディレクトリで、git pull を実行して、更新を反映させた。
Synverll_3_151107.png

make コマンドで Synverll を再度コンパイルした。
Synverll_4_151107.png

example/marsee_example1 に移動して、../../synverll marsee_example1.c mar_ex_top コマンドで合成を行った。
Synverll_5_151107.png

mar_ex_top.v を見ると、__arg_multi_in0, __arg_multi_in0, __arg_multi_out が 32 ビット長になっていて、正しくなった。
Synverll_6_151107.png

Vivado 2015.3 で ZYBO のプロジェクトを作製して、インプリメントしてみた。
Synverll_8_151107.png

インプリメント結果はやはり、IOがオーバーしている。
Synverll_9_151107.png

信号のつなぎ目を修正”のテストベンチ tb.v を流用してシミュレーションをしてみた。
Synverll_7_151107.png
__gm_di[31:0] と __gm_do[31:0] を符号なし十進数にした。__gm_di の2乗が __gm_do に出力されているのが分かる。

新しい mar_ex_top.v を貼っておく。
/*
 * Copyright (C)2005-2015 AQUAXIS TECHNOLOGY.
 *  Don't remove this header.
 * When you use this source, there is a need to inherit this header.
 *
 * This software is released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 *
 * For further information please contact.
 *  URI:    http://www.aquaxis.com/
 *  E-Mail: info(at)aquaxis.com
 */
module mar_ex_top(
input system_clock,
input system_reset,
input __func_start,
output __func_done,
output __func_ready,
output __gm_req,
output __gm_rnw,
input __gm_done,
output [31:0] __gm_adrs,
output [1:0] __gm_leng,
input [31:0] __gm_di,
output [31:0] __gm_do,
// global signal
input [31:0] __args_multi_in0,
input [31:0] __args_multi_in1,
input [31:0] __args_multi_out,
output dummy
);
// wire
wire marsee_example1__func_start;
wire marsee_example1__func_done;
wire marsee_example1__func_ready;
wire marsee_example1__gm_req;
wire marsee_example1__gm_rnw;
wire marsee_example1__gm_done;
wire [31:0] marsee_example1__gm_adrs;
wire [1:0] marsee_example1__gm_leng;
wire [31:0] marsee_example1__gm_di;
wire [31:0] marsee_example1__gm_do;
wire [31:0] marsee_example1__args_multi_in0;
wire [31:0] marsee_example1__args_multi_in1;
wire [31:0] marsee_example1__args_multi_out;
// connection
assign marsee_example1__gm_done = __gm_done;
assign marsee_example1__gm_di = __gm_di;
// Global Memory
assign __gm_req =  marsee_example1__gm_req ;
assign __gm_adrs =  marsee_example1__gm_adrs ;
assign __gm_rnw =  marsee_example1__gm_rnw ;
assign __gm_do =  marsee_example1__gm_do ;
assign __gm_leng =  marsee_example1__gm_leng ;
// system signal
assign marsee_example1__func_start = __func_start;
assign __func_done = marsee_example1__func_done;
assign __func_ready = marsee_example1__func_ready;
assign marsee_example1__args_multi_in0 = __args_multi_in0;
assign marsee_example1__args_multi_in1 = __args_multi_in1;
assign marsee_example1__args_multi_out = __args_multi_out;
// modules
marsee_example1 u_marsee_example1(
// system signals
.__func_clock(system_clock),
.__func_reset(system_reset),
.__func_start(marsee_example1__func_start),
.__func_done(marsee_example1__func_done),
.__func_ready(marsee_example1__func_ready),
// memory bus
.__gm_req(marsee_example1__gm_req),
.__gm_rnw(marsee_example1__gm_rnw),
.__gm_done(marsee_example1__gm_done),
.__gm_adrs(marsee_example1__gm_adrs),
.__gm_leng(marsee_example1__gm_leng),
.__gm_di(marsee_example1__gm_di),
.__gm_do(marsee_example1__gm_do),
// base address
// arguments
.__args_multi_in0(marsee_example1__args_multi_in0),
.__args_multi_in1(marsee_example1__args_multi_in1),
.__args_multi_out(marsee_example1__args_multi_out),
// call instruction
.__dummy()
);
endmodule

marsee_example1.v を貼っておく。
/*
 * Copyright (C)2005-2015 AQUAXIS TECHNOLOGY.
 *  Don't remove this header.
 * When you use this source, there is a need to inherit this header.
 *
 * This software is released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 *
 * For further information please contact.
 *  URI:    http://www.aquaxis.com/
 *  E-Mail: info(at)aquaxis.com
 */
module marsee_example1(
input __func_clock,
input __func_reset,
input __func_start,
output reg __func_done,
output reg __func_ready,
output reg __gm_req,
output reg __gm_rnw,
input __gm_done,
output reg [31:0] __gm_adrs,
output reg [1:0] __gm_leng,
input [31:0] __gm_di,
output reg [31:0] __gm_do,
// Memory Singal
input [31:0] __args_multi_in0,
input [31:0] __args_multi_in1,
input [31:0] __args_multi_out,
// Call Singal
output reg __dummy
);
reg [31:0] __sig_0;
reg [31:0] __sig_1;
reg [31:0] __sig_mul;
wire [31:0] __sig_arrayidx_1;
reg [31:0] __sig_2;
wire [31:0] __sig_arrayidx1_1;
reg [31:0] __sig_3;
reg [31:0] __sig_mul_1;
wire [31:0] __sig_arrayidx2_1;
wire [31:0] __sig_arrayidx_2;
reg [31:0] __sig_4;
wire [31:0] __sig_arrayidx1_2;
reg [31:0] __sig_5;
reg [31:0] __sig_mul_2;
wire [31:0] __sig_arrayidx2_2;
wire [31:0] __sig_arrayidx_3;
reg [31:0] __sig_6;
wire [31:0] __sig_arrayidx1_3;
reg [31:0] __sig_7;
reg [31:0] __sig_mul_3;
wire [31:0] __sig_arrayidx2_3;
wire [31:0] __sig_arrayidx_4;
reg [31:0] __sig_8;
wire [31:0] __sig_arrayidx1_4;
reg [31:0] __sig_9;
reg [31:0] __sig_mul_4;
wire [31:0] __sig_arrayidx2_4;
wire [31:0] __sig_arrayidx_5;
reg [31:0] __sig_10;
wire [31:0] __sig_arrayidx1_5;
reg [31:0] __sig_11;
reg [31:0] __sig_mul_5;
wire [31:0] __sig_arrayidx2_5;
wire [31:0] __sig_arrayidx_6;
reg [31:0] __sig_12;
wire [31:0] __sig_arrayidx1_6;
reg [31:0] __sig_13;
reg [31:0] __sig_mul_6;
wire [31:0] __sig_arrayidx2_6;
wire [31:0] __sig_arrayidx_7;
reg [31:0] __sig_14;
wire [31:0] __sig_arrayidx1_7;
reg [31:0] __sig_15;
reg [31:0] __sig_mul_7;
wire [31:0] __sig_arrayidx2_7;
wire [31:0] __sig_arrayidx_8;
reg [31:0] __sig_16;
wire [31:0] __sig_arrayidx1_8;
reg [31:0] __sig_17;
reg [31:0] __sig_mul_8;
wire [31:0] __sig_arrayidx2_8;
wire [31:0] __sig_arrayidx_9;
reg [31:0] __sig_18;
wire [31:0] __sig_arrayidx1_9;
reg [31:0] __sig_19;
reg [31:0] __sig_mul_9;
wire [31:0] __sig_arrayidx2_9;
assign __sig_arrayidx_1 = (__sig_multi_in0 + (1));
assign __sig_arrayidx1_1 = (__sig_multi_in1 + (1));
assign __sig_arrayidx2_1 = (__sig_multi_out + (1));
assign __sig_arrayidx_2 = (__sig_multi_in0 + (2));
assign __sig_arrayidx1_2 = (__sig_multi_in1 + (2));
assign __sig_arrayidx2_2 = (__sig_multi_out + (2));
assign __sig_arrayidx_3 = (__sig_multi_in0 + (3));
assign __sig_arrayidx1_3 = (__sig_multi_in1 + (3));
assign __sig_arrayidx2_3 = (__sig_multi_out + (3));
assign __sig_arrayidx_4 = (__sig_multi_in0 + (4));
assign __sig_arrayidx1_4 = (__sig_multi_in1 + (4));
assign __sig_arrayidx2_4 = (__sig_multi_out + (4));
assign __sig_arrayidx_5 = (__sig_multi_in0 + (5));
assign __sig_arrayidx1_5 = (__sig_multi_in1 + (5));
assign __sig_arrayidx2_5 = (__sig_multi_out + (5));
assign __sig_arrayidx_6 = (__sig_multi_in0 + (6));
assign __sig_arrayidx1_6 = (__sig_multi_in1 + (6));
assign __sig_arrayidx2_6 = (__sig_multi_out + (6));
assign __sig_arrayidx_7 = (__sig_multi_in0 + (7));
assign __sig_arrayidx1_7 = (__sig_multi_in1 + (7));
assign __sig_arrayidx2_7 = (__sig_multi_out + (7));
assign __sig_arrayidx_8 = (__sig_multi_in0 + (8));
assign __sig_arrayidx1_8 = (__sig_multi_in1 + (8));
assign __sig_arrayidx2_8 = (__sig_multi_out + (8));
assign __sig_arrayidx_9 = (__sig_multi_in0 + (9));
assign __sig_arrayidx1_9 = (__sig_multi_in1 + (9));
assign __sig_arrayidx2_9 = (__sig_multi_out + (9));
reg [31:0] __sig_multi_in0;
reg [31:0] __sig_multi_in1;
reg [31:0] __sig_multi_out;
localparam __state_fin_exec = 0;
localparam __state_start_req = 1;
localparam __state_start_wait = 2;
localparam __state_start_exec = 3;
localparam __state_1_exec = 4;
localparam __state_2_exec = 5;
localparam __state_3_req = 6;
localparam __state_3_wait = 7;
localparam __state_3_exec = 8;
localparam __state_4_req = 9;
localparam __state_4_wait = 10;
localparam __state_4_exec = 11;
localparam __state_5_exec = 12;
localparam __state_6_req = 13;
localparam __state_6_wait = 14;
localparam __state_6_exec = 15;
localparam __state_7_req = 16;
localparam __state_7_wait = 17;
localparam __state_7_exec = 18;
localparam __state_8_req = 19;
localparam __state_8_wait = 20;
localparam __state_8_exec = 21;
localparam __state_9_exec = 22;
localparam __state_10_req = 23;
localparam __state_10_wait = 24;
localparam __state_10_exec = 25;
localparam __state_11_req = 26;
localparam __state_11_wait = 27;
localparam __state_11_exec = 28;
localparam __state_12_req = 29;
localparam __state_12_wait = 30;
localparam __state_12_exec = 31;
localparam __state_13_exec = 32;
localparam __state_14_req = 33;
localparam __state_14_wait = 34;
localparam __state_14_exec = 35;
localparam __state_15_req = 36;
localparam __state_15_wait = 37;
localparam __state_15_exec = 38;
localparam __state_16_req = 39;
localparam __state_16_wait = 40;
localparam __state_16_exec = 41;
localparam __state_17_exec = 42;
localparam __state_18_req = 43;
localparam __state_18_wait = 44;
localparam __state_18_exec = 45;
localparam __state_19_req = 46;
localparam __state_19_wait = 47;
localparam __state_19_exec = 48;
localparam __state_20_req = 49;
localparam __state_20_wait = 50;
localparam __state_20_exec = 51;
localparam __state_21_exec = 52;
localparam __state_22_req = 53;
localparam __state_22_wait = 54;
localparam __state_22_exec = 55;
localparam __state_23_req = 56;
localparam __state_23_wait = 57;
localparam __state_23_exec = 58;
localparam __state_24_req = 59;
localparam __state_24_wait = 60;
localparam __state_24_exec = 61;
localparam __state_25_exec = 62;
localparam __state_26_req = 63;
localparam __state_26_wait = 64;
localparam __state_26_exec = 65;
localparam __state_27_req = 66;
localparam __state_27_wait = 67;
localparam __state_27_exec = 68;
localparam __state_28_req = 69;
localparam __state_28_wait = 70;
localparam __state_28_exec = 71;
localparam __state_29_exec = 72;
localparam __state_30_req = 73;
localparam __state_30_wait = 74;
localparam __state_30_exec = 75;
localparam __state_31_req = 76;
localparam __state_31_wait = 77;
localparam __state_31_exec = 78;
localparam __state_32_req = 79;
localparam __state_32_wait = 80;
localparam __state_32_exec = 81;
localparam __state_33_exec = 82;
localparam __state_34_req = 83;
localparam __state_34_wait = 84;
localparam __state_34_exec = 85;
localparam __state_35_req = 86;
localparam __state_35_wait = 87;
localparam __state_35_exec = 88;
localparam __state_36_req = 89;
localparam __state_36_wait = 90;
localparam __state_36_exec = 91;
localparam __state_37_exec = 92;
localparam __state_38_req = 93;
localparam __state_38_wait = 94;
localparam __state_38_exec = 95;
localparam __state_39_req = 96;
localparam __state_39_wait = 97;
localparam __state_39_exec = 98;
localparam __state_40_req = 99;
localparam __state_40_wait = 100;
localparam __state_40_exec = 101;
localparam __state_41_exec = 102;
localparam __state_42_req = 103;
localparam __state_42_wait = 104;
localparam __state_42_exec = 105;
localparam __state_43_exec = 106;
localparam __state_44_exec = 107;
integer __state;
localparam __label_0 = 0;
localparam __label_entry = 2;
integer __label;
always @(posedge __func_clock or negedge __func_reset) begin
if(!__func_reset) begin
__state <= __state_start_req;
__func_ready <= 1;
__func_done <= 0;
end else begin
case(__state)
__state_start_req: begin
__state <= __state_start_wait;
end
__state_start_wait: begin
if(__func_start) begin
__state <= __state_start_exec;
__func_ready <= 0;
__func_done <= 0;
__sig_multi_in0 <= __args_multi_in0;
__sig_multi_in1 <= __args_multi_in1;
__sig_multi_out <= __args_multi_out;
end
end
__state_start_exec: begin
__state <= __state_1_exec;
end
__state_1_exec: begin
__state <= __state_2_exec;
end
__state_2_exec: begin
__state <= __state_3_req;
__label <= __label_entry;
end
__state_3_req: begin
__state <= __state_3_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_multi_in0);
__gm_leng <= 3;
end
__state_3_wait: begin
if((__gm_done == 1)) begin
__state <= __state_3_exec;
end
__gm_req <= 0;
end
__state_3_exec: begin
__state <= __state_4_req;
__sig_0 <= __gm_di;
end
__state_4_req: begin
__state <= __state_4_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_multi_in1);
__gm_leng <= 3;
end
__state_4_wait: begin
if((__gm_done == 1)) begin
__state <= __state_4_exec;
end
__gm_req <= 0;
end
__state_4_exec: begin
__state <= __state_5_exec;
__sig_1 <= __gm_di;
end
__state_5_exec: begin
__state <= __state_6_req;
__sig_mul <= $signed(__sig_1) * $signed(__sig_0);
end
__state_6_req: begin
__state <= __state_6_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_multi_out);
__gm_leng <= 3;
__gm_do <= __sig_mul;
end
__state_6_wait: begin
if((__gm_done == 1)) begin
__state <= __state_6_exec;
end
__gm_req <= 0;
end
__state_6_exec: begin
__state <= __state_7_req;
end
__state_7_req: begin
__state <= __state_7_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_1);
__gm_leng <= 3;
end
__state_7_wait: begin
if((__gm_done == 1)) begin
__state <= __state_7_exec;
end
__gm_req <= 0;
end
__state_7_exec: begin
__state <= __state_8_req;
__sig_2 <= __gm_di;
end
__state_8_req: begin
__state <= __state_8_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_1);
__gm_leng <= 3;
end
__state_8_wait: begin
if((__gm_done == 1)) begin
__state <= __state_8_exec;
end
__gm_req <= 0;
end
__state_8_exec: begin
__state <= __state_9_exec;
__sig_3 <= __gm_di;
end
__state_9_exec: begin
__state <= __state_10_req;
__sig_mul_1 <= $signed(__sig_3) * $signed(__sig_2);
end
__state_10_req: begin
__state <= __state_10_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_1);
__gm_leng <= 3;
__gm_do <= __sig_mul_1;
end
__state_10_wait: begin
if((__gm_done == 1)) begin
__state <= __state_10_exec;
end
__gm_req <= 0;
end
__state_10_exec: begin
__state <= __state_11_req;
end
__state_11_req: begin
__state <= __state_11_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_2);
__gm_leng <= 3;
end
__state_11_wait: begin
if((__gm_done == 1)) begin
__state <= __state_11_exec;
end
__gm_req <= 0;
end
__state_11_exec: begin
__state <= __state_12_req;
__sig_4 <= __gm_di;
end
__state_12_req: begin
__state <= __state_12_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_2);
__gm_leng <= 3;
end
__state_12_wait: begin
if((__gm_done == 1)) begin
__state <= __state_12_exec;
end
__gm_req <= 0;
end
__state_12_exec: begin
__state <= __state_13_exec;
__sig_5 <= __gm_di;
end
__state_13_exec: begin
__state <= __state_14_req;
__sig_mul_2 <= $signed(__sig_5) * $signed(__sig_4);
end
__state_14_req: begin
__state <= __state_14_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_2);
__gm_leng <= 3;
__gm_do <= __sig_mul_2;
end
__state_14_wait: begin
if((__gm_done == 1)) begin
__state <= __state_14_exec;
end
__gm_req <= 0;
end
__state_14_exec: begin
__state <= __state_15_req;
end
__state_15_req: begin
__state <= __state_15_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_3);
__gm_leng <= 3;
end
__state_15_wait: begin
if((__gm_done == 1)) begin
__state <= __state_15_exec;
end
__gm_req <= 0;
end
__state_15_exec: begin
__state <= __state_16_req;
__sig_6 <= __gm_di;
end
__state_16_req: begin
__state <= __state_16_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_3);
__gm_leng <= 3;
end
__state_16_wait: begin
if((__gm_done == 1)) begin
__state <= __state_16_exec;
end
__gm_req <= 0;
end
__state_16_exec: begin
__state <= __state_17_exec;
__sig_7 <= __gm_di;
end
__state_17_exec: begin
__state <= __state_18_req;
__sig_mul_3 <= $signed(__sig_7) * $signed(__sig_6);
end
__state_18_req: begin
__state <= __state_18_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_3);
__gm_leng <= 3;
__gm_do <= __sig_mul_3;
end
__state_18_wait: begin
if((__gm_done == 1)) begin
__state <= __state_18_exec;
end
__gm_req <= 0;
end
__state_18_exec: begin
__state <= __state_19_req;
end
__state_19_req: begin
__state <= __state_19_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_4);
__gm_leng <= 3;
end
__state_19_wait: begin
if((__gm_done == 1)) begin
__state <= __state_19_exec;
end
__gm_req <= 0;
end
__state_19_exec: begin
__state <= __state_20_req;
__sig_8 <= __gm_di;
end
__state_20_req: begin
__state <= __state_20_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_4);
__gm_leng <= 3;
end
__state_20_wait: begin
if((__gm_done == 1)) begin
__state <= __state_20_exec;
end
__gm_req <= 0;
end
__state_20_exec: begin
__state <= __state_21_exec;
__sig_9 <= __gm_di;
end
__state_21_exec: begin
__state <= __state_22_req;
__sig_mul_4 <= $signed(__sig_9) * $signed(__sig_8);
end
__state_22_req: begin
__state <= __state_22_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_4);
__gm_leng <= 3;
__gm_do <= __sig_mul_4;
end
__state_22_wait: begin
if((__gm_done == 1)) begin
__state <= __state_22_exec;
end
__gm_req <= 0;
end
__state_22_exec: begin
__state <= __state_23_req;
end
__state_23_req: begin
__state <= __state_23_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_5);
__gm_leng <= 3;
end
__state_23_wait: begin
if((__gm_done == 1)) begin
__state <= __state_23_exec;
end
__gm_req <= 0;
end
__state_23_exec: begin
__state <= __state_24_req;
__sig_10 <= __gm_di;
end
__state_24_req: begin
__state <= __state_24_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_5);
__gm_leng <= 3;
end
__state_24_wait: begin
if((__gm_done == 1)) begin
__state <= __state_24_exec;
end
__gm_req <= 0;
end
__state_24_exec: begin
__state <= __state_25_exec;
__sig_11 <= __gm_di;
end
__state_25_exec: begin
__state <= __state_26_req;
__sig_mul_5 <= $signed(__sig_11) * $signed(__sig_10);
end
__state_26_req: begin
__state <= __state_26_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_5);
__gm_leng <= 3;
__gm_do <= __sig_mul_5;
end
__state_26_wait: begin
if((__gm_done == 1)) begin
__state <= __state_26_exec;
end
__gm_req <= 0;
end
__state_26_exec: begin
__state <= __state_27_req;
end
__state_27_req: begin
__state <= __state_27_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_6);
__gm_leng <= 3;
end
__state_27_wait: begin
if((__gm_done == 1)) begin
__state <= __state_27_exec;
end
__gm_req <= 0;
end
__state_27_exec: begin
__state <= __state_28_req;
__sig_12 <= __gm_di;
end
__state_28_req: begin
__state <= __state_28_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_6);
__gm_leng <= 3;
end
__state_28_wait: begin
if((__gm_done == 1)) begin
__state <= __state_28_exec;
end
__gm_req <= 0;
end
__state_28_exec: begin
__state <= __state_29_exec;
__sig_13 <= __gm_di;
end
__state_29_exec: begin
__state <= __state_30_req;
__sig_mul_6 <= $signed(__sig_13) * $signed(__sig_12);
end
__state_30_req: begin
__state <= __state_30_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_6);
__gm_leng <= 3;
__gm_do <= __sig_mul_6;
end
__state_30_wait: begin
if((__gm_done == 1)) begin
__state <= __state_30_exec;
end
__gm_req <= 0;
end
__state_30_exec: begin
__state <= __state_31_req;
end
__state_31_req: begin
__state <= __state_31_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_7);
__gm_leng <= 3;
end
__state_31_wait: begin
if((__gm_done == 1)) begin
__state <= __state_31_exec;
end
__gm_req <= 0;
end
__state_31_exec: begin
__state <= __state_32_req;
__sig_14 <= __gm_di;
end
__state_32_req: begin
__state <= __state_32_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_7);
__gm_leng <= 3;
end
__state_32_wait: begin
if((__gm_done == 1)) begin
__state <= __state_32_exec;
end
__gm_req <= 0;
end
__state_32_exec: begin
__state <= __state_33_exec;
__sig_15 <= __gm_di;
end
__state_33_exec: begin
__state <= __state_34_req;
__sig_mul_7 <= $signed(__sig_15) * $signed(__sig_14);
end
__state_34_req: begin
__state <= __state_34_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_7);
__gm_leng <= 3;
__gm_do <= __sig_mul_7;
end
__state_34_wait: begin
if((__gm_done == 1)) begin
__state <= __state_34_exec;
end
__gm_req <= 0;
end
__state_34_exec: begin
__state <= __state_35_req;
end
__state_35_req: begin
__state <= __state_35_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_8);
__gm_leng <= 3;
end
__state_35_wait: begin
if((__gm_done == 1)) begin
__state <= __state_35_exec;
end
__gm_req <= 0;
end
__state_35_exec: begin
__state <= __state_36_req;
__sig_16 <= __gm_di;
end
__state_36_req: begin
__state <= __state_36_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_8);
__gm_leng <= 3;
end
__state_36_wait: begin
if((__gm_done == 1)) begin
__state <= __state_36_exec;
end
__gm_req <= 0;
end
__state_36_exec: begin
__state <= __state_37_exec;
__sig_17 <= __gm_di;
end
__state_37_exec: begin
__state <= __state_38_req;
__sig_mul_8 <= $signed(__sig_17) * $signed(__sig_16);
end
__state_38_req: begin
__state <= __state_38_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_8);
__gm_leng <= 3;
__gm_do <= __sig_mul_8;
end
__state_38_wait: begin
if((__gm_done == 1)) begin
__state <= __state_38_exec;
end
__gm_req <= 0;
end
__state_38_exec: begin
__state <= __state_39_req;
end
__state_39_req: begin
__state <= __state_39_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_9);
__gm_leng <= 3;
end
__state_39_wait: begin
if((__gm_done == 1)) begin
__state <= __state_39_exec;
end
__gm_req <= 0;
end
__state_39_exec: begin
__state <= __state_40_req;
__sig_18 <= __gm_di;
end
__state_40_req: begin
__state <= __state_40_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_9);
__gm_leng <= 3;
end
__state_40_wait: begin
if((__gm_done == 1)) begin
__state <= __state_40_exec;
end
__gm_req <= 0;
end
__state_40_exec: begin
__state <= __state_41_exec;
__sig_19 <= __gm_di;
end
__state_41_exec: begin
__state <= __state_42_req;
__sig_mul_9 <= $signed(__sig_19) * $signed(__sig_18);
end
__state_42_req: begin
__state <= __state_42_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_9);
__gm_leng <= 3;
__gm_do <= __sig_mul_9;
end
__state_42_wait: begin
if((__gm_done == 1)) begin
__state <= __state_42_exec;
end
__gm_req <= 0;
end
__state_42_exec: begin
__state <= __state_43_exec;
end
__state_43_exec: begin
__state <= __state_fin_exec;
end
__state_44_exec: begin
__state <= __state_fin_exec;
end
__state_fin_exec: begin
__state <= __state_start_req;
__func_ready <= 1;
__func_done <= 1;
end
endcase
end
end
endmodule
  1. 2015年11月07日 06:45 |
  2. Synverll
  3. | トラックバック:0
  4. | コメント:0

メールでの問い合わせ

メールでの問い合わせに関しては、名前程度は書いて頂きたいと思っています。

また、あまりに幅広い範囲の質問は、こちらもメールだけでは、お答えできませんし、そちらもわからないと思います。やはり、一朝一夕とは行かないので、地道にベースを引き上げる必要があると感じます。こちらが説明してもベースが無いとわからないと思います。
それを説明するのに、どれだけページ数が必要になるかわからないのです。こちらでもどのくらい分かっているか?分からないので。。。
まずは、ネットにいろいろとあるチュートリアルをやってみてはいかがでしょうか?それでピンポイントで私の記事に疑問がありましたら、質問をお受け致します。

ソフトウェアは、AXI GPIOのマニュアルとベースアドレスを見て直接叩く方法と、
GPIOのベアメタル・ドライバを使って使う方法とベアメタルでは2種類があると思います。
  1. 2015年11月05日 20:44 |
  2. その他のFPGAの話題
  3. | トラックバック:0
  4. | コメント:0

ZYBOにHDLで書いたラプラシアンフィルタを実装する9(devicetreeの生成、/sys, /devディレクトリ)

ZYBOにHDLで書いたラプラシアンフィルタを実装する8(ビットストリーム生成、BOOT,bin の生成)”の続き。

前回は、Vivado 2015.3 でストラテジーを変更したインプリメントを行って、タイミング制約を満足したインプリメント結果を使ってビットストリームを生成し、SDKを立ち上げて、BOOT.bin を生成した。
今回は、devicetree.dtb を生成して、Micro SDカードに、BOOT.bin と devicetree.dtb を書き込んで、ZYBOに挿入してUbuntu をブートし、/sys ディレクトリと /dev ディレクトリを観察する。

最初にZYBO用のデバイスツリーのソースコードを修正する。デバイスツリーのソースコードは元はDigilent-Linux をGitHub からclone した時に入っていたものだ。(Vivado and zybo linux勉強会資料3180ページ184ページ185ページ186ページ参照)
私のLinux環境は、VirtualBox にインストールした Ubuntu 14.04 なのだ。devicetree.dtb の生成は Ubuntu 14.04 上で行う。

・まずは、”Vivado HLS 2014.4でラプラシアン・フィルタ関数をaxi masterモジュールにする5(BOOT.bin, devicetree.dtb の生成)”で作った drivers_hls_lap_fil ディレクトリをコピーして、貼り付けし、名前を driver_hls_hdl_lap_fil と変更した。
lap_fil_HDL_axim_111_151104.png

・zynq-zybo.dts を gedit で編集して、lap_fil_hdl_axim の項を追加した。(UIO を使用する)
lap_fil_HDL_axim_112_151104.png
bitmap_display_cntrler_axim@43c00000 {
compatible = "generic-uio";
reg = < 0x43c00000 0x10000 >;
};
mt9d111_inf_axim@0x43c10000 {
compatible = "generic-uio";
reg = < 0x43c10000 0x10000 >;
};
mt9d111_axi_iic@0x41600000 {
compatible = "generic-uio";
reg = < 0x41600000 0x10000>;
};
frame_buffer_bmdc@0x17800000 {
compatible = "generic-uio";
reg = < 0x17800000 0x1000000>;
};
lap_filter_axim_hls@0x43c20000 {
compatible = "generic-uio";
reg = < 0x43c20000 0x10000>;
};
lap_fil_hdl_axim@0x43c30000 {
compatible = "generic-uio";
reg = < 0x43c30000 0x10000>;
};

・zynq-zybo.dts をセーブして閉じた。

・LX Terminal で drivers_hls_lap_fil ディレクトリに入った。

../Linux-Digilent-Dev/scripts/dtc/dtc -I dts -O dtb -o devicetree.dtb zynq-zybo.dts コマンドで、zynq-zybo.dts を dtc でコンパイルして、devicetree.dtb を生成した。
lap_fil_HDL_axim_113_151104.png

・ MicroSDカードの第1パーティション ZYBO_BOOT に、前回生成したBOOT.bin と devicetree.dtb をコピーした。
lap_fil_HDL_axim_114_151105.png

・ZYBO にMicroSDカードを挿入して、電源ONした。

・シリアルコンソールにブートメッセージが表示された。

ifconfig コマンドを実行して、DHCPで割り振られたIPアドレスを確認した。
lap_fil_HDL_axim_115_151105.png

・SSHで確認したIPアドレスにログインした。

cd /sys/devices/amba.0/
ls コマンドを実行した。物理アドレスとモジュールが見えた。今回追加したHDL で作製したラプラシアンフィルタIPは、43c30000.lap_fil_hdl_axim だ。以前のVivado HLS 2014.4 で作製したラプラシアンフィルタIPは、43c20000.lap_filter_axim_hls も見えている。
lap_fil_HDL_axim_116_151105.png

cd 43c30000.lap_fil_hdl_axim/
ls
コマンドを実行して、43c30000.lap_fil_hdl_axim ディレクトリに入って内容を見た。
lap_fil_HDL_axim_117_151105.png

cd uio
ls
cd uio5
ls
コマンドを実行して、uio/uio5 ディレクトリに入った。
lap_fil_HDL_axim_118_151105.png

cat name version uevent コマンドを実行した。
lap_fil_HDL_axim_119_151105.png

lap_fil_hdl_axim
devicetree
MAJOR=247
MINOR=5
DEVNAME=uio5


cd /dev
ls uio*
コマンドを実行して、/dev ディレクトリに入って、uio ファイルを見た。
lap_fil_HDL_axim_120_151105.png

・/home/linaro/Apps/lap_fil_hls_1shot ディレクトリに行って、./cam_disp_uio を実行したら、カメラの画像が表示された。
./lap_fil_hls_1shot を実行したら、ラプラシアンフィルタ処理が実行された。問題は無い。
lap_fil_HDL_axim_121_151105.png
  1. 2015年11月05日 04:48 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

フリーの高位合成ツール Synverll を試してみる2

”フリーの高位合成ツール Synverll を試してみる1”の続き。

前回、掛け算のソフトウェアを作って、Synverll で合成してVerilog HDL に変換した。
今回は、Vivado 2015.3 でプロジェクトを作ったのだが、Verilog HDLファイルをコピーしている時にバグらしいのに気づいてしまった。

それは、mar_ex_top.v で global_signal は次のように 1 ビットなのだが
// global signal
input __args_multi_in0,
input __args_multi_in1,
input __args_multi_out,
それらの信号は、marsee_example1.v の Memory Singal に接続されている。
// Memory Singal
input [31:0] __args_multi_in0,
input [31:0] __args_multi_in1,
input [31:0] __args_multi_out,

こちらは 32 ビット幅なので、1 ビットの信号を 32 ビットに接続してしまっている。これらの信号は、ステートマシンで、 __gm_adrs に入力されて、RAMのアドレスとして使われるようなので、1 ビットではまずいと思われる。
取りあえず、安定するまで評価を待つことにした。

  1. 2015年11月03日 18:35 |
  2. Synverll
  3. | トラックバック:0
  4. | コメント:0

ZYBOにHDLで書いたラプラシアンフィルタを実装する8(ビットストリーム生成、BOOT,bin の生成)

ZYBOにHDLで書いたラプラシアンフィルタを実装する7(インプリメント)”の続き。

前回はインプリメントは終了したが、タイミング違反が出ていた。
今回は、”Vivado 2014.4 でインプリメント時にStrategy を変更してインプリメント結果を改善する”を参考にして、同様にStrategy を変更してインプリメントを25個やってみて、一番良い物を取ろうと思う。その後、ビットストリームの生成を行ってから、ハードウェアをエクスポートしてSDKを立ちあげて、FSBLを作り、BOOT.bin を生成する。

ストラテジーを変更したインプリメントは、”Vivado 2014.4 でインプリメント時にStrategy を変更してインプリメント結果を改善する”の時に作ってあるので、今回は、それをそのまま使用する。

・Design Runs ので右クリックし、右クリックメニューから Launch Runs... を選択する。
lap_fil_HDL_axim_98_151101.png

・ Launch Runs ダイアログが表示された。OKボタンをクリックする。
lap_fil_HDL_axim_99_151101.png

・インプリメントが開始された。
lap_fil_HDL_axim_100_151101.png

・すべてのインプリメントが終了した。時間がかかる。寝る前にインプリメントを初めて、次の日の朝起きてから結果を見た。
lap_fil_HDL_axim_101_151102.png

・impl_1 が良さそうなので、impl_1 で右クリックし、右クリックメニューから Make Active を選択した。
lap_fil_HDL_axim_102_151102.png

・Project Summary にも、impl_1 の結果が反映されている。
lap_fil_HDL_axim_103_151102.png

・Flow Navigator -> Program and Debug -> Generate Bitstream を選択して、ビットストリームを生成した。
lap_fil_HDL_axim_104_151103.png

次は、ハードウェアをエクスポートして、SDKを起動する。

・Vivado 2015.3 のFile メニューからExprot -> Export Hardware... を選択する。

・Export Hardware ダイアログが表示される。Include bitstream にチェックを入れてOKボタンをクリックする。
lap_fil_HDL_axim_105_151103.png

・File メニューからLaunch SDK を選択し、SDKを立ち上げる。
lap_fil_HDL_axim_106_151103.png

・SDKが立ち上がった。V_ZYBO_CAMDfL_wapper_hw_platform_0 ができた。
lap_fil_HDL_axim_107_151103.png

・すでにFSBL プロジェクトはあるが、プラットフォームが違うので、FSBL プロジェクトを一旦削除して、V_ZYBO_CAMDfL_wapper_hw_platform_0 をプラットフォームとして作り直した。

・V_ZYBO_CAMDfL_wapper_hw_platform_2 プラットフォームを削除した。
lap_fil_HDL_axim_110_151103.png

・Project Exploer 上でFSBL を右クリックし、右クリックメニューからCreate Boot Image を選択した。

・Creater Zynq Boot Image ダイアログが開いた。u-boot.elf を追加してから、Create Image ボタンをクリックした。
lap_fil_HDL_axim_108_151103.png

・BOOT.bin が再生成された。

・Z:\V_ZYBO_CAMDfL153_tu_HDL\V_ZYBO_CAMDfL143.sdk\FSBL\bootimage にBOOT.bin が生成されている。
lap_fil_HDL_axim_109_151103.png
  1. 2015年11月03日 05:23 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

フリーの高位合成ツール Synverll を試してみる1

FPGAマガジン No.1195 ページからに載っている石原ひでみさんの書いたC言語による高位合成ツールのSynverll を試してみることにした。

Synvell はGoogle で検索してもわかるがGitHub に公開されている

私のVirtualBox 上にインストールしたUbuntu のバージョンは 14.04 なので、apt-get コマンドでは LLVM 3.4 がインストールされる。そこで、FPGAマガジン No.11 で書かれた手順でLLVM 3.6 のソースコードからインストールを行って、夜からやって朝までコンパイルに時間がかかったが、無事に終了した。

Synvell のGitHub から git clone を行った。

次に、FPGAマガジン No.11 で書かれた手順で Synverll 自体をコンパイルした。

これで、Synverll が使えるようになった。

synverll ディレクトリの example ディレクトリに marsee_example1 ディレクトリを作製した。

marsee_example1 ディレクトリの下に、marsee_example1.c を作製した。
Synverll_1_151102.png

marsee_example1.c を下に示す。(2015/11/03:修正)
// marsee_example1.c
// 掛け算サンプル
//
#define ARRAY_LIMIT 10
int marsee_example1(int multi_in0[ARRAY_LIMIT], int multi_in1[ARRAY_LIMIT], int multi_out[ARRAY_LIMIT]){
int i;
for (i=0; i<ARRAY_LIMIT; i++){
multi_out[i] = multi_in0[i] * multi_in1[i];
}
return 0;
}
これを、 marsee_example1 ディレクトリ上で ../../synverll marsee_example1.c mar_ex_top コマンドでC言語からの高位合成を行った。
mar_ex_top.v と memory_map.txt 、mar_ex_top.v が生成された。
Synverll_2_151102.png

mar_ex_top.v を下に示す。
/*
 * Copyright (C)2005-2015 AQUAXIS TECHNOLOGY.
 *  Don't remove this header.
 * When you use this source, there is a need to inherit this header.
 *
 * This software is released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 *
 * For further information please contact.
 *  URI:    http://www.aquaxis.com/
 *  E-Mail: info(at)aquaxis.com
 */
module mar_ex_top(
input system_clock,
input system_reset,
input __func_start,
output __func_done,
output __func_ready,
output __gm_req,
output __gm_rnw,
input __gm_done,
output [31:0] __gm_adrs,
output [1:0] __gm_leng,
input [31:0] __gm_di,
output [31:0] __gm_do,
// global signal
input __args_multi_in0,
input __args_multi_in1,
input __args_multi_out,
output dummy
);
// wire
wire marsee_example1__func_start;
wire marsee_example1__func_done;
wire marsee_example1__func_ready;
wire marsee_example1__gm_req;
wire marsee_example1__gm_rnw;
wire marsee_example1__gm_done;
wire [31:0] marsee_example1__gm_adrs;
wire [1:0] marsee_example1__gm_leng;
wire [31:0] marsee_example1__gm_di;
wire [31:0] marsee_example1__gm_do;
wire marsee_example1__args_multi_in0;
wire marsee_example1__args_multi_in1;
wire marsee_example1__args_multi_out;
// connection
assign marsee_example1__gm_done = __gm_done;
assign marsee_example1__gm_di = __gm_di;
// Global Memory
assign __gm_req =  marsee_example1__gm_req ;
assign __gm_adrs =  marsee_example1__gm_adrs ;
assign __gm_rnw =  marsee_example1__gm_rnw ;
assign __gm_do =  marsee_example1__gm_do ;
assign __gm_leng =  marsee_example1__gm_leng ;
// system signal
assign marsee_example1__func_start = __func_start;
assign __func_done = marsee_example1__func_done;
assign __func_ready = marsee_example1__func_ready;
assign marsee_example1__args_multi_in0 = __args_multi_in0;
assign marsee_example1__args_multi_in1 = __args_multi_in1;
assign marsee_example1__args_multi_out = __args_multi_out;
// modules
marsee_example1 u_marsee_example1(
// system signals
.__func_clock(system_clock),
.__func_reset(system_reset),
.__func_start(marsee_example1__func_start),
.__func_done(marsee_example1__func_done),
.__func_ready(marsee_example1__func_ready),
// memory bus
.__gm_req(marsee_example1__gm_req),
.__gm_rnw(marsee_example1__gm_rnw),
.__gm_done(marsee_example1__gm_done),
.__gm_adrs(marsee_example1__gm_adrs),
.__gm_leng(marsee_example1__gm_leng),
.__gm_di(marsee_example1__gm_di),
.__gm_do(marsee_example1__gm_do),
// base address
// arguments
.__args_multi_in0(marsee_example1__args_multi_in0),
.__args_multi_in1(marsee_example1__args_multi_in1),
.__args_multi_out(marsee_example1__args_multi_out),
// call instruction
.__dummy()
);
endmodule

marsee_example1.v を下に示す。
/*
 * Copyright (C)2005-2015 AQUAXIS TECHNOLOGY.
 *  Don't remove this header.
 * When you use this source, there is a need to inherit this header.
 *
 * This software is released under the MIT License.
 * http://opensource.org/licenses/mit-license.php
 *
 * For further information please contact.
 *  URI:    http://www.aquaxis.com/
 *  E-Mail: info(at)aquaxis.com
 */
module marsee_example1(
input __func_clock,
input __func_reset,
input __func_start,
output reg __func_done,
output reg __func_ready,
output reg __gm_req,
output reg __gm_rnw,
input __gm_done,
output reg [31:0] __gm_adrs,
output reg [1:0] __gm_leng,
input [31:0] __gm_di,
output reg [31:0] __gm_do,
// Memory Singal
input [31:0] __args_multi_in0,
input [31:0] __args_multi_in1,
input [31:0] __args_multi_out,
// Call Singal
output reg __dummy
);
reg [31:0] __sig_0;
reg [31:0] __sig_1;
reg [31:0] __sig_mul;
wire [31:0] __sig_arrayidx_1;
reg [31:0] __sig_2;
wire [31:0] __sig_arrayidx1_1;
reg [31:0] __sig_3;
reg [31:0] __sig_mul_1;
wire [31:0] __sig_arrayidx2_1;
wire [31:0] __sig_arrayidx_2;
reg [31:0] __sig_4;
wire [31:0] __sig_arrayidx1_2;
reg [31:0] __sig_5;
reg [31:0] __sig_mul_2;
wire [31:0] __sig_arrayidx2_2;
wire [31:0] __sig_arrayidx_3;
reg [31:0] __sig_6;
wire [31:0] __sig_arrayidx1_3;
reg [31:0] __sig_7;
reg [31:0] __sig_mul_3;
wire [31:0] __sig_arrayidx2_3;
wire [31:0] __sig_arrayidx_4;
reg [31:0] __sig_8;
wire [31:0] __sig_arrayidx1_4;
reg [31:0] __sig_9;
reg [31:0] __sig_mul_4;
wire [31:0] __sig_arrayidx2_4;
wire [31:0] __sig_arrayidx_5;
reg [31:0] __sig_10;
wire [31:0] __sig_arrayidx1_5;
reg [31:0] __sig_11;
reg [31:0] __sig_mul_5;
wire [31:0] __sig_arrayidx2_5;
wire [31:0] __sig_arrayidx_6;
reg [31:0] __sig_12;
wire [31:0] __sig_arrayidx1_6;
reg [31:0] __sig_13;
reg [31:0] __sig_mul_6;
wire [31:0] __sig_arrayidx2_6;
wire [31:0] __sig_arrayidx_7;
reg [31:0] __sig_14;
wire [31:0] __sig_arrayidx1_7;
reg [31:0] __sig_15;
reg [31:0] __sig_mul_7;
wire [31:0] __sig_arrayidx2_7;
wire [31:0] __sig_arrayidx_8;
reg [31:0] __sig_16;
wire [31:0] __sig_arrayidx1_8;
reg [31:0] __sig_17;
reg [31:0] __sig_mul_8;
wire [31:0] __sig_arrayidx2_8;
wire [31:0] __sig_arrayidx_9;
reg [31:0] __sig_18;
wire [31:0] __sig_arrayidx1_9;
reg [31:0] __sig_19;
reg [31:0] __sig_mul_9;
wire [31:0] __sig_arrayidx2_9;
assign __sig_arrayidx_1 = (__sig_multi_in0 + (1));
assign __sig_arrayidx1_1 = (__sig_multi_in1 + (1));
assign __sig_arrayidx2_1 = (__sig_multi_out + (1));
assign __sig_arrayidx_2 = (__sig_multi_in0 + (2));
assign __sig_arrayidx1_2 = (__sig_multi_in1 + (2));
assign __sig_arrayidx2_2 = (__sig_multi_out + (2));
assign __sig_arrayidx_3 = (__sig_multi_in0 + (3));
assign __sig_arrayidx1_3 = (__sig_multi_in1 + (3));
assign __sig_arrayidx2_3 = (__sig_multi_out + (3));
assign __sig_arrayidx_4 = (__sig_multi_in0 + (4));
assign __sig_arrayidx1_4 = (__sig_multi_in1 + (4));
assign __sig_arrayidx2_4 = (__sig_multi_out + (4));
assign __sig_arrayidx_5 = (__sig_multi_in0 + (5));
assign __sig_arrayidx1_5 = (__sig_multi_in1 + (5));
assign __sig_arrayidx2_5 = (__sig_multi_out + (5));
assign __sig_arrayidx_6 = (__sig_multi_in0 + (6));
assign __sig_arrayidx1_6 = (__sig_multi_in1 + (6));
assign __sig_arrayidx2_6 = (__sig_multi_out + (6));
assign __sig_arrayidx_7 = (__sig_multi_in0 + (7));
assign __sig_arrayidx1_7 = (__sig_multi_in1 + (7));
assign __sig_arrayidx2_7 = (__sig_multi_out + (7));
assign __sig_arrayidx_8 = (__sig_multi_in0 + (8));
assign __sig_arrayidx1_8 = (__sig_multi_in1 + (8));
assign __sig_arrayidx2_8 = (__sig_multi_out + (8));
assign __sig_arrayidx_9 = (__sig_multi_in0 + (9));
assign __sig_arrayidx1_9 = (__sig_multi_in1 + (9));
assign __sig_arrayidx2_9 = (__sig_multi_out + (9));
reg [31:0] __sig_multi_in0;
reg [31:0] __sig_multi_in1;
reg [31:0] __sig_multi_out;
localparam __state_fin_exec = 0;
localparam __state_start_req = 1;
localparam __state_start_wait = 2;
localparam __state_start_exec = 3;
localparam __state_1_exec = 4;
localparam __state_2_exec = 5;
localparam __state_3_req = 6;
localparam __state_3_wait = 7;
localparam __state_3_exec = 8;
localparam __state_4_req = 9;
localparam __state_4_wait = 10;
localparam __state_4_exec = 11;
localparam __state_5_exec = 12;
localparam __state_6_req = 13;
localparam __state_6_wait = 14;
localparam __state_6_exec = 15;
localparam __state_7_req = 16;
localparam __state_7_wait = 17;
localparam __state_7_exec = 18;
localparam __state_8_req = 19;
localparam __state_8_wait = 20;
localparam __state_8_exec = 21;
localparam __state_9_exec = 22;
localparam __state_10_req = 23;
localparam __state_10_wait = 24;
localparam __state_10_exec = 25;
localparam __state_11_req = 26;
localparam __state_11_wait = 27;
localparam __state_11_exec = 28;
localparam __state_12_req = 29;
localparam __state_12_wait = 30;
localparam __state_12_exec = 31;
localparam __state_13_exec = 32;
localparam __state_14_req = 33;
localparam __state_14_wait = 34;
localparam __state_14_exec = 35;
localparam __state_15_req = 36;
localparam __state_15_wait = 37;
localparam __state_15_exec = 38;
localparam __state_16_req = 39;
localparam __state_16_wait = 40;
localparam __state_16_exec = 41;
localparam __state_17_exec = 42;
localparam __state_18_req = 43;
localparam __state_18_wait = 44;
localparam __state_18_exec = 45;
localparam __state_19_req = 46;
localparam __state_19_wait = 47;
localparam __state_19_exec = 48;
localparam __state_20_req = 49;
localparam __state_20_wait = 50;
localparam __state_20_exec = 51;
localparam __state_21_exec = 52;
localparam __state_22_req = 53;
localparam __state_22_wait = 54;
localparam __state_22_exec = 55;
localparam __state_23_req = 56;
localparam __state_23_wait = 57;
localparam __state_23_exec = 58;
localparam __state_24_req = 59;
localparam __state_24_wait = 60;
localparam __state_24_exec = 61;
localparam __state_25_exec = 62;
localparam __state_26_req = 63;
localparam __state_26_wait = 64;
localparam __state_26_exec = 65;
localparam __state_27_req = 66;
localparam __state_27_wait = 67;
localparam __state_27_exec = 68;
localparam __state_28_req = 69;
localparam __state_28_wait = 70;
localparam __state_28_exec = 71;
localparam __state_29_exec = 72;
localparam __state_30_req = 73;
localparam __state_30_wait = 74;
localparam __state_30_exec = 75;
localparam __state_31_req = 76;
localparam __state_31_wait = 77;
localparam __state_31_exec = 78;
localparam __state_32_req = 79;
localparam __state_32_wait = 80;
localparam __state_32_exec = 81;
localparam __state_33_exec = 82;
localparam __state_34_req = 83;
localparam __state_34_wait = 84;
localparam __state_34_exec = 85;
localparam __state_35_req = 86;
localparam __state_35_wait = 87;
localparam __state_35_exec = 88;
localparam __state_36_req = 89;
localparam __state_36_wait = 90;
localparam __state_36_exec = 91;
localparam __state_37_exec = 92;
localparam __state_38_req = 93;
localparam __state_38_wait = 94;
localparam __state_38_exec = 95;
localparam __state_39_req = 96;
localparam __state_39_wait = 97;
localparam __state_39_exec = 98;
localparam __state_40_req = 99;
localparam __state_40_wait = 100;
localparam __state_40_exec = 101;
localparam __state_41_exec = 102;
localparam __state_42_req = 103;
localparam __state_42_wait = 104;
localparam __state_42_exec = 105;
localparam __state_43_exec = 106;
localparam __state_44_exec = 107;
integer __state;
localparam __label_0 = 0;
localparam __label_entry = 2;
integer __label;
always @(posedge __func_clock or negedge __func_reset) begin
if(!__func_reset) begin
__state <= __state_start_req;
__func_ready <= 0;
__func_done <= 0;
end else begin
case(__state)
__state_start_req: begin
__state <= __state_start_wait;
end
__state_start_wait: begin
if(__func_start) begin
__state <= __state_start_exec;
__func_ready <= 0;
__func_done <= 0;
__sig_multi_in0 <= __args_multi_in0;
__sig_multi_in1 <= __args_multi_in1;
__sig_multi_out <= __args_multi_out;
end
end
__state_start_exec: begin
__state <= __state_1_exec;
end
__state_1_exec: begin
__state <= __state_2_exec;
end
__state_2_exec: begin
__state <= __state_3_req;
__label <= __label_entry;
end
__state_3_req: begin
__state <= __state_3_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_multi_in0);
__gm_leng <= 3;
end
__state_3_wait: begin
if((__gm_done == 1)) begin
__state <= __state_3_exec;
end
__gm_req <= 0;
end
__state_3_exec: begin
__state <= __state_4_req;
__sig_0 <= __gm_di;
end
__state_4_req: begin
__state <= __state_4_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_multi_in1);
__gm_leng <= 3;
end
__state_4_wait: begin
if((__gm_done == 1)) begin
__state <= __state_4_exec;
end
__gm_req <= 0;
end
__state_4_exec: begin
__state <= __state_5_exec;
__sig_1 <= __gm_di;
end
__state_5_exec: begin
__state <= __state_6_req;
__sig_mul <= __sig_1 * __sig_0;
end
__state_6_req: begin
__state <= __state_6_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_multi_out);
__gm_leng <= 3;
__gm_do <= __sig_mul;
end
__state_6_wait: begin
if((__gm_done == 1)) begin
__state <= __state_6_exec;
end
__gm_req <= 0;
end
__state_6_exec: begin
__state <= __state_7_req;
end
__state_7_req: begin
__state <= __state_7_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_1);
__gm_leng <= 3;
end
__state_7_wait: begin
if((__gm_done == 1)) begin
__state <= __state_7_exec;
end
__gm_req <= 0;
end
__state_7_exec: begin
__state <= __state_8_req;
__sig_2 <= __gm_di;
end
__state_8_req: begin
__state <= __state_8_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_1);
__gm_leng <= 3;
end
__state_8_wait: begin
if((__gm_done == 1)) begin
__state <= __state_8_exec;
end
__gm_req <= 0;
end
__state_8_exec: begin
__state <= __state_9_exec;
__sig_3 <= __gm_di;
end
__state_9_exec: begin
__state <= __state_10_req;
__sig_mul_1 <= __sig_3 * __sig_2;
end
__state_10_req: begin
__state <= __state_10_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_1);
__gm_leng <= 3;
__gm_do <= __sig_mul_1;
end
__state_10_wait: begin
if((__gm_done == 1)) begin
__state <= __state_10_exec;
end
__gm_req <= 0;
end
__state_10_exec: begin
__state <= __state_11_req;
end
__state_11_req: begin
__state <= __state_11_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_2);
__gm_leng <= 3;
end
__state_11_wait: begin
if((__gm_done == 1)) begin
__state <= __state_11_exec;
end
__gm_req <= 0;
end
__state_11_exec: begin
__state <= __state_12_req;
__sig_4 <= __gm_di;
end
__state_12_req: begin
__state <= __state_12_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_2);
__gm_leng <= 3;
end
__state_12_wait: begin
if((__gm_done == 1)) begin
__state <= __state_12_exec;
end
__gm_req <= 0;
end
__state_12_exec: begin
__state <= __state_13_exec;
__sig_5 <= __gm_di;
end
__state_13_exec: begin
__state <= __state_14_req;
__sig_mul_2 <= __sig_5 * __sig_4;
end
__state_14_req: begin
__state <= __state_14_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_2);
__gm_leng <= 3;
__gm_do <= __sig_mul_2;
end
__state_14_wait: begin
if((__gm_done == 1)) begin
__state <= __state_14_exec;
end
__gm_req <= 0;
end
__state_14_exec: begin
__state <= __state_15_req;
end
__state_15_req: begin
__state <= __state_15_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_3);
__gm_leng <= 3;
end
__state_15_wait: begin
if((__gm_done == 1)) begin
__state <= __state_15_exec;
end
__gm_req <= 0;
end
__state_15_exec: begin
__state <= __state_16_req;
__sig_6 <= __gm_di;
end
__state_16_req: begin
__state <= __state_16_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_3);
__gm_leng <= 3;
end
__state_16_wait: begin
if((__gm_done == 1)) begin
__state <= __state_16_exec;
end
__gm_req <= 0;
end
__state_16_exec: begin
__state <= __state_17_exec;
__sig_7 <= __gm_di;
end
__state_17_exec: begin
__state <= __state_18_req;
__sig_mul_3 <= __sig_7 * __sig_6;
end
__state_18_req: begin
__state <= __state_18_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_3);
__gm_leng <= 3;
__gm_do <= __sig_mul_3;
end
__state_18_wait: begin
if((__gm_done == 1)) begin
__state <= __state_18_exec;
end
__gm_req <= 0;
end
__state_18_exec: begin
__state <= __state_19_req;
end
__state_19_req: begin
__state <= __state_19_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_4);
__gm_leng <= 3;
end
__state_19_wait: begin
if((__gm_done == 1)) begin
__state <= __state_19_exec;
end
__gm_req <= 0;
end
__state_19_exec: begin
__state <= __state_20_req;
__sig_8 <= __gm_di;
end
__state_20_req: begin
__state <= __state_20_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_4);
__gm_leng <= 3;
end
__state_20_wait: begin
if((__gm_done == 1)) begin
__state <= __state_20_exec;
end
__gm_req <= 0;
end
__state_20_exec: begin
__state <= __state_21_exec;
__sig_9 <= __gm_di;
end
__state_21_exec: begin
__state <= __state_22_req;
__sig_mul_4 <= __sig_9 * __sig_8;
end
__state_22_req: begin
__state <= __state_22_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_4);
__gm_leng <= 3;
__gm_do <= __sig_mul_4;
end
__state_22_wait: begin
if((__gm_done == 1)) begin
__state <= __state_22_exec;
end
__gm_req <= 0;
end
__state_22_exec: begin
__state <= __state_23_req;
end
__state_23_req: begin
__state <= __state_23_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_5);
__gm_leng <= 3;
end
__state_23_wait: begin
if((__gm_done == 1)) begin
__state <= __state_23_exec;
end
__gm_req <= 0;
end
__state_23_exec: begin
__state <= __state_24_req;
__sig_10 <= __gm_di;
end
__state_24_req: begin
__state <= __state_24_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_5);
__gm_leng <= 3;
end
__state_24_wait: begin
if((__gm_done == 1)) begin
__state <= __state_24_exec;
end
__gm_req <= 0;
end
__state_24_exec: begin
__state <= __state_25_exec;
__sig_11 <= __gm_di;
end
__state_25_exec: begin
__state <= __state_26_req;
__sig_mul_5 <= __sig_11 * __sig_10;
end
__state_26_req: begin
__state <= __state_26_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_5);
__gm_leng <= 3;
__gm_do <= __sig_mul_5;
end
__state_26_wait: begin
if((__gm_done == 1)) begin
__state <= __state_26_exec;
end
__gm_req <= 0;
end
__state_26_exec: begin
__state <= __state_27_req;
end
__state_27_req: begin
__state <= __state_27_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_6);
__gm_leng <= 3;
end
__state_27_wait: begin
if((__gm_done == 1)) begin
__state <= __state_27_exec;
end
__gm_req <= 0;
end
__state_27_exec: begin
__state <= __state_28_req;
__sig_12 <= __gm_di;
end
__state_28_req: begin
__state <= __state_28_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_6);
__gm_leng <= 3;
end
__state_28_wait: begin
if((__gm_done == 1)) begin
__state <= __state_28_exec;
end
__gm_req <= 0;
end
__state_28_exec: begin
__state <= __state_29_exec;
__sig_13 <= __gm_di;
end
__state_29_exec: begin
__state <= __state_30_req;
__sig_mul_6 <= __sig_13 * __sig_12;
end
__state_30_req: begin
__state <= __state_30_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_6);
__gm_leng <= 3;
__gm_do <= __sig_mul_6;
end
__state_30_wait: begin
if((__gm_done == 1)) begin
__state <= __state_30_exec;
end
__gm_req <= 0;
end
__state_30_exec: begin
__state <= __state_31_req;
end
__state_31_req: begin
__state <= __state_31_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_7);
__gm_leng <= 3;
end
__state_31_wait: begin
if((__gm_done == 1)) begin
__state <= __state_31_exec;
end
__gm_req <= 0;
end
__state_31_exec: begin
__state <= __state_32_req;
__sig_14 <= __gm_di;
end
__state_32_req: begin
__state <= __state_32_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_7);
__gm_leng <= 3;
end
__state_32_wait: begin
if((__gm_done == 1)) begin
__state <= __state_32_exec;
end
__gm_req <= 0;
end
__state_32_exec: begin
__state <= __state_33_exec;
__sig_15 <= __gm_di;
end
__state_33_exec: begin
__state <= __state_34_req;
__sig_mul_7 <= __sig_15 * __sig_14;
end
__state_34_req: begin
__state <= __state_34_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_7);
__gm_leng <= 3;
__gm_do <= __sig_mul_7;
end
__state_34_wait: begin
if((__gm_done == 1)) begin
__state <= __state_34_exec;
end
__gm_req <= 0;
end
__state_34_exec: begin
__state <= __state_35_req;
end
__state_35_req: begin
__state <= __state_35_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_8);
__gm_leng <= 3;
end
__state_35_wait: begin
if((__gm_done == 1)) begin
__state <= __state_35_exec;
end
__gm_req <= 0;
end
__state_35_exec: begin
__state <= __state_36_req;
__sig_16 <= __gm_di;
end
__state_36_req: begin
__state <= __state_36_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_8);
__gm_leng <= 3;
end
__state_36_wait: begin
if((__gm_done == 1)) begin
__state <= __state_36_exec;
end
__gm_req <= 0;
end
__state_36_exec: begin
__state <= __state_37_exec;
__sig_17 <= __gm_di;
end
__state_37_exec: begin
__state <= __state_38_req;
__sig_mul_8 <= __sig_17 * __sig_16;
end
__state_38_req: begin
__state <= __state_38_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_8);
__gm_leng <= 3;
__gm_do <= __sig_mul_8;
end
__state_38_wait: begin
if((__gm_done == 1)) begin
__state <= __state_38_exec;
end
__gm_req <= 0;
end
__state_38_exec: begin
__state <= __state_39_req;
end
__state_39_req: begin
__state <= __state_39_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx_9);
__gm_leng <= 3;
end
__state_39_wait: begin
if((__gm_done == 1)) begin
__state <= __state_39_exec;
end
__gm_req <= 0;
end
__state_39_exec: begin
__state <= __state_40_req;
__sig_18 <= __gm_di;
end
__state_40_req: begin
__state <= __state_40_wait;
__gm_req <= 1;
__gm_rnw <= 1;
__gm_adrs <= (__sig_arrayidx1_9);
__gm_leng <= 3;
end
__state_40_wait: begin
if((__gm_done == 1)) begin
__state <= __state_40_exec;
end
__gm_req <= 0;
end
__state_40_exec: begin
__state <= __state_41_exec;
__sig_19 <= __gm_di;
end
__state_41_exec: begin
__state <= __state_42_req;
__sig_mul_9 <= __sig_19 * __sig_18;
end
__state_42_req: begin
__state <= __state_42_wait;
__gm_req <= 1;
__gm_rnw <= 0;
__gm_adrs <= (__sig_arrayidx2_9);
__gm_leng <= 3;
__gm_do <= __sig_mul_9;
end
__state_42_wait: begin
if((__gm_done == 1)) begin
__state <= __state_42_exec;
end
__gm_req <= 0;
end
__state_42_exec: begin
__state <= __state_43_exec;
end
__state_43_exec: begin
__state <= __state_fin_exec;
end
__state_44_exec: begin
__state <= __state_fin_exec;
end
__state_fin_exec: begin
__state <= __state_start_req;
__func_ready <= 1;
__func_done <= 1;
end
endcase
end
end
endmodule
  1. 2015年11月02日 04:25 |
  2. Synverll
  3. | トラックバック:0
  4. | コメント:0

ZYBOにHDLで書いたラプラシアンフィルタを実装する7(インプリメント)

ZYBOにHDLで書いたラプラシアンフィルタを実装する6(Vivado のブロックデザインにIPを追加)”の続き。

前回では、ブロックデザインが完成した。今回はインプリメントを行う。

・Flow Navigator でGenerate Bitstrem をクリックして、論理合成、インプリメント、ビットストリームの生成を行った。

・ビットストリームは生成されたが、タイミング・エラーが出ている。
lap_fil_HDL_axim_81_151031.png

・Project Summary を見てみると、結構、ロジックが使用されている。
lap_fil_HDL_axim_83_151031.png

・Flow Navigator で Implemented Design をクリックする。
・Report Timing Summary をクリックして、タイミング・エラーを観察する。
lap_fil_HDL_axim_82_151031.png
・Report Timing Summary ダイアログが表示されるので、OKボタンをクリックした。

・Timing Summary が表示された。
lap_fil_HDL_axim_84_151031.png

・clk_fpga0 のSetup タイミング違反はそんなに大したことは無さそうだ。これだと、ストラテジーを変えてインプリメントすれば大丈夫だと思う。
lap_fil_HDL_axim_85_151031.png
後は、Inter-Clock Paths の BUFR_pixel_clk_io_n_0 と clk_fpga_0 の間のタイミング違反が出ているので、この間のタイミング制約を無視するように設定を行う。

・Implemented Design -> Constraints Wizard をクリックして、タイミング制約を編集する。

・Timing Constraints ウインドウの Exceptions -> Set False Path をクリックして、Set False Path ペインの Double Click to create a Set False Path constraint をダブル・クリックした。
lap_fil_HDL_axim_86_151031.png

・Set Flase Path ダイアログが開いた。
・Start Points の From の ... ボタンをクリックした。
lap_fil_HDL_axim_87_151031.png

・Find names of type で Clocks を選択する。
・Find ボタンをクリックする。
・Results で clk_fpaga_0 を選択し、→ キーをクリックする。
lap_fil_HDL_axim_88_151031.png

・Results に clk_fpaga_0 が入った。
lap_fil_HDL_axim_89_151031.png

・From に clk_fpga_0 が入った。
・End Points の To の ... ボタンをクリックした。
lap_fil_HDL_axim_90_151031.png

・Find names of type で Clocks を選択する。
・Find ボタンをクリックする。
・Results で BUFR_pixel_clk_io/O を選択し、→ キーをクリックする。
・To に BUFR_pixel_clk_io/O が入った。
・OKボタンをクリックする。
lap_fil_HDL_axim_91_151031.png

・ clk_fpga_0 から BUFR_pixel_clk_io/O へのパスをFalse Path にする制約が入った。
lap_fil_HDL_axim_92_151031.png

・同様に、 BUFR_pixel_clk_io/O から clk_fpga_0 へのパスをFalse Path にする制約を入れる。
lap_fil_HDL_axim_93_151031.png

・制約が入った。
lap_fil_HDL_axim_94_151031.png

・Timing Summary を見ると、Report is out of data になっていたので、Rerun した。
lap_fil_HDL_axim_95_151031.png

・すると、Inter-Clock Paths はタイミング違反が無くなって、Intra-Clock Paths はSetup が -0.370 ns という結果が出た。
lap_fil_HDL_axim_96_151031.png

・もう一度、インプリメントした結果を示す。
lap_fil_HDL_axim_97_151031.png

まだ、少しタイミング違反が出ているが、だいぶ改善した。
  1. 2015年11月01日 20:56 |
  2. ZYBO
  3. | トラックバック:0
  4. | コメント:0

柿の実を収穫しました

昨日は柿の実を収穫しました。
柿の実もいい感じに色づいてきて、美味しそうになってきました。このまま置いておく鳥に全部食べられちゃいそうなので、収穫しました。
kaki_1_151101.jpg

結構大きくて大きい実が多いです。
柿の実はまだ残っているので、今日も収穫して、取れるものは全部収穫しちゃおうと思います。

今日は犬が犬小屋の床に貼った木の板を剥がして土を掘っちゃうので、コンクリート板を床に置こうと思います。それを買いに行って施工しよう(と言っても土を均して置くだけで良いかな?)と思っています。
  1. 2015年11月01日 05:57 |
  2. 日記
  3. | トラックバック:0
  4. | コメント:0