Accessing a generate block hierarchy

Hi all,
I’m trying to access a verilog hierarchy which was generated by a generate block - but I’m having some problems with it. for example:

verilog file: (let’s assume it is located at “testbench” hierarchy, and an interface named “some_interface” is already defined)

genvar i;
generate
for (i=0;i<3;i++)
begin : GENERATE_HEADER
some_interface some_interface_inst(clk);
assign some_interface_inst.x=1’b0;
assign some_interface_inst.y=1’b1;
end

systemverilog file:

virtual some_interface some_interface_arr[0:2];

for (int i=0;i<3;i++)
some_interface_arr[i]=testbench.GENERATE_HEADER[i].some_interface_inst;

I believe I can’t access a generated verilog hierarchy with a system-verilog for loop (variable i). Am I correct? and if so - is there a way to pass this obstacle?
Thanks in advance,
Eyal.
P.s - What I’m generally trying to do is to get handles to the instantiated interfaces (some_interface) and pass them to system verilog objects in my testbench, using the virtual interface array.

In order to reference an instance created inside a generate-for loop, you must use a constant or another genvar variable. That is because GENERATE_HEADER is not an array, it is part of a hierarchical scope name. So you could do

virtual some_interface some_interface_arr[0:2];
generate 
for (i=0;i<3;i++)
initial some_interface_arr[i]=testbench.GENERATE_HEADER[i].some_interface_inst;
end
endgenerate

If you are using UVM/OVM you should be setting these interfaces in the config_db directly instead of assigning them to a local virtual interface array.

In reply to dave_59:

I am using UVM, and the reason for assigning the interfaces to a local virtual array is to
have the ability of using uvm_config_db::set with a for - loop. I’m pretty sure I can’t use
generate inside a system verilog file (as for the solution suggested). Am I wrong?

In reply to seyaleli1234:

What makes you think you cannot use a generate block in SystemVerilog? If it was in Verilog–it is in SystemVerilog. You can put your uvm_config_db::set in the initial block that is inside the generate-for loop.

In reply to dave_59:

Hi Dave ,

When we set the instantiated interfaces into uvm_config_db# from within the initial block which is inside the generate-for loop, there could be potential race condition between when the run_test() call and these interfaces are set in config_db# because they will be in different initial blocks . I have my bench structure where these interfaces are instantiated in a nested module within the top level module . I’m calling run_test() from initial block of top level module.

module tb_top

master m();

initial begin
m.set_rtl_interfaces();
run_test();
end
endmodule

module master();

virtual vbus_mgt_interface vbus_mgt_if_array[PORT_NUM]; // temp virtual interface array generate for(genvar i=0;i<PORT_NUM;i=i+1) begin: vbus_connect
vbus_mgt_interface vbus_mgt_if(
.ppc(drd_usb_vbus_ppc),
.ovc(),
.vbus_p(vbus_p_bfm),
.id(drd_usb_id)
);
initial begin
vbus_mgt_if_array[i] = vbus_mgt_if;
end

end

endgenerate

function void set_rtl_interfaces();
for(int i=0;i<PORT_NUM;i=i+1) begin uvm_resource_db #(virtual vbus_mgt_interface.TB_PWR_CONNECT)::set_anonymous($psprintf({TOP_USB_ENV,“.drd_env[%0d].vbus_agent[%0d].driver”},i,i),vbus_mgt_if_array[i].TB_PWR_CONNECT);
end
endfunction : set_rtl_interfaces

endmodule

If we want to avoid the initial block in module master , we need direct access of the different instances of interface instantiated within the generate for loop.

Thanks,
Chandra

In reply to dave_59:

Hi Dave,
I’m trying to something similar but for binding my assertions.
Below is my bind statement in my bind assert module:

define NUM_BLKS 4; genvar asrt_inst; generate for (asrt_inst = 0;asrt_inst < NUM_BLKS;asrt_inst = asrt_inst+1)
begin
bind top.u_dut.u_blk_gen[asrt_inst] my_assert u_my_assert (
.

);
end
endgenerate*

