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

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

FPGAの部屋

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

AXI4 Master アクセスのラプラシアン・フィルタ IP3(シミュレーション)

AXI4 Master アクセスのラプラシアン・フィルタ IP2(現在作成中)”の続き。

AXI4 Master アクセスのラプラシアン・フィルタ IPが出来てシミュレーションを行った。

プロジェクトのファイル構成を下に示す。
axi4m_lap_filter_3_131124.png

上の図で、lap_filter_axim.v がトップファイルだ。
lap_filter_axim_LiteS_if.v は、Vivado HLS のAXI4 Lite Slaveモジュールを借用している。
axi4_master_inf.v が、作ってきたAXI4 Master アクセス用のIPだ。
line_read_and_y.v は、1ライン画像データを読んできて、RGBからYに変換するモジュールだ。
Dual_Prot_Memory.v は、1ライン分の画像データを保存しておくライン・バッファである。

下にISEのプロジェクトを示す。
axi4m_lap_filter_4_131124.png

プロジェクトのファイル構成の図でも見えていたと思うが、テストベンチ lap_filter_axim_tb.v を作製してシミュレーションを行った。
テストベンチは最初にAXI4 Lite Slave トランザクションでレジスタをセットする。そうすると、AXI4 Master Readトランザクションが発生して、画像データをReadしてくる。Readされた画像データはRGB-Y変換により、輝度値に変換される。画像の輝度値は、ライン・バッファに保存され、3ライン分たまった所でラプラシアン・フィルタ処理を施され、AXI4 Master Write トランザクションにより、ラプラシアン・フィルタ保存領域にWriteされる。
さて、ISimによるシミュレーション結果を見ていこう。
最初に、AXI4 Lite Slave トランザクションでレジスタをセットする部分のシミュレーション結果を見ることにしよう。下にシミュレーション波形を示す。
axi4m_lap_filter_5_131124.png

最初のReadトランザクションを示す。
axi4m_lap_filter_6_131124.png

Read Address Channel は最初に256バースト転送を3回、32バースト転送を行っている。すべてのトランザクションのARIDは0なので、Readトランザクションはネストされ、順番にRead Data Channelでトランザクションが処理される。Read Address Channel のトランザクション波形を示す。(800x600ピクセルのSVGA画面の1行=800ピクセルを256バースト3回と32バースト1回で Read する)
axi4m_lap_filter_7_131124.png

次にWriteトランザクションを示す。最初のWriteトランザクションのデータはすべて0なので、2番めのWriteトランザクションを下に示す。
axi4m_lap_filter_8_131124.png

Write Address Channel のトランザクションを示す。Readトランザクション同様、256バースト転送を3回、32バースト転送を行っている。
axi4m_lap_filter_9_131124.png

下の図では、上が AXI4 Write で下が AXI4 Readになっているので、トランザクションの様子がよくわかると思う。
axi4m_lap_filter_10_131124.png

フレームの最後は、9.8msec 辺だ。AXI4バスの動作周波数は100MHzとなっている。
axi4m_lap_filter_11_131124.png

フレームの最後の後に、AXI4 Lite Slave トランザクションが1つあるのが見えるだろうか?
axi4m_lap_filter_12_131124.png

これは、AXI4 Lite Slave Readトランザクションで、レジスタの0番地をReadしている。
axi4m_lap_filter_13_131124.png

レジスタ0番地のビットアサインを下に示す。


//------------------------Address Info-------------------
// 0x00 : Control signals
// bit 0 - ap_start (Read/Write/COH)
// bit 1 - ap_done (Read/COR)
// bit 2 - ap_idle (Read)
// bit 3 - ap_ready (Read)
// bit 7 - auto_restart (Read/Write)
// others - reserved


シミュレーション波形を見ると、6をReadできているので、ap_done と ap_idle が立っているのがわかる。

因みに、100MHzでWait無しの最高速で9.8msec です。ちょっと危ないですかね? 危ない時は時は、AXI4バスの動作周波数を150MHzにしてみようかな?と思っています。(16.7msec 以内に処理が終わるかな?ということです)
間に合わない時のその他の対処方法としては、DDR3 SDRAMの帯域は余っているはずなので、ReadトランザクションとWriteトランザクションを重ねあわせることができるはずです。

