15. 强制类型转换
Verilog不能将一个值强制转换成不同的数据类型。SystemVerilog通过使用<type>’操作符提供了数据类型的强制转换功能。这种强制转换可以转换成任意类型,包括用户定义的类型。例如:
int’ (2.0 * 3.0) // 将结果转换为int类型
mytype’ (foo) // 将foo转换为mytype类型
一个值还可以通过在强制转换操作符前指定一个10进制数来转换成不同的向量宽度,例如:
也可以将结果转换成有符号值,例如:
signed’ (x) // 将x转换为有符号值
16. 操作符
Verilog没有C语言的递增(++)和递减(--)操作符。而SystemVerilog加入了几个新的操作符:
l ++和--:递增和递减操作符;
l +=、-=、*=、/=、%=、&=、^=、|=、<<=、>>=、<<<=和>>>=赋值操作符;
17. 唯一性和优先级决定语句
在Verilog中,如果没有遵循严格的编码风格,它的if-else和case语句会在RTL仿真和RTL综合间具有不一致的结果。如果没有正确使用full_case和parallel_case综合指令还会引起一些其它的错误。
SystemVerilog能够显式地指明什么时候一条决定语句的分支是唯一的,或者什么时候需要计算优先级。我们可以在if或case关键字之前使用unique或requires关键字。这些关键字可以向仿真器、综合编译器、以及其它工具指示我们期望的硬件类型。工具使用这些信息来检查if或case语句是否正确建模了期望的逻辑。例如,如果使用unique限定了一个决定语句,那么在不希望的case值出现的时候仿真器就能够发布一个警告信息。
bit [2:0] a;
unique if ((a==0) || (a==1)) y = in1;
else if (a==2) y = in2;
else if (a==4) y = in3; // 值3、5、6、7会引起一个警告
priority if (a[2:1]==0) y = in1; // a是0或1
else if (a[2]==0) y = in2; // a是2或3
else y = in3; // 如果a为其他的值
unique case (a)
0, 1: y = in1;
2: y = in2;
4: y = in3;
endcase // 值3、5、6、7会引起一个警告
priority casez (a)
default : y = in3; //如果a为其他的值
endcase
18. 底部检测的循环
Verilog包含for、while和repeat循环,这几个循环都是在循环的起始处检测循环条件。SystemVerilog加入了一个do-while循环,这种循环在执行语句的结尾处检测循环条件。
19. 跳转语句
在语句的执行过程中,C语言提供了几种方式来跳转到新的语句,包括:return、break、continue和goto。在Verilog中除了通过使用disable语句跳转到语句组的尾部外,没有提供任何其它跳转语句。使用disable语句执行中止和继续功能要求加入块的名字,并且会产生不直观的代码。SystemVerilog加入了C语言的break和continue关键字,这两个关键字不要求使用块名字。另外,SystemVerilog还加入了一个return关键字,它可以用来在任何执行点上退出一个任务或函数。
l break:退出一个循环,与C语言相同;
l continue:跳转到一个循环的尾部,与C语言相同;
l return 表达式:退出一个函数;
l return:退出一个任务或void类型的函数。
SystemVerilog没有包含C语言中的goto语句。
20. 块名字和语句标签
在Verilog中,我们可以通过在begin或fork关键字之后指定名字来为begin-end或fork-jion语句指定名字。这个指定的名字代表整个语句块。SystemVerilog还允许在end或jion关键字之后指定一个匹配的块名字。这种机制很容易将end或jion与对应的begin或fork联系起来,尤其是在一个长的块或嵌套的块中。块结尾处的名字是可选的,但如果使用的话,它必须与块起始处的名字相同。例如:
begin: foo // 在begin之后的块名字
…
fork: bar // 具有名字的嵌套的块
…
jion: bar // 必须具有相同的名字
…
end: foo // 必须具有相同的名字
SystemVerilog还允许像C语言一样为单个语句设置标签。语句标签放置在语句的前面,用来标识这条语句。例如:
initial begin
test1: read_enable = 0;
…
test2: for (i=0; i<=255; i++)
…
end
21. 对事件控制的增强
Verilog使用@标记来控制基于特定事件的执行流,SystemVerilog增强了@事件控制。
l 有条件的事件控制
@标记的一个基本应用就是推断一个具有使能输入的锁存器。下面的例子演示了一个锁存器建模的基本风格。
always @(data or en)
if (en) y <= data;
这种编码风格对仿真来说是效率低下的,因为即使在使能输入无效的时候,数据输入的每次改变都会触发事件控制。
SystemVerilog在事件控制中加入了一个iff条件。只有iff条件为真的条件下,事件控制才会被触发。通过将使能判断移入到事件控制里面,使得只有在锁存器输出能够改变的时候事件控制才会被触发。例如:
always @(a or en iff en==1)
y <= a;
l 事件控制中的表达式
Verilog允许在@事件控制列表中使用表达式,例如:
always @((a * b))
always @(memory[address])
在第一个例子中,是当操作数发生改变的时候还是只有当运算结果发生改变的时候才会触发事件控制?在第二个例子中,是当memory的地址发生变化的时候还是只有当memory的值发生变化的时候才会触发事件控制?当@事件控制中包含表达式的时候,IEEE Verilog标准允许仿真器进行不同的优化。这就可能导致在不同的仿真器间有不同的仿真结果,可能还会导致仿真与综合之间的结果不一致。SystemVerilog加入了一个changed关键字,在事件控制列表中它被用作一个修饰符。@(changed (表达式))能够显式地定义只有当表达式的结果发生改变的时候才会触发事件控制。例如:
always @(changed (a * b))
always @(changed memory[address])
l 事件控制中的赋值
Verilog不允许在事件控制中使用赋值。SystemVerilog允许在事件控制中使用赋值表达式。事件控制仅仅敏感于赋值表达式右侧的变化。例如:
always @(y = a * b)
22. 新的过程
Verilog使用always过程来表示时序逻辑、组合逻辑和锁存逻辑的RTL模型。综合工具和其它软件工具必须根据过程起始处的事件控制列表以及过程内的语句来推断always过程的意图。这种推断会导致仿真结果和综合结果之间的不一致。SystemVerilog增加了三个新的过程来显式地指示逻辑的意图。
l always_ff:表示时序逻辑的过程;
l always_comb:表示组合逻辑的过程;
l always_latch:表示锁存逻辑的过程。
例如:
always_comb @(a or b or sel) begin
if (sel) y = a;
else y = b;
end
软件工具能够检查事件控制敏感列表和过程的内容来保证逻辑的功能匹配过程的类型。例如,工具能够检查一个always_comb过程能够敏感过程内读取的所有外部值,对逻辑的每一个分支的相同变量进行赋值,并且检查分支是否覆盖了所有可能的条件。如果任何一个条件没有满足,软件工具均会报告该过程没有正确建模组合逻辑。