- 2.1 包 Package
- 2.1.1 Package的定义
- 2.1.2 Package的引用
- 2.1.3 synthesis指导
- 2.2 $unit 编译单元声明
- 2.2.1 编码建议
- 2.2.2 SystemVerilog标识符搜索优先级
- 2.2.3 源代码顺序
- 2.2.4 将package导入$unit的编码原则
- 2.2.5 综合指导
- 2.3 未命名语句块中的声明
- 2.4 仿真时间和精度
- 拓展了Verilog的声明空间
- 增强了定义仿真时间单位的能力
Verilog要求局部声明,但是SystemVerilog中的typedef的用户类型希望在多个模块使用。
2.1.1 Package的定义功能:主要是为了使多个模块共享 typedef 定义的用户类型。 格式:
package PACKAGE_NAME
//可综合的结构
//1 parameter、localparam
//2 const
//3 typedef
//4 task function
//5 import
//6 操作符定义重载
//不可综合的结构
//全局变量声明、静态task、静态function
endpackage
按照上面的格式定义一个名为definitions的package:
//example_2_3
package definitions;
typedef enum { ADD, SUB, MUL } opcodes_t;
typedef struct {
logic [31:0] a, b;
opcodes_t opcode;
} instruction_t;
function automatic [31:0] multiplier (input [31:0] a,b);
return a * b;
endfunction
endpackage
注意:package中的parameter不能重新定义。因为它不是模块实例的一部分。
2.1.2 Package的引用方法:以引用example_2_3中的package definitions为例。
- 作用域解析操作符“::”直接引用
module ALU (
input definitions::instruction_t I_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::SUB : result = IW.a - IW.b;
definitions::MUL : result = definitions::multiplier(IW.a, IW.b);
default: ;
endcase
end
endmodule
- 将特定子项导入
module ALU (
input definitions::instruction_t I_IW,
input logic clock,
output logic [31:0] result
);
import definitions::ADD;
import definitions::SUB;
import definitions::MUL;
import definitions::multiplier;
always_ff @( posedge clock )
begin
case (IW.opcode)
ADD : result = IW.a + IW.b;
SUB : result = IW.a - IW.b;
MUL : result = definitions::multiplier(IW.a, IW.b);
default: ;
endcase
end
endmodule
注意:只导入枚举类型的定义(opcodes_t)并不会导入该定义使用的元素(ADD、SUB与MUL)。
- 用通配符将特定子项导入
module ALU (
input definitions::instruction_t I_IW,
input logic clock,
output logic [31:0] result
);
import definitions::*;
always_ff @( posedge clock )
begin
case (IW.opcode)
ADD : result = IW.a + IW.b;
SUB : result = IW.a - IW.b;
MUL : result = definitions::multiplier(IW.a, IW.b);
default: ;
endcase
end
endmodule
注意:使用通配符(*)时,只有实际使用的子项(ADD、SUB与MUL)才会被真正导入。
- 将子项导入$unit声明域中
- 为了能够综合,包中定义的task和function必须声明为 automatic ,并且不能包好static变量。
- 综合不支持包中的变量声明。 说明:自动任务和函数每次调用时才会分配独立的副本,其他如变量等则为所有模块共享,这种不通过端口传递数据的模块间通信是不可综合的。
编译单元(unit):同时编译的所有文件。 编译单元域($unit 域):编译单元在package、module、接口和程序块的外部的声明域。 编译单元域可以包含:
- 时间单位和精度声明
- 变量声明
- net声明
- 常量声明
- 用户定义类型数据声明
- 任务和函数定义 注意:$unit域的声明不是全局的。全局声明无论源文件单独还是同时编译,都会被所有模块共享;$unit域的声明只作用于同时编译的源文件.
- 不要再$unit中进行任何声明,而应在package内。
- 必要时可以将package导入到$unit中。
- Verilog标准定义的局部声明。
- 通配符导入的包中的声明。
- $unit中的声明。
- 设计层次中的声明。
注意:数据标识符和类型标识符必须在引用前声明,否则为声明的标识符将被隐式声明为net类型(通常为wire)。
2.2.4 将package导入$unit的编码原则可在模块声明之前将包导入到$unit域中,比如“2.1.2 Package的引用”中import语句位置换到module外。 注意:
- 按照搜索优先级,import语句必须出现在包中子项被引用之前。
- 多个文件同时编译只有一个 u n i t 域 , 多 个 文 件 单 独 编 译 有 多 个 不 同 的 unit域,多个文件单独编译有多个不同的 unit域,多个文件单独编译有多个不同的unit域,导入的包对其他$unit域不可见。
- 将同样的包导入同一$unit域是非法,在包中利用条件编译避免重复导入。包文件用`include编译命令间接传递。
`ifndef DFFS_DONE
`define DFFS_DONE
package definitions;
typedef enum { ADD, SUB, MUL } opcodes_t;
typedef struct {
logic [31:0] a, b;
opcodes_t opcode;
} instruction_t;
function automatic [31:0] multiplier (input [31:0] a,b);
return a * b;
endfunction
endpackage
import definitions::*;
`endif
design file:xxx.v
`include "definitions.pkg"
注意:包中的变量被所有导入变量的设计块或测试块共享。包中的变量、静态任务和函数都不可综合。
2.2.5 综合指导编译单元域中声明的可综合结构:
- typedef用户定义类型
- automatic function
- automatic task
- parameter、localparam常量
- package导入 注意:最好不要在$unit声明任务、函数和参数,当分开编译时,这些内容对模块不可见。 说明:自动任务和函数的存储区再每次调用时才会实际分配,存储区独立才能保证综合前仿真行为和综合后行为相同。
verilog允许在命名的begin…end或fork…join块中声明局部变量,并且可以用包含块名的层次路径引用局部变量。 SystemVerilog还允许在未命名块中声明局部变量,由于没有层次路径,局部变量不能在局部范围以外的任何地方引用。
2.4 仿真时间和精度与verilog一样,在遇到`timescale后,指定的时间单位和精度一直保持有效到下一条`timescale语句。 SystemVerilog可以直接给时间值指定时间单位:
forever #5ns clock = ~clock;
注意:时间值和时间单位之间不允许有空格。 SystemVerilog增加关键字timeunit和timeprecision使时间单位和精度作为模块定义的一部分。
module chip (
...
);
timeunit 1ns;
timeprecision 10ps;
...
endmodule
说明:timeunit和timeprecision可以在$unit声明,但是必须先于其他任何声明。 时间单位和精度搜索优先级:
- 时间值自带的单位。
- 模块、接口和程序块内部指定的时间单位和精度。
- 父级模块或者接口的时间精度和单位。
- 模块编译时有效的`timescale定义的时间单位和精度。
- $unit中定义的时间单位和精度。
- 仿真器默认的时间单位和精度。