FC2カウンター FPGAの部屋 2018年08月22日
FC2ブログ

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

FPGAの部屋

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

Ultra96のDisplayPort テストパターン生成用IPの作製

Ultra96のDisplayPort にテストパターンを表示するIP を作製しようということで、Vivado HLS 2018.2 で以前作った”Vivado HLS 2014.4 でディスプレイ・コントローラを作る1(高位合成、C/RTLコシミュレーション)”を参照しながら、HD解像度のテストパターンを表示するIP を作製しよう。

テストパターンは4色で左上が赤、右上が緑、左下が青、右下が白となっている。
ソースコードの video_test.cpp を示す。なおHD解像度のタイミングは”VESA DMT 信号タイミング一覧”を参照した。

// video_test.cpp
// 2018/08/21 by marsee
// DisplayPortのLive Video Interfaceに入れるテストパターン(HD解像度)
// 画面を4分割した第1象限は赤、第2象限は緑、第3象限は青、第4象限は白を表示する
//

#include <ap_int.h>

// HD 解像度
#define H_ACTIVE_VIDEO    1920
#define H_FRONT_PORCH    88
#define H_SYNC_PULSE    1 // 44, DPのLive Video Interfaceのタイミングチャートより1パルスにした
#define H_BACK_PORCH    (148 + 43) // 同期信号を1パルスにした分をバックポーチに加算
#define H_SUM            (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH)

#define V_ACTIVE_VIDEO    1080
#define V_FRONT_PORCH    4
#define V_SYNC_PULSE    1 // 5, DPのLive Video Interfaceのタイミングチャートより1パルスにした
#define V_BACK_PORCH    (36 + 4) // 同期信号を1パルスにした分をバックポーチに加算
#define V_SUM            (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH)

void video_test(ap_uint<36> *video_out, ap_uint<1> *display_enable, ap_uint<1> *hsync, ap_uint<1> *vsync){
#pragma HLS INTERFACE ap_none register port=video_out
#pragma HLS INTERFACE ap_none register port=display_enable
#pragma HLS INTERFACE ap_none register port=hsync
#pragma HLS INTERFACE ap_none register port=vsync
#pragma HLS INTERFACE ap_ctrl_none port=return

    ap_uint<16> h_count, v_count;

    for (v_count=0; v_count<V_SUM; v_count++){
        for (h_count=0; h_count<H_SUM; h_count++){
#pragma HLS PIPELINE II=1
            if (h_count >= (H_ACTIVE_VIDEO +H_FRONT_PORCH) && h_count < (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE))
                *hsync = 1;
            else
                *hsync = 0;

            if (v_count >= (V_ACTIVE_VIDEO + V_FRONT_PORCH) && v_count < (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE) && h_count==0)
                *vsync = 1;
            else
                *vsync = 0;

            if (h_count < H_ACTIVE_VIDEO && v_count < V_ACTIVE_VIDEO)
                *display_enable = 1;
            else
                *display_enable = 0;

            if (v_count < V_ACTIVE_VIDEO/2){
                if (h_count < H_ACTIVE_VIDEO/2){
                    *video_out = 0xff0000000; // red = 0xff
                } else if (h_count < H_ACTIVE_VIDEO){
                    *video_out = 0x000ff0000; // green = 0xff
                } else {
                    *video_out = 0x000000000;
                }
            } else if (v_count < V_ACTIVE_VIDEO){
                if (h_count < H_ACTIVE_VIDEO/2){
                    *video_out = 0x000000ff0; // blue = 0xff
                } else if (h_count < H_ACTIVE_VIDEO){
                    *video_out = 0xff0ff0ff0; // red=0xff, green=0xff, blue=0xff
                } else {
                    *video_out = 0x000000000;
                }
            } else {
                *video_out = 0x000000000;
            }
        }
    }
}


次にテストベンチの video_test_tb.cpp を示す。

// video_test_tb.cpp
// 2018/08/21 by marsee
//

#include <ap_int.h>

void video_test(ap_uint<36> *video_out, ap_uint<1> *display_enable, ap_uint<1> *hsync, ap_uint<1> *vsync);

int main(){
    ap_uint<36> video_outb, *video_out;
    ap_uint<1> deb, *display_enable;
    ap_uint<1> hb, *hsync;
    ap_uint<1> vb, *vsync;

    video_out = &video_outb;
    display_enable = &deb;
    hsync = &hb;
    vsync = &vb;

    video_test(video_out, display_enable, hsync, vsync);
    video_test(video_out, display_enable, hsync, vsync);

    return(0);
}


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

Target が 6.70 ns で、Estimated は 3.023 ns だった。さすがにUltraScale+ は性能が良いね。助かる。。。
Latency は 2475002 クロックだった。
Loop1 のLatency は 2475000 クロックだった。これは、(1920+88+44+148) * (1080+4+5+36) = 2475000 クロックなので、ぴったりだ。
リソース使用量は FF が 77 個、LUT は 560 個だった。

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

C/RTL 協調シミュレーション波形を示す。
まずは全体波形から。
video_out_3_180821.png

拡大してみよう。1行の中央で video_out の値が変化しているのが見える。
video_out_4_180821.png

hsync を拡大してみよう。1クロック分 1 になっていることが分かる。
video_out_5_180821.png

vsync を拡大してみる。こちらも 1 クロック分になっているのが分かる。
video_out_6_180821.png

ブロック・レベルのインターフェースを消すために、

#pragma HLS INTERFACE ap_ctrl_none port=return

に変更した。
video_out_7_180821.png

もう一度、C コードの合成を行った。
video_out_8_180821.png

結果は前と同じだった。
合成された結果のVHDLファイルを見ると、制御信号は削除されていた。

entity video_test is
port (
    ap_clk : IN STD_LOGIC;
    ap_rst : IN STD_LOGIC;
    video_out_V : OUT STD_LOGIC_VECTOR (35 downto 0);
    display_enable_V : OUT STD_LOGIC_VECTOR (0 downto 0);
    hsync_V : OUT STD_LOGIC_VECTOR (0 downto 0);
    vsync_V : OUT STD_LOGIC_VECTOR (0 downto 0) );
end;



Export RTLを行った。ただし、Vivado synthesis, place and route にチェックを入れてある。
video_out_9_180821.png

LUT を 53 個、FF を 54 個使用している。
  1. 2018年08月22日 05:24 |
  2. Ultra96
  3. | トラックバック:0
  4. | コメント:0