1. 四值逻辑的逻辑运算

在对比SystemVerilog中的相等运算符之前,先来看一下三种最基本的逻辑运算符,下文中以·表示与运算,以+表示或运算,以'表示非运算。我们都知道在逻辑代数中,只有01,那么在SystemVerilog中,对于四值逻辑(01zx)的逻辑运算结果又会怎样呢?

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

我们通过简单的代码就可以打印出四值逻辑运算的真值表:

与运算(A·B) 0 1 z x
0 0 0 0 0
1 0 1 x x
z 0 x x x
x 0 x x x
或运算(A+B) 0 1 z x
0 0 1 x x
1 1 1 1 1
z x 1 x x
x x 1 x x
非运算 0 1 z x
输出(A' 1 0 x x

由输出结果可知,四值逻辑运算的结果只有01x,并且与常量01运算时,仍然满足逻辑代数的基本公式:0 · A = 01 · A = A0 + A = A1 + A = 1;以及满足公式:A · A = AA + A = A

只不过输出结果不包含zz参与运算时,同x相同,如:1 · z = x0 + z = xz · x = xz + x = x

2. 相等运算符

依然打印出所有的输出结果,如下所示:

== 0 1 z x
0 1 0 x x
1 0 1 x x
z x x x x
x x x x x
!= 0 1 z x
0 0 1 x x
1 1 0 x x
z x x x x
x x x x x
=== 0 1 z x
0 1 0 0 0
1 0 1 0 0
z 0 0 1 0
x 0 0 0 1
!== 0 1 z x
0 0 1 1 1
1 1 0 1 1
z 1 1 0 1
x 1 1 1 0

可以看到,===!==的结果只有01,而==!=的结果有01x。以上结果都是针对单比特值的比较运算,那么对于多比特数据的相等比较运算,结果如何呢?

initial begin
$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 $display("-----------------------------------------------------"); $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
end

对于===!==的输出结果比较容易理解,只有01嘛;而对于==!=的部分输出结果,是否有些困惑呢?比如对比这几个输出:

# 1010 == 10x0 : x
# 1010 == 10x1 : 0
# 1x10 == 1x10 : x

不要被这些结果所迷惑,实际上,这四个相等运算符的规则很简单,都是逐位比较操作数(bit for bit)。对于相等比较,对逐位比较的结果再进行与运算;而对于不相等比较,对逐位比较的结果再进行或运算。比如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'bx & 1'b1,所以结果为1'bx;而对于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'bx | 1'b1,所以结果为1'b1

3. 关于数据的逻辑值

首先,上文中所涉及到的与或非运算,我所使用的都是按位与(&)、按位或(|)、按位非(~),因为对于单比特数据的运算,实际上其与逻辑与(&&)、逻辑或(||)、逻辑非(!)的运算结果相同,如1'b1 & 1'bx1'b1 && 1'bx的结果都是1'bx。那么对于多比特的数据,其逻辑值怎么判断呢?也就是说,比如代码中有if (4'b10x0) begin "something" end,那something会不会运行呢,即4'b10x0的逻辑值是真是假呢?我这里使用两个逻辑非(!)来得到逻辑值:!(!4'b10x0)

initial begin
$display("4'b%b : %b", 4'b0000, !(!4'b0000)); // 0
$display("4'b%b : %b", 4'b1010, !(!4'b1010)); // 1
$display("4'b%b : %b", 4'b1x10, !(!4'b1x10)); // 1
$display("4'b%b : %b", 4'b1z10, !(!4'b1z10)); // 1
$display("4'b%b : %b", 4'bxxxx, !(!4'bxxxx)); // x
$display("4'b%b : %b", 4'bzzzz, !(!4'bzzzz)); // x
$display("4'b%b : %b", 4'bxx00, !(!4'bxx00)); // x
$display("4'b%b : %b", 4'bz0z0, !(!4'bz0z0)); // x
end

