赞
踩
Verilog基础专栏https://blog.csdn.net/weixin_45791458/category_12263729.html
表达式符号
如果想要在计算表达式中获得一直和谐的结果,那么控制表达式中的符号就很重要。有两个系统函数就是为了调整表达式符号,分别是$signed和$unsigned,它们的返回值就是被转换符号后的数值。
例如:
- reg [7 : 0] regA, regB;
- reg signed [7 : 0] regS;
- regA = $unsigned(-4); //regA = 8'b11111100
- regB = $unsigned(-4'sd4); //regB = 8'b00001100
- regS = $signed(4'b1100); //regS = -4
表达式符号规则
表达式符号规则如下所示。
RHS表达式的符号不依赖于LHS,即使最后符号与LHS不同,那也只是在赋值时进行符号转换。
没有基没有位宽的常数为十进制有符号数,如12。否则必须在基数前声明s标志才表示这个常数为有符号的,如3'd4是无符号数,3'sd4是有符号数。
位选的结果是无符号数,不管位选操作数是否有符号。
域选的结果是无符号数,不管域选操作数是否有符号,即使域选的结果是整个向量。
拼接操作符的结果是无符号的,不管操作数是否有符号,即使是只有一个有符号操作数也是如此。
比较操作符的结果是无符号的,不管操作数是否有符号。
real强制转换integer的结果是有符号的。
任何自决定操作数的符号由自己决定,独立于表达式的其他部分。
对于非自决定(上下文环境决定)的操作数(子表达式),如果某操作数是real,那么结果是real;如果某操作数无符号,则结果无符号;如果所有操作数有符号,结果才是有符号的。符号的嵌套和《表达式位宽的确定》一文中的一致。
在这里我们解决《表达式位宽的确定》一文中最后留下的问题,上下文操作数如何拓展位宽?答案就是,如果上下文环境的操作数全是有符号数,则上下文操作数在需要时会符号拓展,否则在需要时会补零拓展。
我们通过一个例子来直观体会
例子:
- module incrementer_with_overflow(input clock,resetN,
- input signed [7 : 0] in,
- output signed [8 : 0] out);
- always@ (posedge clock or negedge resetN)
- if(!resetN)
- out <= 0;
- else
- out <= in + 1'b1;
- endmodule
这里存在一个问题,当in的值是5时,out的值是6,此时是正确的;但是当in的值是-5时,out的值却是252,为什么会这样呢?
因为+是上下文操作符,左右的加数都是上下文决定位宽,且右操作数1'b1是一个无符号数,所以结果是无符号的,1'b1和in会按照无符号数的规则(补零)拓展至9位(因为上下文环境最大位宽的信号是out),当in为5时运算过程是正常的5+1=6;但当in为-5时,8位二进制补码表示为11111011,此时仍然补零拓展为011111011,且与000000001作无符号数加法,结果为011111100即252。
所以如果你想让结果正确,你需要让+号的右操作数也为有符号数,这样in才能作符号拓展并进行有符号数加法(实际上有符号数加法和无符号数加法是一样的)。
你可以把1'b1改成1,这样表示32位有符号数1。
你可以把1'b1改成2'sb1,这样表示2位有符号数1。
为什么不能把1'b1改成1'sb1呢?这是因为1'sb1只有符号位,在Verilog里面,它表示-1。所以如果你这样修改了,最后得到的结果是-5。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。