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

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

FPGAの部屋

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

Vivado ML 2021.1 でデバッグできない2

Vivado ML 2021.1 でデバッグできない1”の続き。

前回は、DFX を含むプロジェクトで、Vivado ML 2021.1 でブロック・デザインで、 Debug を設定し、System ILA IP を実装したが、 Open Hardware Manager した時に ILA ダッシュボードが表示されないという不具合があったということで、DFX を含まないプロジェクトをやってみたが、1 つのプロジェクトは同様に ILA ダッシュボードが表示されなかったが、もう 1 つのより簡単なプロジェクトは正常に ILA ダッシュボードが表示された。今回は、 ILA ダッシュボードが表示されなかったプロジェクトで Debug の数を変化させて ILA ダッシュボードが表示されるか?を調べる。

DFX_filter_test2 プロジェクトの Debug の数は AXI4 Master インターフェースが 2 個、 AXI4-Stream が 3 個、 RGB インターフェースが 1 個だった。
それを、AXI4 Master インターフェースが 2 個と RGB インターフェースが 1 個にしてみる。
ILA_11_210829.png

これで、論理合成、インプリメンテーション、ビットストリームの生成を行って、ハードウェアをエクスポートした。
Viits でプラットフォームをアップデートして、アプリケーション・プロジェクトをビルドし、デバッグ・モードでソフトウェアを起動した。
Vivado で PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target をクリックし、Auto Connect を選択して、ZYBO Z7-20 に接続したところ、 ILA ダッシュボードが表示された。
波形もキャプチャすることができた。
ILA_12_210829.png

RGB インターフェースも見えている。
ILA_13_210829.png

それじゃ、AXI4-Stream インターフェースがダメなのか?ということで、 mt9d111_inf_aixs_0 から vfilp_dma_write_0 に行く AXI4-Stream インターフェースに Debug を設定した。
ILA_14_210830.png

これも同様に、論理合成、インプリメンテーション、ビットストリームの生成を行って、ハードウェアをエクスポートした。
Viits でプラットフォームをアップデートして、アプリケーション・プロジェクトをビルドし、デバッグ・モードでソフトウェアを起動した。
Vivado で PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target をクリックし、Auto Connect を選択して、ZYBO Z7-20 に接続したところ、 ILA ダッシュボードが表示された。
波形もキャプチャすることができた。
ILA_15_210830.png

次に、DMA2axis_0 から through_axis_0 に行く AXI4-Stream インターフェースを追加してみた。これで AXI4 Master インターフェースが 2 個、 AXI4-Stream が 2 個、 RGB インターフェースが 1 個となった。
ILA_16_210830.png

これも同様にしたところ、 ILA ダッシュボードが表示され、波形も表示できた。
ILA_17_210830.png

それじゃ、 Debug の数を AXI4 Master インターフェースが 2 個、 AXI4-Stream が 3 個、 RGB インターフェースが 1 個に戻してみる。
ILA_18_210830.png

これも同様にしたところ、 ILA ダッシュボードが表示され、波形も表示できた。
ILA_19_210830.png

え〜〜。”Vivado ML 2021.1 でデバッグできない1”で最初にやった時は、DFX_filter_test2 プロジェクトの Debug の数が AXI4 Master インターフェースが 2 個、 AXI4-Stream が 3 個、 RGB インターフェースが 1 個で ILA ダッシュボードが表示されなかったが、段々と AXI4-Stream インターフェースを増やしていったら、全部 ILA ダッシュボードが表示された。
なんか不安定なんだろうか? ILA.
  1. 2021年08月31日 05:19 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Vivado ML 2021.1 でデバッグできない1

Zynq の PCAP を使用して DFX する4(Vivado でデバッグできない)”で Vivado ML 2021.1 でブロック・デザインで、 Debug を設定し、System ILA IP を実装したが、 Open Hardware Manager した時に ILA ダッシュボードが表示されないという不具合があった。どのような条件でそうなるかを調べてみよう。

まずは、 DFX を設定してないと大丈夫なのか調べてみよう。
DFX_filter_test_211 プロジェクトから DFX を設定しないプロジェクト DFX_filter_test2 プロジェクトを作成した。
ILA_1_210829.png

ブロック・デザインを示す。
ILA_2_210829.png

System ILA が入っている。

これで、論理合成、インプリメンテーション、ビットストリームの生成を行って、ハードウェアをエクスポートした。
Vitis を起動して、プラットフォームとアプリケーション・プロジェクトを作成し、アプリケーション・ソフトウェアの DFX_filter_test.c を作成した。
アプリケーション・ソフトウェアをデバッグ・モードで起動した。
ILA_3_210829.png

Vivado で PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target をクリックし、Auto Connect を選択して、ZYBO Z7-20 に接続したところ、 ILA ダッシュボードが表示されない。
ILA_4_210829.png

どうやら DFX は関係ないようだ。

次は、”AXI Master インターフェースを含む IP を DFX する1”の DFX_test_211 プロジェクトの DFX がない状態について System ILA を入れて確かめてみよう。

作成した DFX_test2 プロジェクトを示す。
ILA_5_210829.png

ブロック・デザインを示す。
ILA_6_210829.png

これで、論理合成、インプリメンテーション、ビットストリームの生成を行って、ハードウェアをエクスポートした。
Vitis を起動して、プラットフォームとアプリケーション・プロジェクトを作成し、アプリケーション・ソフトウェアの DFX_test.c を作成した。
アプリケーション・ソフトウェアをデバッグ・モードで起動した。
ILA_7_210829.png

Vivado で PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target をクリックし、Auto Connect を選択して、ZYBO Z7-20 に接続したところ、 ILA ダッシュボードが表示された。
ILA_8_210829.png

Vitis で Resume すると、 gtkterm に演算結果が正常に表示された。
ILA_9_210829.png

ILA ダッシュボードに波形が表示された。
ILA_10_210829.png

もしかして、 AXI4 インターフェースだけを Debug すると動作するのか?
次回はそれをやってみよう。
  1. 2021年08月30日 04:20 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Vivado ML 2021.1でボード・ファイルをコピーして、ボード・ファイルをインストールする

Vivado ML 2021.1 は、今までのバージョンの Vivado のボード・ファイルのインストール方法と違って、 New Project ダイアログの Default Part 画面でボードの名前の Status の Install アイコンをクリックしてボード・ファイルをインストールする。(”Vivado ML 2021.1 でボード・ファイルをインストールする”参照)
このやり方で Zybo Z7-20 をインストールして使っていたのだが、たまに Default Part の画面に出てこない時がある。Dafault Part でボード・ファイルを選択できないととっても困るので、やり方を探ってみた。

私のマシンの OS は Ubuntu 18.04 なので、そのつもりで見て欲しい。
Windows では、”VivadoにZyboの設定ファイルを読み込む方法(Vivado ML 2021.1版にも対応)”によると、ボード・ファイルのインストール・フォルダは、”\AppData\Roaming\Xilinx\Vivado\2021.1\xhub\board_store\xilinx_board_store\XilinxBoardStore\Vivado\2021.1\boards\Digilent”ということだった。
それでは、Ubuntu では何処だろう?と考えると、ホーム・ディレクトリの .Xilinx の下だろうと思った。探してみると、”/home/masaaki/.Xilinx/Vivado/2021.1/xhub/board_store/xilinx_board_store/XilinxBoardStore/Vivado/2021.1/boards”がボード・ファイルのインストール・ディレクトリのようだ。
このディレクトリの下に Digilent などの会社のディレクトリがあって、その下にボード・ファイルのディレクトリを入れるようだ。
board_files_1_210828.png

もうすでに zybo-z7-20 のボード・ファイルのディレクトリが入っているがこれは、”XilinxBoardStore/boards/”の Digilent の下からダウンロードしたボード・ファイルのディレクトリを、”/home/masaaki/.Xilinx/Vivado/2021.1/xhub/board_store/xilinx_board_store/XilinxBoardStore/Vivado/2021.1/boards/Digilent”の下にコピーした。

こうするとNew Project ダイアログの Default Part 画面で下の様にリストに出てくるようだ。
board_files_2_210828.png

これでボード・ファイルが出てこなくなることは無いだろう?と思う。使ってみよう。
  1. 2021年08月28日 15:55 |
  2. Vivado
  3. | トラックバック:0
  4. | コメント:0

Zynq の PCAP を使用して DFX する4(Vivado でデバッグできない)

Zynq の PCAP を使用して DFX する3(xdevcfg_polled_example.c をマージする1)”の続き。

前回は、 xdevcfg_polled_example.c を”画像フィルタを DFX する14(DFX_filter_test プロジェクト7)”の DFX_filter_test.c にマージして DFXできたようなのだが、カメラが動作しなくなった。今回は、カメラが動作しない原因を Vivado で Debug を設定し、System ILA IP を実装して確かめてみようとしたが失敗した。

Vivado のブロック・デザインで、 Debug を設定し、System ILA IP を実装した。
PCAP_29_210827.png

Vitis 2021.1 でデバックモードで起動する。
PCAP_21_210826.png

デバックモードの画面の内 xsct の画面を使用する。
まずは、カレントディレクトリを表示する。
pwd
ホーム・ディレクトリにいることが分かった。
PCAP_22_210826.png

ホーム・ディレクトリに lap_filter_axis_partial.bin をコピーした。(”Zynq の PCAP を使用して DFX する2(.bin ファイルの生成)”参照)
PCAP_23_210826.png

lap_filter_axis_partial.bin をメモリにダウンロードした。
dow -data lap_filter_axis_partial.bin 0x11000000
PCAP_24_210826.png

ログを示す。

xsct% pwd
/home/masaaki
xsct% dow -data lap_filter_axis_partial.bin 0x11000000

  0%    0MB   0.0MB/s  ??:?? ETA
 38%    0MB   0.3MB/s  ??:?? ETA
 94%    0MB   0.4MB/s  ??:?? ETA
100%    0MB   0.4MB/s  00:01    
Successfully downloaded /home/masaaki/lap_filter_axis_partial.bin
xsct% 


Resume ボタンをクリックして、ソフトウェアを走らせる。
PCAP_25_210826.png

gtkterm に ”Press the key.”が表示された。
カメラ画像が表示された。
PCAP_27_210826.jpg

この時点で、 Vivado で PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target -> Auto Connect を選択する。
ILA ダッシュボードが表示されるはずが表示されない。。。
PCAP_30_210827.png

DFX ではこの方法でのデバッグはできないのかな?
  1. 2021年08月27日 04:26 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

Zynq の PCAP を使用して DFX する3(xdevcfg_polled_example.c をマージする1)

”Zynq の PCAP を使用して DFX する3(embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/)”の続き。

前回は、”embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/”に良いサンプルがあったので、その内の xdevcfg_selftest_example.c と xdevcfg_polled_example.c をやってみた。今回は、その内の xdevcfg_polled_example.c を”画像フィルタを DFX する14(DFX_filter_test プロジェクト7)”の DFX_filter_test.c にマージして DFX してみよう。

さて、 xdevcfg_polled_example.c を DFX_filter_test.c にマージした。
PCAP_20_210826.png

デバックモードで起動する。
PCAP_21_210826.png

デバックモードの画面の内 xsct の画面を使用する。
まずは、カレントディレクトリを表示する。
pwd
ホーム・ディレクトリにいることが分かった。
PCAP_22_210826.png

ホーム・ディレクトリに lap_filter_axis_partial.bin をコピーした。(”Zynq の PCAP を使用して DFX する2(.bin ファイルの生成)”参照)
PCAP_23_210826.png

lap_filter_axis_partial.bin をメモリにダウンロードした。
dow -data lap_filter_axis_partial.bin 0x11000000
PCAP_24_210826.png

ログを示す。

xsct% pwd
/home/masaaki
xsct% dow -data lap_filter_axis_partial.bin 0x11000000

  0%    0MB   0.0MB/s  ??:?? ETA
 38%    0MB   0.3MB/s  ??:?? ETA
 94%    0MB   0.4MB/s  ??:?? ETA
100%    0MB   0.4MB/s  00:01    
Successfully downloaded /home/masaaki/lap_filter_axis_partial.bin
xsct% 


Resume ボタンをクリックして、ソフトウェアを走らせる。
PCAP_25_210826.png

gtkterm に ”Press the key.”が表示された。
カメラ画像が表示された。
PCAP_27_210826.jpg

Enter キーを押すと、”Download the partial bit file of the Laplacian filter and press the key.”が表示された。
Enter キーを押すと、 ”Press the key.”が表示された。
表示画像はラプラシアン・フィルタのようだが、止まっていて、カメラの前で手を振っても画像に反映されない。
PCAP_28_210826.jpg

DFX は成功したようだが?まだ不可解な部分がある。
もしかして、PS の FCLK_RESET0_N が 0 で全体をリセットしたのか?

DFX_filter_test.c を貼っておく。なお、全部貼ると長いので、 cam_reg_set() を除いたコードを貼っておく。 cam_reg_set() については、”画像フィルタを DFX する13(DFX_filter_test プロジェクト6)”を参照のこと。

// DFX_filter_test.c
// 2021/08/08 by marsee
// 2021/08/09 : Stop the operation of DMA2axis IP on the video side and restart it.
// 2021/08/26 : PCAP partial configuration (Quoted from the following URL)
//              https://github.com/Xilinx/embeddedsw/blob/master/XilinxProcessorIPLib/drivers/devcfg/examples/xdevcfg_polled_example.c

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include "xil_io.h"
#include "xparameters.h"
#include "xdevcfg.h"

#include "xvflip_dma_write.h"
#include "xdma2axis.h"
#include "xthrough_axis.h"
#include "xlap_filter_axis_hw.h"
#include "xsobel_filter_axis_hw.h"

#define CAMERA_DATA_DMA_ADDR    0x10000000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

#define XLAP_FILTER_AXIS_BASEADDR   0x40000000
#define XSOBEL_FILTER_AXIS_BASEADDR 0x40000000

/************************** Constant Definitions *****************************/
/*
 * The following constants map to the XPAR parameters created in the
 * xparameters.h file. They are only defined here such that a user can easily
 * change all the needed parameters in one place.
 */
#define DCFG_DEVICE_ID      XPAR_XDCFG_0_DEVICE_ID

/*
 * The BIT_STREAM_LOCATION is a dummy address and BIT_STREAM_SIZE_WORDS is a
 * dummy size. This has to replaced with the actual location/size of the bitstream.
 *
 * The 2 LSBs of the Source/Destination address when equal to 2�b01 indicate
 * the last DMA command of an overall transfer.
 * The 2 LSBs of the BIT_STREAM_LOCATION in this example is set to 2b01
 * indicating that this is the last DMA transfer (and the only one).
 */
#define BIT_STREAM_LOCATION 0x11000001  /* Bitstream location */
#define BIT_STREAM_SIZE_WORDS   0x20000     /* Size in Words (32 bit)*/

/*
 * SLCR registers
 */
#define SLCR_LOCK   0xF8000004 /**< SLCR Write Protection Lock */
#define SLCR_UNLOCK 0xF8000008 /**< SLCR Write Protection Unlock */
#define SLCR_LVL_SHFTR_EN 0xF8000900 /**< SLCR Level Shifters Enable */
#define SLCR_PCAP_CLK_CTRL XPAR_PS7_SLCR_0_S_AXI_BASEADDR + 0x168 /**< SLCR
                    * PCAP clock control register address
                    */

#define SLCR_PCAP_CLK_CTRL_EN_MASK 0x1
#define SLCR_LOCK_VAL   0x767B
#define SLCR_UNLOCK_VAL 0xDF0D

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);
int XDcfgPolledExample(XDcfg *DcfgInstPtr, u16 DeviceId);

XDcfg DcfgInstance;     /* Device Configuration Interface Instance */

