1.1. 用户自定义类型(typedef)
局部typedef定义:只用于设计的特定部分时,typedef的定义可在module或interface中
共享typedef定义:当在多个模型中使用时,typedef的定义可在包中进行,module,interface,program block可以通过导入packet子项来使用typedef定义
例如:
package chip_types;
`ifdef TWO_STATE
typedef bit dtype_t; //当宏定义TWO_STATE时定义dtype_t为bit类型
`else
typedef logic dtype_t;
`endif
endpackage
import chip_types::dtype_t; // import 定义 into $unit
module counter(
output dtype_t [15:0] count,
input dtype_t clock, resetN
);
...
endmodule
//------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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
1.2. 枚举数据类型(enum)
使用枚举enum:
package chip_types;
typedef enum {
FETCH, WRITE, ADD,
SUB,MULT, DIV, SHIFT, NOP
} instr_t;
//用户自定义枚举类型instr_t
endpackage
import chip_types::*; //import包定义到$unit编译单元域
module controller (input instr_t instruction,...); //input instr_t类型instruction
enum {WAITE, LOAD, STORE} State, NextState; //枚举类型State, NextState,
//他俩的值只能是{}中的label
always_comb begin
if(State == LOAD && instruction == FETCH) //使用label
...
end
endmodule
从包中导入enum时,一般用*导入整个包或者显式导入每个标签。
1.3. 枚举类型标签序列
state //创建单个标签state
state[N] // 创建标签序列 state0,state1, … stateN-1
state[N:M] //创建标签序列,由stateN开始,到stateM(正反向不存在)
1.4. 枚举类型标签作用域
-
enum列表中的label在其作用域内必须是唯一的(label唯一)
-
这里的作用域包括:$unit, modules, interfaces, programs,begin…end blocks, fork…join blocks, tasks and functions
1.5. 枚举类型值
枚举类型值在没有显示指定时,默认int从0自加。且label的值也要唯一(value唯一)
Example:
enum {A=1, B, C, X=24, Y, Z} list; //A=1,B=2,C=3,X=24,Y=25,Z=26
1.6. 枚举类型的基类
枚举类型的默认基类(base type)是int,也可以对枚举类型的基类进行显示声明
Eg:
enum logic [1:0] {WAITE, LOAD, READY} state; //2位宽的枚举类型,四态基类
注意label数涉及到value的值,要与基类类型匹配。
1.7. 自定义枚举类型
typedef enum {WAITE, LOAD, READY} states_t; //自定义枚举类型states_t
states_t state, next_state; //声明枚举state,next_state
同类型枚举变量可以互相赋值
1.7. 枚举类型的专用系统任务(system tasks)和方法(method)
方法(method):SV提供了一些能自动处理enum的内置函数,调用方式(类似C++):
<enum_variable_name>.first:返回指定变量枚举列表的第一个成员的值
<enum_variable_name>.last:返回指定变量枚举列表的最后一个成员的值
<enum_variable_name>.next():从枚举变量的当前位置算起,返回后面第N个 成员的值。如果枚举变量当前值不在枚举变量列表中,则返回列表中第一 个成员的value。可缺省。缺省时返回枚举列表中下一个成员的值。
<enum_variable_name>.prev():从枚举变量的当前位置算起,返回前面第N个 成员的值。如果枚举变量当前值不在枚举变量列表中,则返回列表中最后 一个成员的value。可缺省。缺省时返回枚举列表中前一个成员的值。
<enum_variable_name>.num:返回变量的枚举列表中元素个数
<enum_variable_name>.name:返回枚举变量中代表这个value的字符串
module和interface可以用四种方式引用包中的定义和声明:
1. 用范围解析操作符” :: ”直接引用
2. 将包中特定子项导入(import)到module or interface中
3. 将通配符(*)导入包中的子项到module or interface
4. 将包中子项导入(通过import且可使用*)到$unit声明域中(module外)
编译单元声明(不可综合):
只作用于同时编译的源文件(每次编译为一个单元,多次编译之间互不影响)
SV允许在package, module, interface , program block 的外部进行声明。
这些外部声明在“编译单元域”(compilation-unit scope)中,并且对所有同时编译的module可见
编译单元contain:
- 时间单元和精度声明
- Variable declarations
- Net declarations
- Constant declarations
- User-defined data types, using typedef, enum or class
- Task and function definitions
可在$unit中声明的可综合结构有:
- typedef用户定义类型定义(最好放在package内)
- Automatic functions
- Automatic tasks
- parameter and localparam constants
- package import
建议:
1.枚举类型声明不要在
u
n
i
t
空
间
进
行
声
明
,
声
明
在
命
名
包
中
进
行
2.
可
将
包
i
m
p
o
r
t
到
unit空间进行声明,声明在命名包中进行 2.可将包import到
unit空间进行声明,声明在命名包中进行2.可将包import到unit
3.import语句要出现在package中子项被引用前