本文是学习魏家明老师的《Verilog 编程艺术》之后所记录的关于表达式的位长对结果的影响的笔记。
在程序中往往必不可免的需要用到简单的计算,简单的如+ - ,复杂的有**(幂运算)。
那么有时运算的结果却和理论不符,这是什么原因呢???很可能就是位长的原因。
且看以下几个例子:
1、中间结果因为位长不够而出现丢失:
reg [3:0] a; reg [3:0] b; reg [3:0] c; reg [3:0] d; reg [4:0] e; always @(posedge clk ) begin c = (a + b) >>1; d = (a + b +0) >>1; e = (a + b) >>1; end initial begin a = 0; b = 0; clk = 0; f <= 0; #(10*t) a = 6; #(10*t) b = 6; #(10*t) a = 2; #(10*t) a = 13; #(10*t) b = 10; end
则仿真图位:
结果可以看出当a+b < 16的时候c、d、e的结果都相同,但是当a+b > 15之后,c、d、e的结果就不怎么相同了?什么原因呢?
先来分析c的值,因为a和b都是4位(最大值为15),运算过程都按4位进行,多于4位的中间值的高位被舍弃,所以结果只与中间值的低4位有关,当a+b = 13+6 = 19(1 0011)时,中间值其实为4‘b0011,然后右移一位为4’b0001故结果为1;
而对于d来说,因为有0(未指明位数,默认32位)的参与,虽然没有改变中间值的大小但是改变了中间值的位数,所以中间值应为32bit,右移一位后还为32bit,然后取最后4bit,结果为4‘b1001;
最后对于e,因为位数为5位,比啊,a、b都多一位,所以中间值按照e的来存储,结果也是正确的。
总结:加法计算时,结果最好要比加数最多的位再多一位。中间值的位数由等式左边的和的位数和等式右边的最多位数的加数共同决定。
2、 显示命令的数据由算式中的最长位决定。
reg [3:0] a; reg [3:0] b; reg [4:0] c; initial begin clk = 0; a = 1; b = 4'd4; c = 5'd19; #(10*t) $display("answer = %b",a?b:c); end
从上面可以看出,answer的值肯定是b,而b是4bit,则结果是4’b0100吗??反正结果为:
结果是4,但是竟然有5位,这是怎么回事??因为a?b:c;中位数最多的是c,有5bit,所以结果也是5bit了。
另外:表达式的结果不仅与位数有关,还与表达式本身有关系。