最近用到interface array,了解到可以用generate 来产生,而不需要一个一个来写,不多说,直接上code~~
bit ck[`IF_NUM];
bit ex_ck;
generate
for(genvar ii=0;ii<`IF_NUM;ii++)begin:if_loop
if(ii < `IF_NUM-1)begin:nor_ck
clk_if ck_vif(.clk(ck[ii]));
end
else begin:nor_ck
clk_if ck_vif(.clk(ex_ck));
end
initial begin
uvm_config_db#(virtual clk_if)::set(uvm_root::get(),$sformatf("uvm_test_top.env.ck_agt[%0d].*",ii),"vif",if_loop[ii].nor_ck.ck_vif);
end
end
endgenerate
注意上面引用ck_vif的hierarchy,要加上if_loop[ii].nor_ck ! ! !
stream_if strm_vif[`STM_NUM](.clk(por_ck));
initial begin
force strm_vif[2].clk = 0;
end
上述代码原本期望的结果是只有strm_vif[2].clk被force成0,而实际 产生的结果是所有的strm_vif的clk全部force成了0;
建议声明interface array时 传入的参数也要是array ,上述可结合最上面的例子。
generate
for(genvar ii=0;ii<`STM_NUM;ii++)begin:if_loop
stream_if strm_vif (.clk(por_ck[ii]));
end
endgenerate
for(genvar ii=0;ii<`STM_NUM;ii++)begin
initial begin
force if_loop[ii].strm_vif.clk = 0;
end
end
补充下generate相关知识:
- All unnamed generate blocks will be given the name “genblk< n >”
- generate 块如果不显式声明 label name,系统提供default name “genblk< n >”,比如genblk1,genblk2…
- Each generate construct is assigned its number as described in the previous paragraph even if it does not contain any unnamed generate blocks.
- generate 块如果显式声明 label name,系统仍然会为其产生一个name:genblk< n >.
- If such a name would conflict with an explicitly declared name,then leading zeros are added in front of the number until the name does not conflict.
- 如果系统产生的名字和现存变量冲突,系统会在原来name前面加0,知道不冲突为止。比如,user已经定义变量genblk1,系统则会把需要给第一个块产生name就为genblk01.
module top;
parameter genblk2 = 0;
genvar i;
// The following generate block is implicitly named genblk1
if (genblk2) logic a; // top.genblk1.a
else logic b; // top.genblk1.b
// The following generate block is implicitly named genblk02
// as genblk2 is already a declared identifier
if (genblk2) logic a; // top.genblk02.a
else logic b; // top.genblk02.b
// The following generate block would have been named genblk3
// but is explicitly named g1
for (i = 0; i < 1; i = i + 1) begin : g1 // block name
// The following generate block is implicitly named genblk1
// as the first nested scope inside g1
if (1) logic a; // top.g1[0].genblk1.a
end
// The following generate block is implicitly named genblk4 since
// it belongs to the fourth generate construct in scope "top".
// The previous generate block would have been
// named genblk3 if it had not been explicitly named g1
for (i = 0; i < 1; i = i + 1)
// The following generate block is implicitly named genblk1
// as the first nested generate block in genblk4
if (1) logic a; // top.genblk4[0].genblk1.a
// The following generate block is implicitly named genblk5
if (1) logic a; // top.genblk5.a
endmodule
module top;
typedef enum {
AMBA_BUS1,
AMBA_BUS2,
AMBA_BUS_QUANTITY
} amba_bus_t;
const amba_bus_t amba_bus_first;
amba_interface i_amba_interface[AMBA_BUS_QUANTITY]();
for (genvar i = 0; i < AMBA_BUS_QUANTITY; i++) begin
initial begin
automatic amba_bus_t local_label = amba_bus_first.next(i);
uvm_config_db#(virtual amba_interface)::set(uvm_root::get(), "uvm_test_top", local_label.name(), top.i_amba_interface[i]);
end
end
endmodule : top