提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
一、内建数据类型
相应于verilog将变量类型(如reg)和线网类型(如wire)区分得如此清楚,在SV中新引入了一个数据类型logic。它们的区别和联系在于:
-
Verliog作为硬件描述语言,倾向于认为设计人员自身懂得所描述的电路中哪些变量应被实现为寄存器,哪些变量应被实现为线网类型。这不但有利于后端综合工具,更便于阅读和理解。
-
SV作为侧重于验证的语言,并不十分关心logic类型对应的逻辑应被综合为寄存器还是综合为线网,因为如果logic类型被使用的场景是验证环境,那么他只是作为单纯的变量进行赋值操作,而这些变量只属于软件环境构建。
-
推出logic类型的另一个原因是方便验证人员驱动和连接硬件模块而省去考虑使用reg还是wire的精力。这既节省时间,也避免了出错的可能。
与logic类型对应的数据类型是bit类型,它们均可用来构建矢量类型,区别在于: -
logic为四值逻辑,即可以表示0、1、x、z
-
bit为二值逻辑,只可表示0和1
SV为什么在已有四值逻辑的基础上再引入二值逻辑呢?这是因为,SV在一开始设计时就期待将硬件和软件的世界分离开。在这里,硬件的世界指的就是硬件设计,所以四值逻辑属于这个世界;而软件的世界即验证环境,这里更多的是二值逻辑。所以,有了二值逻辑,验证环境在进行数据运算时不但能提高效率,还能省去其他不必要思考的问题。在这里,我们将四值逻辑的类型和二值逻辑的类型分离列出来:
-
四值逻辑类型:integer、reg 、logic 、net_type(如wire、tri)
-
二值逻辑:byte、shortint、int、longint、bit
如果按照有符号和无符号的划分,那么可以将常见的变量类型划分为:
有符号类型:byte、shortint、int、longint、interer
无符号类型:bit、logic、reg、net_type(如wire、tri)
遇到这些变量类型时,要注意它们的逻辑类型和符号类型。在变量 运算中,应尽量避免对两种不一致的变量进行操作而导致意外的错误。比如,从下面的例子中可以看到有符号变量和无符号变量混用的运算结果会出乎意料:
我们这里分析一下:
- 开始时,signed_vec被赋值为8‘h1000_0000,表达为有符号十进制数值为-128。
- 在开始第一次赋值操作时result_vec=signed_vec,右侧有符号数值-128被赋值到左侧,并且需要从8位扩展为9位,保证有符号数值不变的情况下,首先需要将8’h80扩展为9‘h180(均为-128),进而再赋值到左侧。
- 在第二次赋值操作时,我们首先进行了类型转换操作result_vec=unsigned`(signed_vec),result_vec同signed_vec就比特位的数值没有发生变化,但是实际表达的十进制数值则从-128被赋值为128。
通过上面的例子我们发现,编码时一定要注意操作符左右两侧的符号类型是否一致,如果不一致,要将其转化为同一类型再进行运算。
对于转换方式,我们在上面展示了一种转换方式——静态转换,即在转换的表达式前加上单引号即可,而该方式并不对转换值做检查。如果发生转换失败,我们无从得知,所以与之对应的动态转化$cast(tgt,src)也经常运用到转换操作中。静态转换和动态转换均需要操作符合或者介入系统函数,统称为显示转换。
不需要进行转换的一些操作我们称之为隐式转换。
- 被转换的变量为四值逻辑变量,而被赋值的变量为二值逻辑变量,且位宽不同。
- 在隐式转换中,x_vec[2:0]被保留下来,x_vec[3]则被丢弃,x_vec[0]的值x在转换中被转换为0,即b_vec=’b110
在操作不同的数据类型时,应该注意变量的
- 逻辑变量类型
- 符号类型
- 矢量位宽