实际上,就是对数据的所有位进行或运算,就得到了该数据的逻辑值,所以if (4'b10x0) begin "something" end会执行something。这一部分,主要是想说明,对于四值数据,无论是与或非逻辑运算,还是==!=相等比较运算,结果都可能出现x,且! 1'bx结果还是1'bx,所以下面三种写法,if条件都不成立,最终都只会执行Do ELSE。即,当使用==!=比较四值数据时,结果可能会得到x,并随之出现我们预期之外的效果,这是我们不希望的,所以在验证代码中比较四值数据时,要使用===!==

initial begin
if ( 4'b1010 == 4'b10x0 )
$display("Do IF");
else
$display("Do ELSE"); if ( 4'b1010 != 4'b10x0 )
$display("Do IF");
else
$display("Do ELSE"); if ( !(4'b1010 == 4'b10x0) )
$display("Do IF");
else
$display("Do ELSE");
end

SystemVerilog 中的相等运算符:== or === ?的更多相关文章

  1. systemverilog中奇怪的语法

    1.->运算符 expression_a->expression_b其实等效于(!expression_a || expression_b),systemverilog中利用 || 运算的 ...

  2. java中的移位运算符:<<,>>,>>>总结

    java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,num >& ...

  3. js中的等值运算符(抽象相等==与严格相等===的区别)

    js中的等值运算符 js中的相等分为抽象相等和严格相等,他们有什么区别呢. 在说具体算法前,先提下JS数据类型,JS数据类型分为6类:Undefined Null String Number Bool ...

  4. [.net 面向对象编程基础] (6) 基础中的基础——运算符和表达式

    [.net 面向对象编程基础] (6) 基础中的基础——运算符和表达式 说起C#运算符和表达式,小伙伴们肯定以为很简单,其实要用好表达式,不是一件容易的事.一个好的表达式可以让你做事半功倍的效果,比如 ...

  5. Java中的移位运算符

    java中有三种移位运算符 <<      :     左移运算符,num << 1,相当于num乘以2 >>      :     右移运算符,num >& ...

  6. VB.NET中的除法运算符 与 C#中的除法运算符

    VB.NET中的除法运算符有两个:/(浮点除法).\(整数除法) C#中的除法运算符只有一个:/(除法) VB.NET中的除法运算符与C#中的除法运算符存在很大的差异,使用时注意区分. 关于VB.NE ...

  7. Java中常用的运算符

    运算符是一种“功能”符号,用以通知 Java 进行相关的运算,Java 语言中常用的运算符可分为如下几种: 算数运算符.赋值运算符.比较运算符.逻辑运算符.条件运算符. 一.算数运算符 Java 中常 ...

  8. JavaScript中的逗号运算符

    JavaScript逗号运算符  阅读本文的前提,明确表达式.短语.运算符.运算数这几个概念. 所谓表达式,就是一个JavaScript的“短语”,JavaScript解释器可以计算它,从而生成一个值 ...

  9. php中常用的运算符

    运算符 运算符是告诉PHP做相关运算的标识符号. PHP运算符一般分为算术运算符.赋值运算符.比较运算符.三元运算符.逻辑运算符.字符串连接运算符.错误控制运算符. 1.变量名记得加“$” 符: 2. ...

随机推荐

  1. [JavaScript之BOM与DOM]

    [JavaScript之BOM与DOM] BOM(Browser Object Model)是指浏览器对象模型,它使 JavaScript 有能力与浏览器进行"对话". DOM ( ...

  2. MyBaits自动配置原理

    前言 首先我们建立一个SpringBoot工程,导入mybatis-spring-boot-starter依赖. <dependency> <groupId>org.mybat ...

  3. Django 请求和响应 request return

    request.method 请求方法 request.get  get请求信息 request.post  post请求信息 request.path 请求路径 方法: requset.get_fu ...

  4. 5分钟让你理解K8S必备架构概念,以及网络模型(中)

    写在前面 在这用XMind画了一张导图记录Redis的学习笔记和一些面试解析(源文件对部分节点有详细备注和参考资料,欢迎关注我的公众号:阿风的架构笔记 后台发送[导图]拿下载链接, 已经完善更新): ...

  5. java基础——参数的应用

    命令行传递参数(少用) 有时候,你希望运行一个程序时,在传递给它信息.这个时候,要靠 传递命令行 参数 给main()函数实现. package com.dong.method;​public cla ...

  6. [bug] PyCharm远程Spark集群:Java gateway process exited before sending its port number

    原因 无法连接到集群上的java 解决 方法一: 在右上角Edit Configurations中,添加一条环境变量JAVA_HOME,值为远程机器上的java安装路径 方法二: 直接在代码里写上JA ...

  7. [bug] Job for network.service failed because the control process exited with error code

    原因 复制虚拟机,没有改网卡配置文件 参考 https://blog.csdn.net/dongfei2033/article/details/81124465

  8. [Qt] 事件机制(三)

    在主窗口Widget中增加几个小功能 1.点击左键,在左上角label中显示"haha",点击右键,显示"lala" 在widget.h中添加: 1 #incl ...

  9. Linux单用户模式(修改密码、运行级别)方法详解

    很多新手当面对"忘记 root 账户密码导致无法登陆系统"这个问题时,直接选择重新系统.其实大可不必,我只需要进入 emergency mode(单用户模式)更新 root 账户的 ...

  10. Docker 的神秘世界

    引言 上图就是 Docker 网站的首页,看了这简短的解释,相信你还是不知道它是何方神圣. 讲个故事 为了更好的理解 Docker 是什么,先来讲个故事: 我需要盖一个房子,于是我搬石头.砍木头.画图 ...