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が動作しません]
※方法としてはサンプルデザインを作成して、シミュレーション方法をします。
このブログは「FPGA設計ブログ一覧」の
2. シミュレーションのひとつです。
目次
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デザインを作成します) |
※画像クリックで大きな画像が表示されます。 出典:Vivado® ML Edition |
|
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デザインを作成します) |
※画像クリックで大きな画像が表示されます。 出典:Vivado® ML Edition |
|
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に追加します。 |
出典:Vivado® ML Edition |
シミュレーション
テストベンチ上に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に追加します。 |
出典:Vivado® ML Edition |
|
4. | Add Filesを選択し、sim_tb_top.svを追加します。 |
出典:Vivado® ML Edition |
|
5. | Finishを選択し、終了します。 |
出典:Vivado® ML Edition |
|
6. | Sourcesタブで、下図のようにsim_tb_topがtopデザインになっていることを確認します。 |
出典:Vivado® ML Edition |
シミュレーションの実行
下図のようにSIMULATION→run Simulation→Run Behavioral Simulationを選択、simulationを実行します。(環境依存で、時間がかかる場合があります)
出典:Vivado® ML Edition
観測したい信号を追加し、runを再実行し、波形を観測します。
(LED0[3:0]、LED1[3:0]のLEDが順番に動作していることを波形上で確認できます)
出典:Vivado® ML Edition
EXAMPLEデザイン
本ブログでは、DUAL VIPを利用したシミュレーション方法を紹介しました。
EXAMPLEデザインについては以下よりダウンロードいただけます。
おわりに
いかがでしたでしょうか。簡単の例ですが、これで、DUAL ZYNQが存在するシステムレベルのシミュレーションができました。最後までご覧いただきありがとうございました。
このブログは「FPGA設計ブログ一覧」の
2. シミュレーションのひとつです。
参考資料:
DS941:Zynq-7000 All Programmable SoC Verification IP v1.0
Xilinx Answer 69622
Xilinx Answer 70185
Xilinx Answer 70186
Xilinx Answer 75942