void cam_i2c_init(volatile uint32_t *ov5642_axi_iic) {
    ov5642_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_axi_iic[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 uint32_t *ov5642_axi_iic, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}

int main(){
    XVflip_dma_write XVfilp_dma_write_ap;
    XDma2axis XDma2axis_ap;
    XThrough_axis XTh_axis_ap;
    int inbyte_in;
    int Status;

    XVflip_dma_write_Initialize(&XVfilp_dma_write_ap, 0);
    XDma2axis_Initialize(&XDma2axis_ap, 0);
    XThrough_axis_Initialize(&XTh_axis_ap, 0);

    XVflip_dma_write_Set_fb0_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb1_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb2_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XDma2axis_Set_x_size(&XDma2axis_ap, HORIZONTAL_PIXELS);
    XDma2axis_Set_y_size(&XDma2axis_ap, VERTICAL_LINES);
    XDma2axis_Set_in_V(&XDma2axis_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XThrough_axis_Set_x_size(&XTh_axis_ap, (u32)HORIZONTAL_PIXELS);
    XThrough_axis_Set_y_size(&XTh_axis_ap, (u32)VERTICAL_LINES);

    // vflip_dma_write start
    XVflip_dma_write_Start(&XVfilp_dma_write_ap);
    XVflip_dma_write_EnableAutoRestart(&XVfilp_dma_write_ap);

    // CMOS Camera initialize, ov5642
    cam_i2c_init((volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR);
    cam_reg_set((volatile uint32_t *)(XPAR_AXI_IIC_0_BASEADDR), (uint32_t)0x78); // OV5642 register set
    Xil_Out32(XPAR_MT9D111_INF_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // ov5642 AXI4-Stream Start
    Xil_Out32((XPAR_MT9D111_INF_AXIS_0_BASEADDR+4), 0);

    // bitmap_disp_cont_axis start
    Xil_Out32(XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // dummy address, start

    // through_axis start
    XThrough_axis_Start(&XTh_axis_ap);
    XThrough_axis_EnableAutoRestart(&XTh_axis_ap);

    // DMA2axis start
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    XThrough_axis_DisableAutoRestart(&XTh_axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);
    while(XThrough_axis_IsIdle(&XTh_axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Laplacian filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Status = XDcfgPolledExample(&DcfgInstance, DCFG_DEVICE_ID);
    //Status = XST_SUCCESS;
    if (Status != XST_SUCCESS) {
        xil_printf("Dcfg Polled Example Test Failed\r\n");
        return XST_FAILURE;
    }

    xil_printf("Successfully ran Dcfg Polled Example Test\r\n");

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // laplacian filter start
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    XThrough_axis_DisableAutoRestart(&XTh_axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);
    while(XThrough_axis_IsIdle(&XTh_axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Sobel filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // sobel filter start
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    return(0);
}

/*****************************************************************************/
/**
* This function downloads the Non secure bit stream to the FPGA fabric
* using the Device Configuration Interface.
*
* @param    DcfgInstPtr is a pointer to the instance of XDcfg driver.
* @param    DeviceId is the unique device id of the device.
*
* @return
*       - XST_SUCCESS if successful
*       - XST_FAILURE if unsuccessful
*
* @note     None
*
****************************************************************************/
int XDcfgPolledExample(XDcfg *DcfgInstPtr, u16 DeviceId)
{
    int Status;
    u32 IntrStsReg = 0;
    u32 StatusReg;
    u32 PartialCfg = 0;

    XDcfg_Config *ConfigPtr;

    /*
     * Initialize the Device Configuration Interface driver.
     */
    ConfigPtr = XDcfg_LookupConfig(DeviceId);

    /*
     * This is where the virtual address would be used, this example
     * uses physical address.
     */
    Status = XDcfg_CfgInitialize(DcfgInstPtr, ConfigPtr,
                    ConfigPtr->BaseAddr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }


    Status = XDcfg_SelfTest(DcfgInstPtr);
    if (Status != XST_SUCCESS) {
        return XST_FAILURE;
    }

    /*
     * Check first time configuration or partial reconfiguration
     */
    IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
    if (IntrStsReg & XDCFG_IXR_DMA_DONE_MASK) {
        PartialCfg = 1;
    }

    /*
     * Enable the pcap clock.
     */
    StatusReg = Xil_In32(SLCR_PCAP_CLK_CTRL);
    if (!(StatusReg & SLCR_PCAP_CLK_CTRL_EN_MASK)) {
        Xil_Out32(SLCR_UNLOCK, SLCR_UNLOCK_VAL);
        Xil_Out32(SLCR_PCAP_CLK_CTRL,
                (StatusReg | SLCR_PCAP_CLK_CTRL_EN_MASK));
        Xil_Out32(SLCR_UNLOCK, SLCR_LOCK_VAL);
    }

    /*
     * Disable the level-shifters from PS to PL.
     */
    if (!PartialCfg) {
        Xil_Out32(SLCR_UNLOCK, SLCR_UNLOCK_VAL);
        Xil_Out32(SLCR_LVL_SHFTR_EN, 0xA);
        Xil_Out32(SLCR_LOCK, SLCR_LOCK_VAL);
    }

    /*
     * Select PCAP interface for partial reconfiguration
     */
    if (PartialCfg) {
        XDcfg_EnablePCAP(DcfgInstPtr);
        XDcfg_SetControlRegister(DcfgInstPtr, XDCFG_CTRL_PCAP_PR_MASK);
    }

    /*
     * Clear the interrupt status bits
     */
    XDcfg_IntrClear(DcfgInstPtr, (XDCFG_IXR_PCFG_DONE_MASK |
                    XDCFG_IXR_D_P_DONE_MASK |
                    XDCFG_IXR_DMA_DONE_MASK));

    /* Check if DMA command queue is full */
    StatusReg = XDcfg_ReadReg(DcfgInstPtr->Config.BaseAddr,
                XDCFG_STATUS_OFFSET);
    if ((StatusReg & XDCFG_STATUS_DMA_CMD_Q_F_MASK) ==
            XDCFG_STATUS_DMA_CMD_Q_F_MASK) {
        return XST_FAILURE;
    }

    /*
     * Download bitstream in non secure mode
     */
    XDcfg_Transfer(DcfgInstPtr, (u8 *)BIT_STREAM_LOCATION,
            BIT_STREAM_SIZE_WORDS,
            (u8 *)XDCFG_DMA_INVALID_ADDRESS,
            0, XDCFG_NON_SECURE_PCAP_WRITE);

    /* Poll IXR_DMA_DONE */
    IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
    while ((IntrStsReg & XDCFG_IXR_DMA_DONE_MASK) !=
            XDCFG_IXR_DMA_DONE_MASK) {
        IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
    }

    if (PartialCfg) {
        /* Poll IXR_D_P_DONE */
        while ((IntrStsReg & XDCFG_IXR_D_P_DONE_MASK) !=
                XDCFG_IXR_D_P_DONE_MASK) {
            IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
        }
    } else {
        /* Poll IXR_PCFG_DONE */
        while ((IntrStsReg & XDCFG_IXR_PCFG_DONE_MASK) !=
                XDCFG_IXR_PCFG_DONE_MASK) {
            IntrStsReg = XDcfg_IntrGetStatus(DcfgInstPtr);
        }
        /*
         * Enable the level-shifters from PS to PL.
         */
        Xil_Out32(SLCR_UNLOCK, SLCR_UNLOCK_VAL);
        Xil_Out32(SLCR_LVL_SHFTR_EN, 0xF);
        Xil_Out32(SLCR_LOCK, SLCR_LOCK_VAL);
    }

    return XST_SUCCESS;
}


BIT_STREAM_LOCATION だが、その説明のDeepL 翻訳結果を貼っておく。

Source/Destinationアドレスの2LSBが2b01に等しい場合は、全体の転送の最後のDMAコマンドを示します。
この例のBIT_STREAM_LOCATIONの2つのLSBは2b01に設定され、これが最後のDMA転送(そして唯一の転送)であることを示しています。

  1. 2021年08月26日 05:14 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

Zynq の PCAP を使用して DFX する3(embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/)

Zynq の PCAP を使用して DFX する2(.bin ファイルの生成)”の続き。

前回は、ソフトウェアから DFX を制御したいということで、”Partial Reconfiguration by PCAP: bitstream size not an integer of words?”を参考にして、パーシャル・ビット・ファイルから bin ファイルを生成した。今回は、”embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/”に良いサンプルがあったので、その内の xdevcfg_selftest_example.c と xdevcfg_polled_example.c をやってみる。

embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/”という良いサンプルがあった。
PCAP_19_210825.png

とりあえず、 xdevcfg_selftest_example.c を実行してみよう。
画像フィルタを DFX する14(DFX_filter_test プロジェクト7)”で使用した Vitis 2021.1 のワークスペースを利用する。
当初の予定は独自のコードを作って試してみようということだったので、 DcfgSelTestExample というアプリケーション・プロジェクトを作成した。
DcfgSelTestExample_system -> DcfgSelTestExample -> src に xdevcfg_selftest_example.c ファイルを新規作成し、”embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/xdevcfg_selftest_example.c”のコードをコピー&ペーストした。
PCAP_13_210825.png

ビルドして、Run ボタンをクリックして、実行したところ、gtkterm に成功の表示が出た。
PCAP_14_210825.png

xdevcdg.h を示す。
PCAP_15_210825.png

XDcfg_SelfTest() を示す。
PCAP_16_210825.png

次に”embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/xdevcfg_polled_example.c”をやってみる。
xdevcfg_polled_example.c は PCAP 経由でビット・ファイルをコンフィギュレーションするサンプルのようだ。これを修正すれば、私の用途に使えそうだ。

xdevcfg_polled_example アプリケーション・プロジェクトを作成した。
xdevcfg_polled_example_system -> xdevcfg_polled_example -> src に xdevcfg_polled_example.c ファイルを新規作成して、”embeddedsw/XilinxProcessorIPLib/drivers/devcfg/examples/xdevcfg_polled_example.c”からコピー&ペーストした。
PCAP_17_210825.png

ビルドしてから Run すると、成功した。
PCAP_18_210825.png
  1. 2021年08月25日 05:00 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

Zynq の PCAP を使用して DFX する2(.bin ファイルの生成)

Zynq の PCAP を使用して DFX する1(情報収集)”の続き。

前回は、ソフトウェアから DFX を制御したいということで、Zynq 系で使用できるプロセッサ コンフィギュレーション アクセス ポート (PCAP)について情報収集を行った。今回は、その内の”Partial Reconfiguration by PCAP: bitstream size not an integer of words?”を参考にして、パーシャル・ビット・ファイルから bin ファイルを生成する。

XDcfg_TransferBitfile() を使用して DFX するためには bit ファイルから bin ファイルを生成する必要あるそうだ。(”How to use PCAP to config the PL in zynq”参照)

bin ファイルの生成方法は Vivado の TCL コンソールで write_cfgmem コマンドを使うことだそうだ。(”Partial Reconfiguration by PCAP: bitstream size not an integer of words?”参照)

最初に child_0_impl_1 の DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit を lap_filter_axis_partial.bin に変換する。
PCAP_7_210824.png

Vivado の TCL コンソールで cd コマンドを使用した。
cd /media/masaaki/Ubuntu_Disk/HDL/ZYBO_Z7-20/DFX_filter_test_211/DFX_filter_test_211.runs/child_0_impl_1

write_cfgmem コマンドを使用して bin ファイルを生成した。
write_cfgmem -format BIN -interface SMAPx32 -disablebitswap -loadbit "up 0x0 DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit" lap_filter_axis_partial.bin
PCAP_8_210824.png

write_cfgmem -format BIN -interface SMAPx32 -disablebitswap -loadbit "up 0x0 DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit" lap_filter_axis_partial.bin
Command: write_cfgmem -format BIN -interface SMAPx32 -disablebitswap -loadbit {up 0x0 DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit} lap_filter_axis_partial.bin
Creating config memory files...
INFO: [Writecfgmem 68-23] Start address provided has been multiplied by a factor of 4 due to the use of interface SMAPX32.
Creating bitstream load up from address 0x00000000
Loading bitfile DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit
WARNING: [Writecfgmem 68-32] Bitfile DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit is a Dynamic Function eXchange bitfile. It is not possible to validate that this bitfile is compatible with the SMAPX32 interface.
Memory size is calculated to be 512 KB
Writing file ./lap_filter_axis_partial.bin
Writing log file ./lap_filter_axis_partial.prm
===================================
Configuration Memory information
===================================
File Format        BIN
Interface          SMAPX32
Size               512K
Start Address      0x00000000
End Address        0x0007FFFF

Addr1         Addr2         Date                    File(s)
0x00000000    0x00072863    Aug 21 07:14:31 2021    DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit
1 Infos, 1 Warnings, 0 Critical Warnings and 0 Errors encountered.
write_cfgmem completed successfully


lap_filter_axis_partial.bin が生成された。
PCAP_9_210824.png


child1_impl_1 の DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit を sobel_filter_axis_partial.bin に変換する。
PCAP_10_210824.png

Vivado の TCL コンソールで cd コマンドを使用した。
cd /media/masaaki/Ubuntu_Disk/HDL/ZYBO_Z7-20/DFX_filter_test_211/DFX_filter_test_211.runs/child_1_impl_1

write_cfgmem コマンドを使用して bin ファイルを生成した。
write_cfgmem -format BIN -interface SMAPx32 -disablebitswap -loadbit "up 0x0 DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit" sobel_filter_axis_partial.bin
PCAP_11_210824.png

write_cfgmem -format BIN -interface SMAPx32 -disablebitswap -loadbit "up 0x0 DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit" sobel_filter_axis_partial.bin
Command: write_cfgmem -format BIN -interface SMAPx32 -disablebitswap -loadbit {up 0x0 DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit} sobel_filter_axis_partial.bin
Creating config memory files...
INFO: [Writecfgmem 68-23] Start address provided has been multiplied by a factor of 4 due to the use of interface SMAPX32.
Creating bitstream load up from address 0x00000000
Loading bitfile DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit
WARNING: [Writecfgmem 68-32] Bitfile DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit is a Dynamic Function eXchange bitfile. It is not possible to validate that this bitfile is compatible with the SMAPX32 interface.
Memory size is calculated to be 512 KB
Writing file ./sobel_filter_axis_partial.bin
Writing log file ./sobel_filter_axis_partial.prm
===================================
Configuration Memory information
===================================
File Format        BIN
Interface          SMAPX32
Size               512K
Start Address      0x00000000
End Address        0x0007FFFF

Addr1         Addr2         Date                    File(s)
0x00000000    0x00072863    Aug 21 07:14:37 2021    DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit
1 Infos, 1 Warnings, 0 Critical Warnings and 0 Errors encountered.
write_cfgmem completed successfully


sobel_filter_axis_partial.bin が生成された。
PCAP_12_210824.png
  1. 2021年08月24日 05:24 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

Zynq の PCAP を使用して DFX する1(情報収集)

いままで、DFX をやってきたが、Vivado で RM をリコンフィギュレーションしてきた。この辺りでソフトウェアから DFX を制御したいということで、Zynq 系で使用できるプロセッサ コンフィギュレーション アクセス ポート (PCAP)について情報収集していこう。

PCAP でのコンフィギュレーションについては、”Zynq-7000 SoC テクニカル リファレンス マニュアル UG585 (v1.10) 2015 年 2 月 23 日”の 192 ページからの”6.4 デバイス ブートおよび PL コンフ ィギュレーシ ョ ン”に書いてあった。

Zynq-7000 SoC テクニカル リファレンス マニュアル UG585 (v1.10) 2015 年 2 月 23 日”の 192 ページからの”6.4 デバイス ブートおよび PL コンフ ィギュレーシ ョ ン”から図と文章を引用する。

”6.4.1 PS ソフ トウェアによる PL 制御”を引用する。
PCAP_1_210823.png

”PS ソフ トウェアによる PL 初期化”から引用する。
1. [PCFG_PROG_B] 信号を High にする。
2. [PCFG_PROG_B] 信号を Low にする。
3. [PCAP_INIT] ステータスがリセットされているかポーリングする。
4. [PCFG_PROG_B] 信号を High にする。
5. [PCAP_INIT] ステータスがセットされているかポーリングする。

”6.4.3 PL への PCAP ブリッジ”から引用する。
PCAP ブリ ッジ (AXI-PCAP ブリッジまたは PCAP インターフェイス と も呼ぶ) は、ビットストリームによ る PL コンフィギュレーション、 ブート イメージおよびビットストリームの復号化、 ファイルの認証に使用できます。
PCAP_2_210823.png

DMA 転送を開始するには、 4 つの DMA レジ スタに次の順序で書き込みます。
1. ソース アドレス レジスタ devcfg.DMA_SRC_ADDR
2. デスティネーション アドレス レジスタ devcfg.DMA_DST_ADDR
3. ソース長レジスタ devcfg.DMA_SRC_LEN
4. デスティネーション長レジスタ devcfg.DMA_DEST_LEN (このレジスタへの書き込みにより DMA 転送が開始)

”6.4.4 PCAP データパス コンフィギュレーション”
PCAP でコンフィギュレーションする時のブロック図”図 6-18 : 非セキュアおよびセキュア PL ビ ッ ト ス ト リーム パスの図”を引用する。
PCAP_3_210823.png

”PL の初期化およびコンフィギュレーション レジスタ”
”表 6-23 : PL の制御およびステータス レジスタ ビット”を引用する。
PCAP_4_210823.png
PCAP_5_210823.png
PCAP_6_210823.png

PCAP の資料は Xilinx Forum にもある。
How to use PCAP to config the PL in zynq
Zynq Z0720 PCAP Readback

アプリケーションノートも 2 つ参考になりそうだ。
Zynq-7000 All Programmable SoC デバイスにおけるハー ドウェア アクセラレーターのパーシャル リコンフィギュレーション
xapp1159.zip

Zynq‐7000 AP SoC プロセ ッサにおける Vivado Design Suite を使用したハー ドウェア アクセ ラレータのパーシ ャル リコンフィギュレーション
xapp1231-partial-refonfig-hw-axxelerator-vivado.zip

ライセンスのためブログに書けないが、そのものズバリなので、”Zynq‐7000 AP SoC プロセ ッサにおける Vivado Design Suite を使用したハー ドウェア アクセ ラレータのパーシ ャル リコンフィギュレーション”をやってみよう。

(追加)
、”Zynq‐7000 AP SoC プロセ ッサにおける Vivado Design Suite を使用したハー ドウェア アクセ ラレータのパーシ ャル リコンフィギュレーション”の 14 ページの”デバイス コンフィギュレーションおよびブート フロー”から引用。

1 つのコ ンフィ ギュレーシ ョン エンジンがフル コンフィ ギュ レーション とパーシャル コンフィギュ レーシ ョ ンの両方を管理し ます。パーシャル ビット ストリームにはコンフィギュ レーション フ レームのア ド レス情報が含まれている ため、 これを PL へロードする際に、 リコンフィギャラブル モジュールの物理的な位置を把握し ている必要はあ り ません。


18 ページから引用。

PCAP イ ン ターフ ェ イ ス経由でパーシャル ビット ストリームを転送する前に、is_partial_bitstream デバイス属性が 1 に設定 されている必要があります。 DevC デバイス ノード上での書き込みファイル動作によ り 、 パーシャル ビット ストリームが転送されます。


is_partial_bitstream デバイス属性は Linux の devcfg の属性のようです。(”Partial reconfiguration in linux”参照)

パーシャル・リコンフィギュレーションの資料
Partial Reconfiguration: XDcfg
Partial Reconfiguration by PCAP: bitstream size not an integer of words?
Partial Reconfiguration: Measuring Zynq PCAP Reconfiguration Time
  1. 2021年08月23日 03:38 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する14(DFX_filter_test プロジェクト7)

画像フィルタを DFX する13(DFX_filter_test プロジェクト6)”の続き。

前回は、通過 IP 、ラプラシアン・フィルタ IP 、ソーベル・フィルタ IP の 3 個の IP を DFX で切り替えるべく Vivado 2021.1 の DFX_filter_test プロジェクトに追加するということで、 Vitis 2021.1 を起動して、プラットフォームとアプリケーション・プロジェクトを作成し、ソースコードを作成した。それをビルドして実機で確認することができた。今回は、そのプロジェクトで DFX として、ラプラシアン・フィルタとソーベル・フィルタを切り替えて動作させてみよう。

DFX_filter_test.c を書き換えて、ラプラシアン・フィルタとソーベル・フィルタのパーシャル・ビット・ファイルをコンフィギュレーションできるようにした。更に、 xlap_filter_axis_hw.h と xsobel_filter_axis_hw.h をインポートした。
DFX2_122_210822.png

ここに、OV5642 のレジスタをセットするための関数 cam_reg_set() を除いたコードを貼っておく。 cam_reg_set() については、”画像フィルタを DFX する13(DFX_filter_test プロジェクト6)”を参照のこと。

// DFX_filter_test.c
// 2021/08/08 by marsee
// 2021/08/09 : Stop the operation of DMA2axis IP on the video side and restart it.

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

#include "xvflip_dma_write.h"
#include "xdma2axis.h"
#include "xthrough_axis.h"
#include "xlap_filter_axis_hw.h"
#include "xsobel_filter_axis_hw.h"

#define CAMERA_DATA_DMA_ADDR    0x10000000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

#define XLAP_FILTER_AXIS_BASEADDR   0x40000000
#define XSOBEL_FILTER_AXIS_BASEADDR 0x40000000

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);

void cam_i2c_init(volatile uint32_t *ov5642_axi_iic) {
    ov5642_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_axi_iic[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 uint32_t *ov5642_axi_iic, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}

int main(){
    XVflip_dma_write XVfilp_dma_write_ap;
    XDma2axis XDma2axis_ap;
    XThrough_axis XTh_axis_ap;
    int inbyte_in;

    XVflip_dma_write_Initialize(&XVfilp_dma_write_ap, 0);
    XDma2axis_Initialize(&XDma2axis_ap, 0);
    XThrough_axis_Initialize(&XTh_axis_ap, 0);

    XVflip_dma_write_Set_fb0_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb1_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb2_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XDma2axis_Set_x_size(&XDma2axis_ap, HORIZONTAL_PIXELS);
    XDma2axis_Set_y_size(&XDma2axis_ap, VERTICAL_LINES);
    XDma2axis_Set_in_V(&XDma2axis_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XThrough_axis_Set_x_size(&XTh_axis_ap, (u32)HORIZONTAL_PIXELS);
    XThrough_axis_Set_y_size(&XTh_axis_ap, (u32)VERTICAL_LINES);

    // vflip_dma_write start
    XVflip_dma_write_Start(&XVfilp_dma_write_ap);
    XVflip_dma_write_EnableAutoRestart(&XVfilp_dma_write_ap);

    // CMOS Camera initialize, ov5642
    cam_i2c_init((volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR);
    cam_reg_set((volatile uint32_t *)(XPAR_AXI_IIC_0_BASEADDR), (uint32_t)0x78); // OV5642 register set
    Xil_Out32(XPAR_MT9D111_INF_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // ov5642 AXI4-Stream Start
    Xil_Out32((XPAR_MT9D111_INF_AXIS_0_BASEADDR+4), 0);

    // bitmap_disp_cont_axis start
    Xil_Out32(XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // dummy address, start

    // through_axis start
    XThrough_axis_Start(&XTh_axis_ap);
    XThrough_axis_EnableAutoRestart(&XTh_axis_ap);

    // DMA2axis start
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Laplacian filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // laplacian filter start
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR+XLAP_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XLAP_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Download the partial bit file of the Sobel filter and press the key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    // sobel filter start
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_ROW_DATA, (u32)VERTICAL_LINES);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR+XSOBEL_FILTER_AXIS_CONTROL_ADDR_COL_DATA, (u32)HORIZONTAL_PIXELS);
    Xil_Out32(XSOBEL_FILTER_AXIS_BASEADDR, (u32)0x81);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    return(0);
}


Vitis の Explorer 画面で DFX_filter_test_system を選択し、Run ボタンをクリックする。
gtkterm の画面に”Press the key”と表示された。
この状態では通常のカメラ画像が表示されている。
DFX2_123_210822.jpg

gtkterm 画面で何かのキーを押した。
”Download the partial bit file of the Laplacian filter and press the key.”が表示された。
DFX2_117_210821.png

Vivado で PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target -> Auto Connect を選択する。
HARDWARE MANAGER が表示された。
Program device をクリックする。
DFX2_121_210821.png

DFX_filter_test_i_filter_lap_filter_axis_inst_0_partial.bit を指定してコンフィギュレーションした。
DFX2_118_210821.png

gtkterm で何かキーを押すと、ラプラシアン・フィルタ画像がディスプレイに表示された。
ただしスタート位置が間違っている。
DFX2_124_210822.jpg

もう一度、何かキーを押すと、”Download the partial bit file of the Sobel filter and press the key.”が表示された。
DFX2_119_210821.png

Vivado で DFX_filter_test_i_filter_sobel_filter_axis_inst_0_partial.bit をコンフィギュレーションした。
DFX2_120_210819.png

何かキーを押すと、ソーベル・フィルタの画面がディスプレイに表示された。
これもスタート位置が間違っている。
DFX2_125_210822.jpg

これで、手動での DFX はうまく行ったと思う。
ディスプレイ表示にはバグというかビットマップ・ディスプレイ・コントローラの仕様による不具合はあったが。。。
  1. 2021年08月22日 07:41 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する13(DFX_filter_test プロジェクト6)

画像フィルタを DFX する12(DFX_filter_test プロジェクト5)”の続き。

前回は、通過 IP 、ラプラシアン・フィルタ IP 、ソーベル・フィルタ IP の 3 個の IP を DFX で切り替えるべく Vivado 2021.1 の DFX_filter_test プロジェクトに追加するということで、Generate Output Products、 Dynamic Function eXchange Wizard 、 Pblock の設定、ビットストリームの生成を行った。今回は、ハードウェアをエクスポートし、Vitis を立ちあげて、ディスプレイに表示した。その後で、表示を止めて再表示させた。再表示はできたのだが、画面の表示がおかしくなってしまった。

ハードウェアのエクスポートを行った。
DFX_filter_test_211 ディレクトリに DFX_filter_test_wrapper.xsa が生成された。

Vivado の Tools メニューから Launch Vitis IDE を選択して Vitis を起動する。
DFX_filter_test_211 ディレクトリの下の vitis_work ディレクトリを指定して、ワークスペースに指定した。

Vitis IDE が起動した。
DFX_filter_test_wrapper プラットフォームと、DFX_filter_test アプリケーション・プロジェクトがすでに生成されている。(”画像フィルタを DFX する3(DFX_filter_test プロジェクト2)”参照)
DFX2_105_210818.png

今回の回路用に DFX_filter_test.c を変更した。
DFX2_106_210818.png

アプリケーション・ソフトウェアを Run したところ、画面が表示されない。。。
そこで、デバックモードで Vitis を Run したところ、 Through_axis を設定しようとした時に停止するのが分かった。
DFX2_107_210818.png

ブロック・デザインを確認したところ、 dfx_decoupler_0 の decouple_status が proc_sys_reset_0 の 負入力の aux_reset_in に入っている。ここは正入力の必要がある。
DFX2_108_210819.png

proc_sys_reset_0 をダブルクリックして設定画面を開いた。
Auxilary Reset の Aux Reset Logic Level を 0 から 1 に変更した。
DFX2_109_210819.png

aux_reset_in が正入力に変更できた。
DFX2_110_210819.png

ブロック・デザイン全体を示す。
DFX2_111_210819.png

ハードウェアをエクスポートして、Vitis で DFX_filter_test_wrapper プラットフォームをアップデートした。
DFX_filter_test_system をリビルドした。
DFX2_112_210819.png

gtk_term を起動して、アプリケーション・ソフトウェアを Run すると、

The display stops when you press any key.

と表示された。
この状態でカメラ画像がディスプレイに表示されている。
DFX2_114_210820.jpg

Enter キーを押すと、画像が黒一色になった。

The display resumes when you press any key.

と表示された。
Enter キーを押すとカメラ画像が再度表示されたが、位置がずれている。
DFX2_115_210820.jpg

gtkterm の画像を示す。
DFX2_113_210819.png

DFX_filter_test.c を貼っておく。

// DFX_filter_test.c
// 2021/08/08 by marsee
// 2021/08/09 : Stop the operation of DMA2axis IP on the video side and restart it.

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

#include "xvflip_dma_write.h"
#include "xdma2axis.h"
#include "xthrough_axis.h"

#define CAMERA_DATA_DMA_ADDR    0x10000000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);

void cam_i2c_init(volatile uint32_t *ov5642_axi_iic) {
    ov5642_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_axi_iic[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 uint32_t *ov5642_axi_iic, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}

int main(){
    XVflip_dma_write XVfilp_dma_write_ap;
    XDma2axis XDma2axis_ap;
    XThrough_axis XTh_axis_ap;
    int inbyte_in;

    XVflip_dma_write_Initialize(&XVfilp_dma_write_ap, 0);
    XDma2axis_Initialize(&XDma2axis_ap, 0);
    XThrough_axis_Initialize(&XTh_axis_ap, 0);

    XVflip_dma_write_Set_fb0_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb1_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb2_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XDma2axis_Set_x_size(&XDma2axis_ap, HORIZONTAL_PIXELS);
    XDma2axis_Set_y_size(&XDma2axis_ap, VERTICAL_LINES);
    XDma2axis_Set_in_V(&XDma2axis_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XThrough_axis_Set_x_size(&XTh_axis_ap, (u32)HORIZONTAL_PIXELS);
    XThrough_axis_Set_y_size(&XTh_axis_ap, (u32)VERTICAL_LINES);

    // vflip_dma_write start
    XVflip_dma_write_Start(&XVfilp_dma_write_ap);
    XVflip_dma_write_EnableAutoRestart(&XVfilp_dma_write_ap);

    // CMOS Camera initialize, ov5642
    cam_i2c_init((volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR);
    cam_reg_set((volatile uint32_t *)(XPAR_AXI_IIC_0_BASEADDR), (uint32_t)0x78); // OV5642 register set
    Xil_Out32(XPAR_MT9D111_INF_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // ov5642 AXI4-Stream Start
    Xil_Out32((XPAR_MT9D111_INF_AXIS_0_BASEADDR+4), 0);

    // bitmap_disp_cont_axis start
    Xil_Out32(XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // dummy address, start

    // through_axis start
    XThrough_axis_Start(&XTh_axis_ap);
    XThrough_axis_EnableAutoRestart(&XTh_axis_ap);

    // DMA2axis start
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("The display stops when you press any key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("The display resumes when you press any key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 0: Turn decoupling off

    XThrough_axis_Set_x_size(&XTh_axis_ap, (u32)HORIZONTAL_PIXELS);
    XThrough_axis_Set_y_size(&XTh_axis_ap, (u32)VERTICAL_LINES);
    XThrough_axis_Start(&XTh_axis_ap);
    XThrough_axis_EnableAutoRestart(&XTh_axis_ap);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    return(0);
}

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr){
    cam_i2c_write(axi_iic, device_addr, 0x3103, 0x93);
    cam_i2c_write(axi_iic, device_addr, 0x3008, 0x82);
    cam_i2c_write(axi_iic, device_addr, 0x3017, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x3018, 0xfc);
    cam_i2c_write(axi_iic, device_addr, 0x3810, 0xc2);
    cam_i2c_write(axi_iic, device_addr, 0x3615, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x3000, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3001, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3002, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3003, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3000, 0xf8);
    cam_i2c_write(axi_iic, device_addr, 0x3001, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x3002, 0x5c);
    cam_i2c_write(axi_iic, device_addr, 0x3003, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3004, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3005, 0xb7);
    cam_i2c_write(axi_iic, device_addr, 0x3006, 0x43);
    cam_i2c_write(axi_iic, device_addr, 0x3007, 0x37);
    cam_i2c_write(axi_iic, device_addr, 0x3011, 0x08); // 0x08 - 15fps, 0x10 - 30fps
    cam_i2c_write(axi_iic, device_addr, 0x3010, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x460c, 0x22);
    cam_i2c_write(axi_iic, device_addr, 0x3815, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x370d, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x370c, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3602, 0xfc);
    cam_i2c_write(axi_iic, device_addr, 0x3612, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x3634, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3613, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3605, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x3622, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3604, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x3603, 0xa7);
    cam_i2c_write(axi_iic, device_addr, 0x3603, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x4000, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x401d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3600, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x3605, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3606, 0x3f);
    cam_i2c_write(axi_iic, device_addr, 0x3c01, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0x4f);
    cam_i2c_write(axi_iic, device_addr, 0x5020, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x79);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x22);
    cam_i2c_write(axi_iic, device_addr, 0x5197, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x5500, 0x0a);
    cam_i2c_write(axi_iic, device_addr, 0x5504, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5505, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5080, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x300e, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x4610, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x471d, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x4708, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x3710, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3632, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x3702, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x37);
    cam_i2c_write(axi_iic, device_addr, 0x3631, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x3808, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3809, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380a, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x380b, 0xe0);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x501f, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0x4f);
    cam_i2c_write(axi_iic, device_addr, 0x4300, 0x61); // RGB565
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x73);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3824, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x380c, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x380d, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xe8);
    cam_i2c_write(axi_iic, device_addr, 0x3a0d, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3a0e, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x3818, 0xc1);
    cam_i2c_write(axi_iic, device_addr, 0x3705, 0xdb);
    cam_i2c_write(axi_iic, device_addr, 0x370a, 0x81);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0xc7);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x3803, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3827, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3810, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3804, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x3805, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3806, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x3807, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3a00, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x3a1a, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3a13, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a18, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a19, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x3a08, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x3a09, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0a, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x3a0b, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3004, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x350c, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x350d, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x3500, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x350a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3a0f, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a10, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a1b, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a1e, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a11, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3a1f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3030, 0x0b);
    cam_i2c_write(axi_iic, device_addr, 0x3a02, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a03, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x3a04, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a14, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a15, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x3a16, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a00, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x3a08, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x3a09, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x3a0a, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3a0b, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0d, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3a0e, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x57);
    cam_i2c_write(axi_iic, device_addr, 0x3703, 0x98);
    cam_i2c_write(axi_iic, device_addr, 0x3704, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x589b, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x589a, 0xc5);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5380, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5381, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5382, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5383, 0x4e);
    cam_i2c_write(axi_iic, device_addr, 0x5384, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5385, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x5386, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5387, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5388, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5389, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x538a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538b, 0x31);
    cam_i2c_write(axi_iic, device_addr, 0x538c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538d, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538f, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x5390, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5391, 0xab);
    cam_i2c_write(axi_iic, device_addr, 0x5392, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5393, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x5394, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5480, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5481, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x5482, 0x36);
    cam_i2c_write(axi_iic, device_addr, 0x5483, 0x57);
    cam_i2c_write(axi_iic, device_addr, 0x5484, 0x65);
    cam_i2c_write(axi_iic, device_addr, 0x5485, 0x71);
    cam_i2c_write(axi_iic, device_addr, 0x5486, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x5487, 0x87);
    cam_i2c_write(axi_iic, device_addr, 0x5488, 0x91);
    cam_i2c_write(axi_iic, device_addr, 0x5489, 0x9a);
    cam_i2c_write(axi_iic, device_addr, 0x548a, 0xaa);
    cam_i2c_write(axi_iic, device_addr, 0x548b, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x548c, 0xcd);
    cam_i2c_write(axi_iic, device_addr, 0x548d, 0xdd);
    cam_i2c_write(axi_iic, device_addr, 0x548e, 0xea);
    cam_i2c_write(axi_iic, device_addr, 0x548f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5490, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5491, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5492, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5493, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5494, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5495, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x5496, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5497, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x5498, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5499, 0x86);
    cam_i2c_write(axi_iic, device_addr, 0x549a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549b, 0x5b);
    cam_i2c_write(axi_iic, device_addr, 0x549c, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549d, 0x3b);
    cam_i2c_write(axi_iic, device_addr, 0x549e, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549f, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x54a0, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x54a1, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x54a2, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a3, 0xed);
    cam_i2c_write(axi_iic, device_addr, 0x54a4, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a5, 0xc5);
    cam_i2c_write(axi_iic, device_addr, 0x54a6, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a7, 0xa5);
    cam_i2c_write(axi_iic, device_addr, 0x54a8, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a9, 0x6c);
    cam_i2c_write(axi_iic, device_addr, 0x54aa, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ab, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x54ac, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ad, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x54ae, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x54af, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x3406, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5192, 0x04); // 0x04
    cam_i2c_write(axi_iic, device_addr, 0x5191, 0xf8); // 0xf8
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x5194, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5195, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x518d, 0x3d);
    cam_i2c_write(axi_iic, device_addr, 0x518f, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x518e, 0x3d);
    cam_i2c_write(axi_iic, device_addr, 0x5190, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x518b, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x518c, 0xbd);
    cam_i2c_write(axi_iic, device_addr, 0x5187, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5188, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5189, 0x6e);
    cam_i2c_write(axi_iic, device_addr, 0x518a, 0x68);
    cam_i2c_write(axi_iic, device_addr, 0x5186, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5183, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x24);
    cam_i2c_write(axi_iic, device_addr, 0x5025, 0x82);
    cam_i2c_write(axi_iic, device_addr, 0x5583, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5584, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5580, 0x02); // 0x02
    cam_i2c_write(axi_iic, device_addr, 0x3633, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3702, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3703, 0xb2);
    cam_i2c_write(axi_iic, device_addr, 0x3704, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x370b, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x370d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x52);
    cam_i2c_write(axi_iic, device_addr, 0x3c00, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0xFF);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5500, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5502, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5503, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5504, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5505, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5025, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5380, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5381, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5382, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5383, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5384, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5385, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5386, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5387, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5388, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5389, 0xE1);
    cam_i2c_write(axi_iic, device_addr, 0x538A, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538B, 0x2B);
    cam_i2c_write(axi_iic, device_addr, 0x538C, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538D, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538E, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538F, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5390, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5391, 0xB3);
    cam_i2c_write(axi_iic, device_addr, 0x5392, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5393, 0xA6);
    cam_i2c_write(axi_iic, device_addr, 0x5394, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5480, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5481, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5482, 0x2a);
    cam_i2c_write(axi_iic, device_addr, 0x5483, 0x49);
    cam_i2c_write(axi_iic, device_addr, 0x5484, 0x56);
    cam_i2c_write(axi_iic, device_addr, 0x5485, 0x62);
    cam_i2c_write(axi_iic, device_addr, 0x5486, 0x6c);
    cam_i2c_write(axi_iic, device_addr, 0x5487, 0x76);
    cam_i2c_write(axi_iic, device_addr, 0x5488, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5489, 0x88);
    cam_i2c_write(axi_iic, device_addr, 0x548a, 0x96);
    cam_i2c_write(axi_iic, device_addr, 0x548b, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x548c, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x548d, 0xcc);
    cam_i2c_write(axi_iic, device_addr, 0x548e, 0xe0);
    cam_i2c_write(axi_iic, device_addr, 0x548f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5490, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5491, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5492, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5493, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5494, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5495, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x5496, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5497, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x5498, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5499, 0x26);
    cam_i2c_write(axi_iic, device_addr, 0x549a, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x549b, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x549c, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x549d, 0xee);
    cam_i2c_write(axi_iic, device_addr, 0x549e, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x549f, 0xd8);
    cam_i2c_write(axi_iic, device_addr, 0x54a0, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a1, 0xc7);
    cam_i2c_write(axi_iic, device_addr, 0x54a2, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a3, 0xb3);
    cam_i2c_write(axi_iic, device_addr, 0x54a4, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a5, 0x90);
    cam_i2c_write(axi_iic, device_addr, 0x54a6, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a7, 0x62);
    cam_i2c_write(axi_iic, device_addr, 0x54a8, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a9, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x54aa, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ab, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x54ac, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ad, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x54ae, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x54af, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x54b0, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b1, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x54b2, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b3, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x54b4, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x54b5, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x54b6, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b7, 0xdf);
    cam_i2c_write(axi_iic, device_addr, 0x5583, 0x5d);
    cam_i2c_write(axi_iic, device_addr, 0x5584, 0x5d);
    cam_i2c_write(axi_iic, device_addr, 0x5580, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5587, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5588, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x558a, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x5589, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0xcf);
    cam_i2c_write(axi_iic, device_addr, 0x5800, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x5801, 0x31);
    cam_i2c_write(axi_iic, device_addr, 0x5802, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x5803, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x5804, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5805, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5806, 0x29);
    cam_i2c_write(axi_iic, device_addr, 0x5807, 0x38);
    cam_i2c_write(axi_iic, device_addr, 0x5808, 0x26);
    cam_i2c_write(axi_iic, device_addr, 0x5809, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x580a, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x580b, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x580c, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x580d, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x580e, 0x13);
    cam_i2c_write(axi_iic, device_addr, 0x580f, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5810, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x5811, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5812, 0x8);
    cam_i2c_write(axi_iic, device_addr, 0x5813, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5814, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x5815, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5816, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x5817, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5818, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5819, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x581a, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x581b, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x581c, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x581d, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x581e, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x581f, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x5820, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x5821, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x5822, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x5823, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5824, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5825, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x5826, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x5827, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5828, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5829, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x582a, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x582b, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x582c, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x582d, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x582e, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x582f, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5830, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x5831, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5832, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5833, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5834, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5835, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5836, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x5837, 0x1d);
    cam_i2c_write(axi_iic, device_addr, 0x5838, 0x6e);
    cam_i2c_write(axi_iic, device_addr, 0x5839, 0x39);
    cam_i2c_write(axi_iic, device_addr, 0x583a, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x583b, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x583c, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x583d, 0x23);
    cam_i2c_write(axi_iic, device_addr, 0x583e, 0x2f);
    cam_i2c_write(axi_iic, device_addr, 0x583f, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x5840, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5841, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5842, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5843, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5844, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5845, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5846, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5847, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5848, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5849, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584a, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584b, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x584c, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584d, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584e, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x584f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5850, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5851, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5852, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5853, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5854, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5855, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5856, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5857, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5858, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5859, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x585a, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585b, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585c, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585d, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x585e, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x585f, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5860, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5861, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x5862, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5863, 0x7);
    cam_i2c_write(axi_iic, device_addr, 0x5864, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5865, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5866, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5867, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5868, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x5869, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x586a, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x586b, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x586c, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x586d, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x586e, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x586f, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5870, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5871, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x5872, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5873, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5874, 0x13);
    cam_i2c_write(axi_iic, device_addr, 0x5875, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5876, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5877, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5878, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5879, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x587a, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x587b, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x587c, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x587d, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x587e, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x587f, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5880, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x5881, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5882, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5883, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5884, 0x1d);
    cam_i2c_write(axi_iic, device_addr, 0x5885, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5886, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5887, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5680, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5681, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5684, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5685, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5180, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x52);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5183, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x24);
    cam_i2c_write(axi_iic, device_addr, 0x5186, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5187, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5188, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5189, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x518a, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x518b, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x518c, 0x9c);
    cam_i2c_write(axi_iic, device_addr, 0x518d, 0x36);
    cam_i2c_write(axi_iic, device_addr, 0x518e, 0x34);
    cam_i2c_write(axi_iic, device_addr, 0x518f, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x5190, 0x4c);
    cam_i2c_write(axi_iic, device_addr, 0x5191, 0xf8);
    cam_i2c_write(axi_iic, device_addr, 0x5192, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x5194, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5195, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5196, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5197, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5198, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5199, 0x2f);
    cam_i2c_write(axi_iic, device_addr, 0x519a, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x519b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x519c, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x519d, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x519e, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0f, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a10, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a1b, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a1e, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a11, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3a1f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3800, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x3802, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x3803, 0x8);
    cam_i2c_write(axi_iic, device_addr, 0x3804, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x3805, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x3806, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x3807, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3808, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x3809, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x380a, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x380b, 0x58);
    cam_i2c_write(axi_iic, device_addr, 0x380c, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x380d, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xe8);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5680, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5681, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5684, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5685, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3815, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3818, 0x81); // No Mirror
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0xa7);

    cam_i2c_write(axi_iic, device_addr, 0x4740, 0x21);

    cam_i2c_write(axi_iic, device_addr, 0x501e, 0x2a);
    cam_i2c_write(axi_iic, device_addr, 0x5002, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x501f, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x4300, 0x61);

    return(0);
}

  1. 2021年08月20日 04:59 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する12(DFX_filter_test プロジェクト5)

画像フィルタを DFX する11(DFX_filter_test プロジェクト4)”の続き。

前回は、通過 IP 、ラプラシアン・フィルタ IP 、ソーベル・フィルタ IP の 3 個の IP を DFX で切り替えるべく Vivado 2021.1 の DFX_filter_test プロジェクトに追加するということで、ブロック・デザイン・コンテナを作成し、RM を設定した。今回は、Generate Output Products、 Dynamic Function eXchange Wizard 、 Pblock の設定、ビットストリームの生成を行った。

ラッパー・ファイルの作成は、もうすでに作成されている。

Generate Output Products を行う。
Flow Navigator から Generate Block Design をクリックする。

Generate Output Products ダイアログが表示された。
Generate ボタンをクリックする。
DFX2_91_210816.png

Flow Navigator から Dynamic Function eXchange Wizard を選択する。

Dynamic Function eXchange Wizard ダイアログが表示された。
Next > ボタンをクリックする。
DFX2_92_210816.png

Edit Reconfigurable Modules 画面が表示された。
デフォルトのまま Next > ボタンをクリックする。
DFX2_93_210816.png

Edit Configuration 画面が表示された。
automatically create configuration をクリックする。

config1, config2, config3 が表示された。
DFX2_94_210816.png

Edit Configuration Runs 画面が表示された。
automatically create configuration をクリックする。

impl_1 が config1、 child0_impl_1 が config2、 child1_impl_1 が config3 になっている。
DFX2_95_210816.png

Dynamic Function eXchange Summary 画面が表示された。
Finish ボタンをクリックする。
DFX2_96_210816.png

論理合成していこう。
Flow Navigator の SYNTHESIS -> Run Synthesis をクリックする。

論理合成が成功した。
Synthesis Completed ダイアログが表示された。
Open Synthesized Design のラジオボタンをクリックして、 Synthesized Design を開く。

Synthesized Design の Netlist を開いて filter リコンフィギャブル・モジュールを右クリックし、右クリックメニューから Floorplanning -> Draw Pblock を選択する。
DFX2_97_210816.png

Device タブをクリックして、 X1Y2 領域に適当に PBlock を指定した。(適当と言っても 7 シリーズの FPGA は X1Y2 の領域に Pblock の境界をピッタリ合わせないとダメなようだ)
DFX2_98_210816.png

Pblock Properties 画面で、 RESET_AFTER_RECONFIG のチェックボックスにチェックを入れて、SNAPPING_MODE を ROUTING にする。
SNAPPING_MODE を ON や ROUTING にすると、丁度良い境界から Pblock を取ってくれる。
DFX2_99_210816.png

Pblock の制約を制約ファイルにセーブした。
現在の DFX_filter_test.xdc を示す。

set_property PACKAGE_PIN H16 [get_ports TMDS_Clk_p_0]
set_property PACKAGE_PIN D19 [get_ports {TMDS_Data_p_0[0]}]
set_property PACKAGE_PIN C20 [get_ports {TMDS_Data_p_0[1]}]
set_property PACKAGE_PIN B19 [get_ports {TMDS_Data_p_0[2]}]

set_property IOSTANDARD TMDS_33 [get_ports TMDS_Clk_p_0]
set_property IOSTANDARD TMDS_33 [get_ports {TMDS_Data_p_0[2]}]
set_property IOSTANDARD TMDS_33 [get_ports {TMDS_Data_p_0[1]}]
set_property IOSTANDARD TMDS_33 [get_ports {TMDS_Data_p_0[0]}]

set_property PACKAGE_PIN T14 [get_ports {cam_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[0]}]
set_property PACKAGE_PIN U14 [get_ports {cam_data[6]}]
set_property PACKAGE_PIN T15 [get_ports {cam_data[5]}]
set_property PACKAGE_PIN U15 [get_ports {cam_data[4]}]
set_property PACKAGE_PIN P14 [get_ports {cam_data[3]}]
set_property PACKAGE_PIN V17 [get_ports {cam_data[2]}]
set_property PACKAGE_PIN R14 [get_ports {cam_data[1]}]
set_property PACKAGE_PIN V18 [get_ports {cam_data[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports iic_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports href]
set_property IOSTANDARD LVCMOS33 [get_ports pclk]
set_property IOSTANDARD LVCMOS33 [get_ports standby]
set_property IOSTANDARD LVCMOS33 [get_ports vsync]
set_property IOSTANDARD LVCMOS33 [get_ports xck]
set_property PACKAGE_PIN V15 [get_ports iic_scl_io]
set_property PACKAGE_PIN W14 [get_ports iic_sda_io]
set_property PACKAGE_PIN W15 [get_ports vsync]
set_property PACKAGE_PIN Y14 [get_ports href]
set_property PACKAGE_PIN T11 [get_ports standby]
set_property PACKAGE_PIN T10 [get_ports pclk]
set_property PACKAGE_PIN U12 [get_ports xck]

set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pclk_IBUF]


set_property PULLUP true [get_ports iic_scl_io]
set_property PULLUP true [get_ports iic_sda_io]

create_pblock pblock_filter
add_cells_to_pblock [get_pblocks pblock_filter] [get_cells -quiet [list DFX_filter_test_i/filter]]
resize_pblock [get_pblocks pblock_filter] -add {SLICE_X88Y52:SLICE_X103Y99}
resize_pblock [get_pblocks pblock_filter] -add {DSP48_X3Y22:DSP48_X4Y39}
resize_pblock [get_pblocks pblock_filter] -add {RAMB18_X4Y22:RAMB18_X4Y39}
resize_pblock [get_pblocks pblock_filter] -add {RAMB36_X4Y11:RAMB36_X4Y19}
set_property RESET_AFTER_RECONFIG true [get_pblocks pblock_filter]
set_property SNAPPING_MODE ROUTING [get_pblocks pblock_filter]


インプリメンテーションとビットストリームの生成を行って、成功した。
DFX2_100_210816.png

3 個とも、タイミング・メットしている。
DFX2_101_210816.png

DFX_filter_test_211/DFX_filter_test_211.run ディレクトリの下に impl_1, child0_impl1, child1_impl1 ディレクトリが作成され、各ディレクトリにパーシャル・ビット・ファイルとフルのビット・ファイルが生成されていた。
DFX2_102_210818.png

DFX2_103_210818.png

DFX2_104_210818.png
  1. 2021年08月18日 04:49 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する11(DFX_filter_test プロジェクト4)

画像フィルタを DFX する10(sobel_filter_axis IP 2)”の続き。

前回で、通過 IP 、ラプラシアン・フィルタ IP 、ソーベル・フィルタ IP の 3 個の AXI4-Stream 入出力、 AXI4-Lite インターフェースのレジスタ設定の IP の作成が完了した。今回は、その 3 個の IP を DFX で切り替えるべく Vivado 2021.1 の DFX_filter_test プロジェクトに追加する。

なお、DFX に失敗した DMA_pow2 IP と DMA_square_root8 IP の DFX については、以下のブログ記事にまとまっている。
DFX をやってみよう1(DFX を調べる1)
DFX をやってみよう2(チュートリアル例の説明)
DFX をやってみよう2(DMA_pow2 IP の作成)
”DFX をやってみよう3(DMA_square_root8 IP の作成1)
DFX をやってみよう4(DMA_square_root8 IP の作成2)
DFX をやってみよう5(Vivado 2021.1 で DFX_test プロジェクトを作成)”
DFX をやってみよう6(ブロック・デザイン・コンテナと DFX イネーブル)
DFX をやってみよう7(2 つ目の RM を設定)
DFX をやってみよう8(Generate Output Products と Dynamic Function eXchange Wizard)
”DFX をやってみよう9(Pblock の設定)”
”DFX をやってみよう10(インプリメンテーションとビット・ファイル、パーシャル・ビット・ファイルの生成)”
”DFX をやってみよう11(ハードウェアのエクスポートとフル・ビット・ファイルの動作確認)”
”DFX をやってみよう12(DMA_square_root8 の実行)”
これらの記事を参考に、 3 個の IP を DFX に設定する。

まずは、通過 IP 、ラプラシアン・フィルタ IP 、ソーベル・フィルタ IP の 3 個を DFX_filter_test プロジェクトにコピーする。
DFX_filter_test プロジェクトに lap_filter_axis, sobel_filter_axis, through_axis ディレクトリを作成した。
その下に、各 IP の solution1/impl ディレクトリの下の export.zip を展開した。
DFX2_71_210816.png

まずは、 through_axis と dfx_decoupler をブロック・デザインに追加した。
DFX2_73_210816.png

dfx_decoupler の設定画面を示す。
まずは、 Global Options を示す。
AXIインターフェースと Status Signal をイネーブルしている。
DFX2_74_210816.png

次は Interface Options タブを示す。
filter という名前の axis インターフェースを生成した。
DFX2_75_210816.png

through_axis_0 を階層デザインに指定する。
through_axis_0 を右クリックし、右クリックメニューから Create Hierarchy... を選択する。

Create Hierarchy が表示された。
Cell name に filter と入力して、OK ボタンをクリックする。

filter 階層ができた。
DFX2_76_210816.png

Validate Design を行った。
いつもの DDR skew のクリティカル・ワーニングが出るかも知れない?

階層デザインをブロック・デザイン・コンテナにする。
filter 階層デザインを右クリックし、右クリックメニューから Create Block Design Container... を選択する。

Create Block Design Container ダイアログが表示された。
New Block Design に filter と入力して、OK ボタンをクリックする。

filter 階層デザインが filter.bd ブロック・デザイン・コンテナになった。
DFX2_77_210816.png

filter.bd ブロック・デザイン・コンテナをダブルクリックして Customize Block Design Container ダイアログを表示させる。
Enable Dynamic Function eXchange on this container のチェックボックスにチェックを入れる。
DFX2_78_210816.png

Addressing タブをクリックして、設定を確認した。
DFX2_79_210816.png

filter に DFX マークが付いた。
DFX2_80_210816.png

Validate Design をクリックする。
Validate Design ダイアログが出て、成功した。

DFX に RM を追加する。
filter ブロック・デザイン・コンテナを右クリックし、右クリックメニューから Create Reconfigurable Module... を選択する。
Create Reconfigurable Module ダイアログが表示された。
Reconfigurable Module に lap_filter_axis を入力した。
DFX2_81_210816.png

flter と同じポートを持つ Diagram ウインドウが表示された。

lap_filter_axis IP を追加して配線した。
DFX2_82_210816.png

Address Editor を開いてアドレスをマップした。
0x00000000 にマップされていたので、0x40000000 にアドレスを変更した。
Address Map を示す。
DFX2_83_210816.png

filter ブロック・デザイン・コンテナをダブルクリックして Customize Block Design Container ダイアログを表示させる。
lap_filter_axis が追加されている。
DFX2_84_210816.png

Addressing タブ。
DFX2_85_210816.png

さて、もう一度、DFX に RM を追加する。
filter ブロック・デザイン・コンテナを右クリックし、右クリックメニューから Create Reconfigurable Module... を選択する。
Create Reconfigurable Module ダイアログが表示された。
Reconfigurable Module に sobel_filter_axis を入力した。
DFX2_86_210816.png

flter と同じポートを持つ Diagram ウインドウが表示された。

sobel_filter_axis IP を追加して配線した。
DFX2_87_210816.png

Address Editor を開いてアドレスをマップした。
0x00000000 にマップされていたので、0x40000000 にアドレスを変更した。
DFX2_88_210816.png

filter ブロック・デザイン・コンテナをダブルクリックして Customize Block Design Container ダイアログを表示させる。
sobel_filter_axis が追加されている。
DFX2_89_210816.png

Addressing タブの表示を示す。
DFX2_90_210816.png
  1. 2021年08月17日 05:05 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:2

画像フィルタを DFX する10(sobel_filter_axis IP 2)

画像フィルタを DFX する9(sobel_filter_axis IP 1)”の続き。

前回は、 DFX で切り替えるフィルタの第 2 段として AXI4-Stream インターフェースのソーベル・フィルタを作成するということで、ソースコードとテストベンチ・コードを貼って、 Vitis HLS 2021.1 の sobel_filter_axis3 プロジェクトを作成し、OpenCV を使用できるように設定を行った。今回は、 C シミュレーション、 C コードの合成、 C/RTL 協調シミュレーション、 Export RTL 、 Run Implementation を行う。

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

sobel_filter_axis3/solution1/csim/build ディレクトリに元画像の test2.jpg とソーベル・フィルタ結果の sobel.jpg が作成された。

元画像の test2.jpg を示す。
DFX2_70_210816.jpg

sobel.jpg を示す。
DFX2_63_210815.jpg

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

Function Call Graph を示す。
DFX2_64_210815.png

C/RTL 協調シミュレーションを行った。
レイテンシは 480038 クロックなので、性能は問題無さそうだ。
DFX2_65_210815.png

Function Call Graph を示す。
DFX2_66_210815.png

C/RTL 協調シミュレーションの波形を示す。
DFX2_67_210815.png

TVALID と TREADY がほぼ 1 でスループットが取れていることが分かる。

Export RTL を行って IP を作成した。

Run Implementation で Vivado でインプリメンテーションした時の概算値を計測した。
DFX2_68_210815.png
DFX2_69_210815.png

CP achieved post-implementation が 9.211 ns なので、制約の 10 ns は満たしているが、ちょっと危ない気がする。
画像フィルタを DFX する2(DFX_filter_test プロジェクト1)”の AXI4 インターフェースの動作クロックを 100 MHz から 80 MHz に落としておこう。 100 MHz で問題なくインプリメンテーションできました。
  1. 2021年08月16日 03:49 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する9(sobel_filter_axis IP 1)

画像フィルタを DFX する8(lap_filter_axis IP 2)”の続き。

前回は、AXI4-Stream インターフェースのラプラシアン・フィルタを作成するということで、 C コードの合成、 C/RTL 協調シミュレーション、 Export RTL 、 Run Implementation を行った。
今回は DFX で切り替えるフィルタの第 2 段として AXI4-Stream インターフェースのソーベル・フィルタを作成する。

最初にソースコードの sobel_filter_axis3.cpp を示す。

// sobel_filter_axis3.cpp
// 2020/02/27 by marsee
// 2021/08/14 : Added row, col
//

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

#define HORIZONTAL  0
#define VERTICAL    1

ap_int<32> sobel_fil(ap_int<32> h_or_v, ap_int<32> x0y0, ap_int<32> x1y0, ap_int<32> x2y0, ap_int<32> x0y1,
        ap_int<32> x1y1, ap_int<32> x2y1, ap_int<32> x0y2, ap_int<32> x1y2, ap_int<32> x2y2);
ap_int<32> conv_rgb2y(ap_int<32> rgb);
ap_int<32> square_root8(ap_int<32> val);

int sobel_filter_axis(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, int32_t row, int32_t col){

#pragma HLS INTERFACE mode=s_axilite port=col
#pragma HLS INTERFACE mode=s_axilite port=row
#pragma HLS INTERFACE axis register both port=ins
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE s_axilite port=return

    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> sobel;
    ap_int<32> sobel_val, sobel_h_val, sobel_v_val;

    ap_int<32> line_buf[2][1920];
#pragma HLS array_partition variable=line_buf block factor=2 dim=1
#pragma HLS resource variable=line_buf core=RAM_2P

    ap_int<32> pix_mat[3][3];
#pragma HLS array_partition variable=pix_mat complete

    LOOP_WAIT_USER : do {   // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    LOOP_Y: for(int y=0; y<row; y++){
#pragma HLS LOOP_TRIPCOUNT min=640 max=1080 avg=800
        LOOP_X: for(int x=0; x<col; x++){
#pragma HLS PIPELINE II=1
#pragma HLS LOOP_TRIPCOUNT min=640 max=1920 avg=800
            if (!(x==0 && y==0))    // 最初の入力はすでに入力されている
                ins >> pix; // AXI4-Stream からの入力

            LOOP_PIX_MAT_K: for(int k=0; k<3; k++){
                LOOP_PIX_MAT_M: for(int m=0; m<2; m++){
                    pix_mat[k][m] = pix_mat[k][m+1];
                }
            }
            pix_mat[0][2] = line_buf[0][x];
            pix_mat[1][2] = line_buf[1][x];
            ap_int<32> y_val = conv_rgb2y(pix.data);
            pix_mat[2][2] = y_val;

            line_buf[0][x] = line_buf[1][x];    // 行の入れ替え
            line_buf[1][x] = y_val;

            sobel_h_val = sobel_fil(HORIZONTAL, pix_mat[0][0], pix_mat[0][1], pix_mat[0][2],
                                                pix_mat[1][0], pix_mat[1][1], pix_mat[1][2],
                                                pix_mat[2][0], pix_mat[2][1], pix_mat[2][2]);
            sobel_v_val = sobel_fil(VERTICAL,   pix_mat[0][0], pix_mat[0][1], pix_mat[0][2],
                                                pix_mat[1][0], pix_mat[1][1], pix_mat[1][2],
                                                pix_mat[2][0], pix_mat[2][1], pix_mat[2][2]);
            sobel_val = square_root8(sobel_h_val*sobel_h_val + sobel_v_val*sobel_v_val);
            sobel.data = (sobel_val<<16)+(sobel_val<<8)+sobel_val;

            if(x==0 && y==0) // 最初のピクセル
                sobel.user = 1;
            else
                sobel.user = 0;
            if(x == (col-1)) // 行の最後
                sobel.last = 1;
            else
                sobel.last = 0;

            if(x<2 || y<2)
                sobel.data = 0;

            outs << sobel;
        }
    }
    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 にした
ap_int<32> conv_rgb2y(ap_int<32> rgb){
    ap_int<32> r, g, b, y_f;
    ap_int<32> 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);
}

// sobel filter
// HORZONTAL
// x0y0 x1y0 x2y0  1  2  1
// x0y1 x1y1 x2y1  0  0  0
// x0y2 x1y2 x2y2 -1 -2 -1
// VERTICAL
// x0y0 x1y0 x2y0  1  0 -1
// x0y1 x1y1 x2y1  2  0 -2
// x0y2 x1y2 x2y2  1  0 -1
ap_int<32> sobel_fil(ap_int<32> h_or_v, ap_int<32> x0y0, ap_int<32> x1y0, ap_int<32> x2y0, ap_int<32> x0y1,
        ap_int<32> x1y1, ap_int<32> x2y1, ap_int<32> x0y2, ap_int<32> x1y2, ap_int<32> x2y2){
    ap_int<32> y;

    if(h_or_v == HORIZONTAL){
        y = x0y0 + 2*x1y0 + x2y0 - x0y2 - 2*x1y2 - x2y2;
    } else {
        y = x0y0 - x2y0 + 2*x0y1 - 2*x2y1 + x0y2 - x2y2;
    }
    if(y<0)
        y = -y;
        //y = 0;
    else if(y>255)
        y = 255;
    return(y);
}

// square_root8
// 8bit幅のsquare_rootを求める
ap_int<32> square_root8(ap_int<32> val){
    ap_int<32> temp = 0;
    ap_int<32> square;

    for(int i=7; i>=0; --i){
        temp += (1 << i);
        square = temp * temp;

        if(square > val){
            temp -= (1 << i);
        }
    }

    return(temp);
}

テストベンチ・コードの sobel_filter_axis3_tb.cpp を示す。

// sobel_filter_axis3_tb.cpp
// 2020/02/27 by marsee
// 2021/08/14 : Added row, col, OpenCV
//

#include <stdio.h>
#include <stdint.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>
#include "opencv2/opencv.hpp"
#include "opencv2/imgproc/imgproc.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgcodecs/imgcodecs.hpp"

int sobel_filter_axis(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, int32_t row, int32_t col);
int sobel_filter_soft(int32_t *cam_fb, int32_t *sobel_fb,
        int32_t x_size, int32_t y_size);
int32_t square_root8_soft(int32_t val);

const char INPUT_BMP_FILE[] = "test2.jpg";
const char OUTPUT_BMP_FILE[] = "sobel.jpg";

int main(){
    hls::stream<ap_axis<32,1,1,1> > ins;
    hls::stream<ap_axis<32,1,1,1> > ins_soft;
    hls::stream<ap_axis<32,1,1,1> > outs;
    hls::stream<ap_axis<32,1,1,1> > outs_soft;
    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> vals;

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

    // ピクセルを入れる領域の確保
    std::vector<int32_t> rd_bmp(sizeof(int32_t)*img.cols*img.rows);
    std::vector<int32_t> hw_sobel(sizeof(int32_t)*img.cols*img.rows);
    std::vector<int32_t> sw_sobel(sizeof(int32_t)*img.cols*img.rows);

    // rd_bmp にBMPのピクセルを代入
    cv::Mat_<cv::Vec3b> dst_vec3b = cv::Mat_<cv::Vec3b>(img);
    for (int y=0; y<img.rows; y++){
        for (int x=0; x<img.cols; x++){
            cv::Vec3b pixel;
            pixel = dst_vec3b(y,x);
            rd_bmp[y*img.cols+x] = (pixel[0] & 0xff) | ((pixel[1] & 0xff)<<8) | ((pixel[2] & 0xff)<<16);
            // blue - pixel[0]; green - pixel[1]; red - pixel[2];
        }
    }

    // ins に入力データを用意する
    for(int i=0; i<5; i++){ // dummy data
        pix.user = 0;
        pix.data = i;
        ins << pix;
    }

    for(int j=0; j < img.rows; j++){
        for(int i=0; i < img.cols; i++){
            pix.data = (ap_int<32>)rd_bmp[(j*img.cols)+i];

            if (j==0 && i==0)   // 最初のデータの時に TUSER を 1 にする
                pix.user = 1;
            else
                pix.user = 0;

            if (i == img.cols-1) // 行の最後でTLASTをアサートする
                pix.last = 1;
            else
                pix.last = 0;

            ins << pix;
        }
    }

    sobel_filter_axis(ins, outs, img.rows, img.cols);   // ハードウェアのソーベルフィルタ
    sobel_filter_soft(rd_bmp.data(), sw_sobel.data(), img.cols, img.rows);  // ソフトウェアのソーベルフィルタ

    // ハードウェアとソフトウェアのソーベルフィルタの値のチェック
    for (int y=0; y<img.rows; y++){
        for (int x=0; x<img.cols; x++){
            outs >> vals;
            ap_int<32> val = vals.data;
            hw_sobel[y*img.cols+x] = (int32_t)val;
            if (val != sw_sobel[y*img.cols+x]){
                printf("ERROR HW and SW results mismatch x = %ld, y = %ld, HW = %d, SW = %d\n",
                        x, y, val, sw_sobel[y*img.cols+x]);
                return(1);
            }
        }
    }
    printf("Success HW and SW results match\n");

    const int sobel_row = img.rows;
    const int sobel_cols = img.cols;
    cv::Mat wbmpf(sobel_row, sobel_cols, CV_8UC3);
    // wbmpf にsobel フィルタ処理後の画像を入力
    cv::Mat_<cv::Vec3b> sob_vec3b = cv::Mat_<cv::Vec3b>(wbmpf);
    for (int y=0; y<wbmpf.rows; y++){
        for (int x=0; x<wbmpf.cols; x++){
            cv::Vec3b pixel;
            pixel = sob_vec3b(y,x);
            int32_t rgb = hw_sobel[y*wbmpf.cols+x];
            pixel[0] = (rgb & 0xff); // blue
            pixel[1] = (rgb & 0xff00) >> 8; // green
            pixel[2] = (rgb & 0xff0000) >> 16; // red
            sob_vec3b(y,x) = pixel;
        }
    }

    // ハードウェアのソーベルフィルタの結果を bmp ファイルへ出力する
    cv::imwrite(OUTPUT_BMP_FILE, wbmpf);

    return(0);
}

#define HORIZONTAL  0
#define VERTICAL    1

int32_t sobel_fil_soft(int32_t h_or_v, int32_t x0y0, int32_t x1y0, int32_t x2y0, int32_t x0y1,
        int32_t x1y1, int32_t x2y1, int32_t x0y2, int32_t x1y2, int32_t x2y2);
int32_t conv_rgb2y_soft(int32_t rgb);

int sobel_filter_soft(int32_t *cam_fb, int32_t *sobel_fb,
    int32_t x_size, int32_t y_size){
    int32_t sobel_val, sobel_h_val, sobel_v_val;
    int32_t pix[3][3];

    for(int y=0; y<y_size; y++){
        for(int x=0; x<x_size; x++){
            for(int i=2; i>=0; --i){
                for(int j=2; j>=0; --j){
                    if(x>=2 && y>=2)
                        pix[i][j] = conv_rgb2y_soft(cam_fb[(y-i)*x_size+(x-j)]);
                    else
                        pix[i][j] = 0;
                }
            }
            sobel_h_val = sobel_fil_soft(HORIZONTAL,pix[0][0], pix[0][1], pix[0][2],
                                                    pix[1][0], pix[1][1], pix[1][2],
                                                    pix[2][0], pix[2][1], pix[2][2]);
            sobel_v_val = sobel_fil_soft(VERTICAL,  pix[0][0], pix[0][1], pix[0][2],
                                                    pix[1][0], pix[1][1], pix[1][2],
                                                    pix[2][0], pix[2][1], pix[2][2]);
            sobel_val = square_root8_soft(sobel_h_val*sobel_h_val + sobel_v_val*sobel_v_val);
            sobel_fb[y*x_size+x] = (sobel_val<<16)+(sobel_val<<8)+sobel_val;
        }
    }

    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 にした
int32_t conv_rgb2y_soft(int32_t rgb){
    int32_t r, g, b, y_f;
    int32_t 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);
}

// sobel filter
// HORZONTAL
// x0y0 x1y0 x2y0  1  2  1
// x0y1 x1y1 x2y1  0  0  0
// x0y2 x1y2 x2y2 -1 -2 -1
// VERTICAL
// x0y0 x1y0 x2y0  1  0 -1
// x0y1 x1y1 x2y1  2  0 -2
// x0y2 x1y2 x2y2  1  0 -1
int32_t sobel_fil_soft(int32_t h_or_v, int32_t x0y0, int32_t x1y0, int32_t x2y0, int32_t x0y1,
        int32_t x1y1, int32_t x2y1, int32_t x0y2, int32_t x1y2, int32_t x2y2){
    int32_t y;

    if(h_or_v == HORIZONTAL){
        y = x0y0 + 2*x1y0 + x2y0 - x0y2 - 2*x1y2 - x2y2;
    } else {
        y = x0y0 - x2y0 + 2*x0y1 - 2*x2y1 + x0y2 - x2y2;
    }
    if(y<0)
        y = -y;
        //y = 0;
    else if(y>255)
        y = 255;
    return(y);
}

// square_root8_soft
// 8bit幅のsquare_rootを求める
int32_t square_root8_soft(int32_t val){
    int32_t temp = 0;
    int32_t square;

    for(int i=7; i>=0; --i){
        temp += (1 << i);
        square = temp * temp;

        if(square > val){
            temp -= (1 << i);
        }
    }

    return(temp);
}


Vitis_HLS 2021.1 で ZYBO Z7-20 用の sobel_filter_axis3_tb.cpp を作成した。
DFX2_58_210815.png

OpenCV を使用するために設定を行う。
Project メニューから Project Settings... を選択する。
Project Settings (sobel_filter_axis3) ダイアログが表示された。
左のウインドウから Simulation をクリックする。
test2.jpg の CFLAG に OpenCV へのインクルード・パスを設定した。

-I/usr/local/include


Linker Flags に以下の値を設定した。

-L/usr/local/lib -lopencv_core -lopencv_imgcodecs -lopencv_imgproc


DFX2_59_210815.png

これで、”Ubuntu 18.04 LTS のパソコンに OpenCV 3.4.9 をインストールする”でインストールした OpenCV 3.4.9 が Vitis_HLS から使えるようになった。
  1. 2021年08月15日 04:29 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する8(lap_filter_axis IP 2)

画像フィルタを DFX する7(lap_filter_axis IP 1)”の続き。

前回は、AXI4-Stream インターフェースのラプラシアン・フィルタを作成するということで、ソースコードとテストベンチ・コードを貼って、 C シミュレーションを行った。今回は、C コードの合成、 C/RTL 協調シミュレーション、 Export RTL 、 Run Implementation を行う。

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

Function Call Graph を示す。
DFX2_51_210812.png

Schedule Viewer を示す。
DFX2_52_210812.png

C/RTL 協調シミュレーションを行った。結果を示す。
Latency は 480022 クロックで良い感じだ。
DFX2_53_210812.png

Function Call Graph を示す。
DFX2_54_210812.png

C/RTL 協調シミュレーションの波形を示す。
DFX2_55_210814.png

TVALID と TREADY がほとんど 1 で、スループットが高いのが分かる。

Export RTL を行った。
lap_filter_axis/solution1/impl ディレクトリに IP が圧縮された export.zip が生成されていた。

Run Implementation を行った。結果を示す。
DFX2_56_210814.png
DFX2_57_210814.png

CP achieved post-implementation が 8.674 ns だった。たぶんだ丈夫だろう?
  1. 2021年08月14日 04:20 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する7(lap_filter_axis IP 1)

画像フィルタを DFX する6(through_axis IP 2)”の続き。

前回は、AXI4-Stream インターフェースの通過するだけの IP 、 through_axis を作成した。これはカメラ画像を表示するのに使用する。今回は、 AXI4-Stream インターフェースのラプラシアン・フィルタを作成する。ソースコードとテストベンチ・コードを貼って、 C シミュレーションを行った。

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

//
// lap_filter_axis.cpp
// 2015/05/01
// 2015/06/25 : 修正、ラプラシアンフィルタの値が青だけになっていたので、RGBに拡張した
// 2019/08/29 : row, colを引数として入力できるように変更
// 2021/08/12 : intからint32_tに変更
//

#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <ap_axi_sdata.h>

int32_t laplacian_fil(  int32_t x0y0, int32_t x1y0, int32_t x2y0,
                        int32_t x0y1, int32_t x1y1, int32_t x2y1,
                        int32_t x0y2, int32_t x1y2, int32_t x2y2);
int32_t conv_rgb2y(int32_t rgb);

int lap_filter_axis(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, int32_t row, int32_t col){
#pragma HLS INTERFACE s_axilite port=col
#pragma HLS INTERFACE s_axilite port=row
#pragma HLS INTERFACE axis register both port=ins
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE s_axilite port=return

    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> lap;

    uint32_t line_buf[2][1920];
#pragma HLS array_partition variable=line_buf block factor=2 dim=1
#pragma HLS resource variable=line_buf core=RAM_2P

    int32_t pix_mat[3][3];
#pragma HLS array_partition variable=pix_mat complete

    int32_t lap_fil_val;

    Loop1 : do {    // user が 1になった時にフレームがスタートする
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
        ins >> pix;
    } while(pix.user == 0);

    Loop2 : for (int y=0; y<row; y++){
#pragma HLS LOOP_TRIPCOUNT min=48 max=1080 avg=600
        Loop3 : for (int x=0; x<col; x++){
#pragma HLS LOOP_TRIPCOUNT min=64 max=1920 avg=800
#pragma HLS PIPELINE II=1
            if (!(x==0 && y==0))    // 最初の入力はすでに入力されている
                ins >> pix; // AXI4-Stream からの入力

            Loop4 : for (int k=0; k<3; k++){
                Loop5 : for (int m=0; m<2; m++){
#pragma HLS UNROLL
                    pix_mat[k][m] = pix_mat[k][m+1];
                }
            }
            pix_mat[0][2] = line_buf[0][x];
            pix_mat[1][2] = line_buf[1][x];

            int32_t y_val = conv_rgb2y(pix.data);
            pix_mat[2][2] = y_val;

            line_buf[0][x] = line_buf[1][x];    // 行の入れ替え
            line_buf[1][x] = y_val;

            lap_fil_val = laplacian_fil(    pix_mat[0][0], pix_mat[0][1], pix_mat[0][2],
                                        pix_mat[1][0], pix_mat[1][1], pix_mat[1][2],
                                        pix_mat[2][0], pix_mat[2][1], pix_mat[2][2]);
            lap.data = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる

            if (x<2 || y<2) // 最初の2行とその他の行の最初の2列は無効データなので0とする
                lap.data = 0;

            if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
                lap.user = 1;
            else
                lap.user = 0;

            if (x == (col-1))   // 行の最後で TLAST をアサートする
                lap.last = 1;
            else
                lap.last = 0;

            outs << lap;    // AXI4-Stream へ出力
        }
    }

    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 にした
int32_t conv_rgb2y(int32_t rgb){
    int32_t r, g, b, y_f;
    int32_t y;

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

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

    return(y);
}

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

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


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

// lap_filter_axis_tb.cpp
// 2015/05/01
// 2015/08/17 : BMPファイルを読み書きするように変更した
// 2019/08/29 : row, colを引数として入力できるように変更
// 2021/08/12 : intからint32_tに変更
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include <ap_axi_sdata.h>

#include "bmp_header.h"

int lap_filter_axis(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, int32_t row, int32_t col);

int32_t laplacian_fil_soft( int32_t x0y0, int32_t x1y0, int32_t x2y0,
                            int32_t x0y1, int32_t x1y1, int32_t x2y1,
                            int32_t x0y2, int32_t x1y2, int32_t x2y2);
int32_t conv_rgb2y_soft(int32_t rgb);
int lap_filter_axis_soft(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, int32_t width, int32_t height);

#define CLOCK_PERIOD 10

int main()
{
    using namespace std;

    hls::stream<ap_axis<32,1,1,1> > ins;
    hls::stream<ap_axis<32,1,1,1> > ins_soft;
    hls::stream<ap_axis<32,1,1,1> > outs;
    hls::stream<ap_axis<32,1,1,1> > outs_soft;
    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> vals;
    ap_axis<32,1,1,1> vals_soft;

    BITMAPFILEHEADER bmpfhr; // BMPファイルのファイルヘッダ(for Read)
    BITMAPINFOHEADER bmpihr; // BMPファイルのINFOヘッダ(for Read)
    FILE *fbmpr, *fbmpw;
    int32_t *rd_bmp, *hw_lapd;
    int32_t blue, green, red;

    if ((fbmpr = fopen("test2.bmp", "rb")) == NULL){ // test.bmp をオープン
        fprintf(stderr, "Can't open test.bmp by binary read mode\n");
        exit(1);
    }
    // bmpヘッダの読み出し
    fread(&bmpfhr.bfType, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfSize, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved1, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfReserved2, sizeof(uint16_t), 1, fbmpr);
    fread(&bmpfhr.bfOffBits, sizeof(uint32_t), 1, fbmpr);
    fread(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpr);

    // ピクセルを入れるメモリをアロケートする
    if ((rd_bmp =(int32_t *)malloc(sizeof(int32_t) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate rd_bmp memory\n");
        exit(1);
    }
    if ((hw_lapd =(int32_t *)malloc(sizeof(int32_t) * (bmpihr.biWidth * bmpihr.biHeight))) == NULL){
        fprintf(stderr, "Can't allocate hw_lapd memory\n");
        exit(1);
    }

    // rd_bmp にBMPのピクセルを代入。その際に、行を逆転する必要がある
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = fgetc(fbmpr);
            green = fgetc(fbmpr);
            red = fgetc(fbmpr);
            rd_bmp[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] = (blue & 0xff) | ((green & 0xff)<<8) | ((red & 0xff)<<16);
        }
    }
    fclose(fbmpr);

    // ins に入力データを用意する
    for(int i=0; i<5; i++){ // dummy data
        pix.user = 0;
        pix.data = i;
        ins << pix;
    }

    for(int j=0; j < bmpihr.biHeight; j++){
        for(int i=0; i < bmpihr.biWidth; i++){
            pix.data = (ap_int<32>)rd_bmp[(j*bmpihr.biWidth)+i];

            if (j==0 && i==0)   // 最初のデータの時に TUSER を 1 にする
                pix.user = 1;
            else
                pix.user = 0;

            if (i == bmpihr.biWidth-1) // 行の最後でTLASTをアサートする
                pix.last = 1;
            else
                pix.last = 0;

            ins << pix;
            ins_soft << pix;
        }
    }

    lap_filter_axis(ins, outs, bmpihr.biHeight, bmpihr.biWidth);
    lap_filter_axis_soft(ins_soft, outs_soft, bmpihr.biWidth, bmpihr.biHeight);

    // ハードウェアとソフトウェアのラプラシアン・フィルタの値のチェック
    cout << endl;
    cout << "outs" << endl;
    for(int j=0; j < bmpihr.biHeight; j++){
        for(int i=0; i < bmpihr.biWidth; i++){
            outs >> vals;
            outs_soft >> vals_soft;
            ap_int<32> val = vals.data;
            ap_int<32> val_soft = vals_soft.data;

            hw_lapd[(j*bmpihr.biWidth)+i] = (int32_t)val;

            if (val != val_soft){
                printf("ERROR HW and SW results mismatch i = %ld, j = %ld, HW = %d, SW = %d\n", i, j, (int32_t)val, (int32_t)val_soft);
                return(1);
            }
            if (vals.last)
                //cout << "AXI-Stream is end" << endl
                ;
        }
    }
    cout << "Success HW and SW results match" << endl;
    cout << endl;

    // ハードウェアのラプラシアンフィルタの結果を temp_lap.bmp へ出力する
    if ((fbmpw=fopen("temp_lap.bmp", "wb")) == NULL){
        fprintf(stderr, "Can't open temp_lap.bmp by binary write mode\n");
        exit(1);
    }
    // BMPファイルヘッダの書き込み
    fwrite(&bmpfhr.bfType, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfSize, sizeof(uint32_t), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved1, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfReserved2, sizeof(uint16_t), 1, fbmpw);
    fwrite(&bmpfhr.bfOffBits, sizeof(uint32_t), 1, fbmpw);
    fwrite(&bmpihr, sizeof(BITMAPINFOHEADER), 1, fbmpw);

    // RGB データの書き込み、逆順にする
    for (int y=0; y<bmpihr.biHeight; y++){
        for (int x=0; x<bmpihr.biWidth; x++){
            blue = hw_lapd[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] & 0xff;
            green = (hw_lapd[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x] >> 8) & 0xff;
            red = (hw_lapd[((bmpihr.biHeight-1)-y)*bmpihr.biWidth+x]>>16) & 0xff;

            fputc(blue, fbmpw);
            fputc(green, fbmpw);
            fputc(red, fbmpw);
        }
    }
    fclose(fbmpw);
    free(rd_bmp);
    free(hw_lapd);

    return 0;
}

int lap_filter_axis_soft(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs, int32_t width, int32_t height){
    ap_axis<32,1,1,1> pix;
    ap_axis<32,1,1,1> lap;
    uint32_t **line_buf;
    int32_t pix_mat[3][3];
    int32_t lap_fil_val;
    int i;

    // line_buf の1次元目の配列をアロケートする
    if ((line_buf =(uint32_t **)malloc(sizeof(uint32_t *) * 2)) == NULL){
        fprintf(stderr, "Can't allocate line_buf[3][]\n");
        exit(1);
    }

    // メモリをアロケートする
    for (i=0; i<2; i++){
        if ((line_buf[i]=(uint32_t *)malloc(sizeof(uint32_t) * width)) == NULL){
            fprintf(stderr, "Can't allocate line_buf[%d]\n", i);
            exit(1);
        }
    }

    do {    // user が 1になった時にフレームがスタートする
        ins >> pix;
    } while(pix.user == 0);

    for (int y=0; y<height; y++){
        for (int x=0; x<width; x++){
            if (!(x==0 && y==0))    // 最初の入力はすでに入力されている
                ins >> pix; // AXI4-Stream からの入力

            for (int k=0; k<3; k++){
                for (int m=0; m<2; m++){
                    pix_mat[k][m] = pix_mat[k][m+1];
                }
            }
            pix_mat[0][2] = line_buf[0][x];
            pix_mat[1][2] = line_buf[1][x];

            int32_t y_val = conv_rgb2y_soft(pix.data);
            pix_mat[2][2] = y_val;

            line_buf[0][x] = line_buf[1][x];    // 行の入れ替え
            line_buf[1][x] = y_val;

            lap_fil_val = laplacian_fil_soft(    pix_mat[0][0], pix_mat[0][1], pix_mat[0][2],
                                        pix_mat[1][0], pix_mat[1][1], pix_mat[1][2],
                                        pix_mat[2][0], pix_mat[2][1], pix_mat[2][2]);
            lap.data = (lap_fil_val<<16)+(lap_fil_val<<8)+lap_fil_val; // RGB同じ値を入れる

            if (x<2 || y<2) // 最初の2行とその他の行の最初の2列は無効データなので0とする
                lap.data = 0;

            if (x==0 && y==0) // 最初のデータでは、TUSERをアサートする
                lap.user = 1;
            else
                lap.user = 0;

            if (x == (width-1))    // 行の最後で TLAST をアサートする
                lap.last = 1;
            else
                lap.last = 0;

            outs << lap;    // AXI4-Stream へ出力
        }
    }

    for (i=0; i<2; i++)
        free(line_buf[i]);
    free(line_buf);

    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 にした
int32_t conv_rgb2y_soft(int32_t rgb){
    int32_t r, g, b, y_f;
    int32_t y;

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

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

    return(y);
}

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

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


Vitis_HLS 2021.1 の lap_filter_axis プロジェクトを示す。
DFX2_45_210812.png

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

lap_filter_axis/solution1/csim/build ディレクトリに元画像の test2.bmp とラプラシアン・フィルタ結果の temp_lap.bmp が作成された。

元画像の test2.bmp を示す。
DFX2_47_210812.jpg

ラプラシアン・フィルタ画像の temp_lap.bmp を示す。
DFX2_48_210812.jpg
  1. 2021年08月13日 05:12 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する6(through_axis IP 2)

画像フィルタを DFX する5(through_axis IP 1)”の続き。

前回は、DFX のリコンフィギャブル・モジュール(RM)として、AXI4-Stream の通過 IP の through_axis を作成する。この IP は AXI4-Stream のデータをそのまま AXI4-Stream に出力する。Vitis HLS 2021.1 の through_axis プロジェクトを示し、ソースコードとテストベンチ・コードを貼って、 C シミュレーションを行った。今回は、その through_axis の Vitis HLS プロジェクトで C コードの合成、 C/RTL 協調シミュレーション、 Export RTL 、 Run Implementation を行う。

C コードの合成から結果を示す。
DFX2_36_210811.png
DFX2_37_210811.png

Timing Violation が出ている。

Function Call Graph を示す。
DFX2_38_210811.png

Schedule Viewer で Timing Violation のパスを表示させた。
DFX2_39_210811.png

x のループの for 文だった。

C/RTL 協調シミュレーションを行った。結果を示す。
Latency は 480007 クロックだった。 800 x 600 行なので、 480000 ピクセルのはずなので、 7 クロックだけ余計だった。
DFX2_40_210811.png

Function Call Graph を示す。
DFX2_41_210811.png

C/RTL 協調シミュレーションの波形を示す。
TVALID も TREADY もほとんど 1 だった。
DFX2_42_210811.png

Export RTL を行って、 IP として出力した。

RTL Synthesys, Place & Route のラジオボタンをクリックして、Run Implementation を行った。
結果を示す。
DFX2_43_210811.png
DFX2_44_210811.png

CP achieved post-implementation は 8.653 ns なので、大丈夫そうだ。
  1. 2021年08月12日 03:40 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する5(through_axis IP 1)

画像フィルタを DFX する4(DFX_filter_test プロジェクト3)”の続き。

前回は、DFX のために、ビデオ側の DMA2axis IP の動作を一度止めて、再起動した時にカメラ画像が表示されることを確認できた。今回は、DFX のリコンフィギャブル・モジュール(RM)として、AXI4-Stream の通過 IP の through_axis を作成する。この IP は AXI4-Stream のデータをそのまま AXI4-Stream に出力する。Vitis HLS 2021.1 の through_axis プロジェクトを示し、ソースコードとテストベンチ・コードを貼った。

Vitis HLS 2021.1 の through_axis プロジェクトを示す。
DFX2_34_210811.png

through_axis.cpp を示す。

// through_axis.cpp
// 2021/08/07 by marsee
//

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

int through_axis(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs,
        int16_t x_size, int16_t y_size){
#pragma HLS INTERFACE mode=s_axilite port=y_size
#pragma HLS INTERFACE mode=s_axilite port=x_size
#pragma HLS INTERFACE mode=axis register_mode=both port=outs register
#pragma HLS INTERFACE mode=axis register_mode=both port=ins register
#pragma HLS INTERFACE mode=s_axilite port=return
    ap_axis<32,1,1,1> pix;

    do {
#pragma HLS LOOP_TRIPCOUNT min=1 max=1 avg=1
    // user が 1になった時にフレームがスタートする
        ins >> pix;
    } while(pix.user == 0);
    LOOP_Y: for(int16_t i=0; i<y_size; i++){
#pragma HLS LOOP_TRIPCOUNT avg=600 max=1080 min=480
        LOOP_X: for(int16_t j=0; j<x_size; j++){
#pragma HLS LOOP_TRIPCOUNT avg=800 max=1920 min=640
#pragma HLS PIPELINE II=1
            if (!(i==0 && j==0))    // 最初の入力はすでに入力されている
                ins >> pix; // AXI4-Stream からの入力
            outs << pix;
        }
    }
    return(0);
}


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

// through_axis_tb.cpp
// 2021/08/07 by marsee
//

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

int through_axis(hls::stream<ap_axis<32,1,1,1> >& ins, hls::stream<ap_axis<32,1,1,1> >& outs,
        int16_t x_size, int16_t y_size);

int main(){
    hls::stream<ap_axis<32,1,1,1> > outs;
    hls::stream<ap_axis<32,1,1,1> > ins;
    ap_axis<32,1,1,1> vals;

    for(int i=0; i<600; i++){
        for(int j=0; j<800; j++){
            vals.data = i*800+j;
            if(i==0 && j==0)
                vals.user = 1;
            else
                vals.user = 0;
            if(j == (800-1))
                vals.last = 1;
            else
                vals.last = 0;
            ins << vals;
        }
    }

    through_axis(ins, outs, 800, 600);

    for(int i=0; i<600; i++){
        for(int j=0; j<800; j++){
            outs >> vals;
            if(vals.data != (i*800+j)){
                printf("Error : i = %d, j = %d, (i*800)+j = %d; vals.data = %d\n",
                        i, j, (i*800)+j, vals.data);
                return(1);
            }
            if(vals.user == 1 && i==0 && j==0){
                printf("User is 1 at the time of frame start\n");
            } else if(vals.user == 1){
                printf("Error: User is 1 at times other than frame start\n");
                return(1);
            }
            if(vals.last == 0 && j==(800-1)){
                printf("Error:Last is 0 at the end of the line\n");
                return(1);
            }
        }
    }
    return(0);
}


C シミュレーションを行った。
DFX2_35_210811.png
  1. 2021年08月11日 06:37 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する4(DFX_filter_test プロジェクト3)

画像フィルタを DFX する3(DFX_filter_test プロジェクト2)”の続き。

前回は、、ハードウェアをエクスポートし、Vitis 2021.1 を起動して、プラットフォームとアプリケーション・プロジェクトを作成する。そして、アプリケーション・ソフトウェアを記述してビルドし、ZYBO Z7-20 の実機で確認したところ、動作した。今回は、DFX のために、ビデオ側の DMA2axis IP の動作を一度止めて、再起動した時にカメラ画像が表示されるのか?を検証する。

DFX_filter_test.c を書き換えた。
DFX2_32_210810.png

”The display stops when you press any key.”を表示して、何かキーを押すと、DMA2axis IP を停止して、”The display resumes when you press any key.”を表示して、何かキーを押すと DMA2axis IP を再スタートする。

これで ZYBO Z7-20 でやってみたところ、アプリケーション・ソフトウェアを起動すると、カメラ画像がディスプレイに表示され、”The display stops when you press any key.”を表示するので、Enter キーを押すと、カメラ画像が真っ暗になった。
”The display resumes when you press any key.”を表示しているので、また、Enter キーを押したところカメラ画像が再表示された。

gtkterm の表示を示す。なお、最初の 2 行の表示は、以前のアプリケーション・ソフトウェアを起動した名残だ。
DFX2_33_210810.png

アプリケーション・ソフトウェアの DFX_filter_test.c を貼っておく。

// DFX_filter_test.c
// 2021/08/08 by marsee
// 2021/08/09 : Stop the operation of DMA2axis IP on the video side and restart it.

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

#include "xvflip_dma_write.h"
#include "xdma2axis.h"

#define CAMERA_DATA_DMA_ADDR    0x10000000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);

void cam_i2c_init(volatile uint32_t *ov5642_axi_iic) {
    ov5642_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_axi_iic[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 uint32_t *ov5642_axi_iic, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}

int main(){
    XVflip_dma_write XVfilp_dma_write_ap;
    XDma2axis XDma2axis_ap;
    int inbyte_in;

    XVflip_dma_write_Initialize(&XVfilp_dma_write_ap, 0);
    XDma2axis_Initialize(&XDma2axis_ap, 0);

    XVflip_dma_write_Set_fb0_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb1_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb2_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XDma2axis_Set_x_size(&XDma2axis_ap, HORIZONTAL_PIXELS);
    XDma2axis_Set_y_size(&XDma2axis_ap, VERTICAL_LINES);
    XDma2axis_Set_in_V(&XDma2axis_ap, (u32)CAMERA_DATA_DMA_ADDR);

    // vflip_dma_write start
    XVflip_dma_write_Start(&XVfilp_dma_write_ap);
    XVflip_dma_write_EnableAutoRestart(&XVfilp_dma_write_ap);

    // CMOS Camera initialize, ov5642
    cam_i2c_init((volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR);
    cam_reg_set((volatile uint32_t *)(XPAR_AXI_IIC_0_BASEADDR), (uint32_t)0x78); // OV5642 register set
    Xil_Out32(XPAR_MT9D111_INF_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // ov5642 AXI4-Stream Start
    Xil_Out32((XPAR_MT9D111_INF_AXIS_0_BASEADDR+4), 0);

    // bitmap_disp_cont_axis start
    Xil_Out32(XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // dummy address, start

    // DMA2axis start
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("The display stops when you press any key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // Display Stopped
    XDma2axis_DisableAutoRestart(&XDma2axis_ap);
    while(XDma2axis_IsIdle(&XDma2axis_ap)==0);

    printf("The display resumes when you press any key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    // DMA2axis resumes
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    return(0);
}

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr){
    cam_i2c_write(axi_iic, device_addr, 0x3103, 0x93);
    cam_i2c_write(axi_iic, device_addr, 0x3008, 0x82);
    cam_i2c_write(axi_iic, device_addr, 0x3017, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x3018, 0xfc);
    cam_i2c_write(axi_iic, device_addr, 0x3810, 0xc2);
    cam_i2c_write(axi_iic, device_addr, 0x3615, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x3000, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3001, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3002, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3003, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3000, 0xf8);
    cam_i2c_write(axi_iic, device_addr, 0x3001, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x3002, 0x5c);
    cam_i2c_write(axi_iic, device_addr, 0x3003, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3004, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3005, 0xb7);
    cam_i2c_write(axi_iic, device_addr, 0x3006, 0x43);
    cam_i2c_write(axi_iic, device_addr, 0x3007, 0x37);
    cam_i2c_write(axi_iic, device_addr, 0x3011, 0x08); // 0x08 - 15fps, 0x10 - 30fps
    cam_i2c_write(axi_iic, device_addr, 0x3010, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x460c, 0x22);
    cam_i2c_write(axi_iic, device_addr, 0x3815, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x370d, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x370c, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3602, 0xfc);
    cam_i2c_write(axi_iic, device_addr, 0x3612, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x3634, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3613, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3605, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x3622, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3604, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x3603, 0xa7);
    cam_i2c_write(axi_iic, device_addr, 0x3603, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x4000, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x401d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3600, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x3605, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3606, 0x3f);
    cam_i2c_write(axi_iic, device_addr, 0x3c01, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0x4f);
    cam_i2c_write(axi_iic, device_addr, 0x5020, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x79);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x22);
    cam_i2c_write(axi_iic, device_addr, 0x5197, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x5500, 0x0a);
    cam_i2c_write(axi_iic, device_addr, 0x5504, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5505, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5080, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x300e, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x4610, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x471d, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x4708, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x3710, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3632, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x3702, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x37);
    cam_i2c_write(axi_iic, device_addr, 0x3631, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x3808, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3809, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380a, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x380b, 0xe0);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x501f, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0x4f);
    cam_i2c_write(axi_iic, device_addr, 0x4300, 0x61); // RGB565
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x73);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3824, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x380c, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x380d, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xe8);
    cam_i2c_write(axi_iic, device_addr, 0x3a0d, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3a0e, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x3818, 0xc1);
    cam_i2c_write(axi_iic, device_addr, 0x3705, 0xdb);
    cam_i2c_write(axi_iic, device_addr, 0x370a, 0x81);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0xc7);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x3803, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3827, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3810, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3804, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x3805, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3806, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x3807, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3a00, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x3a1a, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3a13, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a18, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a19, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x3a08, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x3a09, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0a, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x3a0b, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3004, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x350c, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x350d, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x3500, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x350a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3a0f, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a10, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a1b, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a1e, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a11, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3a1f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3030, 0x0b);
    cam_i2c_write(axi_iic, device_addr, 0x3a02, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a03, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x3a04, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a14, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a15, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x3a16, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a00, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x3a08, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x3a09, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x3a0a, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3a0b, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0d, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3a0e, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x57);
    cam_i2c_write(axi_iic, device_addr, 0x3703, 0x98);
    cam_i2c_write(axi_iic, device_addr, 0x3704, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x589b, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x589a, 0xc5);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5380, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5381, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5382, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5383, 0x4e);
    cam_i2c_write(axi_iic, device_addr, 0x5384, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5385, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x5386, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5387, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5388, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5389, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x538a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538b, 0x31);
    cam_i2c_write(axi_iic, device_addr, 0x538c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538d, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538f, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x5390, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5391, 0xab);
    cam_i2c_write(axi_iic, device_addr, 0x5392, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5393, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x5394, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5480, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5481, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x5482, 0x36);
    cam_i2c_write(axi_iic, device_addr, 0x5483, 0x57);
    cam_i2c_write(axi_iic, device_addr, 0x5484, 0x65);
    cam_i2c_write(axi_iic, device_addr, 0x5485, 0x71);
    cam_i2c_write(axi_iic, device_addr, 0x5486, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x5487, 0x87);
    cam_i2c_write(axi_iic, device_addr, 0x5488, 0x91);
    cam_i2c_write(axi_iic, device_addr, 0x5489, 0x9a);
    cam_i2c_write(axi_iic, device_addr, 0x548a, 0xaa);
    cam_i2c_write(axi_iic, device_addr, 0x548b, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x548c, 0xcd);
    cam_i2c_write(axi_iic, device_addr, 0x548d, 0xdd);
    cam_i2c_write(axi_iic, device_addr, 0x548e, 0xea);
    cam_i2c_write(axi_iic, device_addr, 0x548f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5490, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5491, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5492, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5493, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5494, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5495, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x5496, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5497, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x5498, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5499, 0x86);
    cam_i2c_write(axi_iic, device_addr, 0x549a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549b, 0x5b);
    cam_i2c_write(axi_iic, device_addr, 0x549c, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549d, 0x3b);
    cam_i2c_write(axi_iic, device_addr, 0x549e, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549f, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x54a0, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x54a1, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x54a2, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a3, 0xed);
    cam_i2c_write(axi_iic, device_addr, 0x54a4, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a5, 0xc5);
    cam_i2c_write(axi_iic, device_addr, 0x54a6, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a7, 0xa5);
    cam_i2c_write(axi_iic, device_addr, 0x54a8, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a9, 0x6c);
    cam_i2c_write(axi_iic, device_addr, 0x54aa, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ab, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x54ac, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ad, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x54ae, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x54af, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x3406, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5192, 0x04); // 0x04
    cam_i2c_write(axi_iic, device_addr, 0x5191, 0xf8); // 0xf8
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x5194, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5195, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x518d, 0x3d);
    cam_i2c_write(axi_iic, device_addr, 0x518f, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x518e, 0x3d);
    cam_i2c_write(axi_iic, device_addr, 0x5190, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x518b, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x518c, 0xbd);
    cam_i2c_write(axi_iic, device_addr, 0x5187, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5188, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5189, 0x6e);
    cam_i2c_write(axi_iic, device_addr, 0x518a, 0x68);
    cam_i2c_write(axi_iic, device_addr, 0x5186, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5183, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x24);
    cam_i2c_write(axi_iic, device_addr, 0x5025, 0x82);
    cam_i2c_write(axi_iic, device_addr, 0x5583, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5584, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5580, 0x02); // 0x02
    cam_i2c_write(axi_iic, device_addr, 0x3633, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3702, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3703, 0xb2);
    cam_i2c_write(axi_iic, device_addr, 0x3704, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x370b, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x370d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x52);
    cam_i2c_write(axi_iic, device_addr, 0x3c00, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0xFF);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5500, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5502, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5503, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5504, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5505, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5025, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5380, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5381, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5382, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5383, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5384, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5385, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5386, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5387, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5388, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5389, 0xE1);
    cam_i2c_write(axi_iic, device_addr, 0x538A, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538B, 0x2B);
    cam_i2c_write(axi_iic, device_addr, 0x538C, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538D, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538E, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538F, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5390, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5391, 0xB3);
    cam_i2c_write(axi_iic, device_addr, 0x5392, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5393, 0xA6);
    cam_i2c_write(axi_iic, device_addr, 0x5394, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5480, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5481, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5482, 0x2a);
    cam_i2c_write(axi_iic, device_addr, 0x5483, 0x49);
    cam_i2c_write(axi_iic, device_addr, 0x5484, 0x56);
    cam_i2c_write(axi_iic, device_addr, 0x5485, 0x62);
    cam_i2c_write(axi_iic, device_addr, 0x5486, 0x6c);
    cam_i2c_write(axi_iic, device_addr, 0x5487, 0x76);
    cam_i2c_write(axi_iic, device_addr, 0x5488, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5489, 0x88);
    cam_i2c_write(axi_iic, device_addr, 0x548a, 0x96);
    cam_i2c_write(axi_iic, device_addr, 0x548b, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x548c, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x548d, 0xcc);
    cam_i2c_write(axi_iic, device_addr, 0x548e, 0xe0);
    cam_i2c_write(axi_iic, device_addr, 0x548f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5490, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5491, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5492, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5493, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5494, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5495, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x5496, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5497, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x5498, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5499, 0x26);
    cam_i2c_write(axi_iic, device_addr, 0x549a, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x549b, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x549c, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x549d, 0xee);
    cam_i2c_write(axi_iic, device_addr, 0x549e, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x549f, 0xd8);
    cam_i2c_write(axi_iic, device_addr, 0x54a0, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a1, 0xc7);
    cam_i2c_write(axi_iic, device_addr, 0x54a2, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a3, 0xb3);
    cam_i2c_write(axi_iic, device_addr, 0x54a4, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a5, 0x90);
    cam_i2c_write(axi_iic, device_addr, 0x54a6, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a7, 0x62);
    cam_i2c_write(axi_iic, device_addr, 0x54a8, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a9, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x54aa, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ab, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x54ac, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ad, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x54ae, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x54af, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x54b0, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b1, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x54b2, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b3, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x54b4, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x54b5, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x54b6, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b7, 0xdf);
    cam_i2c_write(axi_iic, device_addr, 0x5583, 0x5d);
    cam_i2c_write(axi_iic, device_addr, 0x5584, 0x5d);
    cam_i2c_write(axi_iic, device_addr, 0x5580, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5587, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5588, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x558a, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x5589, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0xcf);
    cam_i2c_write(axi_iic, device_addr, 0x5800, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x5801, 0x31);
    cam_i2c_write(axi_iic, device_addr, 0x5802, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x5803, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x5804, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5805, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5806, 0x29);
    cam_i2c_write(axi_iic, device_addr, 0x5807, 0x38);
    cam_i2c_write(axi_iic, device_addr, 0x5808, 0x26);
    cam_i2c_write(axi_iic, device_addr, 0x5809, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x580a, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x580b, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x580c, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x580d, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x580e, 0x13);
    cam_i2c_write(axi_iic, device_addr, 0x580f, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5810, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x5811, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5812, 0x8);
    cam_i2c_write(axi_iic, device_addr, 0x5813, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5814, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x5815, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5816, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x5817, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5818, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5819, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x581a, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x581b, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x581c, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x581d, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x581e, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x581f, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x5820, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x5821, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x5822, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x5823, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5824, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5825, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x5826, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x5827, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5828, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5829, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x582a, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x582b, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x582c, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x582d, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x582e, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x582f, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5830, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x5831, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5832, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5833, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5834, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5835, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5836, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x5837, 0x1d);
    cam_i2c_write(axi_iic, device_addr, 0x5838, 0x6e);
    cam_i2c_write(axi_iic, device_addr, 0x5839, 0x39);
    cam_i2c_write(axi_iic, device_addr, 0x583a, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x583b, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x583c, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x583d, 0x23);
    cam_i2c_write(axi_iic, device_addr, 0x583e, 0x2f);
    cam_i2c_write(axi_iic, device_addr, 0x583f, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x5840, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5841, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5842, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5843, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5844, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5845, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5846, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5847, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5848, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5849, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584a, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584b, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x584c, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584d, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584e, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x584f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5850, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5851, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5852, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5853, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5854, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5855, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5856, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5857, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5858, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5859, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x585a, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585b, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585c, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585d, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x585e, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x585f, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5860, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5861, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x5862, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5863, 0x7);
    cam_i2c_write(axi_iic, device_addr, 0x5864, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5865, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5866, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5867, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5868, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x5869, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x586a, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x586b, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x586c, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x586d, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x586e, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x586f, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5870, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5871, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x5872, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5873, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5874, 0x13);
    cam_i2c_write(axi_iic, device_addr, 0x5875, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5876, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5877, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5878, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5879, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x587a, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x587b, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x587c, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x587d, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x587e, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x587f, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5880, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x5881, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5882, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5883, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5884, 0x1d);
    cam_i2c_write(axi_iic, device_addr, 0x5885, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5886, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5887, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5680, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5681, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5684, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5685, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5180, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x52);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5183, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x24);
    cam_i2c_write(axi_iic, device_addr, 0x5186, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5187, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5188, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5189, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x518a, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x518b, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x518c, 0x9c);
    cam_i2c_write(axi_iic, device_addr, 0x518d, 0x36);
    cam_i2c_write(axi_iic, device_addr, 0x518e, 0x34);
    cam_i2c_write(axi_iic, device_addr, 0x518f, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x5190, 0x4c);
    cam_i2c_write(axi_iic, device_addr, 0x5191, 0xf8);
    cam_i2c_write(axi_iic, device_addr, 0x5192, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x5194, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5195, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5196, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5197, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5198, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5199, 0x2f);
    cam_i2c_write(axi_iic, device_addr, 0x519a, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x519b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x519c, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x519d, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x519e, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0f, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a10, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a1b, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a1e, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a11, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3a1f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3800, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x3802, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x3803, 0x8);
    cam_i2c_write(axi_iic, device_addr, 0x3804, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x3805, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x3806, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x3807, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3808, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x3809, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x380a, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x380b, 0x58);
    cam_i2c_write(axi_iic, device_addr, 0x380c, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x380d, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xe8);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5680, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5681, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5684, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5685, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3815, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3818, 0x81); // No Mirror
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0xa7);

    cam_i2c_write(axi_iic, device_addr, 0x4740, 0x21);

    cam_i2c_write(axi_iic, device_addr, 0x501e, 0x2a);
    cam_i2c_write(axi_iic, device_addr, 0x5002, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x501f, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x4300, 0x61);

    return(0);
}

  1. 2021年08月10日 03:33 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する3(DFX_filter_test プロジェクト2)

画像フィルタを DFX する2(DFX_filter_test プロジェクト1)”の続き。

前回は、Vivado 2021.1 で作成した DFX のベースとなる DFX_filter_test プロジェクトを作成し、ブロック・デザインを作成して論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。今回は、ハードウェアをエクスポートし、Vitis 2021.1 を起動して、プラットフォームとアプリケーション・プロジェクトを作成する。そして、アプリケーション・ソフトウェアを記述してビルドし、ZYBO Z7-20 の実機で確認する。
なお、カメラは秋月電子の”OV5642使用500万画素カメラ M12レンズ付き B0020”を使用している。画像は SVGA で、 800 行 X 600 列だ。

ハードウェアをエクスポートして、 DFX_filter_test_wrapper.xsa を作成した。
DFX2_28_210809.png

Vitis 2021.1 を立ち上げて、 DFX_filter_test ディスプレイの下に vitis_work ディレクトリ作成し、そこをワーク・ディレクトリに指定した。

Vitis 2021.1 が立ち上がった。
Create Application Project をクリックする。

DFX_filter_test_wrapper プラットフォームと DFX_filter_test アプリケーション・プロジェクトを作成した。

DMA_pow2_test_system -> DMA_pow2_test -> src に DFX_filter_test.c ファイルを新規作成して、コードを書いた。
DFX2_29_210809.png

