Verilog语法之运算符详解
Verilog语法之运算符详解
Verilog是一种硬件描述语言,广泛应用于数字电路设计中。运算符是Verilog语言中的重要组成部分,用于实现各种逻辑和算术运算。本文将详细介绍Verilog中的各种运算符,包括算术运算符、关系运算符、等式运算符、逻辑运算符、位运算符、缩减运算符、移位运算符、条件运算符和拼接运算符,并通过具体的代码示例和仿真结果来说明每个运算符的使用方法和特性。
1. 运算符概述
Verilog的运算符与C语言基本类似,包括算术运算符、关系运算符、等式运算符、逻辑运算符、位运算、缩减运算符、移位运算符、条件运算符、拼接运算符等。各种运算符与条件运算符在同时使用时,具有一定优先级顺序(从高到低)。
2. 算术运算符
注意:除法(/)或取模(%)运算时,如果B取值为0,那么仿真输出的运算结果将会是不确定值x;如果进行运算的值A或C有任何位的值是x或z,那么运算的整个结果值都会是x。取模(%)运算结果的符号只与A的符号一致。以下是一个可以进行实际运行的testbench文件,用以观察这些运算的实际效果。
module testbench_top();
integer A,B;
integer C;
initial begin
A=100;
B=33;
C=A+B;
$display("%0d + %0d = %0d", A, B, C);
C=A-B;
$display("%0d - %0d = %0d", A, B, C);
C=A*B;
$display("%0d * %0d = %0d", A, B, C);
C=A/B;
$display("%0d / %0d = %0d", A, B, C);
A=10;
B=3;
C=A**B;
$display("%0d ** %0d = %0d", A, B, C);
C=A%B;
$display("%0d %% %0d = %0d", A, B, C);
A=100;
B=20;
C=A%B;
$display("%0d %% %0d = %0d", A, B, C);
A=-100;
B=33;
C=A%B;
$display("%0d %% %0d = %0d", A, B, C);
A=100;
B=-33;
C=A%B;
$display("%0d %% %0d = %0d", A, B, C);
$stop;
end
endmodule
运算结果如下:
3. 关系运算符
使用关系运算符的表达式结果若是true,则返回结果1,否则返回结果0。参与关系运算的任意一个数据中若包含x或z,则其仿真结果必定是一位不确定值x。当关系运算符两侧的数据位宽不一致时,位宽较少的数据会自动扩展到与位宽较多的数据一样的位宽,扩展位的数据都以0填充。所有关系运算符具有相同的运算优先级。
4. 等式运算符
等式运算符包括逻辑等号==、逻辑不等号!=、全等号===和不全等号!==。
等式运算符将会实现逐位比较,若等式两侧的位宽不同,则位宽较少的数据将自动扩展位宽并与位宽较多的数据位宽相等,扩展位以0填充。与关系运算操作一样,灯饰运算操作在结果为true时,返回结果1,否则返回结果0。
全等号===和不全等号!==可用于仿真测试脚本,但不可综合。全等号中可以包含x和z,并参与逐位比较。逻辑等式运算的任意一个数据中若包含x或z,则其仿真结果必定是一位的不确定值x。
5. 逻辑运算符
逻辑与(&&)、逻辑或(||)、逻辑非(!)。
!A
if(!A) if(A==0)
A&&B
A||B
6. 位运算符
位运算符包括与(&)、位或(|)、位取反()、位异或(^)、位同或(^或^~)。位运算符实现运算数值间的逻辑运算操作。
module testbench_top;
reg [7:0] A,B;
reg [7:0] C;
initial begin
A=8'b10101110;
B=8'b10010110;
C=A&B;
$display("%b & %b = %b", A, B, C);
C=A|B;
$display("%b | %b = %b", A, B, C);
C=~A;
$display("~%b = %b", A, C);
C=A^B;
$display("%b ^ %b = %b", A, B, C);
C=A~^B;
$display("%b ~^ %b = %b", A, B, C);
$stop;
end
endmodule
运算结果如下:
7. 减缩运算符
缩减运算符对单个操作数的每个位之间进行递推运算,最后的运算结果是一位的二进制数。缩减运算符包括缩减与(&)、缩减或(|)、缩减与非(&)、缩减或非(|)、缩减异或(^)、缩减同或(~^)。
module testbench_top();
reg [3:0] A,B,C,D;
initial begin
A=4'b1111;
B=4'b0000;
C=4'b0110;
D=4'b1000;
$display("A=%b, B=%b, C=%b, D=%b", A, B, C, D);
$display("&A=%b, &B=%b, &C=%b, &D=%b", &A, &B, &C, &D);
$display("|A=%b, |B=%b, |C=%b, |D=%b", |A, |B, |C, |D);
$display("~&A=%b, ~&B=%b, ~&C=%b, ~&D=%b", ~&A, ~&B, ~&C, ~&D);
$display("~|A=%b, ~|B=%b, ~|C=%b, ~|D=%b", ~|A, ~|B, ~|C, ~|D);
$display("^A=%b, ^B=%b, ^C=%b, ^D=%b", ^A, ^B, ^C, ^D);
$display("~^A=%b, ~^B=%b, ~^C=%b, ~^D=%b", ~^A, ~^B, ~^C, ~^D);
$stop;
end
endmodule
运算结果如下:
8. 移位运算符
移位运算符包括逻辑运算符何算术运算符。左移运算符将运算符左侧的数值(A或B)向左移动num个位,低位补0;右移运算符将运算符左侧的数值向右移动num个位,高位补0。如果赋值的结果是无符号数,则算术右移(>>>)的高位补0;如果赋值结果是有符号数,则算术右移(>>>)高位补1。
语法示例:
A<<num
B<<<num
C>>num
D>>>num
代码示例:
module testbench_top();
reg [3:0] A,B;
reg signed [3:0] C,D;
initial begin
A=4'b0001;
B=(A<<2);
$display("(A<<2) = %b", B);
C=4'b1000;
D=(C>>>2);
$display("(C>>>2) = %b", D);
$stop;
end
endmodule
结果如下:
9. 条件运算符
条件运算符?:的基本格式如下:
A=B?C:D;
如果B的表达式为True,那么将C的值赋给A;否则将D的值赋给A。
示例代码如下:
module testbench_top();
reg flag;
reg [3:0] A,B,C;
wire [3:0] D;
initial begin
A=8;
B=2;
flag=1;
#20;
flag=0;
#20;
$stop;
end
assign D=flag ? (A+B) : (A-B);
always @(*) begin
C=flag ? A:B;
end
endmodule
10. 拼接运算符
拼接运算符使用一对大括号{}实现。在{}中将几个信号的某些位详细列出来,中间使用逗号分隔开,表示一个由多个位拼接在一起的信号。常量或变量都可以使用拼接运算符。拼接运算符允许嵌套使用。具体使用方式如下:
{A,B,C}
{3{A}}
{A,{2{A,B}},C}
具体示例代码如下:
module testbench_top();
reg [1:0] A=2'b00, B=2'b11, C=2'b10;
reg [5:0] D= 6'd0;
reg [5:0] E= 6'd0;
reg [11:0] F= 12'd0;
initial begin
#10;
D={A,B,C};
$display("D={A,B,C} = {%b,%b,%b}=%b", A, B, C,D);
E={3{A}};
$display("E={3{A}}={3{%b}}=%b", A, E);
F={A, {2{A,B}}, C};
$display("F={A, {2{A,B}}, C} = {%b,{2{%b,%b}},%b}=%b", A, A, B, C, F);
#10;
$stop;
end
endmodule
结果如下: