1. 强制类型转换
1.1 静态转换(编译时转换)
静态转换有三种,分别是数据类型强制转换、向量宽度强制转换和符号强制转换,格式分别为:
-
数据类型强制转换:’()
7 + int'(2.0 * 3.0); //将(2.0 * 3.0)的结果转换成整型 //然后加7
-
向量宽度强制转换:’()
logic [15:0] a, b, y; y = a + b ** 16'(2); //将文本值2强制转换为16位宽
-
符号强制转换:’()
shortint a, b; int y; y = y - singed'({a, b}); //将拼接结果强制转换成有符号值
静态强制转换是编译时的转换,转换的操作总会运行,而不会检查结果的有效性
下面对数据类型强制转换和向量宽度强制转换做了仿真:
module trans_static_tb;
int i;
logic [2:0] a;
initial begin
i = 1 + int'(1.0 + 2.0); //静态类型转换,
//强制转换成 int类型
a = 3'b100;
end
initial begin
$display ("\n \t the var i is: %0d", i);
$display ("\n \t the array is: %b", 8'(a)); //静态类型转换,
//打印时将为宽拓展至8位
end
endmodule
仿真结果如下:
1.2 动态强制类型转换
系统函数$cast
是动态的,并且在运行时进行带转换数值的检查
动态强制类型转换的格式为:$cast(dest_var, source_var);
,系统函数$cast
有两个变量:目标变量和源变量
下面几种情况会导致无效的强制类型转换:
-
将real类型转换成int类型,而实数太大,没有办法用int来描述
int radius, area; always @(posedge clock) $cast (area, 3.154 * radius ** 2); //强制转换操作符的结果被装换为area类型
-
将一个数值转换成枚举类型,而它不在枚举类型的合法值列表中
typedef enum {s1, s2, s3} state_t; state_t state, next_state; always_latch begin $cast (next_state, state + 1); end
$cast可以作为任务调用也可以作为函数调用,作为任务调用时,如果转换不成功,会报告运行时错误,但作为函数调用时,不会报告运行时错误
系统函数$cast具有返回值,如果转换成功,返回1
;转换失败,返回0
例如:
typedef enum {s1, s2, s3} state_t;
state_t state, next_state;
always_comb begin
status = $cast(next_state, state + 1);
if(status == 0) //如果强制转换不成功
next_state = s1;
end
$cast函数不能和直接修改源表达式的操作符(++, +=)一块用
$cast函数主要用途是将表达式的结果赋给枚举类型变量
静态强制转换是可综合的,动态强制转换由于一些综合工具可能不支持$cast系统函数
系统函数和系统任务都是不可综合的
下面这个例子,将0.25*8
动态装换成int
类型,并通过系统函数$cast
判断转换是否成功
module trans_auto_tb;
bit a;
int value;
initial begin
a = $cast(value, 0.25 * 8); //将0.25*8的值转换成int类型
//若转换成功,a为1,否则a为0
end
initial begin
$display ("\n \t a is: %b", a);
$display ("\n \t value is: %d", value);
end
endmodule
仿真结果如下:
2. 常数
2.1 Verilog中的常数
Verilog提供了三种常数类型parameter
、specparam
和localparam
- parameter:可以在确立时使用
defparam
或者内嵌参数重定义进行重新定义的常数 - specparam:可以在确立时从SDF文件中重定义的常数
- localparam:确立期常数,不能重定义,但其价值可以基于其他常数
确立实质上是软件工具建立模块实例代表的设计层次的过程
Verilog限制parameter
、specparam
和localparam
常数的声明只能在模块、静态任务和静态函数中,不允许在动态任务和动态函数中
2.2 SV中的常数
关键字const
允许将任何变量声明为常数,const形式的常数直到确立完成后才被赋值
const常数的使用范围:
- 在动态任务和函数等动态环境中声明
- 被赋予一个线网或变量值而非常数表达式
- 被赋予一个对象值,这个值可以在任何设计层次定义
const常数的声明必须包含数据类型,例如:
const logic [23:0] C1 = 7; //24位常数const int C2 = 15; //32位常数const real C3 = 3.14; //实数常数const C4 = 5; //错误,因为没有给定数据类型
const常数实质上是一个只能被初始化的变量