ZYBO Z7-20 を用意して、USB ケーブルを接続し、電源を ON する。
gtkterm を立ち上げて Port に ttyUSB1 を指定し、ビットレートを 115200 bit/sec に指定する。
Vitis の Explorer で DFX_filter_test_system を選択し、 Run ボタンをクリックする。

gtkterm に”Configure the partial bit file in Vivado and then press any key.”が表示された。
DFX2_30_210809.png

ディスプレイを見ると、カメラ画像が表示されていた。
DFX2_31_210809.jpg

成功だ。

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

// DFX_filter_test.c
// 2021/08/08 by marsee
//

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

#include "xvflip_dma_write.h"
#include "xdma2axis.h"

#define CAMERA_DATA_DMA_ADDR    0x10000000

#define HORIZONTAL_PIXELS   800
#define VERTICAL_LINES      600

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr);

void cam_i2c_init(volatile uint32_t *ov5642_axi_iic) {
    ov5642_axi_iic[64] = 0x2; // reset tx fifo ,address is 0x100, i2c_control_reg
    ov5642_axi_iic[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 uint32_t *ov5642_axi_iic, uint32_t device_addr, uint32_t write_addr, uint32_t write_data){
    ov5642_axi_iic[66] = 0x100 | (device_addr & 0xfe); // Slave IIC Write Address, address is 0x108, i2c_tx_fifo
    ov5642_axi_iic[66] = (write_addr >> 8) & 0xff;  // address upper byte
    ov5642_axi_iic[66] = write_addr & 0xff;           // address lower byte
    ov5642_axi_iic[66] = 0x200 | (write_data & 0xff);      // data
    cam_i2x_write_sync();
}

int main(){
    XVflip_dma_write XVfilp_dma_write_ap;
    XDma2axis XDma2axis_ap;
    int inbyte_in;

    XVflip_dma_write_Initialize(&XVfilp_dma_write_ap, 0);
    XDma2axis_Initialize(&XDma2axis_ap, 0);

    XVflip_dma_write_Set_fb0_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb1_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XVflip_dma_write_Set_fb2_V(&XVfilp_dma_write_ap, (u32)CAMERA_DATA_DMA_ADDR);
    XDma2axis_Set_x_size(&XDma2axis_ap, HORIZONTAL_PIXELS);
    XDma2axis_Set_y_size(&XDma2axis_ap, VERTICAL_LINES);
    XDma2axis_Set_in_V(&XDma2axis_ap, (u32)CAMERA_DATA_DMA_ADDR);

    // vflip_dma_write start
    XVflip_dma_write_Start(&XVfilp_dma_write_ap);
    XVflip_dma_write_EnableAutoRestart(&XVfilp_dma_write_ap);

    // CMOS Camera initialize, ov5642
    cam_i2c_init((volatile uint32_t *)XPAR_AXI_IIC_0_BASEADDR);
    cam_reg_set((volatile uint32_t *)(XPAR_AXI_IIC_0_BASEADDR), (uint32_t)0x78); // OV5642 register set
    Xil_Out32(XPAR_MT9D111_INF_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // ov5642 AXI4-Stream Start
    Xil_Out32((XPAR_MT9D111_INF_AXIS_0_BASEADDR+4), 0);

    // bitmap_disp_cont_axis start
    Xil_Out32(XPAR_BITMAP_DISP_CONT_AXIS_0_BASEADDR, CAMERA_DATA_DMA_ADDR); // dummy address, start

    // DMA2axis start
    XDma2axis_Start(&XDma2axis_ap);
    XDma2axis_EnableAutoRestart(&XDma2axis_ap);

    printf("Configure the partial bit file in Vivado and then press any key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    return(0);
}

int cam_reg_set(volatile unsigned *axi_iic, unsigned int device_addr){
    cam_i2c_write(axi_iic, device_addr, 0x3103, 0x93);
    cam_i2c_write(axi_iic, device_addr, 0x3008, 0x82);
    cam_i2c_write(axi_iic, device_addr, 0x3017, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x3018, 0xfc);
    cam_i2c_write(axi_iic, device_addr, 0x3810, 0xc2);
    cam_i2c_write(axi_iic, device_addr, 0x3615, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x3000, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3001, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3002, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3003, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3000, 0xf8);
    cam_i2c_write(axi_iic, device_addr, 0x3001, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x3002, 0x5c);
    cam_i2c_write(axi_iic, device_addr, 0x3003, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3004, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3005, 0xb7);
    cam_i2c_write(axi_iic, device_addr, 0x3006, 0x43);
    cam_i2c_write(axi_iic, device_addr, 0x3007, 0x37);
    cam_i2c_write(axi_iic, device_addr, 0x3011, 0x08); // 0x08 - 15fps, 0x10 - 30fps
    cam_i2c_write(axi_iic, device_addr, 0x3010, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x460c, 0x22);
    cam_i2c_write(axi_iic, device_addr, 0x3815, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x370d, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x370c, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3602, 0xfc);
    cam_i2c_write(axi_iic, device_addr, 0x3612, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x3634, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3613, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3605, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x3622, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3604, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x3603, 0xa7);
    cam_i2c_write(axi_iic, device_addr, 0x3603, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x4000, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x401d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3600, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x3605, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3606, 0x3f);
    cam_i2c_write(axi_iic, device_addr, 0x3c01, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0x4f);
    cam_i2c_write(axi_iic, device_addr, 0x5020, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x79);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x22);
    cam_i2c_write(axi_iic, device_addr, 0x5197, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x5500, 0x0a);
    cam_i2c_write(axi_iic, device_addr, 0x5504, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5505, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5080, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x300e, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x4610, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x471d, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x4708, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x3710, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3632, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x3702, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x37);
    cam_i2c_write(axi_iic, device_addr, 0x3631, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x3808, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3809, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380a, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x380b, 0xe0);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x501f, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0x4f);
    cam_i2c_write(axi_iic, device_addr, 0x4300, 0x61); // RGB565
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x73);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3824, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x380c, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x380d, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xe8);
    cam_i2c_write(axi_iic, device_addr, 0x3a0d, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3a0e, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x3818, 0xc1);
    cam_i2c_write(axi_iic, device_addr, 0x3705, 0xdb);
    cam_i2c_write(axi_iic, device_addr, 0x370a, 0x81);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0xc7);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x3803, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3827, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3810, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3804, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x3805, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3806, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x3807, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3a00, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x3a1a, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x3a13, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a18, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a19, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x3a08, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x3a09, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0a, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x3a0b, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3004, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x350c, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x350d, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x3500, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3501, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3502, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x350a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x350b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3a0f, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a10, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a1b, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a1e, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a11, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3a1f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3030, 0x0b);
    cam_i2c_write(axi_iic, device_addr, 0x3a02, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a03, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x3a04, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a14, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a15, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x3a16, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3a00, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x3a08, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x3a09, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x3a0a, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3a0b, 0xd0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0d, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x3a0e, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x57);
    cam_i2c_write(axi_iic, device_addr, 0x3703, 0x98);
    cam_i2c_write(axi_iic, device_addr, 0x3704, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x589b, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x589a, 0xc5);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5380, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5381, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5382, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5383, 0x4e);
    cam_i2c_write(axi_iic, device_addr, 0x5384, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5385, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x5386, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5387, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5388, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5389, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x538a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538b, 0x31);
    cam_i2c_write(axi_iic, device_addr, 0x538c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538d, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538f, 0x0f);
    cam_i2c_write(axi_iic, device_addr, 0x5390, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5391, 0xab);
    cam_i2c_write(axi_iic, device_addr, 0x5392, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5393, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x5394, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5480, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5481, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x5482, 0x36);
    cam_i2c_write(axi_iic, device_addr, 0x5483, 0x57);
    cam_i2c_write(axi_iic, device_addr, 0x5484, 0x65);
    cam_i2c_write(axi_iic, device_addr, 0x5485, 0x71);
    cam_i2c_write(axi_iic, device_addr, 0x5486, 0x7d);
    cam_i2c_write(axi_iic, device_addr, 0x5487, 0x87);
    cam_i2c_write(axi_iic, device_addr, 0x5488, 0x91);
    cam_i2c_write(axi_iic, device_addr, 0x5489, 0x9a);
    cam_i2c_write(axi_iic, device_addr, 0x548a, 0xaa);
    cam_i2c_write(axi_iic, device_addr, 0x548b, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x548c, 0xcd);
    cam_i2c_write(axi_iic, device_addr, 0x548d, 0xdd);
    cam_i2c_write(axi_iic, device_addr, 0x548e, 0xea);
    cam_i2c_write(axi_iic, device_addr, 0x548f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5490, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5491, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5492, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5493, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5494, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5495, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x5496, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5497, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x5498, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5499, 0x86);
    cam_i2c_write(axi_iic, device_addr, 0x549a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549b, 0x5b);
    cam_i2c_write(axi_iic, device_addr, 0x549c, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549d, 0x3b);
    cam_i2c_write(axi_iic, device_addr, 0x549e, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x549f, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x54a0, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x54a1, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x54a2, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a3, 0xed);
    cam_i2c_write(axi_iic, device_addr, 0x54a4, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a5, 0xc5);
    cam_i2c_write(axi_iic, device_addr, 0x54a6, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a7, 0xa5);
    cam_i2c_write(axi_iic, device_addr, 0x54a8, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54a9, 0x6c);
    cam_i2c_write(axi_iic, device_addr, 0x54aa, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ab, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x54ac, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ad, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x54ae, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x54af, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x3406, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5192, 0x04); // 0x04
    cam_i2c_write(axi_iic, device_addr, 0x5191, 0xf8); // 0xf8
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x5194, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5195, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x518d, 0x3d);
    cam_i2c_write(axi_iic, device_addr, 0x518f, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x518e, 0x3d);
    cam_i2c_write(axi_iic, device_addr, 0x5190, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x518b, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x518c, 0xbd);
    cam_i2c_write(axi_iic, device_addr, 0x5187, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5188, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5189, 0x6e);
    cam_i2c_write(axi_iic, device_addr, 0x518a, 0x68);
    cam_i2c_write(axi_iic, device_addr, 0x5186, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5183, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x24);
    cam_i2c_write(axi_iic, device_addr, 0x5025, 0x82);
    cam_i2c_write(axi_iic, device_addr, 0x5583, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5584, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5580, 0x02); // 0x02
    cam_i2c_write(axi_iic, device_addr, 0x3633, 0x07);
    cam_i2c_write(axi_iic, device_addr, 0x3702, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3703, 0xb2);
    cam_i2c_write(axi_iic, device_addr, 0x3704, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x370b, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x370d, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3620, 0x52);
    cam_i2c_write(axi_iic, device_addr, 0x3c00, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0xFF);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5500, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5502, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5503, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5504, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5505, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5025, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5300, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5301, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5302, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5303, 0x7c);
    cam_i2c_write(axi_iic, device_addr, 0x530c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x530d, 0x0c);
    cam_i2c_write(axi_iic, device_addr, 0x530e, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x530f, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5310, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5311, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5308, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5309, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5304, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5305, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5306, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5307, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5314, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5315, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x5319, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5316, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5317, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5318, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5380, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5381, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5382, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5383, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5384, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5385, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5386, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5387, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5388, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5389, 0xE1);
    cam_i2c_write(axi_iic, device_addr, 0x538A, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538B, 0x2B);
    cam_i2c_write(axi_iic, device_addr, 0x538C, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538D, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538E, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x538F, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5390, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5391, 0xB3);
    cam_i2c_write(axi_iic, device_addr, 0x5392, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5393, 0xA6);
    cam_i2c_write(axi_iic, device_addr, 0x5394, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5480, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5481, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5482, 0x2a);
    cam_i2c_write(axi_iic, device_addr, 0x5483, 0x49);
    cam_i2c_write(axi_iic, device_addr, 0x5484, 0x56);
    cam_i2c_write(axi_iic, device_addr, 0x5485, 0x62);
    cam_i2c_write(axi_iic, device_addr, 0x5486, 0x6c);
    cam_i2c_write(axi_iic, device_addr, 0x5487, 0x76);
    cam_i2c_write(axi_iic, device_addr, 0x5488, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x5489, 0x88);
    cam_i2c_write(axi_iic, device_addr, 0x548a, 0x96);
    cam_i2c_write(axi_iic, device_addr, 0x548b, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x548c, 0xb8);
    cam_i2c_write(axi_iic, device_addr, 0x548d, 0xcc);
    cam_i2c_write(axi_iic, device_addr, 0x548e, 0xe0);
    cam_i2c_write(axi_iic, device_addr, 0x548f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5490, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5491, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x5492, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5493, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5494, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5495, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x5496, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5497, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x5498, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x5499, 0x26);
    cam_i2c_write(axi_iic, device_addr, 0x549a, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x549b, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x549c, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x549d, 0xee);
    cam_i2c_write(axi_iic, device_addr, 0x549e, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x549f, 0xd8);
    cam_i2c_write(axi_iic, device_addr, 0x54a0, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a1, 0xc7);
    cam_i2c_write(axi_iic, device_addr, 0x54a2, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a3, 0xb3);
    cam_i2c_write(axi_iic, device_addr, 0x54a4, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a5, 0x90);
    cam_i2c_write(axi_iic, device_addr, 0x54a6, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a7, 0x62);
    cam_i2c_write(axi_iic, device_addr, 0x54a8, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54a9, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x54aa, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ab, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x54ac, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x54ad, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x54ae, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x54af, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x54b0, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b1, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x54b2, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b3, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x54b4, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x54b5, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x54b6, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x54b7, 0xdf);
    cam_i2c_write(axi_iic, device_addr, 0x5583, 0x5d);
    cam_i2c_write(axi_iic, device_addr, 0x5584, 0x5d);
    cam_i2c_write(axi_iic, device_addr, 0x5580, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x5587, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5588, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x558a, 0x09);
    cam_i2c_write(axi_iic, device_addr, 0x5589, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5000, 0xcf);
    cam_i2c_write(axi_iic, device_addr, 0x5800, 0x48);
    cam_i2c_write(axi_iic, device_addr, 0x5801, 0x31);
    cam_i2c_write(axi_iic, device_addr, 0x5802, 0x21);
    cam_i2c_write(axi_iic, device_addr, 0x5803, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x5804, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5805, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5806, 0x29);
    cam_i2c_write(axi_iic, device_addr, 0x5807, 0x38);
    cam_i2c_write(axi_iic, device_addr, 0x5808, 0x26);
    cam_i2c_write(axi_iic, device_addr, 0x5809, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x580a, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x580b, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x580c, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x580d, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x580e, 0x13);
    cam_i2c_write(axi_iic, device_addr, 0x580f, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5810, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x5811, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5812, 0x8);
    cam_i2c_write(axi_iic, device_addr, 0x5813, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5814, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x5815, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5816, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x5817, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5818, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5819, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x581a, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x581b, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x581c, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x581d, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x581e, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x581f, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x5820, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x5821, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x5822, 0x4);
    cam_i2c_write(axi_iic, device_addr, 0x5823, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5824, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5825, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x5826, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x5827, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5828, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5829, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x582a, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x582b, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x582c, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x582d, 0x6);
    cam_i2c_write(axi_iic, device_addr, 0x582e, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x582f, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5830, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x5831, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5832, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5833, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5834, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5835, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5836, 0x15);
    cam_i2c_write(axi_iic, device_addr, 0x5837, 0x1d);
    cam_i2c_write(axi_iic, device_addr, 0x5838, 0x6e);
    cam_i2c_write(axi_iic, device_addr, 0x5839, 0x39);
    cam_i2c_write(axi_iic, device_addr, 0x583a, 0x27);
    cam_i2c_write(axi_iic, device_addr, 0x583b, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x583c, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x583d, 0x23);
    cam_i2c_write(axi_iic, device_addr, 0x583e, 0x2f);
    cam_i2c_write(axi_iic, device_addr, 0x583f, 0x41);
    cam_i2c_write(axi_iic, device_addr, 0x5840, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5841, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5842, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5843, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5844, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5845, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5846, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5847, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5848, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5849, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584a, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584b, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x584c, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584d, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x584e, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x584f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5850, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5851, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5852, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5853, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5854, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5855, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5856, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5857, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x5858, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x5859, 0xe);
    cam_i2c_write(axi_iic, device_addr, 0x585a, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585b, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585c, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x585d, 0xa);
    cam_i2c_write(axi_iic, device_addr, 0x585e, 0x9);
    cam_i2c_write(axi_iic, device_addr, 0x585f, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5860, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x5861, 0xb);
    cam_i2c_write(axi_iic, device_addr, 0x5862, 0xd);
    cam_i2c_write(axi_iic, device_addr, 0x5863, 0x7);
    cam_i2c_write(axi_iic, device_addr, 0x5864, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5865, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5866, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5867, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x5868, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x5869, 0x12);
    cam_i2c_write(axi_iic, device_addr, 0x586a, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x586b, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x586c, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x586d, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x586e, 0x18);
    cam_i2c_write(axi_iic, device_addr, 0x586f, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5870, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5871, 0x16);
    cam_i2c_write(axi_iic, device_addr, 0x5872, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x5873, 0xf);
    cam_i2c_write(axi_iic, device_addr, 0x5874, 0x13);
    cam_i2c_write(axi_iic, device_addr, 0x5875, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x5876, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5877, 0x17);
    cam_i2c_write(axi_iic, device_addr, 0x5878, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5879, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x587a, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x587b, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x587c, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x587d, 0x1c);
    cam_i2c_write(axi_iic, device_addr, 0x587e, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x587f, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5880, 0x1b);
    cam_i2c_write(axi_iic, device_addr, 0x5881, 0x1f);
    cam_i2c_write(axi_iic, device_addr, 0x5882, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5883, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5884, 0x1d);
    cam_i2c_write(axi_iic, device_addr, 0x5885, 0x1e);
    cam_i2c_write(axi_iic, device_addr, 0x5886, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x5887, 0x1a);
    cam_i2c_write(axi_iic, device_addr, 0x528a, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x528b, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x528c, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x528d, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x528e, 0x40);
    cam_i2c_write(axi_iic, device_addr, 0x528f, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x5290, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x5292, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5293, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x5294, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5295, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5296, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5297, 0x08);
    cam_i2c_write(axi_iic, device_addr, 0x5298, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5299, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x529a, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529b, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x529c, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529d, 0x28);
    cam_i2c_write(axi_iic, device_addr, 0x529e, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x529f, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x5282, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5680, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5681, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5684, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5685, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5180, 0xff);
    cam_i2c_write(axi_iic, device_addr, 0x5181, 0x52);
    cam_i2c_write(axi_iic, device_addr, 0x5182, 0x11);
    cam_i2c_write(axi_iic, device_addr, 0x5183, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5184, 0x25);
    cam_i2c_write(axi_iic, device_addr, 0x5185, 0x24);
    cam_i2c_write(axi_iic, device_addr, 0x5186, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5187, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5188, 0x14);
    cam_i2c_write(axi_iic, device_addr, 0x5189, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x518a, 0x60);
    cam_i2c_write(axi_iic, device_addr, 0x518b, 0xa2);
    cam_i2c_write(axi_iic, device_addr, 0x518c, 0x9c);
    cam_i2c_write(axi_iic, device_addr, 0x518d, 0x36);
    cam_i2c_write(axi_iic, device_addr, 0x518e, 0x34);
    cam_i2c_write(axi_iic, device_addr, 0x518f, 0x54);
    cam_i2c_write(axi_iic, device_addr, 0x5190, 0x4c);
    cam_i2c_write(axi_iic, device_addr, 0x5191, 0xf8);
    cam_i2c_write(axi_iic, device_addr, 0x5192, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x5193, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x5194, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5195, 0xf0);
    cam_i2c_write(axi_iic, device_addr, 0x5196, 0x03);
    cam_i2c_write(axi_iic, device_addr, 0x5197, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x5198, 0x05);
    cam_i2c_write(axi_iic, device_addr, 0x5199, 0x2f);
    cam_i2c_write(axi_iic, device_addr, 0x519a, 0x04);
    cam_i2c_write(axi_iic, device_addr, 0x519b, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x519c, 0x06);
    cam_i2c_write(axi_iic, device_addr, 0x519d, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x519e, 0xa0);
    cam_i2c_write(axi_iic, device_addr, 0x3a0f, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a10, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a1b, 0x3c);
    cam_i2c_write(axi_iic, device_addr, 0x3a1e, 0x30);
    cam_i2c_write(axi_iic, device_addr, 0x3a11, 0x70);
    cam_i2c_write(axi_iic, device_addr, 0x3a1f, 0x10);
    cam_i2c_write(axi_iic, device_addr, 0x3800, 0x1);
    cam_i2c_write(axi_iic, device_addr, 0x3801, 0x50);
    cam_i2c_write(axi_iic, device_addr, 0x3802, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x3803, 0x8);
    cam_i2c_write(axi_iic, device_addr, 0x3804, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x3805, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x3806, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x3807, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3808, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x3809, 0x20);
    cam_i2c_write(axi_iic, device_addr, 0x380a, 0x2);
    cam_i2c_write(axi_iic, device_addr, 0x380b, 0x58);
    cam_i2c_write(axi_iic, device_addr, 0x380c, 0xc);
    cam_i2c_write(axi_iic, device_addr, 0x380d, 0x80);
    cam_i2c_write(axi_iic, device_addr, 0x380e, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x380f, 0xe8);
    cam_i2c_write(axi_iic, device_addr, 0x5001, 0x7f);
    cam_i2c_write(axi_iic, device_addr, 0x5680, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5681, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5682, 0x5);
    cam_i2c_write(axi_iic, device_addr, 0x5683, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5684, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5685, 0x0);
    cam_i2c_write(axi_iic, device_addr, 0x5686, 0x3);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x5687, 0xc0);
    cam_i2c_write(axi_iic, device_addr, 0x3815, 0x02);
    cam_i2c_write(axi_iic, device_addr, 0x3503, 0x00);
    cam_i2c_write(axi_iic, device_addr, 0x3818, 0x81); // No Mirror
    cam_i2c_write(axi_iic, device_addr, 0x3621, 0xa7);

    cam_i2c_write(axi_iic, device_addr, 0x4740, 0x21);

    cam_i2c_write(axi_iic, device_addr, 0x501e, 0x2a);
    cam_i2c_write(axi_iic, device_addr, 0x5002, 0x78);
    cam_i2c_write(axi_iic, device_addr, 0x501f, 0x01);
    cam_i2c_write(axi_iic, device_addr, 0x4300, 0x61);

    return(0);
}

  1. 2021年08月09日 04:32 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する2(DFX_filter_test プロジェクト1)

