FC2カウンター FPGAの部屋 2019年01月14日
FC2ブログ

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

FPGAの部屋

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

Ultra96のDisplayPortを使用するためのIPを作成する2(pattern_gen_axis IP)

Ultra96のDisplayPortを使用するためのIPを作成する1(概要編)”の続き。

前回は、Ultra96 の PS のDisp;ayPort に出力するために、Video_out に同期信号に同期した画像出力をPS の Live Video の video_in に入れる必要があったので、そのブロック図を示した。今回は、その内のpattern_gen_axis IP (pattern_out_axis のはずだったが作ってみたら手元が狂って名前が変わってしまった。悪しからずご了承ください)をVivado HLS 2018.3 で作成してみよう。

pattern_gen_axis.cpp を貼っておく。

// pattern_gen_axis.cpp
// 2019/01/13 by marsee
//

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

int pattern_gen_axis(hls::stream<ap_axis<32,1,1,1> >& outs,
        int v_size, int h_size,
        ap_uint<1> &init_done, ap_uint<1> &init_done_out
){
#pragma HLS INTERFACE ap_none register port=init_done_out
#pragma HLS INTERFACE s_axilite port=init_done
#pragma HLS INTERFACE s_axilite port=v_size
#pragma HLS INTERFACE s_axilite port=h_size
#pragma HLS INTERFACE axis register both port=outs
#pragma HLS INTERFACE s_axilite port=return
    ap_axis<32,1,1,1> out_val;

    init_done_out = init_done;

    LOOP_Y: for(int y=0; y<v_size; y++){
#pragma HLS LOOP_TRIPCOUNT min=768 max=768 avg=768
        LOOP_X: for(int x=0; x<h_size; x++){
#pragma HLS LOOP_TRIPCOUNT min=1024 max=1024 avg=1024
#pragma HLS PIPELINE II=1
            if (y < v_size/2){
                if (x < h_size/2){
                    out_val.data = 0xff0000; // *red=0xff; *green=0; *blue=0;
                } else if (x < h_size){
                    out_val.data = 0x00ff00; // *red=0; *green=0xff; *blue=0;
                } else {
                    out_val.data = 0x000000; // *red=0; *green=0; *blue=0;
                }
            } else if (y < v_size){
                if (x < h_size/2){
                    out_val.data = 0x0000ff; // *red=0; *green=0; *blue=0xff;
                } else if (x < h_size){
                    out_val.data = 0xffffff; // *red=0xff; *green=0xff; *blue=0xff;
                } else {
                    out_val.data = 0x000000; // *red=0; *green=0; *blue=0;
                }
            } else {
                out_val.data = 0x000000; // *red=0; *green=0; *blue=0;
            }

            if(x==0 && y==0)
                out_val.user = 1;
            else
                out_val.user = 0;
            if(x == h_size-1)
                out_val.last = 1;
            else
                out_val.last = 0;

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


pattern_gen_axis_tb.cpp を貼っておく。

// pattern_gen_axis_tb.cpp
// 2019/01/13 by marsee
//

#include <ap_int.h>
#include <hls_stream.h>
#include <iostream>
#include <fstream>
#include "hls_opencv.h"
#include "ap_axi_sdata.h"
#include "hls_video.h"

int pattern_gen_axis(hls::stream<ap_axis<32,1,1,1> >& outs,
        int v_size, int h_size,
        ap_uint<1> &init_done, ap_uint<1> &init_done_out
);

#define V_SIZE 60
#define H_SIZE 80

int main(){
    using namespace cv;

    hls::stream<ap_axis<32,1,1,1> > outs;
    ap_axis<32,1,1,1> pix;
    ap_uint<1> init_done = 1;
    ap_uint<1> init_done_out = 0;

    pattern_gen_axis(outs, V_SIZE, H_SIZE, init_done, init_done_out);

    Mat dst = Mat(V_SIZE, H_SIZE, CV_8UC3);

    Mat_<Vec3b> dst_vec3b = Mat_<Vec3b>(dst);

    for(int y=0; y<dst.rows; y++){
        for(int x=0; x<dst.cols; x++){
            Vec3b pixel;
            outs >> pix;
            ap_int<32> rgb = pix.data;
            pixel[0] = (rgb & 0xff); // blue
            pixel[1] = (rgb & 0xff00) >> 8; // green
            pixel[2] = (rgb & 0xff0000) >> 16; // red
            dst_vec3b(y,x) = pixel;
        }
    }
    imwrite("pattern_out.bmp", dst);

    return(0);
}



pattern_gen_axis プロジェクトを示す。
DisplayPort_test_58_190114.png

C シミュレーションを行った。
DisplayPort_test_59_190114.png

pattern_out.bmp が生成されていた。テストバターンになっている。
DisplayPort_test_60_190114.png

C コードの合成を行った。
DisplayPort_test_61_190114.png

TRIPCONT は XGA 解像度にしたので、1024 X 768 = 786432 ピクセルということになる。レイテンシは、786436 クロックなので、4 クロックしか増えていないので、ほぼ 1 クロック 1 ピクセル処理を実現できている。

C/RTL 協調シミュレーションを行った。
DisplayPort_test_62_190114.png

テストベンチでは、 80 X 60 ピクセルのテストバターンを使用しているので、80 X 60 = 4800 ピクセルになる。結果は4854 クロックなので、ほぼ 1 クロックで 1 ピクセル処理になっている。

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

outs_TVALID と outs_TREADY が安定して 1 であることが分かる。

Export RTL を行った。結果を示す。
DisplayPort_test_63_190114.png

HD 解像度のクロック 148.5 MHz まで対応することを考えているので、200 MHz で動作するように周期を 5 ns に設定した。
CP achieved post-implementation は 2.259 ns で大丈夫そうだ。
  1. 2019年01月14日 05:40 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0