【SystemVerilog基础】SystemVerilog语法之逻辑等(==)、全等(===)和匹配等(==?)

有感:作为硅农,我们的世界不仅仅是0和1的苟且,还有x和z的恐惧。

前言

首先,来认识一下这几个符号的等于和不等的写法:

  • 逻辑等(==)和 逻辑不等(!=
  • 全等(===)和 不全等(!==
  • 通配符等于(==?)和 通配符不等(!=?

在这里插入图片描述
其次,再复习一下基本的单比特与运算、或运算,其真值表如下:

在这里插入图片描述

乍一看,似乎还挺复杂的不是嘛,其实还是有规律可循的。首先由输出结果可知,四值逻辑运算的结果只有0、1和x,并且与常量0和1运算时,仍然满足逻辑代数的基本公式:0 · A = 01 · A = A0 + A = A1 + A = 1;以及满足公式:A · A = AA + A = A。总结下来,最重要的就是两句话:

  • 0与上任何值都等于0;
  • 1或上任何值都等于1。

一、逻辑等(==)和 逻辑不等(!=

逻辑等(==)和 逻辑不等(!=)是我们在开发中用的最多的,它的返回结果在SystemVerilog中有三种:01x

  • 针对单比特的逻辑等和逻辑不等运算有如下表格:

在这里插入图片描述

  • 针对多比特的逻辑等和逻辑不等运算有如下代码:
  $display("%b == %b : %b", 4'b1010, 4'b1011, 4'b1010 == 4'b1011); // 0
  $display("%b != %b : %b", 4'b1010, 4'b1011, 4'b1010 != 4'b1011); // 1

  $display("%b == %b : %b", 4'b1010, 4'b10x0, 4'b1010 == 4'b10x0); // x
  $display("%b == %b : %b", 4'b1010, 4'b10x1, 4'b1010 == 4'b10x1); // 0 注意!注意!注意!
  $display("%b != %b : %b", 4'b1010, 4'b10x0, 4'b1010 != 4'b10x0); // x
  $display("%b != %b : %b", 4'b1010, 4'b10x1, 4'b1010 != 4'b10x1); // 1

  $display("%b == %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 == 4'b1x10); // x
  $display("%b == %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 == 4'b1x10); // x
  $display("%b != %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 != 4'b1x10); // x
  $display("%b != %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 != 4'b1x10); // x

如何去理解逻辑等和逻辑不等运算呢?

  • 我之前是这样理解的:只要比较中含有x或z,那么输出就是x。(注意,这是我之前错误的理解!)显然,这个理解可以直接用反例: 4'b1010 == 4'b10x1 // 输出0 来打脸!

既然上述理解是错误的,那么应该如何正确理解呢?莫急,且听我娓娓道来!

  • 实际上,多比特逻辑等和逻辑不等的运算规则很简单,都是逐位比较操作数(bit for bit)。对于逻辑等比较,对逐位“逻辑等”比较的结果再进行与运算;而对于逻辑不等比较,对逐位“逻辑不等”比较的结果再进行或运算
  • 比如:4'b1010 == 4'b10x1,则等价于(1'b1 == 1'b1) & (1'b0 == 1'b0) & (1'b1 == 1'bx) & (1'b0 == 1'b1),即1'b1 & 1'b1 & 1'bx & 1'b0,所以结果为1'b0
  • 再比如:4'b1010 != 4'b10x1,则等价于(1'b1 != 1'b1) | (1'b0 != 1'b0) | (1'b1 != 1'bx) | (1'b0 != 1'b1),即1'b0 | 1'b0 | 1'bx | 1'b1,所以结果为1'b1

二、全等(===)和 不全等(!==

全等,“全”顾名思义就是会去匹配四种状态值:0、1、x、z,它的返回结果有两种:01

  • 针对单比特的全等和不全等运算有如下表格:
    在这里插入图片描述

  • 针对多比特的全等和不全等运算有如下代码:

  $display("%b === %b : %b", 4'b1010, 4'b1011, 4'b1010 === 4'b1011); // 0
  $display("%b !== %b : %b", 4'b1010, 4'b1011, 4'b1010 !== 4'b1011); // 1

  $display("%b === %b : %b", 4'b1010, 4'b10x0, 4'b1010 === 4'b10x0); // 0
  $display("%b === %b : %b", 4'b1010, 4'b10x1, 4'b1010 === 4'b10x1); // 0
  $display("%b !== %b : %b", 4'b1010, 4'b10x0, 4'b1010 !== 4'b10x0); // 1
  $display("%b !== %b : %b", 4'b1010, 4'b10x1, 4'b1010 !== 4'b10x1); // 1

  $display("%b === %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 === 4'b1x10); // 1
  $display("%b === %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 === 4'b1x10); // 0
  $display("%b !== %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 !== 4'b1x10); // 0
  $display("%b !== %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 !== 4'b1x10); // 1

重要结论:对于===!==的输出多比特输出比较容易理解,只有0和1嘛,每一位都匹配上是1,否之为0!

对于全等和全不等,记住上述结论就够用了,但为了更加深刻的理解,这里稍稍引申一下。

  • 实际上,不仅仅多比特逻辑等和逻辑不等的运算规则满足逐位比较多比特全等和不全等的运算规则也满足逐位比较,即:对于全等比较,对逐位全等比较的结果再进行与运算;而对于不全等比较,对逐位不全等比较的结果再进行或运算
  • 比如:4'b1010 === 4'b10x0,则等价于(1'b1 === 1'b1) & (1'b0 === 1'b0) & (1'b1 === 1'bx) & (1'b0 === 1'b0),即1'b1 & 1'b1 & 1'b0 & 1'b1,所以结果为1'b0
  • 再比如:4'b1010 !== 4'b10x1,则等价于(1'b1 !== 1'b1) | (1'b0 !== 1'b0) | (1'b1 !== 1'bx) | (1'b0 !== 1'b1),即1'b0 | 1'b0 | 1'b1 | 1'b1,所以结果为1'b1

三、匹配等(==?)和 匹配不等(!=?

匹配等(==?)和 匹配不等(!=?)是同样也是逐位比较的,返回结果有三种:01x

需要特别注意的是:“匹配等”仅仅可以把右侧操作数中的 x和z 当做 0/1 来匹配左侧操作数中的 0/1,当然了右侧 x/z 可以对应匹配左侧的 x/z(无序)。说着可能有点拗口,看下面的表格便一目了然了!

  • 针对单比特的“匹配等”和“匹配不等”运算有如下表格(注意:需要区分操作数在运算符的哪一侧!):

在这里插入图片描述

  • 针对多比特的“匹配等”和“匹配不等”运算有如下代码:
  $display("%b ==? %b : %b", 4'b1010, 4'b1011, 4'b1010 ==? 4'b1011); // 0
  $display("%b !=? %b : %b", 4'b1010, 4'b1011, 4'b1010 !=? 4'b1011); // 1

  $display("%b ==? %b : %b", 4'b1010, 4'b10x0, 4'b1010 ==? 4'b10x0); // 1
  $display("%b ==? %b : %b", 4'b1010, 4'b10x1, 4'b1010 ==? 4'b10x1); // 0
  $display("%b !=? %b : %b", 4'b1010, 4'b10x0, 4'b1010 !=? 4'b10x0); // 0
  $display("%b !=? %b : %b", 4'b1010, 4'b10x1, 4'b1010 !=? 4'b10x1); // 1

  $display("%b ==? %b : %b", 4'b1010, 4'b10x0, 4'b10x0 ==? 4'b1010 ); // x
  $display("%b ==? %b : %b", 4'b1010, 4'b10x1, 4'b10x1 ==? 4'b1010 ); // 0
  $display("%b !=? %b : %b", 4'b1010, 4'b10x0, 4'b10x0 !=? 4'b1010 ); // x
  $display("%b !=? %b : %b", 4'b1010, 4'b10x1, 4'b10x1 !=? 4'b1010 ); // 1

  $display("%b ==? %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 ==? 4'b1x10); // 1
  $display("%b ==? %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 ==? 4'b1x10); // 1
  $display("%b !=? %b : %b", 4'b1x10, 4'b1x10, 4'b1x10 !=? 4'b1x10); // 0
  $display("%b !=? %b : %b", 4'b1z10, 4'b1x10, 4'b1z10 !=? 4'b1x10); // 0

同前面介绍的逻辑(不)等、(不)全等一样,匹配等也满足逐位比较的运算规则:

  • 结论:对于“匹配等”比较,对逐位“匹配等”比较的结果再进行与运算;而对于“匹配不等”比较,对逐位“匹配不等”比较的结果再进行或运算。
  • 比如:4'b1010 ==? 4'b10x0,则等价于(1'b1 ==? 1'b1) & (1'b0 ==? 1'b0) & (1'b1 ==? 1'bx) & (1'b0 ==? 1'b0),即1'b1 & 1'b1 & 1'b1 & 1'b1,所以结果为1'b1
  • 再比如:4'b10x0 !=? 4'b1010,则等价于(1'b1 !=? 1'b1) | (1'b0 !=? 1'b0) | (1'bx !=? 1'b1) | (1'b0 !=? 1'b0),即1'b0 | 1'b0 | 1'bx | 1'b0,所以结果为1'bx
  • 再比如:4'b10x1 !=? 4'b1010,则等价于(1'b1 !=? 1'b1) | (1'b0 !=? 1'b0) | (1'bx !=? 1'b1) | (1'b1 !=? 1'b0),即1'b0 | 1'b0 | 1'bx | 1'b1,所以结果为1'b1

四、总结

综上,无论是逻辑等(==)、全等(===)还是匹配等(==?),都遵循按位比较原则,即:对于相等比较,对逐位比较的结果再进行与运算;而对于不等比较,对逐位比较的结果再进行或运算。

参考

附录

单比特运算测试代码(以“逻辑等”为例,其他运算类比替换即可):

logic v[4] = '{1'b0, 1'b1, 1'bz, 1'bx};
initial begin
  foreach(v[i])
    foreach(v[j])
      $display("%b == %b : %b", v[i], v[j], v[i] == v[j]);
end
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MoorePlus

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值