画像フィルタを DFX する1(概要)”の続き。

前回は、 AXI4-Stream 入出力のフィルタ IP を切り替えてみようということで、カメラ表示システムのフィルタを DFX で切り替えるシステムを説明した。今回は、Vivado 2021.1 で作成した DFX のベースとなる DFX_filter_test プロジェクトを紹介する。

Vivado 2021.1 で作成した DFX のベースとなる DFX_filter_test プロジェクトを示す。
ZYBO Z7-20 用のプロジェクトだ。
DFX2_22_210808.png

DFX_filter_test ブロック・デザインを示す。
DFX2_21_210807.png

Zynq Processing System 7 のクロックの設定を示す。
メインの FLCK_CLK0 が 100 MHz で、 SVGA 用のピクセル・クロックが FCK_CLK1 の 40 MHz 、カメラ・モジュール用の 24 MHz が FCLK_CLK2 だ。
DFX2_24_210808.png

Zynq Processing System 7 の PS-PL Configuration では、 S AXI HP0 にチェックを入れて、活かした。
DFX2_25_210808.png

rgb2dvi_0 は TMDS clock range で < 80MHz(720p) のラジオボタンをチェックした。
DFX2_26_210808.png

各 IP の説明をする。
vflip_dma_write は ”垂直方向が反転している画像のDMA(vflip_dma_write)”に書いた。

