Menu Close

Verilog 中not ~ !的区别

在Verilog语法中分为逻辑运算符位运算符等。虽然表面上看意思差不多,但各个运算符的用法并不相同,产生的结果也不一样。下文我们将针对这两种运算符进行详细讲解,并以实例及仿真结果帮助读者快速深入的理解。

  1. 运算符!是逻辑运算符

运算符”!”一般是对关系运算符和等式运算符产生的结果进行求非,如!(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]=1a[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都是例化名,当然也可以用其它名称替代。

门级电路的语法结构如下,使用门级电路描述与普通数字电路设计几乎相同,这里不再累述。

  1. and nand or nor xor xnor [instance name] (out, in1, …, inN);

 // [] is optional and | is selection   

  1. buf not [instance name] (out1, out2, …, outn,  in);  
  2. bufif0 bufif1 notif0 notif1 [instance name] (output A, input B,  input control );
  3. pullup pulldown [instance name] (output A);   

 

对应视频:

Posted in FPGA, Verilog, 文章

1 Comment

  1. wangff

    学习本节课后有几点收获,1、运算符”!”一般是对关系运算符和等式运算符产生的结果进行求非;2、无论运算的对象是一位的变量,还是向量,逻辑非运算符!的结果是1位的结果;3、当关系运算或等式运算有’X’,’Z’等数值存在时,结果为’X’;4、运算符~是位运算符,其含义是对运算的变量按位求反;5、not在Verilog不是运算符,是门级设计中的一个可例化的名称;

    文章内容非常丰富,很值得反复学习揣摩,文中列举了大量实例,通过仿真测试,观察仿真图形,会理解的更加透彻!

发表回复

相关链接