FPGAの部屋

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

FPGAの部屋の有用と思われるコンテンツのまとめサイトを作りました。ご利用ください。 http://marsee101.web.fc2.com/index.html

Ultra96-V2 の高速、低速コネクタ用PMOD 拡張基板がバグってた。CSI0_MCLK と CSI1_MCLK が 1.8V バンクの信号だった。それを1.2V の信号に入れてしまった。他の似たような信号名の信号はすべて 1.2V だったので、間違ってしまった。パターンをカットする必要がある。

Ultra96-V2 の高速、低速コネクタ用PMOD 拡張基板に Pmod VGA を接続する1(準備編)”を修正する。

4d8a25b4.png


86337981.png


インターフェース用IC U7 の 3 、 4 番ピンをパターンカットする。(ピンクの線でパターンカットする)
d84c4960.png

Ultra96-V2 の高速、低速コネクタ用PMOD 拡張基板に Pmod VGA を接続する1(準備編)”の続き。

前回は、高速、低速コネクタ用PMOD 拡張基板の FPGA のピン・アサインを調べた。今回は、高速、低速コネクタ用PMOD 拡張基板のPMOD に接続する Pmod VGA を使用するためのディスプレイ・コントローラを Vitis HLS 2020.1 を使用して作成しよう。

このディスプレイ・コントローラは Vivado HLS セミナに使用しているソースコードを流用している。
入力は無く、出力だけとなる。出力の画像は、画面を4分割し、第1象限は赤、第2象限は緑、第3象限は青、第4象限は白を表示する。
ソースコードとテストベンチのコードを示す。
ソースコードの display_cont.cpp を示す。

// display_cont.cpp
// 2015/06/03 by marsee
//
// 画面を4分割した第1象限は赤、第2象限は緑、第3象限は青、第4象限は白を表示する
//

#include <stdio.h>
#include <string.h>
#include <ap_int.h>

// SVGA 解像度
#define H_ACTIVE_VIDEO    800
#define H_FRONT_PORCH    40
#define H_SYNC_PULSE    128
#define H_BACK_PORCH    88
#define H_SUM            (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE + H_BACK_PORCH)

#define V_ACTIVE_VIDEO    600
#define V_FRONT_PORCH    1
#define V_SYNC_PULSE    4
#define V_BACK_PORCH    23
#define V_SUM            (V_ACTIVE_VIDEO + V_FRONT_PORCH + V_SYNC_PULSE + V_BACK_PORCH)

void display_cont_sub(ap_uint<8> *red, ap_uint<8> *green, ap_uint<8> *blue, ap_uint<1> *display_enable, ap_uint<1> *hsyncx, ap_uint<1> *vsyncx){
#pragma HLS INTERFACE ap_none register port=red
#pragma HLS INTERFACE ap_none register port=green
#pragma HLS INTERFACE ap_none register port=blue
#pragma HLS INTERFACE ap_none register port=display_enable
#pragma HLS INTERFACE ap_none register port=hsyncx
#pragma HLS INTERFACE ap_none register port=vsyncx
#pragma HLS INTERFACE ap_ctrl_hs 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 rewind
            if (h_count >= (H_ACTIVE_VIDEO +H_FRONT_PORCH) && h_count < (H_ACTIVE_VIDEO + H_FRONT_PORCH + H_SYNC_PULSE))
                *hsyncx = 0;
            else
                *hsyncx = 1;

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

            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){
                    *red=0xff; *green=0; *blue=0;
                } else if (h_count < H_ACTIVE_VIDEO){
                    *red=0; *green=0xff; *blue=0;
                } else {
                    *red=0; *green=0; *blue=0;
                }
            } else if (v_count < V_ACTIVE_VIDEO){
                if (h_count < H_ACTIVE_VIDEO/2){
                    *red=0; *green=0; *blue=0xff;
                } else if (h_count < H_ACTIVE_VIDEO){
                    *red=0xff; *green=0xff; *blue=0xff;
                } else {
                    *red=0; *green=0; *blue=0;
                }
            } else {
                *red=0; *green=0; *blue=0;
            }
        }
    }
}


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

