注:扫码关注小青菜哥哥的weixin公众号,免费获得更多优质的核探测器与电子学内容~
本篇为“verilog基础干货”篇的最后一篇,小青菜哥哥对verilog的数值运算规则做一个总结吧!
在实际FPGA工程开发过程中,数值运算有时会出现莫名其妙的运算结果,小青菜哥哥就曾经在项目上吃过这方面的大亏,所以研究透这些规则很重要!很重要!很重要!
- 整数(integer)除法(a/b)应向零截断结果的任何小数部分(例如:4/3=1)。
- 对于除法(a/b)或取模(a%b)运算符,如果第二个操作数为零,则整个结果值应为 x。
- 对于取模运算符(a%b),当 a被 b 整除时结果为零。
- 取模运算(a%b)的结果应采用第一个操作数的符号(例如:-10%3=-1,11%-3=2)。
- 如果幂运算符(a**b)的任一操作数为实数、整数或有符号数,则幂运算符的结果应为实数。如果两个操作数都是无符号的,那么结果应该是无符号的。如果第一个操作数为零且第二个操作数为非正数,或者如果第一个操作数为负数且第二个操作数不是整数值,则幂运算符的结果为x。
- 对于关系表达式(a<b,a>b,a<=b,a>=b),当使用两个位长不等的操作数并且其中一个或两个操作数是无符号时,位长较小的操作数应在最高有效位一侧填充零以扩展到较大操作数的位长。
- 当关系表达式的两个操作数都是有符号整数操作数(整数、有符号 reg/wire 数据类型或无位宽、无基数的整数)时,表达式应被解释为有符号值之间的比较。当关系表达式的任一操作数是实操作数时,另一个操作数应转换为等效的实数值,并且该表达式应解释为两个实数值之间的比较。否则表达式应被解释为无符号值之间的比较。
- 对于条件运算(a?b:c),如果表达式b和c的位宽不同,则位宽短的表达式需要高位填充0以满足二者位宽相同。例子如下:
module bitlength();
reg [3:0] a,b,c;
reg [4:0] d;
initial begin
a = 9;
b = 8;
c = 1;
$display("answer = %b", c ? (a&b) : d);
end
endmodule
//the $display statement will display: answer = 01000
9, 表达式位宽规则
1)表达式的位数(称为表达式的大小)应由表达式中涉及的操作数和给出表达式的上下文确定。
2)自定表达式是一种表达式的位长完全由表达式本身确定的表达式。
3)上下文确定的表达式是其中表达式的位长由表达式的位长以及它是另一个表达式的一部分这一事实确定的表达式。例如赋值表达式右侧的位大小取决于其自身和左侧的表达式大小。
表 29 显示了表达式的形式将如何确定表达式结果的位长。表29中i、j、k表示操作数的表达式,L(i)表示i表示的操作数的位长。
例子如下:
reg [3:0] a;
reg [5:0] b;
reg [15:0] c;
initial begin
a = 4’hF;
b = 6’hA;
$display("a*b=%h", a*b);// 表达式大小自行决定
c = {a**b}; // 由于连接运算符 {},表达式 a**b 是自定的
$display("a**b=%h", c);
c = a**b; // 表达式大小由 c 决定
$display("c=%h", c);
end
此示例的输出:
a*b=16 // 'h96 被截断为 'h16,因为表达式大小是 6
a**b=1 // 表达式大小为 4 位(a 的大小)
c=ac61 // 表达式大小为 16 位(c 的大小)
10,带符号表达式
如果要获得一致的结果,控制表达式的符号很重要。 除了一般的有符号数运算规则之外,还可以使用两个系统函数来处理表达式的类型转换:$signed() 和 $unsigned()。 这些函数处理输入表达式并返回一个与输入表达式具有相同大小和值以及函数定义的类型的值:
$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
11,表达式类型规则:以下是确定表达式结果类型的规则:
1)表达式类型仅取决于操作数。它不依赖于 LHS(如果有)。
2)无base和size的十进制数是有符号的(例如:5)。
3)有基数base的数是无符号的,除非在基数说明符中使用了s符号(如“4'sd12”)才是有符号数。
4)位选择(例如a[0])结果都是无符号的,与操作数无关。
5)无论操作数如何,部分选择(例如a[3:0])结果都是无符号的,即使部分选择指定了整个向量 也是如此。例如:
reg [15:0] a;
reg signed [7:0] b;
initial
a = b[7:0]; // b[7:0] 是无符号的,因此零扩展
end
6)无论操作数如何,连接({})结果都是无符号的。
7)关系比较结果 (1, 0) 是无符号的,与操作数无关。
8)通过类型强制转换为整数的实数是有符号的。
9)任何自定操作数的符号和大小由操作数本身决定,与表达式的其余部分无关。
10)对于非自定操作数,适用以下规则:
(1)如果任一操作数为实数,则结果为实数;
(2)如果任一操作数是无符号的,则无论运算符如何,结果都是无符号的;
(3)无论运算符如何,如果所有操作数都有符号,则结果将有符号;
今天的博文就到这里了,有问题请在小青菜哥哥的公众号留言,谢谢!