包(package)的使用
package声明
SystemVerilog包提供了一种额外的机制,用于在多个SystemVerilog模块、接口、程序和检查器之间共享参数、数据、任务、函数、序列、属性和检查器声明。
包是显式命名的作用域,出现在源文本的最外层(与顶级模块和原语处于同一级别)。
其中,我们可以理解,其实package里包的就是一些数据的。像interface,module是不能定义在package中的。
包的作用
1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。由于包创建了新的命名空间(namespace),所以不会跟其他包中的任何名字产生命名冲突。使用包这种机制,更容易实现访问控制,并且让定位相关类更加简单。
补充:感觉System Verilog语言会将小的模块进行拆分,归类,每次创建一个执行一个任务数据包。这个包的大小会不同。但是感觉都是拆分的思想。
在package中引用数据
1)用范围解析操作符::
直接引用;
2)将包中特定子项导入到模块或接口中,用import
导入;
3)用通配符*
导入包中的子项到模块或接口中;
注意这里导入后函数就是直接使用的,变量需要使用句柄加.的形式
定义一个包
实例:
package definitions; //定义一个包
parameter VERSION = "1.1"; //定义包中一个参数
typedef enum{ADD, SUB, MUL} opcodes_t; //定义包中枚举opcodes_t
typedef struct {
logic [31:0] a, b;
opcodes_t opcode; //声明自定义类型变量
} instruction_t; //定义包中结构体instruction_t
function automatic [31:0] multiplier (input [31:0] a, b); //定义函数function,其中参数为a,b
return a * b; // 用户定义的function代码从这开始
endfunction //function定义结束
endpackage //包定义结束
使用范围解析操作符::直接引用
module ALU(
input definitions::instruction_t IW, //用范围解析操作符::引用definitions包中的instruction_t结构体,并对其命名为IW
input logic clock,
output logic [31:0] result
);
always_ff @(posedge clock) begin
case (IW.opcode)
definitions::ADD : result = IW.a + IW.b; //用范围解析操作符::引用definitions包中的枚举ADD
definitions::SUB : result = IW.a - IW.b;
definitions::MUL : result = definitions::
multiplier(IW.a, IW.b);
endcase
end
endmodule
导入package中的子项import
module ALU(
input definitions::instruction_t IW,
input logic clock,
output logic [31:0] result
);
import definitions::ADD; //用import导入definitions包中的枚举ADD
import definitions::SUB;
import definitions::MUL;
import definitions::multiplier;
always_comb begin
case (IW.opcode)
ADD : result = IW.a + IW.b; //前面导入包中特定子项后,该子项在模块/接口中可见,可直接使用
SUB : result = IW.a - IW.b;
MUL : result = multiplier(IW.a, IW.b);
endcase
end
endmodule
使用通配符*导入所有的定义名称import
module ALU(
input definitions::instruction_t IW,
input logic clock,
output logic [31:0] result
);
import definitions::*; // 通配符导入。实际上是将包添加到标识符搜索路径中
always_comb begin
case (IW.opcode)
ADD : result = IW.a + IW.b; //引用ADD时,在definitions包中查找该名称的定义
SUB : result = IW.a - IW.b;
MUL : result = multiplier(IW.a, IW.b);
endcase
end
endmodule