//
// display_cont_tb.cpp
// 2015/06/03 by marsee
//

#include <stdio.h>
#include <string.h>
#include <ap_int.h>

void display_cont_sub(ap_uint<8> *red, ap_uint<8> *green, ap_uint<8> *blue, ap_uint<1> *display_enable, ap_uint<1> *hsyncx, ap_uint<1> *vsyncx);
int main(){
    ap_uint<8> redb, *red;
    ap_uint<8> greenb, *green;
    ap_uint<8> blueb, *blue;
    ap_uint<1> deb, *display_enable;
    ap_uint<1> hb, *hsyncx;
    ap_uint<1> vb, *vsyncx;

    red = &redb;
    green = &greenb;
    blue = &blueb;
    display_enable = &deb;
    hsyncx = &hb;
    vsyncx = &vb;

    display_cont_sub(red, green, blue, display_enable, hsyncx, vsyncx);
    display_cont_sub(red, green, blue, display_enable, hsyncx, vsyncx);

    return 0;
}


Vitis HLS 2020.1 を起動して、プロジェクトを作成する。
1a577b5a.png


display_cont_201 プロジェクトを作成する。
847e3f3b.png


SVGA 出力なので、 Clock Period を 25 ns に設定し、 xczu3eg-sbva484-1-e に設定した。
c16e8187.png


display_cont_201 プロジェクトが作成され、ソースコードとテストベンチを追加した。
d8292222.png


Top Function を display_cont_sub に設定した。
53f86b50.png


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


C コードの合成のレポートを示す。
0c55755d.png


66168 クロックは、(800+40+128+88)×(600+1+4+23) で画像フレームの総クロック数をとなっている。

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


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


1 回目と 2 回目のつなぎの部分を拡大してみた。その部分で余計なクロックは無いようだ。
71a42958.png


(800+40+128+88)×25 ns = 26400 ns = 26.4 us となる。

合成された VHDL コードの entity 部分を見てみると ap_ctrl_hs の制御信号が追加されている。 ap_start などだ。

entity display_cont_sub is
port (
    ap_clk : IN STD_LOGIC;
    ap_rst : IN STD_LOGIC;
    ap_start : IN STD_LOGIC;
    ap_done : OUT STD_LOGIC;
    ap_idle : OUT STD_LOGIC;
    ap_ready : OUT STD_LOGIC;
    red : OUT STD_LOGIC_VECTOR (7 downto 0);
    green : OUT STD_LOGIC_VECTOR (7 downto 0);
    blue : OUT STD_LOGIC_VECTOR (7 downto 0);
    display_enable : OUT STD_LOGIC_VECTOR (0 downto 0);
    hsyncx : OUT STD_LOGIC_VECTOR (0 downto 0);
    vsyncx : OUT STD_LOGIC_VECTOR (0 downto 0) );
end;


ap_start などの余計な制御信号を削除するために、Vitis HLS の INTERFACE 指示子の ap_ctrl_hs を ap_ctrl_none に変更した。
b324c607.png


これで C コードの合成を行った。
9e0ea5a5.png


合成された VHDL コードの entity 部分を再度確認すると、制御信号が削除されていた。

entity display_cont_sub is
port (
    ap_clk : IN STD_LOGIC;
    ap_rst : IN STD_LOGIC;
    red : OUT STD_LOGIC_VECTOR (7 downto 0);
    green : OUT STD_LOGIC_VECTOR (7 downto 0);
    blue : OUT STD_LOGIC_VECTOR (7 downto 0);
    display_enable : OUT STD_LOGIC_VECTOR (0 downto 0);
    hsyncx : OUT STD_LOGIC_VECTOR (0 downto 0);
    vsyncx : OUT STD_LOGIC_VECTOR (0 downto 0) );
end;


