SystemVerilog package

SystemVerilog引入了包(package)概念,用于解决Verilog中全局声明的问题。包可以包含参数、typedef、任务和函数等,提供了一种共享定义的方式。通过作用域解析操作符、import语句或通配符导入,可以在不同模块中引用包中的内容。包的导入可以选择性导入特定子项,或者使用通配符导入所有子项,提高了代码复用性和组织性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

SystemVerilog package

在Verilog中,由于不能进行全局声明,因此当一个声明在多个设计块中用到,那么这个声明必须在每个块中进行声明,这样不仅显得冗余,而且如果在其中一个块中对声明进行了更改,却忘记修改其他设计块中出现的该声明,就会导致错误

基于这一点,SystemVerilog增加了包(package)

1. 包的定义

package是为了使多个块共享用户定义类型的定义

package定义在packageendpackage之间

package中可综合的结构有一下几种:

  • parameter和localparam常量定义
  • const常量定义
  • typedef用户定义类型
  • 全自动task和function定义
  • 从其他package中import语句
  • 操作符重载定义

package中可以进行全局变量声明、静态任务定义和静态函数定义

package是一个独立的声明空间,不需要包含在Verilog模块中

下面是一个简单的package定义的例子:

package definitions;
    parameter	version = "1.1";
    
    typedef enum {ADD, SUB, MUL} opcodes_t;

    typedef struct {
        logic	[31:0]	a, b;
        opcodes_t	opcode;	//声明的opcode中包含 ADD, SUB和MUL
    } instruction_t;
    
    function	automatic	[31:0]	multiplier	(input	[31:0]	a, b);
        return a * b;
    endfunction
endpackage 

在Verilog中,parameter常量可以重新定义,localparam常量不能重新定义

在package中,parameter常量和localparam常量均不可重新定义

2. 应用package的内容

引用package的方式有如下四种:

  1. 用范围解析操作符直接引用
  2. 将package中特定子项导入到模块或接口中
  3. 用通配符导入包中的子项到模块或接口中
  4. 将包中子项导入到$unit声明域中

2.1 作用域解析操作符引用package

作用域解析操作符为: :

package名和package中子项名有双冒号 (: 😃 隔开

借用上例中定义的package,用作用域解析操作进行引用:

module	ALU (
	input	definitions: : instruction_t IW, //用IW代表上例中instruction_t
    input	logic	clk,
    output	logic	[31:0]	result
);
    always_ff @ (posedge clk) begin
        case (IW.opcode) //IW即可代表上例中instruction_t
            definitions: :	ADD	:	result = IW.a + IW.b;
            definitions: :	SUB	:	result = IW.a - IW.b;
            definitions: :	MUL	:	result = definitions: :	multiplier(IW.a, IW.b); //调用上例中的function
        endcase
    end
endmodule

2.2 导入package中特定子项

SV允许用import语句将package中特定子项导入到模块中

import语句是package中子项局部可见,导入的package定义或声明就和模块或接口中的一个局部定义名一样

通过导入特定子项的方法,将上例进行简化:

module	ALU (
	input	definitions: : instruction_t IW, //用IW代表上例中instruction_t
    input	logic	clk,
    output	logic	[31:0]	result
);
    import	definitions: : ADD;
    import	definitions: : SUB;
    import	definitions: : MUL;
    import	definitions: : multiplier;
    
    always_ff @ (posedge clk) begin
        case (IW.opcode) //IW即可代表上例中instruction_t
            ADD	:	result = IW.a + IW.b;
            SUB	:	result = IW.a - IW.b;
            MUL	:	result = multiplier(IW.a, IW.b); //调用上例中的function
        endcase
    end
endmodule

导入特定子项时,对于导入枚举类型只会导入枚举类型定义并不会导入那个定义使用的元素

例如import definitions: : opcode_t;,这个导入不会起作用

为了局部引用,每个枚举元素必须显示导入

2.3 通配符导入

通配符为*

通配符可以使package中所有子项都成为可见的,但通配符并不会自动导入整个package,只有实际使用的子项才真正被导入

下面使用通配符将上例简化:

module	ALU (
	input	definitions: : instruction_t IW, //用IW代表上例中instruction_t
    input	logic	clk,
    output	logic	[31:0]	result
);
    import	definitions: : *;	//通配符导入
    
    always_ff @ (posedge clk) begin
        case (IW.opcode) //IW即可代表上例中instruction_t
            ADD	:	result = IW.a + IW.b;
            SUB	:	result = IW.a - IW.b;
            MUL	:	result = multiplier(IW.a, IW.b); //调用上例中的function
        endcase
    end
endmodule

$unit声明域内容较多,单独记录


本文主要摘自《SystemVerilog硬件设计与建模》

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值