(2013/11/25:追記)
このラプラシアン・フィルタ AXI4 Master IP はハードウェアとしてVerilog HDLで記述したのだが、わざとCでの高位合成結果のHDLに合わせてメモリベースで設計されている。この場合はハードウェアといえどもクロックベースの設計を行っていないので、ソフトウェア同様、フレームに処理が間に合うかどうかを確定できない。
  1. 2013年11月24日 04:34 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP2(現在作成中)

AXI4 Master アクセスのラプラシアン・フィルタ IP1(構想)”の構想を元に、現在、AXI4 Master アクセスのラプラシアン・フィルタ IPを作製中だ。
axi4m_lap_filter_2_131121.png

結構、行数が多くなっている。まだ書き終わらない。こうして見ると、Vivado HLSでC言語からHDLを生成してれるのはとっても楽だ。早く、うまくいくようになってほしいと思う。

なお、AXI4 Master アクセスのラプラシアン・フィルタ IPには、今まで作ってきた、AXI4 Master Interfaceモジュールや、AXI Slave BFMなどを使用する予定だ。むしろ、ここで使うために作ってきた。

AXI4 Slave Bus Functional Model (axi_slave_BFM.vhd)
AXI4 Master Interfaceモジュールの作製1(仕様の検討)
AXI4 Master Interfaceモジュールの作製2(シミュレーション)
AXI4 Master Interfaceモジュールの作製3(シミュレーション2)
AXI4 Master Interfaceモジュールの作製4(axi4_master_inf.v のHDLソース)
AXI4 Master Interfaceモジュールの作製5(Write用FIFOのXCO)
AXI4 Master Interfaceモジュールの作製6(Read用FIFOのXCO)

  1. 2013年11月21日 05:25 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

AXI4 Master アクセスのラプラシアン・フィルタ IP1(構想)

以前にもラプラシアン・フィルタをFPGAのハードウェアで作ったことがあるが、それは、1連のパイプラインされた構造だった。1ピクセルの画像データが入ってきて、パイプラインにデータが満たされていれば、ラプラシアン・フィルタ後のデータが出てくる構造だ。下にそのブロック図を示す。(”画像のエッジ検出6(3X3での方式の検討)”参照)
edge_detect_11_091111.png

今回はわざとこの構造は取らずに、C言語からHLSで合成したようにシリアライズしてみようと思うのだが、なかなかわざと遅くしようと作ったことがなので、戸惑っている。ともかくC言語からHDLを合成したようにメモリベースで、ある程度シリアライズされた構成で作ってみようと思う。

最初はメモリベースのシングルバッファリングで作ることにした。そのフロー図を下に示す。
axi4m_lap_filter_1_131116.png

上の図の四角い箱の中身は並列に実行する。つまり、”1ライン分ピクセルデータをMemory Readし白黒変換”までをパイプライン化するわけだ。

これで実装してやってみよう。今回は、あえてCでのハードウェア実装にこだわって実力を見てみようと思う。

更に、現在のラインバッファの数は3つだが、ラインバッファの数を4つにすれば、クロックごとに同期しなくてもラインごとに同期すれば、3番目の”1ライン分ピクセルデータをMemory Readし白黒変換”と”1ラインのラプラシアン・フィルタ Memory Wite”を重ねあわせることができるはずだ。これによる性能の向上を見てみようと思う。
  1. 2013年11月16日 09:54 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う2

”Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う1”でVivado HLS 2013.3 でC言語から合成したIPが動かないということを書いた。今回は、予め入れておいたChipScope を使用して、ラプラシアン・フィルタAXI4 Master IPの2つのAXI4 Masterバスと1つのAXI4 Lite Slaveバスの波形を見てみた。

まずは、レジスタを設定するAXI4 Lite Slave から見ていこう。
まずはキャプチャされた全体を下に示す。
HLS_lap_fil_axim_43_131026.png

次は最初のWriteしている部分を見ていこう。
HLS_lap_fil_axim_44_131026.png

AXI4 Lite SlaveアクセスのWriteは以下の通り。

1.最初の5つのWriteは初期化
2.画像データのアドレス(0x19107000)
3.ラプラシアン・フィルタ用の画像データのアドレス(0x192DC000)
4.ap_startのWrite
3.2つのデータのvld


その後は、2ビット目の ap_done が立たないかどうかをポーリングしている。面白いのは、RDATAから 2回1、1回0が読めることだ。
HLS_lap_fil_axim_45_131026.png