Here, the RTL is under gen block of u_blk_gen[gen_var], and I’m trying to bind my assertion to each instance of the generated instance.
The path instances of the RTL, generated using the generate block are :

  1. top.u_dut.u_blk_gen[0]
  2. top.u_dut.u_blk_gen[1]
  3. top.u_dut.u_blk_gen[2]
  4. top.u_dut.u_blk_gen[3]

And with the bind statement, I get the below compile error:
*
bind top.u_dut.u_blk_gen[gpt_asrt_inst] my_assert u_my_assert (
|
ncvlog: E,ILLGVR (/home/user/assertion_bind.v,165|72): This genvar cannot be used in this context [12.1.3(IEEE 2001)].

Is there a work around for such scenario?

In reply to suhas.ns:

It would help to show the generate block in your RTL, but I think you are missing an instance name in your bind statement. It should be

bind top.u_dut.u_blk_gen[asrt_inst].instname my_assert u_my_assert (

If you are binding to all instances of a module, then you do not need an instance specific bind. You could do

bind targetname my_assert u_my_assert (

In reply to dave_59:

In reply to suhas.ns:
It would help to show the generate block in your RTL, but I think you are missing an instance name in your bind statement. It should be

bind top.u_dut.u_blk_gen[asrt_inst].instname my_assert u_my_assert (

even with the instname, I face same compilation issue.

If you are binding to all instances of a module, then you do not need an instance specific bind. You could do

bind targetname my_assert u_my_assert (

Here, I’m binding to all instances, but issue is that each RTL instance is with different parameters and the my assertion has to be binded to the RTL instance with the same set of parameters which I’ll be passing while binding. And that is the reason I’m trying to bind for each instance.

In reply to suhas.ns:
You need to show a complete self contained example that demonstrates the problem as I’m unable to reproduce your issue.

In reply to dave_59:

Hi Dave,
Below is the RTL module dut code snapshot where u_blk is instantiated using generate block:


`define NUM_BLKS 4

localparam [5:0]PARAM1_ARY[3:0]  = '{16,16,32,40};
localparam [1:0]PARAM2_ARY[3:0]  = '{1,2,2,3};


genvar blk_inst;
generate
for (blk_inst = 0;blk_inst < `NUM_BLKS;blk_inst = blk_inst+1) 
  
begin : u_blk_gen
       blk   #(
                .PARAM1(PARAM1_ARY[blk_inst]),
                .PARAM2(PARAM2_ARY[blk_inst])
              )
        u_blk (
                .* //ports mapping done here
              );
end
endgenerate

For the above RTL code, the instance’s path I see it in the waveforms is as below:


top.u_dut.u_blk_gen[0].u_blk
top.u_dut.u_blk_gen[1].u_blk
top.u_dut.u_blk_gen[2].u_blk
top.u_dut.u_blk_gen[3].u_blk

For the above RTL, I’m trying to bind my assertion as below in a similar fashion wherein even by assertion module has the same parameters:


localparam [5:0]ASRT_PARAM1_ARY[3:0]  = '{16,16,32,40};
localparam [1:0]ASRT_PARAM2_ARY[3:0]  = '{1,2,2,3};

genvar asrt_inst;
generate
for (asrt_inst = 0;asrt_inst < `NUM_BLKS;asrt_inst = asrt_inst+1) 
begin 
bind top.u_dut.u_blk_gen[asrt_inst].u_blk my_assert #(
                .PARAM1(ASRT_PARAM1_ARY[asrt_inst]),
                .PARAM2(ASRT_PARAM2_ARY[asrt_inst])
              )
u_my_assert 
(
.*//ports mapping done here
);
end

endgenerate

And below is the compilation error I get:


file: /home/user/assertion_bind.v
bind top.u_dut.u_blk_gen[asrt_inst].u_blk my_assert #(
                                  |
ncvlog: *E,ILLGVR (/home/user/assertion_bind.v,167|68): This genvar cannot be used in this context [12.1.3(IEEE 2001)].
	module worklib.assertion_bind:v

*In reply to suhas.ns:*If you want more help form me, I need this in the form of a complete self contained example.

In reply to dave_59:

Code at EDA playground:
Self contained code here

In reply to dave_59:
There is nothing illegal about your code. Contact your vendor for support.