变量初始化的确定性

变量初始化的确定性

SystemVerilog初始化顺序
SystemVerilog标准增强了变量的内嵌初始化。SystemVerilog规定所有内嵌初始化先于仿真时刻0执行的事件。这就保证了如果Initial或者always过程块读取具有内嵌初始值的变量时取得正确的初始值,这个确定行为消除了Verilog标准中的不确定性。

注意:SystemVerilog变量内嵌初始化不引发仿真事件。

使用增强的SystemVerilog进行的仿真结果完全包含在允许的、但不确定的使用Verilog进行的仿真结果中,

logic resetN = 0; //声明并初始化reset
always@(posedge clock ,negedge resetN)
	if(!resetN) count <= 0; //reset低电平有效
	else count <= count + 1;

SystemVerilog中是仿真器在激活always过程块之前,先进行resetN的初始化。此后,仍然在0仿真时刻,当always块被激活后,它会等待下一个时钟上升沿或resetN下降沿。因为resetN的初始化已经发生了,计数器在0时刻不会被触发,而是等待下一个时钟上升沿或者resetN下降沿。

时序逻辑的异步输入初始化

--在仿真时刻0,使用两态数据类型施加复位
module counter (
		input wire clock,resetN,
		output logic[15:0] count
);
always@(posedge clock,negedge resetN)
	if(!resetN) count <= 0; //reset低电平有效
	else count <= count + 1;
endmodule

module test;
wire [15:0] count;
bit clock;
bit resetN = 1;//resetN初始化无效值
counter dut(clock,resetN,count);
always #10 clock = ~clock;
initial begin
	resetN = 0;//在0时刻插入低电平有效的复位
	#2 resetN = 1; //在clock上升沿之前去除复位
	$display("\n count = %0d(expect 0)\n",count);
	#1 $finish;
end
endmodule

在上面的例子中,计数器有一个异步的复位输入。这个复位低电平有效,也就是在resetN跳变为0时,计数器会被复位。为了在仿真时刻0时对计数器进行复位,resetN输入必须跳变为逻辑0。如果resetN被声明为一个两态的数据类型,例如bit。如上面的测试平台例子,其缺省初始值是逻辑0。测试平台中的第一个测试是通过将resetN置为0来插入复位。第一个测试不会引发对resetN的仿真事件,因此counter模块的敏感列表不会因resetN的变化而触发过程块对counter复位。
为保证resetN置为0时resetN发生变化,resetN的带内嵌初始化声明为逻辑1–复位无效状态

bit resetN = 1;//resetN初始化无效值
提示:测试平台应该将变量初始化为无效 状态

SystemVerilog内嵌变量初始化的确定性可以保证0仿真时刻事件的发生顺序。如果变量使用内嵌初始化设成无效状态,然后使用initial或者always过程块置为有效状态,SystemVerilog就保证了内嵌初始化先发生,然后才进行过程块初始化赋值。

强制类型装换
SystemVerilog加入强制数据类型转换的能力。强制类型转换不同于在赋值时转变为数值。使用强制类型转换,不用赋值,在一个表达式内,一个数值就可以转换成一个新的类型。
(1)静态转换(编译时转换)

--数据类型强制转换
<type>'(<expression>) --将一个值强制转换成任意数据类型,包括用户自定义类型
7+int'(2.0 * 3.0)  //将(2.0*3.0)的结果转换为整型,然后加7

--向量宽度强制转换
<size>'(<expression>)  --将一个值强制转换成任意向量宽度
logic[15:0] a,b,y;
y = a + b**16'(2); //将文本值2强制转换为16位宽

--符号强制转换
<sign>'(<expression>)  --将一个值强制转换成有符号或无符号
shortint a,b;
int y;
y = y - signed'({a,b}); //将拼接结果强制转换为有符号值

静态强制转换和错误检测
静态强制转换操作符是一种编译时的转换。要强制转换的表达式在运行时总会被转换,而不会检查要转换的表达式是否在要转换成的类型的合法范围内。因此,必须注意不能将非法值赋给变量。

typedef enum{s1,s2,s3} states_t;
states_t state,next_state;
always_comb
begin
	if(state != s3)
		next_state = states_t'(state+1);
	else
		next_state = s1;
end

(2)动态强制类型转换
上面描述的SystemVerilog强制类型转换是一种编译时转换,转换操作总会运行,而不会检测结果的有效性。如果需要进一步的检验,SystemVerilog提供一个新的系统函数$cast,这是动态的,在运行时进行待转换数值的检查。
系统函数 $cast有两个变量,一个目标函数和一个源变量

$cast(dest_var,source_exp);

int radius,area;
always@(posedge clock)
	$cast(area,3.154*radius**2);
	//强制转换操作符的结果被转换为area类型

$cast试图将源表达式赋给目标变量。如果赋值是无效的,将会报告一个运行时错误,并且目标变量保持不变。
将real类型转换成int类型,而实数太大,没有办法用int来描述
将一个数值转换成枚举类型,而它不在枚举类型的合法值列表中

typedef enum{s1,s2,s3} states_t;
states_t state,next_state;
always_latch 
begin
	$cast(next_state,state+1);
end

$cast也可作为任务被调用
$cast可以作为系统函数调用,它会返回一个状态标志来显示强制类型转换成功与否。如果转换成功, $cast返回1,;如果不成功, $cast函数返回0,并且不改变目标变量。作为函数调用时,不报告运行时错误。

typedef enum{s1,s2,s3} states_t;
states_t state,next_state;
int status;
always_latch 
begin
	status = $cast(next_state,state+1);
	if(status == 0)  //如果强制转换不成功
		next_state = s1;
end
注意:$cast函数不能和直接修改源表达式的操作符,如++或+=一块使用
$cast(next_state,++state);

$cast的主要用途是将表达式的结果赋给枚举类型变量
使用编译时强制类型转换符用于综合

静态的编译时强制转换操作是可综合的。综合工具可能不支持动态的$cast系统函数。一般情况下,系统任务和系统函数不是一种可综合的结构。用于综合的更好的编码方式是使用静态强制转换操作符进行强制类型转换。

常数

parameter是一个可用确立(elaboration)时使用defparam或者内嵌参数重定义进行重新定义的常数。
specparam是一个可以在确立时从SDF文件中重定义的常数。
localparam是确立期常数,不能重定义。但是它的值可以基于其他常数。

常数负层次引用值不合法
常数不允许在自动任务和函数中
SystemVerilog加入了将任何变量声明为常数的能力–使用const关键字。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可以用在自动任务和函数中。
一个const常数实质是一个只能被初始化的变量。因为const形式的常数是在运行期间确定数值而不是确立期。一个const常数可以在自动任务和函数中声明,也可以在模块、静态任务和函数中声明。在begin…end块和fork…join块中声明的变量也可以声明为一个常数变量。

task automatic c;
	const int N = 5; //N是一个常数
	...
endtask
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

傻童:CPU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值