#systemverilog# 关键字之 package 常见用法

本文详细介绍了SystemVerilog的package概念,包括其作为作用域的特性,用于组织和避免命名冲突。讨论了包的用途,如组织相关声明、控制访问权限。还探讨了如何引用包中的数据,如直接使用范围解析操作符、导入特定子项以及使用通配符。通过实例展示了在实际使用中的注意事项,如不能在package中include接口或另一个package,import的使用规则以及include和import的区别。
摘要由CSDN通过智能技术生成

Package 包的概念

SystemVerilog包提供了一种额外的机制,用于在多个SystemVerilog模块module、接口interface、程序program和检查器checker之间共享参数、数据、任务、函数、序列、属性和检查器等声明。
包是一种显式命名的作用域,出现在源文本的最外层(与顶级模块和原语处于同一级别),其实package里包的就是一些数据,而像interface,module是不能定义在package中的,不仅不能定义,甚至不能在package 中去include my_interface.sv、include my_module.sv。

Package 包的作用

1、把功能相似或相关的类或接口组织在同一个包中,方便类的查找和使用。
2、如同文件夹一样,包也采用了树形目录的存储方式。同一个包中的类名字是不同的,不同的包中的类的名字是可以相同的,当同时调用两个不同包中相同类名的类时,应该加上包名加以区别。因此,包可以避免名字冲突。
3、包也限定了访问权限,拥有包访问权限的类才能访问某个包中的类。由于包创建了新的命名空间(namespace),所以不会跟其他包中的任何名字产生命名冲突。使用包这种机制,更容易实现访问控制,并且让定位相关类更加简单。

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

经验总结

 1)在package里include 一个interface.sv文件,出错如下,所以在package里不能include 一个interface;

2)在package里直接import另一个package是找不到的,即使在前面已经include了这个package

3)package里`include另外一个package,是不允许的,编译报错。

4)include和import的区别

   include 是把所有的文本内容原样插入到代码中;

   import 不会把文本内容插入,其作用是把package的内容引入import 语句所在的作用域。

5)  package中无法include另一个package,那么能否import 另外一个package的内容呢?

   可以的,如果需要在a.pkg中import b.pkg,需要在include a.pkg之前include b.pkg,如下:

      `include b.pkg

      `include a.pkg

     否则,会出现找不到package的情况。

 6)如何在一个package 中import 另一个package?

     如果在package a_pkg中import了package b_pkg::type_b,那么在module1中import a_pkg::*时,无法引用到type_b。因为a_pkg只是使得b_pkg::type_b在a_pkg域中可见并加以使用,并未定义在a_pkg中。所以,用户需要牢记一点的是,import操作使得类型可见的域只是调用该import时当前的域。例如下面的例子中,a_pkg中可见b_pkg::b_mon,但是module1则无法可见a_pkg::b_mon

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值