1. 株式会社PALTEK
  2. TECHブログ
  3. 技術情報
  4. Vivado®2020.2でZynq® UltraScale+™ MPSoC Verification IP (VIP)を利用したシミュレーション(発展編③)~DUAL Zynq® UltraScale+™ MPSoCのシミュレーション方法:サンプルデザインあり~

TECHブログ

Vivado®2020.2でZynq® UltraScale+™ MPSoC Verification IP (VIP)を利用したシミュレーション(発展編③)~DUAL Zynq® UltraScale+™ MPSoCのシミュレーション方法:サンプルデザインあり~

Vivado®2020.2でZynq® UltraScale+™ MPSoC Verification IP (VIP)を利用したシミュレーション(発展編③)~DUAL Zynq® UltraScale+™ MPSoCのシミュレーション方法:サンプルデザインあり~

前編(発展編②)まではVIPを使用したシミュレーションを紹介しました。
複数のZynq® UltraScale+™ MPSoCデバイスを使用して構成したシステムのFPGA間通信を含めた統合シミュレーションが必要になったことを背景に、今回はDUAL VIPを利用したシミュレーションを紹介します。

なお、本篇で使用したEXAMPLEデザインはダウンロードできるよう準備していますので、気になる方はダウンロードしていただければと思います。あわせてご確認ください。

それでは、始めましょう。

※これから説明する方法は、behavioralシミュレーションのみ機能します。

[PROJECTに複数PSが存在するため、SIMULATION以外のPROCESSが動作しません]

※方法としてはサンプルデザインを作成して、シミュレーション方法をします。

目次

PS0のBDデザインの作成

1. 以下のコードをダウンロードしてください。
ダウンロードはこちら
コードをすべて選択し、ファイル名をdesign_1.tclとして保存します。
(全部で1,811行があり、1,811行目がcreate_root_design ""であることを確認してください)
2. 適当な場所にdualvipのフォルダを作成し、1で作ったdesign_1.tclをdualvip フォルダに保存します。
3. Vivado®2020.2を起動します。tcl consoleで2にて作成したdualvipフォルタに移動して、source design_1.tcl を入力し、tclを実行します。(BDデザインを作成します)

※画像クリックで大きな画像が表示されます。

4. source windowに作成されたdesign_1(design_1.bd)を右クリック、create HDL wrapperを選択し、Design_1_wrapper.vを生成します。

PS1のBDデザインの作成

1. 以下のコードをダウンロードしてください。
ダウンロードはこちら
コードをすべて選択し、ファイル名をdesign_1a.tclとして保存します。
(全部で1,811行があり、1,811行目がcreate_root_design ""であることを確認してください)
2. 適当な場所にdualvipのフォルダを作成し、1で作ったdesign_1a.tclをdualvip フォルダに保存します。
3. Vivado®2020.2を起動します。tcl consoleで2にて作成したdualvipフォルダに移動して、source design_1a.tcl を入力し、tclを実行します。(BDデザインを作成します)

※画像クリックで大きな画像が表示されます。

4. source windowに作成されたdesign_1(design_1.bd)を右クリック、create HDL wrapperを選択し、Design_1a_wrapper.vを生成します。

PS0とPS1を含めたTOP(RTL)デザインの作成

