package相当于一个功能包,里面包括了很多组件,有结构体,函数,接口等等。使用的时候使用import packagename::*;
即可。其中::表示解析符,把这个包的内容解析过来。
在大型设计中经常会用,在一个包中定义好很多结构体,接口等等。这样使用的时候直接Import进来即可。减少了重复冗余的代码,并且更容易维护。(对于初学者这些其实都不用掌握,只有大型设计才会用到!)
二维数组。声明方式和Verilog的二维数组不太一样。并且该二维数组可以一次性操作整个数组,减少了代码数量。具体例子可以看下图。
我们可以看到直接输入一个结构体,对结构体进行操作,非常方便。
Interface这个概念非常重要,它能够大幅减少我们的代码量。不知道大家有没有很辛苦的写大量的input、output。非常的麻烦,interface完美的解决了这个问题。我们可以将多组信号封装在一个Interface当中,这样我们就不用再写那么多那么多的input、output了。实际设计中我们还需要通过modport指定master和slave来确定具体各个信号是输入还是输出。
第一部分介绍了declare相关的优化,接下来介绍programming(硬件建模)相关的优化。
我们使用三个不同的always来替代之前的always块。这样可以更好的说明我们的意图,软件也可以更好的验证功能模块是否符合预期。传统的Verilog需要猜(推理)这段always块会生成什么逻辑。而SV显式指定以后,编译器会去验证这段代码是否会生成你想生成的逻辑,如果不是会直接报错。避免了意料之外的设计。
使用case()inside去替代casex和casez。很多时候我们是不在乎那个bit是什么,但是这样就会潜在的无法检查X态。而使用case()inside。我们不在乎他的值,但是它如果是X态或者高阻态,会揭示出来。这样避免了X态无法揭露的问题。
使用uniqe说明只会同时满足其中的某一个,如果满足多个或者一个都不满足会直接报warning。更详细的可以看下这篇文章:胖胖龙:SV中priority case 和unique case的区别
新增了一些运算符。这里掌握++ -- +=
这些就可以了
增加了强制类型转换操作。如果做过LINT就知道这些操作很有用。比如图中所示的将两个a拼接右移b赋给a。右边是64bit,左边是32比特,实际上是不匹配的。但是可以用强制转换进行匹配,以消除warning。
使用.*自动连接同名的信号。该设计是简化大家的设计,但是大家要注意连接是否符合自己的预期,这个地方由于不小心导致的错误还是挺多的。
Verilog中我们想给一个信号赋全1需要写很多的1或者F。但是SV中只需要写'1就可以表示全1,非常的方便。(注意,1代表只有最低比特是1,'1代表所有的bit都是1)。
使用`begin_keywords
告诉编译器,使用哪个年代的关键词(因为SV和Verilog关键词不完全一样)。通过这种方式提高可复用性。
然后是关于function和task的优化,这里需要大家看上面附上的那个paper链接文档。
剩下几页是讲综合工具的支持,也是讲了个大概,需要大家重点看paper链接文档。我这里不详细介绍了。
最后两页做了个总结。