UPGRADE YOUR BROWSER

We have detected your current browser version is not the latest one. Xilinx.com uses the latest web technologies to bring you the best online experience possible. Please upgrade to a Xilinx.com supported browser:Chrome, Firefox, Internet Explorer 11, Safari. Thank you!

cancel
Showing results for 
Search instead for 
Did you mean: 
Contributor
Contributor
576 Views
Registered: ‎06-07-2012

How to store an handle on the Zynq VIP

Jump to solution

Hi,

 

I have started using the Zynq VIP to do AXI transactions, as noted in DS940.  Here is a small portion of my initial testbench, modified from the Zynq example design.

 

        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.wait_reg_update(32'h43c00240, 32'h00001300, 32'hFFFFECFF, 250, 30000, read_data);

        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.write_data(32'h43c00240,4, 32'h00010000, resp);

        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.write_data(32'h43c10400,4, 32'h00000100, resp);

The calls to the Zynq VIP model all refer to the whole hierarchy.  So If I build a whole library of validation, and then the hierarchy changes, I would have have to seach-and-replace in all files to put the new hierarchy to reach the VIP.  This would be VERY bad  programming.

 

Is there a way to store the handle to the VIP in a single local or global handle and then call it from the handle?   Here is an example of what I mean

vip_type processor;

processor = tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst;

processor.write_data();

processor.read_data();

processor.read_interrupt();

 

That way, if the hierarchy changes, there is a single place where it has to be fixed (or it can be set as a parameter to the constructor of my validation class)

PG267 shows the general AXI VIP and how to get an handle on VIP. Here is an example:

import axi_vip_pkg::*;

import gaia_zynq_axi_vip_0_0_pkg::*;

gaia_zynq_axi_vip_0_0_mst_t agent;

agent = new("master vip agent",tb.zynq_sys.gaiadut.Xgaia.gaia_zynq_i.axi_vip_0.inst.IF);

agent.start_master(); // agent start to run


 

If I look in the source code of the Zynq Vip (file processing_system7_vip_v1_0_vl_rfs.sv ), starting around line 6885:

axi_mst_agent #(1,address_bus_width, data_bus_width, data_bus_width, id_bus_width,id_bus_width,0,0,0,0,0,1,1,1,1,0,1,1,1,1,1,1) mst;

...

initial begin
mst
= new("mst",master.IF);
tr_m
= new("master monitor trans");
mst.start_master();
end

So the Zynq VIP does the same thing, but the handle to the axi_mst_agent is generated inside the model and the example design only shows how to use it through complete hierarchy.

 

Anybody has a suggestion?

 

Thanks,

 

jf

 

 

 

 

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Contributor
Contributor
454 Views
Registered: ‎06-07-2012

Re: How to store an handle on the Zynq VIP

Jump to solution

Hi @demarco,

 

Thank you for reviving the thread, I had forgotten about it.

 

I did try to use a define and it wouldn't work, but that must have been a typo on my side.  Yes that is a Verilog question, not really a Xilinx question.  Getting an handle on the Zynq model however is a Xilinx question.

 

When the code is put into a Class in a Package, it cannot call a the model through hierarchical reference.  That is a 'normal' language limitation.  And as you may guess, putting all the simulation environment code in a single top file isn't clean.  Putting everything in  many 'include files isn't much better.

 

The solution is to use an interface.  Here is an example code:

interface cpu_if;
    wire req;
    //reg [31:0] read_data;
    //reg resp;

    task fpga_soft_reset(input[31:0] reset_ctrl);
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.fpga_soft_reset(reset_ctrl);
    endtask : fpga_soft_reset
    
    task read_data(input [31:0] start_addr, input [7:0] rd_size, output[(256*8)-1:0] rd_data, output [1:0] response);
        //$display("dans read_data");
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.read_data(start_addr,rd_size,rd_data,response);
    endtask : read_data

    task write_data(input [31:0] start_addr, input [7:0] wr_size,input [(256*8)-1:0] w_data, output [1:0] response);
        //$display("dans write_data");
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.write_data(start_addr,wr_size, w_data, response);
    endtask: write_data

    task automatic wait_reg_update(input [31:0] addr, input [31:0] data_i, input [31:0] mask_i, input [31:0] time_interval, input [31:0] time_out, output [31:0] data_o);
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.wait_reg_update(addr, data_i, mask_i, time_interval, time_out, data_o);
    endtask : wait_reg_update
    
    task automatic read_mem(input [31:0] start_addr, input [7:0] no_of_bytes, output[1023:0] data);
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.read_mem(start_addr, no_of_bytes, data);
    endtask : read_mem 

    
endinterface : cpu_if

 

That interface is statically instantiated in my top module.  Every object under my top module receives an handle to the interface when, so every object can call the interface:

cpu_if zcpu = handle_received_from_top;

 

zcpu.read_data(...);

zcpu.write_data(...);

etc.

If the architecture ever changes, I just have to fix the few tasks in the interface defined in the top module and I don't have to change a single line of code in the objects.

 

If you want to forward that information to whoever makes the documentation of DS940 or Zynq Example design, feel free to do it.  I think it would help new Zynq users.

 

jf

2 Replies
Xilinx Employee
Xilinx Employee
465 Views
Registered: ‎10-04-2016

Re: How to store an handle on the Zynq VIP

Jump to solution

Hi @jlarin,

This isn't really a Xilinx specific question but rather a general Verilog question.

You could use the 'define compiler directive to perform text substitutions. For example:

'define ZYNQ_VIP_0 test_bench.mpsoc_sys.design_1_i.zynq_ultra_ps_e_0.inst

...

'ZYNQ_VIP_0.pre_load_mem(2'b00, 32'h00010000, 4096);

 

Regards,

Deanna

-------------------------------------------------------------------------
Don’t forget to reply, kudo, and accept as solution.
-------------------------------------------------------------------------
0 Kudos
Highlighted
Contributor
Contributor
455 Views
Registered: ‎06-07-2012

Re: How to store an handle on the Zynq VIP

Jump to solution

Hi @demarco,

 

Thank you for reviving the thread, I had forgotten about it.

 

I did try to use a define and it wouldn't work, but that must have been a typo on my side.  Yes that is a Verilog question, not really a Xilinx question.  Getting an handle on the Zynq model however is a Xilinx question.

 

When the code is put into a Class in a Package, it cannot call a the model through hierarchical reference.  That is a 'normal' language limitation.  And as you may guess, putting all the simulation environment code in a single top file isn't clean.  Putting everything in  many 'include files isn't much better.

 

The solution is to use an interface.  Here is an example code:

interface cpu_if;
    wire req;
    //reg [31:0] read_data;
    //reg resp;

    task fpga_soft_reset(input[31:0] reset_ctrl);
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.fpga_soft_reset(reset_ctrl);
    endtask : fpga_soft_reset
    
    task read_data(input [31:0] start_addr, input [7:0] rd_size, output[(256*8)-1:0] rd_data, output [1:0] response);
        //$display("dans read_data");
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.read_data(start_addr,rd_size,rd_data,response);
    endtask : read_data

    task write_data(input [31:0] start_addr, input [7:0] wr_size,input [(256*8)-1:0] w_data, output [1:0] response);
        //$display("dans write_data");
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.write_data(start_addr,wr_size, w_data, response);
    endtask: write_data

    task automatic wait_reg_update(input [31:0] addr, input [31:0] data_i, input [31:0] mask_i, input [31:0] time_interval, input [31:0] time_out, output [31:0] data_o);
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.wait_reg_update(addr, data_i, mask_i, time_interval, time_out, data_o);
    endtask : wait_reg_update
    
    task automatic read_mem(input [31:0] start_addr, input [7:0] no_of_bytes, output[1023:0] data);
        tb.zynq_sys.gaiadut.gaia_zynq_i.processing_system7_0.inst.read_mem(start_addr, no_of_bytes, data);
    endtask : read_mem 

    
endinterface : cpu_if

 

That interface is statically instantiated in my top module.  Every object under my top module receives an handle to the interface when, so every object can call the interface:

cpu_if zcpu = handle_received_from_top;

 

zcpu.read_data(...);

zcpu.write_data(...);

etc.

If the architecture ever changes, I just have to fix the few tasks in the interface defined in the top module and I don't have to change a single line of code in the objects.

 

If you want to forward that information to whoever makes the documentation of DS940 or Zynq Example design, feel free to do it.  I think it would help new Zynq users.

 

jf