相关文章
Verilog基础专栏https://blog.csdn.net/weixin_45791458/category_12263729.html
整数常量可以由十进制、十六进制、八进制或二进制格式指定。
整数常量有两种表现形式。
第一种表现形式是一个简单的十进制数,应指定为0到9的数字序列,可以选择在前面加上加号(+)或减号(-)一元运算符开头。例如8,12,15,-5,-9,-11等。
第二种表现形式包含了最多三个标记:一个可选的位宽常数、一个跟着基数字符的单引号(这个必须要有,否则只能是第一种形式),以及表示数字值的数字。
第一个标记是位宽常数,根据这个确切的常数指定了整数常数的位宽大小,这个常数的形式应该是非0的无符号十进制数。
第二个标记是格式基数,应由一个不区分大小写的字母组成,该字母指定数字的基数,可选择在其前面加上单个字符s(或S)以表示有符号数,在其前面再加上单引号字符(')。合法的基数指定是d、D、h、H、o、O、b或B,分别表示十进制、十六进制、八进制和二进制的基。注意:字母和单引号之间不能有任何空白,即字母紧跟单引号。
第三个标记是无符号数字,应包含对指定基数合法的数字(例如对于十进制,不能出现a-f的字母),第三个标记和第二个标记的字母间可以添加空格,十六进制使用到的a-f不区分大小写,可能使用到的x和z也不区分大小写。
在第一种表现形式即不使用位宽和基数格式的简单十进制数被认为是有符号整数。
在第二种表现形式中,如果使用s指示符,则第三个标记中的无符号数字被解释为有符号数,否则被解释为无符号数。s不影响第三个标记中数的指定,而只影响其解释。
第二种表现形式的整数常数前面的加号(+)或减号(-)是一元运算符,第二个标记和第三个标记间的一元运算符是不合法的,如2'b-3是不合法的。
在任何一种表现形式中,负数都是以2的补码形式表现的。
在第二种表现形式中,x表示十六进制、八进制和二进制常量中的未知值(不能在十进制中使用,除非第三个标记中只有一个x或z表示所有位都是x或z),而z表示高阻值(它们都仅可出现在第二种表现形式)。x在以十六进制为基的数中设置4位为未知,在八进制中为3位,在二进制中为1位。类似地,z应将4位、3位和1位分别设置为高阻抗值。
在第二种表现形式中,如果第三个标记中的无符号数字的位宽小于位宽常数指定的大小,则无符号数字会在左边填0直到大小吻合(这里并不会因为有s指示符而进行符号拓展),如果无符号数字的最高位是x或z,则会向左填充x或z;如果无符号数字的位宽大于位宽常数指定的大小,则应从左侧截断无符号数。、
当在数字中使用时,问号(?)字符是z字符的Verilog HDL替代。
除第一个字符外,下划线字符(_)在数字中的任何位置都是合法的,下划线字符可以忽略,它只是为了便于阅读,此功能可用于分解长数字。
一个未指定位宽的整数常量(即第一种形式或没有指定位宽的第二种形式)的位宽应至少为32位(和integer相同)。
注意:根据Verilog基础:表达式位宽的确定(位宽拓展)一文中的内容,所有的整数常量都会根据上下文环境位宽拓展至表达式的最大位宽,拓展规则根据RHS的内容(其中包括这个数的符号性)可以是补零拓展或符号拓展(这里的拓展和上面说的无符号数字的位宽小于位宽常数指定的大小而产生的拓展不一样,这个拓展是在其之后进行)。
说了这么多,不如拿一些具体的例子来看。
例1 未指定位宽的整数常量(位宽至少和integer一样)
659 // 第一种表现形式的简单十进制数
'h 837FF // 第二种表现形式的十六进制数
'o7460 // 第二种表现形式的八进制数
4af // 非法(第二种表现形式的十六进制数需要'h标记)
例2 指定位宽的整数常量
4'b1001 // 第二种表现形式的二进制数,位宽为4
5 'D 3 // 第二种表现形式的十进制数,位宽为5
3'b01x // 第二种表现形式的二进制数,位宽为3,最低位是x
12'hx // 第二种表现形式的十六进制数,位宽为12,
x设置了低4位为x,所以会向左填充x直到12位
16'hz // 第二种表现形式的十六进制数,位宽为16,
z设置了低4位为z,所以会向左填充z直到16位
例3 使用符号标记的整数常量(第二种表现形式)
8 'd -6 // 虽然看起来这是-6的八位二进制补码,但这非法,负号不应该出现在这个位置
-8 'd 6 // 这才是-6的八位二进制补码(但没有s指示符,这个补码会被解释为一个无符号数)
4 'shf // 有s标记,后面的f被解释为四位二进制补码1111,即这个数是-1,数值上等同于-4'h 1
但-4'h 1没有负数的性质
-4 'sd15 // 有s标记,后面的15被解释为四位二进制补码1111,即表示-1,但前面又有负号,
所以会对补码1111整体取反加1(包括符号位),这可以得到-1相反数即1的补码,
所以结果是0001
16'sd? // 注意到之前所说的“不能在十进制中使用,除非第三个标记中只有一个x或z表示所
有位都是x或z”,所以这表示16位都为z,且被解释为有符号数
例4 符号性对计算的影响
integer IntA;
IntA = -12/3;// 因为integer是32位,-12、3和integer是一样的位宽,所以不会有位宽拓展发
生,-12、3都是有符号数,所以根据有符号数的除法计算结果为-4(以补码的
形式表现)
IntA = -'d12/3; // 因为-'d12、3和integer是一样的位宽,所以不会有位宽拓展发生,-'d12是无
符号数,所以除法按照无符号数的规则进行,'d12即0000...0001100(32位),
负号表示求-12的32位补码即二进制数11111111111111111111111111110100,
十进制表示为4294967284,除以3得到舍去小数的结果1431655761
IntA = -'sd12/3; // 这和IntA = -12/3同理,-'sd12取得了-12的32位补码,且因为s,这解释为有
符号数-'sd12、3都是有符号数,所以根据有符号数的除法计算结果为-4
(以补码的形式表现)
IntA = -4'sd12/3; // -4'sd12即-4'sb1100,即-4的补码,有负号即表示4的补码,所以1100取反
加1,相当于4'sb0100,按照有符号数的除法,4/3=1,结果为1
总结:s指示符只影响符号性,从而影响了计算是以有符号的形式还是无符号的形式,负号就是把第三个标记处的无符号数字当做有符号数,然后求其相反数的补码,通俗理解就是把第三个标记处的无符号数字整体取反加一(因为一个数相反数的补码,等于这个数的补码整体取反加一,包括符号位)。
想要符号数运算更深入的了解,可以看这篇Verilog基础:位宽拓展和有符号数运算的联系文章来源:https://www.toymoban.com/news/detail-476654.html
想知道运算是以有符号数还是无符号数进行,可以看这篇Verilog基础:表达式符号的确定文章来源地址https://www.toymoban.com/news/detail-476654.html
到了这里,关于Verilog基础:表达式中的整数常量(integer)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!