次は、画像データが入っているCAM_FBのReadを見ていこう。
下に、1ライン分(800ワード、1ワード=4バイト)のReadアクセスを示す。
HLS_lap_fil_axim_46_131026.png

RDATAを見ると、いろいろなデータが読めているのがわかる。

最初のアドレス転送を引き伸ばしてみてみよう。
HLS_lap_fil_axim_47_131026.png

最初のトランザクションは、0x19107000番地から256ワードのバースト転送であることがわかる。0x19107000はAXI4 Lite Slave で書かれた画像データのスタートアドレスだ。

次に、ラプラシアン・フィルタを掛けた後のデータのWriteアクセスを見ていく。
HLS_lap_fil_axim_48_131026.png

WDATAを見ると、すべてのデータが0になっている。これはおかしい。

最初の部分を拡大すると、0x192DC000番地から256ワードのWriteのアドレス転送を行っている。これは、AXI4 Lite Slave で書かれたラプラシアン・フィルタ用の画像データのアドレスだ。
HLS_lap_fil_axim_49_131026.png

今まで見てきたように、Vivado HLS 2013.3 で生成されたラプラシアン・フィルタIPには2つの問題がある。

1.ap_doneが 1 にならない。
2.ラプラシアン・フィルタのWriteデータが全て 0 になっている。


とりあえず、シミュレーションがうまくいかないのと合わせて、まだバグがある感じがする?
  1. 2013年10月26日 05:49 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う1

Vivado HLS 2013.3でラプラシアン・フィルタ関数をaxi masterモジュールにする”でC言語からHDLに合成したラプラシアン・フィルタIPをDigilent LinuxのXPSプロジェクトに組み込んで、動作を確認したが、結果から言うと動作しなかった。

前回、C言語からHDLに合成したラプラシアン・フィルタIPをDigilent LinuxのXPSプロジェクトの pcores フォルダに入れなおして、Project Navigator から論理合成、インプリメント、ビットストリームの生成を行った。

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

AXI4 Master 版ラプラシアン・フィルタを動作されるソフトウェアを実行したが、ap_done が帰ってこない。Vivado 2013.2 の時とソフト的には同様の結果だった。

AXI4 Master版ラプラシアン・フィルタIPの制御用ソフトウェアを貼ってなかったようなので、貼っておく
lap_filter_axim.c から下に示す。

// lap_filter_axim.c
// AXI4 Master のVivado HLS出力ハードウェア・バージョン
// RGBをYに変換後にラプラシアンフィルタを掛ける。
// ピクセルのフォーマットは、{8'd0, R(8bits), G(8bits), B(8bits)}, 1pixel = 32bits
// 2013/10/15

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#include <fcntl.h>
#include <assert.h>
#include <ctype.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <linux/kernel.h>
#include "lap_fil_axim_uty.h"

#define LAP_FILTER_AXIM_HW_ADDRESS    0x49000000    // ラプラシアン・フィルタのAXI4 Masterハードウェアのアドレス

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

#define PAGE_SIZE (4*1024)
#define BLOCK_SIZE (4*1024)

#define BUFSIZE    1024

#define MEASURE_COUNT    5000

int conv_rgb2y(int rgb);
int chkhex(char *str);
volatile unsigned *setup_io(off_t mapped_addr, unsigned int *buf_addr);