1. 以下枠内の文字をすべて選択し、COPY→TEXT Editorに貼り付け、ファイル名をdesign_2.vに保存します。
`timescale 1 ps / 1 ps
module design_2
   (CLK_IN1_D_com_0_clk_n,
    CLK_IN1_D_com_0_clk_p,
    CLK_IN1_D_com_1_clk_n,
    CLK_IN1_D_com_1_clk_p,
    LED3_0_0,
    LED3_0_1);
input  CLK_IN1_D_com_0_clk_n;
input  CLK_IN1_D_com_0_clk_p;
input  CLK_IN1_D_com_1_clk_n;
input  CLK_IN1_D_com_1_clk_p;  
output [3:0]LED3_0_0;
output [3:0]LED3_0_1;

  wire CLK_IN1_D_com_0_1_CLK_N;
  wire CLK_IN1_D_com_0_1_CLK_P;
  wire CLK_IN1_D_com_1_1_CLK_N;
  wire CLK_IN1_D_com_1_1_CLK_P;
  wire [3:0]design_1_0_LED3_0;
  wire [3:0]design_1_1_LED3_0;

  assign CLK_IN1_D_com_0_1_CLK_N = CLK_IN1_D_com_0_clk_n;
  assign CLK_IN1_D_com_0_1_CLK_P = CLK_IN1_D_com_0_clk_p;
  assign CLK_IN1_D_com_1_1_CLK_N = CLK_IN1_D_com_1_clk_n;
  assign CLK_IN1_D_com_1_1_CLK_P = CLK_IN1_D_com_1_clk_p;
  assign LED3_0_0[3:0] = design_1_0_LED3_0;
  assign LED3_0_1[3:0] = design_1_1_LED3_0;
  design_1_wrapper u0_design_1_wrapper
       (.CLK_IN1_D_com_clk_n(CLK_IN1_D_com_0_1_CLK_N),
        .CLK_IN1_D_com_clk_p(CLK_IN1_D_com_0_1_CLK_P),
        .LED3_0(design_1_0_LED3_0));
  design_1a_wrapper u1_design_1a_wrapper
       (.CLK_IN1_D_com_clk_n(CLK_IN1_D_com_1_1_CLK_N),
        .CLK_IN1_D_com_clk_p(CLK_IN1_D_com_1_1_CLK_P),
        .LED3_0(design_1_1_LED3_0));
endmodule
2. design_2.vをadd sources でprojectに追加します。

シミュレーション

テストベンチ上にPS0(VIP)とPS1(VIP)を別々に定義し、シミュレーションします。

1. 以下枠内の文字をすべて選択し、COPY→TEXT Editorに貼り付け、適当な所にsim_tb_top.svとして保存します。

`timescale 1ps/1ps
`define ZYNQ_VIP_0 sim_tb_top.u_design_2.u0_design_1_wrapper.design_1_i.zynq_ultra_ps_e_0.inst
`define ZYNQ_VIP_1 sim_tb_top.u_design_2.u1_design_1a_wrapper.design_1a_i.zynq_ultra_ps_e_0.inst
`define  XILINX_SIMULATOR
`ifdef XILINX_SIMULATOR
`endif

module sim_tb_top;

  // Input clock is assumed to be equal to the memory clock frequency
  // User should change the parameter as necessary if a different input
  // clock frequency is used
  localparam real CLKIN_PERIOD_NS = 9996 / 1000.0;

  //initial begin
  //   $shm_open("waves.shm");
  //   $shm_probe("ACMTF");
  //end
//////////////////////////////////////////////

  reg                  ddrref_clk_i;
  reg                  com_clk_i;
  reg                  gtref_clk_i;


  reg  [31:0] cmdName;
  bit  en_model;
  tri  model_enable = en_model;

  /////////////////////////

wire         COM_CLKN0;        //input
wire         COM_CLKP0;        //input

wire [3:0]   LED;
wire [3:0]   LED1;
///////////////////////////
wire ARESET_N;
reg tb_ACLK;
reg tb_ARESETn;
wire temp_clk;
wire temp_rstn;
reg resp;
reg [31:0] read_data;
reg [31:0] read_data1;
reg [127:0] read_data128;
reg [7:0]  irq_status;
reg [31:0] src_data;
reg [31:0] dst_data;

int cdma_tb_pass = 1;


design_2
u_design_2
(
    .CLK_IN1_D_com_0_clk_n  (COM_CLKN0           ),
    .CLK_IN1_D_com_0_clk_p  (COM_CLKP0           ),
    .CLK_IN1_D_com_1_clk_n  (COM_CLKN0           ),
    .CLK_IN1_D_com_1_clk_p  (COM_CLKP0           ),    
    .LED3_0_0               (LED                 ),
    .LED3_0_1               (LED1                 )
);

  //**************************************************************************//
  // Clock Generation
  //**************************************************************************//

  initial begin
    tb_ACLK      = 1'b0;
    ddrref_clk_i = 1'b0;
    com_clk_i    = 1'b0;

  end

  always        tb_ACLK = #(10000/2)  ~tb_ACLK;
  always   ddrref_clk_i = #(9996/2.0) ~ddrref_clk_i; //100.04Mhz
  always      com_clk_i = #(40000/2.0) ~com_clk_i;   //25Mhz


   //**************************************************************************//
  assign PL0_DDR_SYSCLK_clk_p =  ddrref_clk_i;
  assign PL0_DDR_SYSCLK_clk_n = ~ddrref_clk_i;

  assign COM_CLKP0 =  com_clk_i;
  assign COM_CLKN0 = ~com_clk_i;

  /////////////////////////////////////////////////////////////////////////////

    initial begin
        $display ("running the tb");
         tb_ARESETn = 1'b0;
         en_model = 1'b0;
         repeat(200)@(posedge tb_ACLK);
         en_model = 1'b1;
         #5
         tb_ARESETn = 1'b1;
          @(posedge tb_ACLK);
         repeat(200) @(posedge tb_ACLK);

        `ZYNQ_VIP_0.por_srstb_reset(1'b0);
        `ZYNQ_VIP_0.fpga_soft_reset(32'h1);
        `ZYNQ_VIP_1.por_srstb_reset(1'b0);
        `ZYNQ_VIP_1.fpga_soft_reset(32'h1);
        
        
        #2000000 ;  // This delay depends on your clock frequency. It should be at least 16 clock cycles.
        `ZYNQ_VIP_0.por_srstb_reset(1'b1);
        `ZYNQ_VIP_0.fpga_soft_reset(32'h0);
        `ZYNQ_VIP_1.por_srstb_reset(1'b1);
        `ZYNQ_VIP_1.fpga_soft_reset(32'h0);
        
       // Set debug level info to off. For more info, set to 1.
        `ZYNQ_VIP_0.set_debug_level_info(1);
        `ZYNQ_VIP_0.set_stop_on_error(1);
        `ZYNQ_VIP_1.set_debug_level_info(1);
        `ZYNQ_VIP_1.set_stop_on_error(1);
             
////////////////////////////////////////////////////////////////////////////////////////
        //This drives the LEDs on the GPIO output      
        `ZYNQ_VIP_0.write_data(32'hA0000000,4, 32'h00000001, resp);
         `ZYNQ_VIP_0.write_data(32'hA0000000,4, 32'h00000002, resp);
         `ZYNQ_VIP_0.write_data(32'hA0000000,4, 32'h00000004, resp);
         `ZYNQ_VIP_0.write_data(32'hA0000000,4, 32'h00000008, resp);
        $display ("U0 LEDs are toggled, observe the waveform");
        //This drives the LEDs on the GPIO output      
         `ZYNQ_VIP_1.write_data(32'hA1000000,4, 32'h00000001, resp);
         `ZYNQ_VIP_1.write_data(32'hA1000000,4, 32'h00000002, resp);
         `ZYNQ_VIP_1.write_data(32'hA1000000,4, 32'h00000004, resp);
         `ZYNQ_VIP_1.write_data(32'hA1000000,4, 32'h00000008, resp);     
              
        $display ("U1 LEDs are toggled, observe the waveform");
                
        $display ("Simulation completed");
        $stop;
           
      end


    assign temp_clk = tb_ACLK;
    assign temp_rstn = tb_ARESETn;

endmodule
2. Vivado®2020.2を起動し、基本編で作成したPROJECTを開きます。
3. File→Add Sources で下図のようにsim_tb_top.svをPROJECTに追加します。

4. Add Filesを選択し、sim_tb_top.svを追加します。

5. Finishを選択し、終了します。

6. Sourcesタブで、下図のようにsim_tb_topがtopデザインになっていることを確認します。

シミュレーションの実行

下図のようにSIMULATION→run Simulation→Run Behavioral Simulationを選択、simulationを実行します。(環境依存で、時間がかかる場合があります)

観測したい信号を追加し、runを再実行し、波形を観測します。
(LED0[3:0]、LED1[3:0]のLEDが順番に動作していることを波形上で確認できます)

EXAMPLEデザイン

本ブログでは、DUAL VIPを利用したシミュレーション方法を紹介しました。
EXAMPLEデザインについては以下よりダウンロードいただけます。

おわりに

いかがでしたでしょうか。簡単の例ですが、これで、DUAL ZYNQが存在するシステムレベルのシミュレーションができました。最後までご覧いただきありがとうございました。

 

お問い合わせ

 

このブログのシリーズ