cancel
Showing results for 
Search instead for 
Did you mean: 
Adventurer
Adventurer
724 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
Adventurer
Adventurer
602 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

View solution in original post

2 Replies
Highlighted
Xilinx Employee
Xilinx Employee
613 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
Adventurer
Adventurer
603 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

View solution in original post