马上注册,看完整文章,学更多FPGA知识。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
5.4 逻辑运算符
本文档编号:001100000061
需要看对应的视频,请点击视频编号:001100000061
1. 本节主要进行组合逻辑的介绍,包括:程序语句(assign语句、always语句),数字进制(二进制、不定态、高阻态),算数运算符(加、减、乘、除运算符),逻辑运算符(逻辑与、或、非运算符),按位逻辑运算符(单目按位与、或、非运算符,双目按位与、或、异或运算符),关系运算符,移位运算符(左移、右移运算符),条件运算符(三目运算符、if语句、case语句、选择语句等),拼接运算符;
2. ALTERA和VIVADO文档
在Verilog HDL语言中存在3种逻辑运算符,它们分别是: (1)&&:逻辑与; (2) | | :逻辑或; (3)!:逻辑非。
5.4.1逻辑与
“&&”是双目运算符,其要求有两个操作数,如a && b。
(1)1位逻辑与 | reg A,B; always@(*)begin C=A&&B; end |
A和B都为1时,C为1,否则C为0。 对应硬件电路图如下所示:
(2)多位逻辑与 | reg[2:0] A,B,C; always@(*)begin C=A&&B; end |
A或B都不为0时,C为1,否则为0。 对应硬件电路图如下所示:
5.4.2逻辑或
“||”是双目运算符,其要求有两个操作数,如 a||b。 (1)1位逻辑或 | reg A,B; always@(*)begin C=A||B; end |
A和B其中1个为1,C为1,否则C为0。 对应硬件电路图如下图所示:
(2)多位逻辑或 | reg[2:0] A,B,C; always@(*)begin C=A||B; end |
A和B其中1个非0,C为1,否则C为0。 对应硬件电路图如下图所示:
5.4.3逻辑非
“!”是单目运算符,只要求有一个操作数,如!(a>b)。 对操作数a需要先判断非a是否为真,为真就执行{}内的操作,为假的话就结束操作。 下表为逻辑运算的真值表,其表示当a和b的值为不同的组合时各种逻辑运算所得到的值。 表1.3- 10逻辑运算的真值表
逻辑运算符最后的结果只有逻辑真或逻辑假两种,即1或0。一般情况下用逻辑运算符作判断条件时逻辑与操作只能是两个1位宽的数,只有两个表达式同时为真才为真,有一个为假则为假。 如果操作数是多位的,则可以将操作数看做整体,若操作数中每一位都是0值则为逻辑0值;若操作数中有1则为逻辑1值。
| assign a = 4’b0111 && 4’b1000; assign b = 4’b0111 || 4’b1000; assign c = !4’b0111; |
由于4’b0111和4’b1000都不是0,不为0则被认为是逻辑真,所以上面的代码等效于如下代码。 | assign a = 1’b1 && 1’b1; assign b = 1’b1 || 1’b1; assign c = !(1’b1); |
也就是结果为a 为逻辑真,b 为逻辑真,c 为逻辑假。
5.4.4经验总结
逻辑运算符中“&&”和“||”的优先级低于算数运算符;“!”的优先级高于双目逻辑运算符。 举例如下: (a < b)&&(c > d)可写成:a < b && c > d ; (a = = b)| |(c = = d)可写成:a = = b | | c = = d ; (!a)| |(a > b)可写成:!a | | a > b 。 |
笔者使用心得:逻辑运算符两边对应的是1比特信号 | wire[3:0] a, b; assign d = a &&b ; |
请读者注意上文代码,其中a和b都是多比特信号,表示两个多比特信号进行逻辑与。这句代码的正确理解是:当a不等于0 并且 b不等于0时,d的值为1。然而即使是有过多年工作经验的工程师也很难从直观上直接理解上文代码所隐含的意思。不等于0就是表示逻辑真,等于0就表示逻辑假的这一概念很容易被忽略。
因此上文代码,虽然从功能上没有错误,但设计师在设计中不应该以炫耀技术为目的进行代码编写,而且这种写法很容易出现误设计的情况,例如可能原本要表达 assign d =a & b,但最后由于设计不够直观而写成了上面的代码,导致设计出现问题。因此在设计中写出直观能理解,让自己与他者看到代码时可以立刻明白代码的意思非常重要,所以笔者建议上面代码写成如下形式。 | wire[3:0] a, b; assign d = (a!=0) && (b!=0) ; |
笔者使用心得2:不要试图记住优先级,而是要多用括号
实际上,工程师们在工作中并不会记住所有优先级排序,记住所有的优先级的这一工作也并不会大幅度的提升工程师的工作效率。在设计中可能会遇到如下所示代码: (1)a < b && c > d ; (2)a = = b | | c = = d ; (3)!a | | a > b 。 假如没有记住运算符的优先级,遇到类似这三个例子的情况时势必会花一定的时间来理清思路,思考究竟先判断哪部分。假如工程师能够记住优先级,也需要就这些代码进行沟通和检查的工作,而且人是容易犯错的,而这些错误经常会被忽略,很难被检查出来。 因此,为了提高程序的可读性,明确表达各运算符间的优先关系,笔者建议读者在设计时多使用括号。上面的三个例子就可分别写成: 1)(a < b)&&(c > d); 2)(a = = b)| |(c = = d); 3)(!a)| |(a > b)。
笔者使用心得3:多用“逻辑与”和“逻辑或”,少用逻辑非 “逻辑与”翻译成中文就是“并且”,“逻辑或”翻译成中文就是“或者”。假设有一个信号flag,0表示空闲,1表示忙。“(!(flag==0)&& a==4’b1000)”,读起来就是“在空闲的时候取其反状态,并且当a等于4’b1000时条件成立”。这样读起来非常拗口,并且在阅读这一代码时还需要脑袋还要多转一下弯,多进行一层思考。为了让代码更加直观,笔者建议上面的例子写成“flag==1 && a==4’b1000”,读起来就是“在忙并且 a等于4’b1000的时候”条件成立。
|