FC2カウンター FPGAの部屋 VGA画像をXGA画像やHD画像に変換するdisp_dmar_axis_vga IP 4(やっと完成1)
FC2ブログ

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

FPGAの部屋

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

VGA画像をXGA画像やHD画像に変換するdisp_dmar_axis_vga IP 4(やっと完成1)

VGA画像をXGA画像やHD画像に変換するdisp_dmar_axis_vga IP 3(2 種類の実装を試した)”の続き。

前回は、disp_dmar_axis IP 用のソースコードを 2 種類作って試してみたが、うまく行かなかった。今回は、風呂掃除をしていた時にひらめいたdisp_dmar_axis IP の実装を試してみよう。

風呂掃除をしていた時にふとひらめいた。いままで画像を拡張しない時はうまく行っていたdisp_dmar_axis IP があるのだから、それにHLSストリーム・インターフェースで画像を拡大するIP を付けたらどうか?そして、それらを並列化したら良いのでは?というアイデアだった。やはり、風呂掃除はアイデアが湧くのでお勧めである。皆さん、風呂掃除をしましょう。。。w

さて、今回はファイルも分けて、VGA画像を 3 チャネル分DMA するのが、vga_dmar_axis.cpp で、HLSストリーム・インターフェースで画像を拡大するIP が axis_expand.cpp (ちょっと名前をミスった)、全体をまとめるのが、disp_dmar_axis_vga.cpp となる。

disp_dmar_axis_vga.cpp のソースコードを示す。今回はインターフェースを変更して、row, col つまり画像の縦横のピクセル数を入力するようにした。

// disp_dmar_axis_vga.cpp
// 2019/07/11 by marsee
//

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

#include "disp_dmar_axis_vga.h"

int vga_dmar_axis(volatile ap_int<32> *fb0, volatile ap_int<32> *fb1, volatile ap_int<32> *fb2,
        AXI_STREAM &outs, ap_uint<2> active_frame);

int axis_expand(AXI_STREAM &ins, AXI_STREAM &outs, int row, int col);

int disp_dmar_axis_vga(volatile ap_int<32> *fb0, volatile ap_int<32> *fb1, volatile ap_int<32> *fb2,
        AXI_STREAM &outs, ap_uint<16> row, ap_uint<16> col, ap_uint<2> &active_frame){
#pragma HLS DATAFLOW
#pragma HLS INTERFACE ap_ctrl_hs port=return
#pragma HLS INTERFACE ap_none port=active_frame
#pragma HLS INTERFACE s_axilite port=row
#pragma HLS INTERFACE s_axilite port=col
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE m_axi depth=307200 port=fb2 offset=slave
#pragma HLS INTERFACE m_axi depth=307200 port=fb1 offset=slave
#pragma HLS INTERFACE m_axi depth=307200 port=fb0 offset=slave

    AXI_STREAM dmad;
#pragma HLS STREAM variable=dmad depth=64 dim=1

    vga_dmar_axis(fb0, fb1, fb2, dmad, active_frame);
    axis_expand(dmad, outs, row, col);
    
    return(0);
}


次に、vga_dmar_axis.cpp を示す。

// vga_dmar_axis.cpp
// 2019/07/13 by marsee
//

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

#include "disp_dmar_axis_vga.h"

int disp_dmar_fb0(volatile ap_int<32> *fb0, AXI_STREAM &outs, int max_width, int max_height);
int disp_dmar_fb1(volatile ap_int<32> *fb1, AXI_STREAM &outs, int max_width, int max_height);
int disp_dmar_fb2(volatile ap_int<32> *fb2, AXI_STREAM &outs, int max_width, int max_height);

int vga_dmar_axis(volatile ap_int<32> *fb0, volatile ap_int<32> *fb1, volatile ap_int<32> *fb2,
        AXI_STREAM &outs, ap_uint<2> active_frame){

    AP_AXIU32 pix;

    if (active_frame == (ap_uint<2>)0)
        disp_dmar_fb2(fb2, outs, VGA_WIDTH, VGA_HEIGHT);
    else if (active_frame == (ap_uint<2>)1)
        disp_dmar_fb0(fb0, outs, VGA_WIDTH, VGA_HEIGHT);
    else
        disp_dmar_fb1(fb1, outs, VGA_WIDTH, VGA_HEIGHT);
    return(0);
}

int disp_dmar_fb0(volatile ap_int<32> *fb0, AXI_STREAM &outs, int max_width, int max_height){
    AP_AXIU32 pix;

    LOOP_Y0: for (int y=0; y<max_height; y++){
#pragma HLS LOOP_TRIPCOUNT min=480 max=480 avg=480
        LOOP_X0: for (int x=0; x<max_width; x++){
#pragma HLS LOOP_TRIPCOUNT min=640 max=640 avg=640
#pragma HLS PIPELINE II=1
            pix.data = fb0[(y*max_width)+x];

            if (x==0 && y==0)
                pix.user = 1;
            else
                pix.user = 0;

            if (x == max_width-1)
                pix.last = 1;
            else
                pix.last = 0;

            outs << pix;
        }
    }
    return(0);
}

