Verilog系列:package多层导入

前面已经了解了package是如何导入到其他结构(module\interface\program)("Verilog系列:package封装成员"),除此之外,package也可以导入到其他的package,然后再通过其他的package导入到其他的结构中.可能会有人文为什么要这样做?对于一个巨大的项目,很有可能出现不同的设计人员,他们使用各自定义的package,当最后要将整个设计进行整合时就需要整合这些package,为此,SystemVerilog提供了package之间相互导入的功能,本文将以示例说明.


【示例】将一个package导入到另一个package
`timescale 1 ns / 1 ps
package p1;
    typedef enum {FALSE,TRUE} bool_t;
    bool_t b = FALSE;
    bool_t c = TRUE;
    int    d = 3;
    int    e = 4;
endpackage    // p1

package p2;
    import p1::*;
    int c =d;
endpackage    // p2

module top_tb;
import p2::*;
logic [31:0] tmp1,tmp2;
initial begin
    tmp1 = c;
    // tmp2 = d; // illegal
    $display("tmp1 is %h",tmp1); 
end
endmodule
【仿真结果】
# tmp1 is 00000003

11行通过p1::*使p1中的成员在p2中可见,p2中声明c同时使用p1中的d对其进行初始化.15行开始的module中通过p2::*,使其中的成员在module中可见,但是此时需要注意,虽然p1中的成员在p2中可见,但是其在module中并不可见.例如示例中的d,module中并不可见,所以直接将d赋给tmp2会报找不到d的错误.也就是说一个package中的成员import到另一个package中后,其中的成员并不会随着另一个package导入到其他结构中.那么如何实现一个package中的成员导入到另一个package后还能够随着另一个package导入到其他架构中呢?请看下例.


【示例】
`timescale 1 ns / 1 ps
package p1;
    typedef enum {FALSE,TRUE} bool_t;
    bool_t b = FALSE;
    bool_t c = TRUE;
    int    d = 3;
    int    e = 4;
endpackage    // p1

package p2;
    import p1::*;
    export p1::*;
    int c = d;
endpackage    // p2

module top_tb;
import p2::*;
logic [31:0] tmp1,tmp2;
initial begin
    tmp1 = c;
    tmp2 = d;
    $display("tmp1 is %h,tmp2 is %h",tmp1,tmp2); 
end
endmodule
【仿真结果】
# tmp1 is 00000003,tmp2 is 00000003

示例中通过在第12行增加p1export声明后,p1中的元素不仅在p2中可见,而且也可以随着p2导入到其他的结构中.但是这里有一点需要注意,采用通配符导入方式仅仅表示只是p1中的内容在p2中可见,具体p1中哪个成员导入到p2中取决于p2中使用了p1中的哪个成员.如下例.


【示例】
`timescale 1 ns / 1 ps
package p1;
    typedef enum {FALSE,TRUE} bool_t;
    bool_t b = FALSE;
    bool_t c = TRUE;
    int    d = 3;
    int    e = 4;
endpackage    // p1

package p2;
    import p1::*;
    export p1::*;
    int c = d;
endpackage    // p2

module top_tb;
import p2::*;
logic [31:0] tmp1,tmp2,tmp3;
initial begin
    tmp1 = c;
    tmp2 = d;
    tmp3 = e; // illegal!
    $display("tmp1 is %h,tmp2 is %h,tmp3 is %h",tmp1,tmp2,tmp3); 
end
endmodule

【仿真结果】

编译错误!

虽然11行和12行采用了通配符使p1中的元素在p2中可见,但是实际上可以被访问的只有p2中使用的d.那么p2采用通配符模式导入module中时,p2中并没有使用e,所以此时e并不存在于p2中也就对于module不可见.如果在p2中没有对d的引用,那么在moduled也是不可见的.


【示例】
`timescale 1 ns / 1 ps
package p1;
    typedef enum {FALSE,TRUE} bool_t;
    bool_t b = FALSE;
    bool_t c = TRUE;
    int    d = 3;
    int    e = 4;
endpackage    // p1

package p2;
    import p1::d;
    export p1::*;
    int c = d;
    // int f = e; // illegal
endpackage    // p2

module top_tb;
import p2::*;
logic [31:0] tmp1,tmp2;
initial begin
    tmp1 = c;
    tmp2 = d;
    $display("tmp1 is %h,tmp2 is %h",tmp1,tmp2); 
end
endmodule
【仿真结果】
# tmp1 is 00000003,tmp2 is 00000003

11行导入了p1中的d,虽然export使用“export p1::*”的方式试图使p1中所有的成员对外可见,而实际上只有import导入的d对外可见,其他的成员对外并不可见,例如14行编译时就会提示找不到额.

【示例】

`timescale 1 ns / 1 ps
package p1;
    typedef enum {FALSE,TRUE} bool_t;
    bool_t b = FALSE;
    bool_t c = TRUE;
    int    d = 3;
    int    e = 4;
endpackage    // p1

package p2;
    import p1::*;
    export p1::d;
    int c = d;
    int f = e;
endpackage    // p2

module top_tb;
import p2::*;
logic [31:0] tmp1,tmp2,tmp3;
initial begin
    tmp1 = c;
    tmp2 = d;
    // tmp3 = e; // illegal
    tmp3 = f;
    $display("tmp1 is %h,tmp2 is %h,tmp3 is %h",tmp1,tmp2,tmp3); 
end
endmodule
【仿真结果】
# tmp1 is 00000003,tmp2 is 00000003,tmp3 is 00000004

11行使p1中所有成员在p2中可见,所以14行可以访问到p1中的e.

12行允许p2在导出时其中的d对外可见,注意此处并没有显式的说明e对外可见,所以在22行可以访问到p1中的d,但是23行并不能访问到e.

为了更好地总结,这里我们假设p1要导入到p2,然后p2再导入到其他结构中,通过上述几种示例及仿真结果可以总结如下:

场景

说明

package p2;

    import p1::*;

    export p1::*;

endpackage

如果p1中的成员在p2中被访问了,那么该被访问的成员在p2导入到其他结构时对其它结构可见

package p2;

import p1::var_n;

export p1::*;

endpackage

var_np2导入到其他结构时对其它结构可见,p1中的其他成员对于p2可见

package p2;

import p1::*;

export p1::var_n;

endpackage

同上

 可见,import表征了package中哪些成员对外可见,export则表征了哪些成员在当前package导出时可被访问.同时这里还需要注意,export只能在package结构中使用.



全部评论
之前学过verilog,现在都忘的差不多了
点赞 回复 分享
发布于 2022-10-08 17:56 山西

相关推荐

点赞 评论 收藏
分享
点赞 收藏 评论
分享
牛客网
牛客企业服务