在Verilog语法中分为逻辑运算符,位运算符等。虽然表面上看意思差不多,但各个运算符的用法并不相同,产生的结果也不一样。下文我们将针对这两种运算符进行详细讲解,并以实例及仿真结果帮助读者快速深入的理解。
-
运算符!是逻辑运算符,
运算符”!”一般是对关系运算符和等式运算符产生的结果进行求非,如!(a>b), !(a==b)等;
使用时也会有一些简略的写法:
如果a是1bit变量, b = !a 可以等效于 b = (a==1’b0), b = (a != 1’b1);
如果a是向量,如a[3:0],则 b = !a[3:0] 等效为 b = (a[3:0] ==0);
或者, b = !a[3:0] 等效为 b = (~| a[3:0] );
解释如下:
如果a[3:0]的值为0, 则 !a[3:0] 返回的结果为真(true)或1’b1;
如果a[3:0]的值不为0, 如 a[3:0]=1 或 a[3:0]=4’b1111 等值,则 !a[3:0] 返回结果为假(false)或1’b0。
但当关系运算或等式运算有’X’,’Z’等数值存在时,结果为’X’。
无论运算的对象是一位的变量,还是向量,逻辑非运算符!的结果是1位的结果。
注意:由于关系运算符或等式运算符有 ‘X’,’Z’等值参与运算时,可能会引起‘X’的传递。
例:测试运算符在变量或表达式中存在’x’时的返回值。
实体文件如下:
module test_not ( input [3:0] a,b, output [3:0] c,d,e, output [3:0] kk, output reg [3:0] f,g ); assign c = (a == b); assign d = (a != b); assign e = !a; assign kk = d[0] ? 1'b1 : 1'b0; always@(*)begin if(!a) f = 1'b1; else f = 1'b0; if(a) g = 1'b1; else g = 1'b0; end endmodule
仿真程序如下:
module tb; reg [3:0] a, b; wire [3:0] c, d, e, f, g; wire [3:0] kk; initial begin a = 0; b = 0; #10 a = 4'b11xx; b = 4'b1x1x; #10 b = 4'b11xx; #10 a = 4'bxxxx; b = 4'bxxxx; #10 a = 0; b = 4'bxxxx; #10 a = 4'b1111; b = 4'bxxxx; #10; end test_not test_not_inst ( .a (a), .b (b), .c (c), .d (d), .e (e), .kk(kk), .f (f), .g (g) ); endmodule
仿真波形如图1,
图1
结果分析:
(1)比较运算(关系或等式),只要有’X’参与,结果为’X’.
(2) !a的结果可以看出,如果a的值,明确的为4’b0000,那么!a结果为1’b1。a的值明确的不为0, 那么!a结果为1’b0。如果各种组合当中, a 的值可能出现4’b0000 时也可能出现非4’b0000 时(如a的值为4’b00xx, 则a可能为4’b0001或4’b0010等),那么这种情况下 !a 的结果为1’bx;
(3) ?运算符引起 ‘X’的传递
(4)if语句阻止’X’的传递。详细分析见” if “语句的描述。
2. 运算符~是位运算符,
其含义是对运算的变量按位求反。
如果运算的变量是1位位宽的,”~”运算的结果与”!”运算结果相同;
而对向量则是完全不同的。如!a[3:0],其结果是一位的,如果a[3:0]==0,其计算结果为1’b1。如果a[3:0]!=0,则结果为1’b0;而~a[3:0]的结果为 {~a[3],~a[2],~a[1],~a[0]},是4位位宽的,可见结果完全不同。
3. not 例化
not在Verilog不是运算符,是门级设计中的一个可例化的名称,与not对应还有and, or, xor, nand …等门级电路符号。这些电路符号在门级设计中比较常用,如not ii (b,a);可以解释为例化了一个电路,例化名为ii, b=~a; 注意在VHDL语言中 not,and ,or ,xor等都是对应的运算符。
not 例化格式如下:
not [instannce name] (out1, out2, …, outn, in); //输入为in, 可以有多个输出out1,out2,…., outn等,其中每一个输出都是输入取反的结果。
例:RTL级设计
y = (!a & b) | (a & !b);
可以用门级描述如下:
module gate_test ( input a, b, output y ); wire na, nb; wire t_and1, t_and2; wire t_xor; wire t_xnor; not i0 (na, a); not i1 (nb, b); and i2 (t_and1, b, na); and i3 (t_and2, nb, a); or i4 (y, t_and2, t_and1); xor i5 (t_xor, a, b ); xnor i6 (t_xnor, a, b ); endmodule
其中 i0, i1, i2, i3, i4都是例化名,当然也可以用其它名称替代。
门级电路的语法结构如下,使用门级电路描述与普通数字电路设计几乎相同,这里不再累述。
- and | nand | or | nor | xor | xnor [instance name] (out, in1, …, inN);
// [] is optional and | is selection
- buf | not [instance name] (out1, out2, …, outn, in);
- bufif0 | bufif1 | notif0 | notif1 [instance name] (output A, input B, input control );
- pullup | pulldown [instance name] (output A);
对应视频:
学习本节课后有几点收获,1、运算符”!”一般是对关系运算符和等式运算符产生的结果进行求非;2、无论运算的对象是一位的变量,还是向量,逻辑非运算符!的结果是1位的结果;3、当关系运算或等式运算有’X’,’Z’等数值存在时,结果为’X’;4、运算符~是位运算符,其含义是对运算的变量按位求反;5、not在Verilog不是运算符,是门级设计中的一个可例化的名称;
文章内容非常丰富,很值得反复学习揣摩,文中列举了大量实例,通过仿真测试,观察仿真图形,会理解的更加透彻!