int disp_dmar_fb1(volatile ap_int<32> *fb1, AXI_STREAM &outs, int max_width, int max_height){
    AP_AXIU32 pix;

    LOOP_Y1: for (int y=0; y<max_height; y++){
#pragma HLS LOOP_TRIPCOUNT min=480 max=480 avg=480
        LOOP_X1: for (int x=0; x<max_width; x++){
#pragma HLS LOOP_TRIPCOUNT min=640 max=640 avg=640
#pragma HLS PIPELINE II=1
            pix.data = fb1[(y*max_width)+x];

            if (x==0 && y==0)
                pix.user = 1;
            else
                pix.user = 0;

            if (x == max_width-1)
                pix.last = 1;
            else
                pix.last = 0;

            outs << pix;
        }
    }
    return(0);
}

int disp_dmar_fb2(volatile ap_int<32> *fb2, AXI_STREAM &outs, int max_width, int max_height){
    AP_AXIU32 pix;

    LOOP_Y2: for (int y=0; y<max_height; y++){
#pragma HLS LOOP_TRIPCOUNT min=480 max=480 avg=480
        LOOP_X2: for (int x=0; x<max_width; x++){
#pragma HLS LOOP_TRIPCOUNT min=640 max=640 avg=640
#pragma HLS PIPELINE II=1
            pix.data = fb2[(y*max_width)+x];

            if (x==0 && y==0)
                pix.user = 1;
            else
                pix.user = 0;

            if (x == max_width-1)
                pix.last = 1;
            else
                pix.last = 0;

            outs << pix;
        }
    }
    return(0);
}


axis_expand.cpp を示す。

// axis_expand.cpp
// 2019/07/13 by marsee
//


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

#include "disp_dmar_axis_vga.h"

int axis_expand(AXI_STREAM &ins, AXI_STREAM &outs, int row, int col){
    AP_AXIU32 pix;
    int x_padding = (col - VGA_WIDTH)/2;
    int y_padding = (row - VGA_HEIGHT)/2;

    for(int y=0; y<row; y++){
#pragma HLS LOOP_TRIPCOUNT min=600 max=1080 avg=768
        for(int x=0; x<col; x++){
#pragma HLS LOOP_TRIPCOUNT min=800 max=1920 avg=1024
#pragma HLS PIPELINE II=1
            if (y < y_padding || y >= y_padding+VGA_HEIGHT){
                pix.data = 0;
                pix.dest = 0;
                pix.id = 0;
                pix.keep = 0;
                pix.strb = 0;
            }else if (x < x_padding || x >= x_padding+VGA_WIDTH){
                pix.data = 0;
                pix.dest = 0;
                pix.id = 0;
                pix.keep = 0;
                pix.strb = 0;
            }else{
                ins >> pix;
            }

            if (x==0 && y==0)
                pix.user = 1;
            else
                pix.user = 0;

            if (x == col-1)
                pix.last = 1;
            else
                pix.last = 0;

            outs << pix;
        }
    }
    return(0);
}


前と同じだが、disp_dmar_axis_vga.h を示す。


// disp_dmar_axis_vga.h
// 2019/07/11 by marsee
//

#ifndef __DISP_DMAR_AXIS_VGA_H__
#define __DISP_DMAR_AXIS_VGA_H__

#include "ap_axi_sdata.h"
#include "hls_video.h"

#define VGA_WIDTH 640
#define VGA_HEIGHT 480

#define SVGA_WIDTH 800
#define SVGA_HEIGHT 600

#define XGA_WIDTH 1024
#define XGA_HEIGHT 768

#define HD_WIDTH 1920
#define HD_HEIGHT 1080

#define RESO_SVGA 0
#define RESO_XGA 1
#define RESO_HD  2

typedef hls::stream<ap_axiu<32,1,1,1> > AXI_STREAM;
typedef ap_axiu<32,1,1,1> AP_AXIU32;
typedef hls::Scalar<3, unsigned char> RGB_PIXEL;
typedef hls::Mat<HD_HEIGHT, HD_WIDTH, HLS_8UC3> RGB_IMAGE;
typedef hls::Mat<HD_HEIGHT, HD_WIDTH, HLS_8UC1> GRAY_IMAGE;

#endif


最後にbmp_file0.bmp だが、ブログに貼れないのでPNG ファイルを示す。
disp_dmar_axis_vga_8_190712.png
  1. 2019年07月15日 05:15 |
  2. Vivado HLS
  3. | トラックバック:0
  4. | コメント:0

コメント

コメントの投稿


管理者にだけ表示を許可する

トラックバック URL
https://marsee101.blog.fc2.com/tb.php/4584-043281d6
この記事にトラックバックする(FC2ブログユーザー)