DMA2axis は”Vitis HLS 2020.2 で DMA2axis IP を作る1”に書いた。

bitmap_disp_cont_axis は”ビットマップ・ディスプレイ・コントローラをAXI4-Stream対応にする4(ソースコードの公開)”で書いた。

rgb2dvi は Digilent 社の Github から頂いてきた。

制約ファイルの DFX_filter_test.xdc を貼っておく。

set_property PACKAGE_PIN H16 [get_ports TMDS_Clk_p_0]
set_property PACKAGE_PIN D19 [get_ports {TMDS_Data_p_0[0]}]
set_property PACKAGE_PIN C20 [get_ports {TMDS_Data_p_0[1]}]
set_property PACKAGE_PIN B19 [get_ports {TMDS_Data_p_0[2]}]

set_property IOSTANDARD TMDS_33 [get_ports TMDS_Clk_p_0]
set_property IOSTANDARD TMDS_33 [get_ports {TMDS_Data_p_0[2]}]
set_property IOSTANDARD TMDS_33 [get_ports {TMDS_Data_p_0[1]}]
set_property IOSTANDARD TMDS_33 [get_ports {TMDS_Data_p_0[0]}]

set_property PACKAGE_PIN T14 [get_ports {cam_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[7]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[6]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[5]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[4]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[3]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[2]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[1]}]
set_property IOSTANDARD LVCMOS33 [get_ports {cam_data[0]}]
set_property PACKAGE_PIN U14 [get_ports {cam_data[6]}]
set_property PACKAGE_PIN T15 [get_ports {cam_data[5]}]
set_property PACKAGE_PIN U15 [get_ports {cam_data[4]}]
set_property PACKAGE_PIN P14 [get_ports {cam_data[3]}]
set_property PACKAGE_PIN V17 [get_ports {cam_data[2]}]
set_property PACKAGE_PIN R14 [get_ports {cam_data[1]}]
set_property PACKAGE_PIN V18 [get_ports {cam_data[0]}]

