(1)verilog编译器将基数形式的负整数当作unsigned处理,如此例中的-4'd12被表示为
1111 1111 1111 1111 1111 1111 1111 0100
其来历是取-4'd12绝对值即12的补码,也就是12的反码加1:
原码: 0000 0000 0000 0000 0000 0000 0000 1100 (这里长度为何取32是因为基数形式的整数虽然无符号,但也是整数,故和integer一样取32位)
反码: 1111 1111 1111 1111 1111 1111 1111 0011
补码:1111 1111 1111 1111 1111 1111 1111 0100
无论左侧的赋值对象是integer型的Tab,还是reg型的Bar,verilog首先都是将-4'd12解释成上述12的补码。但有一点区别是对最高有效位含义不同,
在赋给integer型的Tab时,被解释成负号,而赋给reg型的Bar时,被当成有效数据。所以会出现下面的现象(也是书上的例子);
reg [0:5] Bar; //unsigned
integer Tab;//signed
Bar=-4‘d12; //52,向量值为110100,这里的6位是赋值时对32位补码的截断效应,所有二进制位都被当成数据处理
Tab=-4’d12; //-12,位形式为 1111 1111 1111 1111 1111 1111 1111 0100,最左侧的1被解释成signed数的负号
如果此处将Bar定义为reg [0:31] Bar;然后赋值Bar=-4'd12;得到的无符号数的位形式也为1111 1111 1111 1111 1111 1111 1111 0100,但最左侧的1会被当成数据处理,所以如果转成十进制为4294967284,而不是-12,但请注意实际上二者的二进制形式是完全一样的。
(2)理解了上述规则后,现在再往前走一步,即作一个简单的除法,就回到你的这个问题上来。
verilog编译这个除法再赋值是从右向左进行的,即先计算右侧的表达式,没有疑义,-4'd12/4被解释成无符号数的除法,很简单,所有的位都当作数据,除以4等效于数据右移2位,左侧空出的两个位补0,即
0011 1111 1111 1111 1111 1111 1111 1101,然后才是赋值的事情,如果是integer,则最左侧的0被解释成正整数的正号,即书上所说的十进制的1073741821。但如果是reg,则最高位的0当成数据,但书上的Bar=-4'd12/4; 为什么会被解释为十进制的61呢,这和前面一样是赋值时的截断效应,即Bar是6bit的reg,所以6:31被截掉了,仅剩下了6bit的11 1101,化成十进制当然是61。
(3)如果理解了以上陈述后,那么对signed数除法的赋值例子也能很清楚的理解了,如也是书上的例子:
Bar=-12/4;
Tab=-12/4;
实际上未赋值前有符号除法的结果是一样的都是1111 1111 1111 1111 1111 1111 1111 1101,但对Bar的赋值不仅最高位被解释成数据而且被截断成111101,而Tab赋值结果为-3(十进制)。
同样如果将Bar定义为[0:31]的reg,且结果的位模式也是1111 1111 1111 1111 1111 1111 1111 1101,但由于Bar是unsigned的,verilog编译器会将最左侧的1解释为数据,所以化成十进制是4294967293。
(4)小结一下:算术操作是按照操作数的signed和unsigned进行的;而赋值是完全拷贝,若长度超出则截断;赋值结果的解释完全由赋值对象的signed还是unsigned确定,signed将最高位解释为符号,而unsigned解释为数据,所以即使对同一表达式会有不同结果。
文章评论(0条评论)
登录后参与讨论