int main()
{
    FILE *fd;
    unsigned int bitmap_dc_reg_addr;
    unsigned int read_num;
    volatile unsigned *bm_disp_cnt_reg;
    unsigned int fb_addr, next_frame_addr;
    int return_val;
    struct timeval start_time, end_time;
    unsigned int rmmap_cnt=0, wmmap_cnt=0;
    unsigned int lap_fil_hw, *lap_fil_hw_addr;
    char buf[BUFSIZE], *token;
    unsigned int val;
    unsigned int bitmap_buf;

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

    // fb_start_addr.txt の内容をパイプに入れる
    memset(buf, '\0'sizeof(buf)); // buf すべてに\0 を入れる
    // fb_start_addr.txt を開く
    fd = popen("cat /Apps/fb_start_addr.txt""r");
    if (fd != NULL){
        read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
        if (read_num > 0){
            sscanf(buf, "%x\n", &fb_addr);
        }
    }
    pclose(fd);

    // ラプラシアンフィルタの結果を入れておくフレーム・バッファ
    next_frame_addr = ((fb_addr + (ALL_PIXEL_VALUE*4)) & (~(int)(PAGE_SIZE-1))) + PAGE_SIZE;

    // Vivado HLS で作製したラプラシアン・フィルタIPのアドレスを取得
    lap_fil_hw_addr = setup_io((off_t)LAP_FILTER_AXIM_HW_ADDRESS, &lap_fil_hw);

    lap_fil_initialize(lap_fil_hw_addr);    // ラプラシアン・フィルタIPの初期化とap_start
    // ラプラシアン・フィルタAXI4 Master IPスタート
    return_val = laplacian_fil_hw(lap_fil_hw_addr, fb_addr, next_frame_addr);
    printf("return Value = %d\n", return_val);
    
    munmap((unsigned int *)lap_fil_hw_addr, BLOCK_SIZE);
    free((unsigned int *)lap_fil_hw);

    // bitmap-disp-cntrler-axi-master のアドレスを取得
    memset(buf, '\0'sizeof(buf)); // buf すべてに\0 を入れる
    // ls /sys/devices/axi.0 の内容をパイプに入れる
    fd = popen("ls /sys/devices/axi.0""r");
    if (fd != NULL){
        read_num = fread(buf, sizeof(unsigned char), BUFSIZE, fd);
        if (read_num > 0){
            token = buf;
            if ((token=strtok(token, ".\n")) != NULL){
                do {
                    if (chkhex(token)){ // 16進数
                        sscanf(token, "%x", &val);
                    } else {
                        if (strcmp(token, "bitmap-disp-cntrler-axi-master") == 0)
                            bitmap_dc_reg_addr = val;
                    }
                }while((token=strtok(NULL, ".\n")) != NULL);
            }
        }
    }
    pclose(fd);

    // ラプラシアンフィルタの掛かった画像のスタートアドレスを bitmap-disp-cntrler-axi-master にセット
    bm_disp_cnt_reg = setup_io((off_t)bitmap_dc_reg_addr, &bitmap_buf);
    *bm_disp_cnt_reg = next_frame_addr;

    munmap((unsigned int *)bm_disp_cnt_reg, BLOCK_SIZE);
    free((unsigned int *)bitmap_buf);

    gettimeofday(&end_time, NULL);
    printf("rmmap_cnt = %d\n", rmmap_cnt);
    printf("wmmap_cnt = %d\n", wmmap_cnt);
    if (end_time.tv_usec < start_time.tv_usec) {
        printf("total time = %d.%6.6d sec\n", end_time.tv_sec - start_time.tv_sec - 11000000 + end_time.tv_usec - start_time.tv_usec);
    }
    else {
        printf("total time = %d.%6.6d sec\n", end_time.tv_sec - start_time.tv_sec, end_time.tv_usec - start_time.tv_usec);
    }
    return(0);
}


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

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

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

    return(y);
}