set_property IOSTANDARD LVCMOS33 [get_ports iic_scl_io]
set_property IOSTANDARD LVCMOS33 [get_ports iic_sda_io]
set_property IOSTANDARD LVCMOS33 [get_ports href]
set_property IOSTANDARD LVCMOS33 [get_ports pclk]
set_property IOSTANDARD LVCMOS33 [get_ports standby]
set_property IOSTANDARD LVCMOS33 [get_ports vsync]
set_property IOSTANDARD LVCMOS33 [get_ports xck]
set_property PACKAGE_PIN V15 [get_ports iic_scl_io]
set_property PACKAGE_PIN W14 [get_ports iic_sda_io]
set_property PACKAGE_PIN W15 [get_ports vsync]
set_property PACKAGE_PIN Y14 [get_ports href]
set_property PACKAGE_PIN T11 [get_ports standby]
set_property PACKAGE_PIN T10 [get_ports pclk]
set_property PACKAGE_PIN U12 [get_ports xck]

set_property CLOCK_DEDICATED_ROUTE FALSE [get_nets pclk_IBUF]


set_property PULLUP true [get_ports iic_scl_io]
set_property PULLUP true [get_ports iic_sda_io]


論理合成、インプリメンテーション、ビットストリームの生成を行って成功した。
Project Summary を示す。
DFX2_27_210808.png
  1. 2021年08月08日 04:28 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

画像フィルタを DFX する1(概要)

AXI Master インターフェースを含む IP を DFX する2”で AXI4 Master インターフェースの IP の 2 乗IP と平方根 IP を DFX で切り替えることができた。

今回は AXI4-Stream 入出力のフィルタ IP を切り替えてみよう。

現在、 Vivado 2021.1 で DFX_filter_test_211 プロジェクトを作成中だ。
これは、ZYBO Z7-20 ボードを使用し、カメラ側では、OV5642 カメラを使用して、カメラデータを ZYBO Z7-20 の DDR SDRAM に DMA Write する。そのカメラデータをビデオ側では DDR SDRAM から DMA Read し、ビットマップ・ディスプレイ・コントローラでHDMI に出力する。
DFX2_21_210807.png

ビデオ側の DMA2axis_0 と bitmap_disp_cont_axis_0 の間に AXI4-Stream をただ通過させる though_axis IP とラプラシアン・フィルタ IP とソーベル・フィルタ IP を DFX で切り替えてみよう。
  1. 2021年08月07日 07:39 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

AXI Master インターフェースを含む IP を DFX する2

AXI Master インターフェースを含む IP を DFX する1”の続き。

DFX Coupler と DFX Shutdown Manager をブログで勉強してきたが、その内の DFX Coupler を使用して、前回 DFX に失敗した DMA_pow2 IP と DMA_square_root8 IP の DFX をやっていこうということで、前回は、Vivado 2021.1 で ZYBO Z7-20 の DFX_test プロジェクトを作成し、 DMA_pow2 IP と DMA_square_root8 IP の DFX のブロック・デザインを作成して、ビット・ファイルを作成できた。そして、ハードウェアをエクスポートして、 XSA ファイルを作成した。
今回は、Vitis 2021.1 でプラットフォームとアプリケーション・プロジェクトを作成し、DMA_pow2 と DMA_square_root8 の DFX を実機で確かめてみよう。

Vivado 2021.1 から Vitis 2021.1 を起動して、 DFX_test_211 ディレクトリの下に、 vitis_work ディレクトリを作成した。

DFX_trest_wrapper プラットフォームと DMA_pow2_test アプリケーション・プロジェクトを作成した。

DMA_pow2_test アプリケーション・プロジェクトに DMA_pow2_test3.c ファイルを新規作成した。
DMA_square_root8 IP のドライバから xdma_square_root8_hw.h を vitis_work/DMA_pow2_test/src ディレクトリにインポートした。
ビルドして成功した。
DFX2_16_210804.png

DMA_pow2_test3.c を貼っておく。

// DMA_pow2_test3.c
// 2021/08/01 by marsee
//

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

volatile int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
volatile int result[10];

void Xil_DCacheFlush(void);
void Xil_DCacheInvalidate(void);

#define XPAR_XDMA_SQUARE_ROOT8_0_BASEADDR 0x40000000

