(C) by T.IZUMI, Oct 2015
Ver. 2015.10.30.a

いずみ研トレーニング課題

Javaベース高位合成系 Synthesijer による回路モジュール設計例

ターゲットボード
ZYBO
ターゲットFPGA
XC7Z010-1CLG400C
※それ以外のボードでトライする場合は、ボードの仕様に合わせてxdcファイルとトップ記述、およびIP Integrator でのProcessor Systemの設定を書き換えるべし。
開発環境
Synthesijer 20151020
Windows+cygwin
Oracle Java SDK Standard Edition 8 (JDK SE 8u65)
Xilinx Vivado 2015.2
Xilinx SDK 2015.2
課題パッケージ
http://www.ritsumei.ac.jp/se/re/izumilab/lecture/15ZyboLedSjr.zip

0. 準備

このくらい自力でインストールしなさい…、と言いたいところだが、ヒントを少し。

Java のインストール

Synthesijer の合成をかけるだけなら JRE (Java Runtime Environment) だけあればOK。 JRE はウェブアプリを使っていると自動でインストールされていることが多い。 Java でのテストベンチのコンパイルなどには JDK (Java Software Development Kit)が必要。

Synthesijer のインストール

Vivado のインストール


1. Java 記述と合成 (Synthesijer)

1-1. 内容の確認と設定

1-2. Java シミュレーション

1-3. 回路合成

Tips: cygwinの表示文字コードの設定…cygwin端末を右クリック→Options→Text→Locale


2. プロジェクトの生成 (Vivado)

2-1. プロジェクト生成

2-2. ファイルの確認

※public 変数に対応する _in,_we,_outの処理

【zybo_top.vより】
   sjrtest sjrtest_i
     (.clk(clk),
      .sw_in(sjr_sw_in),
      .sw_we(1),                             //常時書込
      .sw_out(),                             //読出不使用
      .ld_in(0),                             //書込不使用
      .ld_we(0),                             //書込不使用
      .ld_out(sjr_ld_out),
      .time_in(sjr_time_in),
      .time_we(1),                           //常時書込
      .time_out(),                           //読出不使用
      .start_time_in(0),                     //書込不使用
      .start_time_we(0),                     //書込不使用
      .start_time_out(sjr_start_time_out),
      .end_time_in(0),                       //書込不使用
      .end_time_we(0),                       //書込不使用
      .end_time_out(sjr_end_time_out),
      .run_n(sjr_run_n),
      .run_return(sjr_run_return),
      .run_busy(sjr_run_busy),
      .run_req(sjr_run_req),
      .reset(~rstn));


3. プロセッサシステム構築 (Vivado)

ここでは、テストベンチとして Zynq PS とその GPIO ポートを用いる。

instance, port入力出力
gpio_0, port 1時刻カウンタ
gpio_0, port 2ボタン、スイッチ
gpio_1, port 1method の busymethod の req
gpio_1, port 2method の戻り値method の引数
gpio_2, port 1method 開始時刻
gpio_2, port 2method 終了時刻

※プロセッサをテストベンチとして使用するため、 クロック精度での反応ができない。 そこで req 信号は verilog側で1クロックのパルスに変換している。

【zybo_top.vより】
    wire   sjr_run_req_curr;
    reg    sjr_run_req_prev=0;
    always @(posedge clk)
      sjr_run_req_prev<=(rstn)?sjr_run_req_curr:0;
    assign sjr_run_req=sjr_run_req_curr&~sjr_run_req_prev;

※Synthesijer では AXI port に接続するためのライブラリもあるが、 ここでは素直な method 呼出そのものを確認するのが目的であり、 Zynq PS はあくまでもテストベンチであるため、 敢えてそれは使用しない。

3-1. Block Design の生成と登録

3-2. Zynq PS(ARM) の配置と設定

3-3. GPIOの配置・接続

3-4. クロック、リセットを出力

3-5. GPIO ポートの追加

3-6. ブロック図の確認

3-7. アドレス空間の確認

3-8. システム生成


4. 仮合成と実機デバグの準備 (Vivado)

実機デバッグでは、いったん論理合成を通してから、 観測したい信号やレジスタをマークし、 さらにデバッグ用のモジュールを設定登録する。 そして、再合成する。

4-1. 観測対象のマーク

4-2. 論理合成

4-3. デバッグモジュールの設定と観測信号の登録

(*1)   ここで(画面B1)Netlistから信号やレジスタを右クリックして Mark Debug することもできる。しかし、ソースコード中の信号やレジスタは論理合成の最適化により名前が代わったり、縮退して消えてしまったりする。 また、 xdc ファイルの中で set_property MARK_DEBUG true [get_nets {uartrx/datao[*]}] などとすると予めマークできそうなものだが、それでも信号&名前の保存は保証されないようだ。


5. コンパイル (Vivado)


6. コンフィグレーション (Vivado)


7. プロセッサシステム情報のエクスポート (Vivado)

ソフトウェア開発のためにプロセッサシステムの情報をエクスポートする。


8. ソフトウェア開発プロジェクトの設定(SDK)

Xilinx SDK 上でのソフトウェア開発環境をセットアップする。

8-1. SDK の起動

8-2. プロジェクトの生成


9. ソースコードの登録 (SDK)

【sjrtest.cより】
  counter=0;
  while(1){
    pb1=XGpioPs_ReadPin(&gpiops,PB1_PIN);
    pb2=XGpioPs_ReadPin(&gpiops,PB2_PIN);
    led=(counter++&0x100000)?1:0;
    XGpioPs_WritePin(&gpiops,LED_PIN,led);

    if ((pb1_prev==0&&pb1==1)||(pb2_prev==0&&pb2==1)) {
      n=pb1?0x10000000:0x01000000;
      printf("run(%08x)\n",n);
      while ((*sjr_run_busy_p)==1){
	led=(counter++&0x80000)?1:0;
	XGpioPs_WritePin(&gpiops,LED_PIN,led);
      }
      *sjr_run_n_p=n;
      *sjr_run_req_p=1;// req is filtered to be 1clk pulse in top.v
      *sjr_run_req_p=0;
      while ((*sjr_run_busy_p)==1){
	led=(counter++&0x40000)?1:0;
	XGpioPs_WritePin(&gpiops,LED_PIN,led);
      }
      r=*sjr_run_return_p;
      t0=*sjr_start_time_p;
      t1=*sjr_end_time_p;
      t=t1-t0;
      printf("return = %08x\n",r);
      printf("start  = %08x\n",t0);
      printf("end    = %08x\n",t1);
      printf("time   = %08x\n",t);
    }
    pb1_prev=pb1;
    pb2_prev=pb2;
  }


10. コンパイルと実行(SDK)

10-1. コンパイル

10-2. 標準入出力とUARTの接続

10-3. 実行

10-4. 再実行


11. 動作確認 (SDK,Vivado)

11-1. 回路モジュールの仕様

11-2. テストベンチプログラムの仕様

11-3. 動作確認