//
// Set up a memory regions to access GPIO
//
volatile unsigned *setup_io(off_t mapped_addr, unsigned int *buf_addr)
// void setup_io()
{
    int  mem_fd;
    char *gpio_mem, *gpio_map;

   /* open /dev/mem */
   if ((mem_fd = open("/dev/mem", O_RDWR|O_SYNC) ) < 0) {
      printf("can't open /dev/mem \n");
      printf("mapped_addr = %x\n", mapped_addr);
      exit (-1);
   }

   /* mmap GPIO */

   // Allocate MAP block
   if ((gpio_mem = malloc(BLOCK_SIZE + (PAGE_SIZE-1))) == NULL) {
      printf("allocation error \n");
      exit (-1);
   }
    *buf_addr = gpio_mem;    // mallocしたアドレスをコピー

   // Make sure pointer is on 4K boundary
   if ((unsigned long)gpio_mem % PAGE_SIZE)
     gpio_mem += PAGE_SIZE - ((unsigned long)gpio_mem % PAGE_SIZE);

   // Now map it
   gpio_map = (unsigned char *)mmap(
      (caddr_t)gpio_mem,
      BLOCK_SIZE,
      PROT_READ|PROT_WRITE,
      MAP_SHARED|MAP_FIXED,
      mem_fd,
      mapped_addr
   );

   if ((long)gpio_map < 0) {
      printf("mmap error %d\n", (int)gpio_map);
      printf("mapped_addr = %x\n", mapped_addr);
      exit (-1);
   }

   close(mem_fd); // /dev/mem のクローズ

   // Always use volatile pointer!
   // gpio = (volatile unsigned *)gpio_map;
   return((volatile unsigned *)gpio_map);

// setup_io

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


Vivado HLS で生成された xlap_filter_axim_hw.h を下に示す。

// ==============================================================
// File generated by Vivado(TM) HLS - High-Level Synthesis from C, C++ and SystemC
// Version: 2013.2
// Copyright (C) 2013 Xilinx Inc. All rights reserved.
// 
// ==============================================================

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

#define XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL       0x00
#define XLAP_FILTER_AXIM_LITES_ADDR_GIE           0x04
#define XLAP_FILTER_AXIM_LITES_ADDR_IER           0x08
#define XLAP_FILTER_AXIM_LITES_ADDR_ISR           0x0c
#define XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_CTRL 0x10
#define XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA 0x14
#define XLAP_FILTER_AXIM_LITES_BITS_CAM_ADDR_DATA 32
#define XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_CTRL 0x18
#define XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA 0x1c
#define XLAP_FILTER_AXIM_LITES_BITS_LAP_ADDR_DATA 32
#define XLAP_FILTER_AXIM_LITES_ADDR_AP_RETURN     0x20
#define XLAP_FILTER_AXIM_LITES_BITS_AP_RETURN     32


次に、lap_fil_axim_uty.h を下に示す。


/*
* lap_fil_axim_uty.h
*
* Created on: 2013/10/15
* Author: Masaaki
*/

#ifndef LAP_FIL_AXIM_UTY_H_
#define LAP_FIL_AXIM_UTY_H_

void lap_fil_initialize(unsigned int *lap_fil_hw_addr);
int laplacian_fil_hw(unsigned int *lap_fil_hw_addr, unsigned int *cam_fb, unsigned int *lap_fb);

#endif /* LAP_FIL_AXIM_UTY_H_ */


最後に、lap_fil_axim_uty.c を下に示す。

/* * lap_fil_axim_uty.c * *  Created on: 2013/10/15 *      Author: Masaaki */

#include "xlap_filter_axim_hw.h"

#define AP_START_BIT_POS        1    // ap_start のビット位置 bit0
#define AP_DONE_BIT_POS            2    // ap_done のビット位置 bit1
#define AP_AUTO_RESTART_BIT_POS    0x80    // auto_restart のビット位置 bit7
#define VLD_BIT_POS                1

void lap_fil_initialize(unsigned int *lap_fil_hw_addr)
{
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL) = 0;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_GIE) = 0;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_IER) = 0;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_CTRL) = 0;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_CTRL) = 0;
}

// ラプラシアン・フィルタ・スタート
int laplacian_fil_hw(unsigned int *lap_fil_hw_addr, unsigned int cam_fb, unsigned int lap_fb)
{
    int ap_status, ap_done;
    int ap_return;
    int cam_fb_read, lap_fb_read;
    int cam_addr_vld, lap_addr_vld;

    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA) = cam_fb;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA) = lap_fb;
    cam_fb_read = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA);
    lap_fb_read = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA);

    // ap_start enable
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL) = AP_START_BIT_POS;

     // vld enable
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_CTRL) = VLD_BIT_POS;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_CTRL) = VLD_BIT_POS;

    // wait ap_done
    do{
        ap_status = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL);
        ap_done = ap_status & AP_DONE_BIT_POS;
        cam_addr_vld = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_CTRL);
        lap_addr_vld = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_CTRL);
    }while(!ap_done);
    
    // ap_return read
    ap_return = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_RETURN);
    //printf("ap_return = %d\n", ap_return);
    return(ap_return);
}

  1. 2013年10月26日 04:25 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う3

Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う2”の続き。

前回は、Vivado HLSで作ったAXI4 Lite Slave と AXI4 Master の 2種類のAXIバスを実装するラプラシアン・フィルタ IPをXPSのカスタムIPとして、SDKからのソフトウェア制御で使用してみたら動作しなかった(ap_done がアサートされなかった)という問題が合った。
今回は、XPSプロジェクトに入れてあったChipScope AXI Monitor を使用してAXI4バスのトランザクションを見ることにした。

早速、ChipScope Analyzer を立上て、CDCファイルをインポートしてデータポートの名前を確定した。
最初に、lap_filter_axim_top_0のAXI4 Lite Slave のバス・トランザクションを観察した。下にその波形を示す。
HLS_lap_fil_axim_38_131017.png