int main(){
    XDma_pow2 XDMA_pow2_ap;
    XDma_pow2_Config *XDMA_pow2_apPtr;
    int i, inbyte_in;
    u32 status;

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

    // Initialize the Device
    int Xlap_status = XDma_pow2_CfgInitialize(&XDMA_pow2_ap, XDMA_pow2_apPtr);
    if (Xlap_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XDma_pow2\n");
        return(-1);
    }

    XDma_pow2_Set_data(&XDMA_pow2_ap, (u32)&data[0]);
    XDma_pow2_Set_result(&XDMA_pow2_ap, (u32)&result[0]);

    Xil_DCacheFlush(); // Flush data[10] cache to memory

    XDma_pow2_Start(&XDMA_pow2_ap);

    while(!XDma_pow2_IsDone(&XDMA_pow2_ap)) ;

    Xil_DCacheInvalidate(); // Invalidate result[10]
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, data[i], i, result[i]);
    }

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 1); // 1: Turn decoupling on

    printf("Configure the partial bit file in Vivado and then press any key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    Xil_Out32(XPAR_DFX_DECOUPLER_0_BASEADDR, 0); // 1: Turn decoupling off

    Xil_Out32((XPAR_XDMA_SQUARE_ROOT8_0_BASEADDR+XDMA_SQUARE_ROOT8_CONTROL_ADDR_DATA_DATA), (u32)&data[0]);
    Xil_Out32((XPAR_XDMA_SQUARE_ROOT8_0_BASEADDR+XDMA_SQUARE_ROOT8_CONTROL_ADDR_RESULT_DATA), (u32)&result[0]);

    Xil_DCacheFlush(); // Flush data[10] cache to memory

    Xil_Out32(XPAR_XDMA_SQUARE_ROOT8_0_BASEADDR,(u32)1); // Start

    status = Xil_In32(XPAR_XDMA_SQUARE_ROOT8_0_BASEADDR);
    //while(!(status & 0x2)) // Wait ap_done
        //status = Xil_In32(XPAR_XDMA_SQUARE_ROOT8_0_BASEADDR);
    sleep(1);

    Xil_DCacheInvalidate(); // Invalidate result[10]
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, data[i], i, result[i]);
    }

    return 0;

}


ZYBO Z7-20 に電源をON にして、 gtkterm を立ち上げて 115200 bps, 8 bit, no stop bit で ZYBO Z7-20 に接続する。

VItis の Explorer ウインドウの DMA_pow2_test_system をクリックして、Run ボタンをクリックする。

ZYBO Z7-20 をコンフィギュレーションして、 DMA_pow2_test.elf が走る。

2 乗した結果を表示して、”Configure the partial bit file in Vivado and then press any key.”を表示して、キー入力待ちで停止した。
DFX2_17_210804.png

Vivado で Flow Navigator の PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target をクリックして、出てきた Auto Connect をクリックする。
Hardware Manager が開く。 Program device をクリックする。
DFX2_18_210804.png

Prgram Device ダイアログが表示された。
Bitstream File に DFX_test_211/DFX_test_211.runs/child_0_impl_1/DFX_test_i_DMA_pow2_DMA_square_root8_0_inst_0_partial.bit を指定した。
Program ボタンをクリックする。
DFX2_19_210804.png

gtkterm に戻って、Enter キーを押したところ、平方根の値が表示された。
DFX2_20_210804.png

AXI4 Master インターフェースを持つブロック・デザイン・コンテナの DFX が成功した。
やった。。。IDAさんありがとうございました


追加で一言、RM のドライバが Vitis に伝わらないのが不満だな。。。それで、DMA_square_root8 のコードにドライバを使えなかった。Vitis が DFX 対応になって欲しい。
  1. 2021年08月05日 04:56 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

AXI Master インターフェースを含む IP を DFX する1

DFX CouplerDFX Shutdown Manager をブログで勉強してきたが、その内の DFX Coupler を使用して、前回 DFX に失敗した DMA_pow2 IP と DMA_square_root8 IP の DFX をやっていこう。

DFX に失敗した DMA_pow2 IP と DMA_square_root8 IP の DFX については、以下のブログ記事にまとまっている。
DFX をやってみよう1(DFX を調べる1)
DFX をやってみよう2(チュートリアル例の説明)
DFX をやってみよう2(DMA_pow2 IP の作成)
”DFX をやってみよう3(DMA_square_root8 IP の作成1)
DFX をやってみよう4(DMA_square_root8 IP の作成2)
DFX をやってみよう5(Vivado 2021.1 で DFX_test プロジェクトを作成)”
DFX をやってみよう6(ブロック・デザイン・コンテナと DFX イネーブル)
DFX をやってみよう7(2 つ目の RM を設定)
DFX をやってみよう8(Generate Output Products と Dynamic Function eXchange Wizard)
”DFX をやってみよう9(Pblock の設定)”
”DFX をやってみよう10(インプリメンテーションとビット・ファイル、パーシャル・ビット・ファイルの生成)”
”DFX をやってみよう11(ハードウェアのエクスポートとフル・ビット・ファイルの動作確認)”
”DFX をやってみよう12(DMA_square_root8 の実行)”

2 が 2 つあるな。タイトル付けに失敗した。

さて、 DFX Coupler を使用して DFX を行う RM を構成していく。

DFX_test_211 を削除して作り直した。
DFX2_10_210804.png

作成した DFX_test ブロック・デザインを示す。
DFX2_11_210804.png

DMA_pow2 の AXI4 Master インターフェースの m_axi_gmem に dfx_decoupler_0 を接続している。
DMA_pow2 のリセット端子 ap_rst_n は専用のリセット用 IP の proc_sys_reset_0 を使用している。
proc_sys_reset_0 の aux_reset_in には、 dfx_decoupler_0 の decouple_status を入力した。つまり RM をリコンフィギュレーションの間リセットするようにした。
DMA_pow2 の s_axi_control には、 dfx_decoupler を接続しなかった。それは、スレーブの応答する IP なので、自律的にトランザクションを始めることができず、影響がないと思ったからだ。

dfx_decuopler_0 の AXI インターフェースの設定画面を示す。
DFX2_4_210802.png

DMA_pow2 DFX モジュールをダブルクリックして設定を確認する。
Customize Block Design Container ダイアログが表示された。
DFX2_12_210804.png

RM として DMA_circuit.bd (DMA_pow2)と DMA_square_root8_0.bd が選択されている。
Enable Dynamic Function eXchange on this container にチェックが入っている。

Addressing タブを示す。
DMA_square_root8_0.bd のアドレスを 0x40010000 に変更したが、その IP だけリコンフィギュレーションして、アドレスに関係する AXI Interconnect は RM モジュールに入っていないので、DMA_circuit.bd と同じアドレスでも良かったかも知れない?
DFX2_13_210804.png

Address Map を示す。
DFX2_14_210804.png

ビットストリームを生成した。
DFX2_15_210804.png

最初に DMA_square_root8_0.bd の DMA_square_root8 IP でタイミング・エラーがでてしまった。
そこで、Vitis HLS に戻って、100 MHz で動作するのではなく、もっと速い周波数で動作する IP に作り直した。

ハードウェアをエクスポートした。

この記事には結果しか書いていないが、DFX のチュートリアルを見たかったら、上にあるブログリンクを順番にクリアしていくと良いと思う。ただし、ブロック・デザインはこの記事のブロック・デザインに変更して欲しい。
  1. 2021年08月04日 04:33 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

DFX AXI Shutdown Manager について

DFX Decuopler について”に続いて、DFX AXI Shutdown Manager について勉強していこう。

DFX AXI Shutdown Manager のマニュアルは”Dynamic Function eXchange AXI Shutdown Manager v1.0 LogiCORE IP Product Guide Vivado Design Suite PG377 (v1.0) June 3, 2020”を使用する。

例えばカメラ画像を連続的にフィルタを掛けてディスプレイに表示している時に DFX で リコンフィギャブル・モジュール(RM)を入れ替えるとする。その場合には、 AXI インターフェースは連続動作しているので、非同期に RM を入れ替えると AXI インターフェースのトランザクションが完了できなくて、デッドロックする場合がある。その時に、DFX AXI Shutdown Manager を使うと AXI インターフェースを完了できて、デッドロックを防ぐことができるようだ。

DFX AXI Shutdown Manager にはパス・スルー・モード(Pass Through mode)とシャットダウン・モード(Shutdown mode)の2つのモードがある。
パス・スルー・モードが通常の動作モードで AXI インターフェースの間に入れてパス・スルーするモードのようだ。
シャットダウン・モードは、シャットダウン時のモードで RM を入れ替える時にシャットダウンして、上流側のトランザクションを覚えておくようだ。
具体的には、request_shutdown 信号がアサートされるか、request_shutdown レジスタ・ビットを立てるとシャットダウン・モードになって、その時に、トランザクションを受信すると、Shutdown ManagerIPによって処理されるトランザクションとして格納されるようだ。

制御信号は request_shutdown 信号を使用するか、もしくは、AXIインターフェースの request_shutdown レジスタを使用するか?どちらかを使用するようだ。

Dynamic Function eXchange ControllerCoreとの統合
Dynamic Function eXchange AXI Shutdown Manager v1.0 LogiCORE IP Product Guide Vivado Design Suite PG377 (v1.0) June 3, 2020”の 8 ページの”Control Status”の”Integration with Dynamic Function eXchange Controller Core”の Google 翻訳結果を引用する。

DFX AXI Shutdown Managerコアは、Dynamic Function eXchangeControllerコアで動作するように設計されています。適切なVirtualSocketManagerのvsm_ _rm_shutdown_req出力は、ShutdownManagerのrequest_shutdown制御信号に直接接続できます。複数のシャットダウンマネージャが使用されている場合、vsm_ _rm_shutdown_req信号を各のrequest_shutdown制御信号に直接接続できます。詳細については、Dynamic Function eXchange Controller IP LogiCORE IP製品ガイド(PG374)を参照してください。


ポート名
Dynamic Function eXchange AXI Shutdown Manager v1.0 LogiCORE IP Product Guide Vivado Design Suite PG377 (v1.0) June 3, 2020”の 8 ページの”Control Status”の Google 翻訳結果を引用する。

request_shutdown :(入力)アサートするとシャットダウン・モードで、ディアサートするとパス・スルー・モードになる。


shutdown_requested : (出力)シャットダウンが要求されたときにアサートされます。request_shutdown信号、またはレジスタインターフェイスを介して。 このシグナルは、他のShutdownManagerインスタンスのrequest_shutdown入力を駆動するために使用できます。


in_shutdown :(出力)シャットダウンが要求され、保留中のすべてのトランザクションが処理されたときにアサートされます。 この信号は、読み取りチャネルと書き込みチャネルの両方がシャットダウンモードに入ったことを示します。


wr_in_shutdown :(出力)Write Channel In Shutdown(ライトチャンネル・イン・シャットダウン)。シャットダウンが要求され、保留中のすべての書き込みトランザクションが処理されたときにアサートされます。この信号は、ライトチャネルがシャットダウンモードに入ったことを示します。(DeepL翻訳しました)


rd_in_shutdown :(出力)Read Channel In Shutdown(リードチャンネル・イン・シャットダウン)。シャットダウンが要求され、保留中のすべての読み出しトランザクションが処理されたときにアサートされます。シャットダウンが要求され、保留中のすべてのリード・トランザクションが処理されたときにアサートされます。この信号は 読み取りチャネルがシャットダウンモードに入ったことを示します。(DeepL翻訳しました)


wr_irq :(出力)書き込みトランザクションを受信し、request_shutdownがアサートされると、1クロックサイクルにわたってアサートされるレベルベースの割り込みです。このトランザクションはコアでは処理されず、割り込みはシステムに警告するためのものです。割り込みは、もはや存在しないリコンフィギュラブル・モジュールと何かが通信しようとしていることをシステムに警告するためのものです。と通信しようとしていることをシステムに警告するためのものです。(DeepL翻訳しました)


rd_irq :(出力)読み取りトランザクションを受信し、request_shutdownがアサートされると、1クロックサイクルにわたってアサートされるレベルベースの割り込みです。このトランザクションはコアによって渡されることはなく、この割り込みはシステムに警告するためのものです。割り込みは、存在しなくなった再構成モジュールと何かが通信しようとしていることをシステムに警告するためのものです。(DeepL翻訳しました)


irq :(出力)wr_irqまたはrd_irqのいずれかがアサートされたときにアサートされるレベルベースの割り込みです。(DeepL翻訳しました)



Register Space
Dynamic Function eXchange AXI Shutdown Manager v1.0 LogiCORE IP Product Guide Vivado Design Suite PG377 (v1.0) June 3, 2020”の 10 ページの”Table 2: Register Address Space”、”Table 3: Control Register”、”Table 4: Status Register”を引用する。
DFX2_8_210802.png

ブロック・デザインを作成して、DFX AXI Shutdown Manager を Add IP してみた。
ダブルクリックして設定情報を表示した。
DFX2_9_210802.png

Control Interface Type は Signal と AXI LITE がある。
Datapath Protocol は AXI4MM と AXI4LITE がある。AXI4-Stream は無い。
  1. 2021年08月03日 03:54 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

DFX Decuopler について

DFX をやってみよう12(DMA_square_root8 の実行)”で DMA_pow2 IP と DMA_square_root8 IP を DFX で入れ替えようとしたら、DMA_square_root8 IP のパーシャル・ビットファイルをコンフィギュレーションしたところで、ソフトウェアの動作が止まってしまった。これは、パーシャル・リコンフィギュレーション中に AXI インターフェースの信号が出力されていしまうからだということで、 DFX Decuopler を使うということをツィッターで IDA さんに教えていただいた。いつもありがとうございます。
それで、今回のブログでは、 DFX Decuopler について学んでいこう。

DFX Decuopler のマニュアルは、”Dynamic Function eXchange Decoupler v1.0 LogiCORE IP Product Guide Vivado Design Suite PG375 (v1.0) June 3, 2020”のようだ。これを勉強していこう。

DFX Decuopler の機能は基本的にハンドシェーク信号をパーシャル・リコンフィギュレーションの間、非アクティブにしておくことだ。
セレクタを使用して、ハンドシェーク信号に非アクティブなロジック・レベルを入力する。例えば AXI インターフェースでは 0 を入れる。

Dynamic Function eXchange Decoupler v1.0 LogiCORE IP Product Guide Vivado Design Suite PG375 (v1.0) June 3, 2020”の 16 ページの”Figure 3: Default Decoupling for AXI4-Stream Interfaces”を引用する。
DFX2_1_210802.png

これは AXI4-Stream の場合だが、DFX 側の rp_... 信号と、スタティック・ロジック側の s_... 信号の間に片方の入力が 0 のセレクタが入っているのが分かる。そしてそのセレクタの切り替えは decuope 信号になっている。
シンプルな AXI4-Stream では、 tvalid と tready でハンドシェーク指定しているので、その信号だけにセレクタが入っていて、t_data はスルーとなっている。

それでは、実際に Vivado の iP インテグレターで使用する DFX_Decuopler を見てみよう。
もう、AXIインターフェースの DFX は動作しているのだが、そのブロック・デザインに使用した DFX Decuopler だ。
DFX2_2_210802.png

ダブルクリックして設定を見ていこう。
DFX2_4_210802.png

Enable the AXI Lite interface にチェックが入っているので、 AXI-Lite の DFX Decuopler の設定用ポートが追加されている。
この設定用ポートのアドレス・マップを
Dynamic Function eXchange Decoupler v1.0 LogiCORE IP Product Guide Vivado Design Suite PG375 (v1.0) June 3, 2020”の 11 ページの”Table 8: Control Register (Offset 00h)”と 12 ページの”Table 9: Status Register (Offset 00h)”を引用する。
DFX2_6_210802.png
DFX2_7_210802.png

つまり、0x00 番地に 1 を書くとデカップリングがイネーブルになる。つまり、制御信号に 0 を入力するわけだ。パーシャル・リコンフィギュレーションの間は 0x00 番地を 1 にしておく。

次に、Enable the Decuople Status Signal にチェックが入っているので、ステータス出力が出力されている。これは、私のデザインでは、Processor_System_Reset IP のリセット入力に入っている。

次に、 Interface Options タブを見ていこう。
DFX2_4_210802.png

ここではデカップリングが必要なインターフェースを指定する。現在は、 aximm_rtl:1.0 が指定されていて、AXI Master インターフェースが指定されている。
DMA_pow2 と DMA_square_root8 IP にはその他に AXI4-Lite Slave の設定用ポートがあるが、こちらはマスタとなってトランザクションを開始することが無いからなのか? デカップリングしなくても大丈夫だった。

Interface VLNV で使用するインターフェースを指定するのだが、たくさんのインターフェースを選択することができる。
DFX2_5_210802.png
  1. 2021年08月02日 04:54 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0

DFX をやってみよう16(DFX の実行と Vitis のソフトウェア実行の影響を調べる)

DFX をやってみよう15(Dynamic Function eXchange Wizard と I/O Planing 、 Pblock の指定)”の続き。

前回は、Generate Output Products を実行して、Dynamic Function eXchange Wizard を実行してから、 Synthesized Design で I/O Planing 、 Pblock の指定を行った。今回は、 DFX のコンフィギュレーションを確かめて、Vitis のソフトウェアを実行する際の DFX の影響を調べてみよう。

Flow Navigator から Generate Bitstream をクリックして、ビット・ファイルを作成する。

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

Bitstream Generation Completed ダイアログが表示された。
Cancel ボタンをクリックする。

imp_1 、 child_0_impl_1 共に wirte_bitstream Complete! になっていた。
DFX_145_210729.png

DFX_test2_211/DFX_test2_211.runs/impl_1 ディレクトリには、 DFX_test2_i_Blink1_Blink1_inst_0_partial.bit, FX_test2_i_Blink1_Blink1_inst_0_routed.dcp, DFX_test2_wrapper.bit が生成されていた。
DFX_146_210730.png

DFX_test2_211/DFX_test2_211.runs/child_0_impl_1 ディレクトリには、 DFX_test2_i_Blink1_Blink05_inst_0_partial.bit, DFX_test2_i_Blink1_Blink05_inst_0_routed.dcp, DFX_test2_wrapper.bit が生成されていた。
DFX_147_210730.png

ビットファイルができたので、コンフィギュレーションしてみよう。今回は、コンフィギュレーションしただけで、LED が点滅する。
まずは、DFX_test2_211/DFX_test2_211.runs/impl_1 ディレクトリのフル・ビットファイルの DFX_test2_wrapper.bit をコンフィギュレーションする。

Flow Navigator から PROGRAM AND DEBUG -> Open Hardware Manager -> Open Target -> Auto Connect を選択して、 Zynq に接続した。
Program Device をクリックすると、 Program Device ダイアログが表示された。
Bitstream file に DFX_test2_211/DFX_test2_211.runs/child_0_impl_1 ディレクトリの DFX_test2_wrapper.bit を指定して Program ボタンをクリックする。
DFX_148_210730.png

LD0 が 1 秒間隔で点滅した。

次に、もう一度、Program Device をクリックして、 Program Device ダイアログを表示した。
今度は、DFX_test2_211/DFX_test2_211.runs/child_0_impl_1 ディレクトリの DFX_test2_i_Blink1_Blink05_inst_0_partial.bit を指定して、 Program ボタンをクリックする。
DFX_149_210730.png

LD0 の点滅が速くなって、 0.5 秒間隔で点滅した。

DFX 成功だ。

次に、 Vitis でソフトウェアを実行しても DFX できるかどうか?を調べてみよう。

Vivado でハードウェアをエクスポートした。
DFX_test2_wrapper.xsa が生成された。
DFX_150_210730.png

Vivado 2021.1 の Tools メニューから Launch Vitis IDE を選択して、 Vitis 2021.1 を起動する。

Vitis IDE Launcher ダイアログが表示された。
Browse... ボタンをクリックする。

Select Workspace Directory ダイアログが表示された。
新規ディレクトリ作成ボタンをクリックして、新規ディレクトリを作成する。

DFX_test2_211 ディレクトリの下に、 vitis_work ディレクトリを作成した。
Open ボタンをクリックする。

Vitis IDE Launcher ダイアログに戻るので、 Launch ボタンをクリックする。
DFX_151_210730.png

Vitis 2021.1 が立ち上がった。
Create Application Project をクリックする。

DFX_test2_wrapper プラットフォームと DMA_pow2_test プロジェクトを生成した。
DFX_152_210730.png

DMA_pow2_test2.c を作成して、ビルドし成功した。
DFX_154_210730.png

DMA_pow2_test2.c を示す。

// DMA_pow2_test2.c
// 2021/07/30 by marsee
//

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

volatile int data[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
volatile int result[10];

void Xil_DCacheFlush(void);
void Xil_DCacheInvalidate(void);

int main(){
    XDma_pow2 XDMA_pow2_ap;
    XDma_pow2_Config *XDMA_pow2_apPtr;
    int i, inbyte_in;

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

    // Initialize the Device
    int Xlap_status = XDma_pow2_CfgInitialize(&XDMA_pow2_ap, XDMA_pow2_apPtr);
    if (Xlap_status != XST_SUCCESS){
        fprintf(stderr, "Could not Initialize XDma_pow2\n");
        return(-1);
    }

    XDma_pow2_Set_data(&XDMA_pow2_ap, (u32)&data[0]);
    XDma_pow2_Set_result(&XDMA_pow2_ap, (u32)&result[0]);

    Xil_DCacheFlush(); // Flush data[10] cache to memory

    XDma_pow2_Start(&XDMA_pow2_ap);

    while(!XDma_pow2_IsDone(&XDMA_pow2_ap)) ;

    Xil_DCacheInvalidate(); // Invalidate result[10]
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, data[i], i, result[i]);
    }

    printf("Configure the partial bit file in Vivado and then press any key.");
    fflush(stdout);
    inbyte_in = inbyte();
    printf("\n"); fflush(stdout);

    for(i=0; i<10; i++){
        data[i] = i+1;
    }
    Xil_DCacheFlush(); // Flush data[10] cache to memory

    XDma_pow2_Start(&XDMA_pow2_ap);

    while(!XDma_pow2_IsDone(&XDMA_pow2_ap)) ;

    Xil_DCacheInvalidate(); // Invalidate result[10]
    for(i=0; i<10; i++){
        printf("data[%d] = %d, result[%d] = %d\n", i, data[i], i, result[i]);
    }

    return 0;

}



Run すると gtkterm に 2 乗の結果が表示された。
LD0 は 1 秒間隔で点滅している。
DFX_155_210730.png

Vivado から DFX_test2_211/DFX_test2_211.runs/child_0_impl_1 ディレクトリの DFX_test2_i_Blink1_Blink05_inst_0_partial.bit を指定して、 Program ボタンをクリックする。
DFX_156_210730.png

LD0 の点滅間隔が 0.5 秒間隔になった。DFX 成功だ。

gtkterm に戻って Enter キーを押すと、もう一度、 2 乗結果が表示された。
DFX によるソフトウェア実行の影響は無いようだ。
DFX_157_210730.png
  1. 2021年08月01日 07:24 |
  2. Dynamic Function eXchange
  3. | トラックバック:0
  4. | コメント:0