これで問題ないので、Export RTL を行って、IP を作成する。
Ultra96expb_PMOD_VGA_18_200730.png

IP が生成された。

AR# 75369 2020.1 緊急パッチ - Vivado タイミングおよび制約 - 間違って自動生成されたクロック名、解析の違い、ツールのクラッシュなど、複数の問題を修正するためのパッチ”を適用してみよう。

AR# 75369 の問題の説明文を引用する。

問題 1:

同じバージョンの Vivado に DCP を読み込むと、名前が変更されたクロックおよび自動生成されたクロック名が正しく維持されず、タイミング解析の結果が間違いになります。

この問題は、DCP が別のバージョンの Vivado で生成され、開かれている場合には発生しません。

問題 2:

階層ピンで定義されている生成クロックがあるとき、インメモリ デザインと読み込まれた DCP との間のタイミング結果値に差が出る可能性があり、そのネットのすべてのロード ピンへクロックが伝播するのをブロックします。

ロード ピンが生成クロックの定義によってブロックされていなければ、この問題は発生しません。

問題 3:

制約にコレクション (opt/place_design を実行する前と opt/place_design を実行した後のリスト) がある場合、置き換えられたオブジェクトの一部がコレクションに追加されます。
リストのリストは Vivado 2020.1 では現在サポートされていません。
デザインが Vivado 2020.1 でインプリメントされていて、同じ Vivado 2020.1 で DCP が再度読み込まれている場合は、問題は発生しません。

インプリメンテーションと DCP の再読み込みで異なるバージョンの Vivado が使われている使用されている場合は、この問題が発生します。

このケースでは、タイミングの不一致が一部あるので、一部のパターンが一致しないことが原因でチェックポイントが再度読み込まれると、警告メッセージが生成されます。

問題 4:

「Phase 1.3 Build Placer Netlist Model」という配置フェーズで Vivado がクラッシュします。


添付されているパッチのインストール手順の内の方法1 を試してみよう。
方法1 を引用する。

方法 1: (Vivado 2014.4 およびそれ以降のみ)
1. $XILINX_VIVADO/patches ディレクトリ (Linux) または C:\Xilinx\Vivado\\patches ディレクトリ (Windows) に移動します (このディレクトリがない場合は作成します)。
2. 「AR75369」という名前で始まるディレクトリに ZIP アーカイブを解凍します。
注記: ほとんどの解凍ツールでは、ZIP ファイルと同じ名前のディレクトリが解凍時に自動的に作成されます。
3. 元のインストール場所から Vivado を実行します。


まずは、
source /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vitis/2020.1/settings64.sh
が実行済みのターミナルで、
echo $XILINX_VIVADO
を実行した時の結果は
/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vivado/2020.1
だった。

/media/masaaki/Ubuntu_Disk/tools/Xilinx/Vivado/2020.1 に patches ディレクトリを作成した。
AR75369_vivado_2020_1_preliminary_rev1.zip を同じディレクトリにダウンロードした。
eab88476.png


AR75369_vivado_2020_1_preliminary_rev1.zip を表示すると、vivado ディレクトリが見えた。
c3c127c3.png


方法1 の様に AR75369 で始まるディレクトリ名ではないので、 /media/masaaki/Ubuntu_Disk/tools/Xilinx/Vivado/2020.1/patches ディレクトリの下に AR75369_vivado_2020_1_preliminary_rev1 ディレクトリを作成した。
d345f28c.png


AR75369_vivado_2020_1_preliminary_rev1 ディレクトリの下に、AR75369_vivado_2020_1_preliminary_rev1.zip を解凍した。
9c683de3.png


この状態にで Vivado 2020.1 を vivado & で起動すると起動メッセージに

Vivado v2020.1_AR75369 (64-bit)

があった。以前の Vivado の起動メッセージと比べてみた。
955d295c.png


起動した Vivado 2020.1 もタイトルが、 Vivado 2020.1_AR75369 になっていた。
59f1308d.png


AR# 75369 が当たったようだ。

↑このページのトップヘ