もう一度、AXI4 Lite Slave バスのアドレスマップを示す。

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


レジスタをアクセスする部分のソフトウェアを下に示す。

    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA) = cam_fb;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA) = lap_fb;
    cam_fb_read = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_DATA);
    lap_fb_read = *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_DATA);

    // ap_start enable
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_AP_CTRL) = AP_START_BIT_POS;

     // vld enable
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_CAM_ADDR_CTRL) = VLD_BIT_POS;
    *(volatile int *)((unsigned int)lap_fil_hw_addr + (unsigned int)XLAP_FILTER_AXIM_LITES_ADDR_LAP_ADDR_CTRL) = VLD_BIT_POS;


問題なくRead, Writeできているようだ。

次に、M_AXI_CAM_FB を見てみよう。
HLS_lap_fil_axim_39_131017.png

バーストでReadアクセスを行っている。
最初のアドレス転送の部分を拡大してみよう。
HLS_lap_fil_axim_40_131017.png

最初のアドレス開始位置は0x19107000 でレジスタに書いた値と同じだ。
カメラのフレーム・バッファのReadは問題ないようだ。

ラプラシアン・フィルタのフレーム・バッファへのWriteはどうだろう?
M_AXI_LAP_FB AXIバスのAWVALID でトリガを掛けてもトリガが掛からなかった。
HLS_lap_fil_axim_41_131017.png

ラプラシアン・フィルタのフレーム・バッファへのWriteは発生していないようだ。もう少し調査する必要がある。
  1. 2013年10月17日 05:13 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0

Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う2

Vivado HLSで作ったラプラシアン・フィルタAXI4 Master IPを使う1”の続き。

・前回はXPSプロジェクトを完成させたので、Project Navigator に戻って論理合成、インプリメントを行ったが、問題なく終了した。
HLS_lap_fil_axim_28_131015.png

・例によって、Design ウインドウのHierarchy から system_i を選んで、Processes ウインドウのExport Hardware Design To SDK with Bitstream をダブルクリックしてハードウェアをエクスポートした。
HLS_lap_fil_axim_29_131015.png

・続いて、SDKが立ち上がる。lap_filter_axim_top_0 が 0x49000000 にマップされていた。
HLS_lap_fil_axim_30_131015.png

・Project メニューからClean... を選択して、すべてのプロジェクトをコンパイルすると、FSBLとstandalone_bsp がエラーだった。

・FSBLとstandalone_bsp を消去して、FSBL と FSBL_bspを新規作成した。

・lag_fil_hls_axim プロジェクトを新規作成した。

・lap_fil_hls_axim.c, lap_fil_axim_uty.c, lap_fil_axim_uty.h, を作製した。

・xlap_filter_axim_hw.h を Vivado_HLS\lap_filter_axim\solution1\impl\drivers\lap_filter_axim_top_v1_00_a\src からコピーした。
HLS_lap_fil_axim_31_131016.png

・SDカードに入れるブートイメージを作製した。
HLS_lap_fil_axim_32_131016.png

・u-boot.bin が出来た。
HLS_lap_fil_axim_33_131016.png

・BOOT.bin に書き換えた。
HLS_lap_fil_axim_34_131016.png

・BOOT.bin をSDカードに入れて、Linuxをブート。

・lap_fil_hls_axim のデバック・コンフィギュレーションを作って、デバック。
HLS_lap_fil_axim_35_131016.png

・デバックモードになった。
HLS_lap_fil_axim_36_131016.png

デバックしているが、いまのところ ap_done が上がらずに原因を調査中。

(追記)
Vivado HLSでのSystemC のCo-Simulation をしたところエラーになった。
HLS_lap_fil_axim_37_131016.png

@E [SIM-304] Aborting co-simulation: C TB simulation failed.
@E [SIM-320] Generating test vectors failed.
”@E [SIM-4] *** C/RTL co-simulation finished: FAIL ***


Generating test vectors failed”ということで、よく原因がわからない?

(2013/10/26:追記)
AXI4 Master版ラプラシアン・フィルタIPの制御用ソフトウェアの全ソースは、”Vivado HLS 2013.3 で作ったラプラシアン・フィルタAXI4 Master IPを使う1”を参照。
  1. 2013年10月16日 05:18 |
  2. Co-design
  3. | トラックバック:0
  4. | コメント:0