如果想表示图2—8所示的二选一MUX,该如何表示呢?下例展示了3种二选一MUX的表达方式,分别使用了assign和always。
图2—8 二选一选择器(MUX)原理图
那么如图2—9所示的多选一MUX,又该如何表示呢?
图2—9 多选一MUX原理图
因为使用assign表示显然会过于复杂,所以需要用always块表示。表示方法有两种,其一如下例所示。
其二如下例所示。
需要注意的是,上面两种表达综合出来的电路是不同的,其中,第2种所综合的电路如图2—9所示,而第1种综合出来的电路如图2—10所示,从图2—10可见,使用if表述的选择关系,综合的电路是一层一层逐渐展开的,写在if最前面的语句,掌握着最终的选择权,因而优先级最高,再往后优先级逐层下降,而使用case表述的MUX,每个选择都是并列的,优先级相同。
图2—10 包含优先级的电路
使用if表述,有可能出现隐藏逻辑,即设计者没有考虑到,但实际会被综合出来的逻辑门。隐藏逻辑是设计的隐患,设计者在写代码时应该清楚其逻辑含义,尽量避免出现隐藏逻辑。为了避免设计中出现隐藏逻辑,在实际项目中往往会提倡使用case语句来表达。
下例中反映出if的优先级特征,条件 s 5包含 s ==4的情况,因为 s 5优先,因而当 s ==4时, z 的赋值是 a 而不是 b 。如果设计意图是要在 s ==4时使 z = b ,则应当将其写在 s 5之前。
同样的逻辑可以改写为下例中case的形式。使用case会使 z 的赋值更加明确,因为在写case语句时能够强迫设计者更加细致地思考问题,从而避免隐藏逻辑。在写case语句时,需要注意default的用法。这里假设信号 s 的位宽是3比特,数值范围为0~7,在下例中已经将这些情况都讨论完全了,因而default可以省略,但一般项目要求default都要写,以避免设计者遗漏了某些情况而造成隐藏逻辑。
case有一种变体是casez,它可以拓展case的使用范围。如果case(s)的情况有很多,例如10000个,需要对这10000种情况进行适当归类,才能让代码简练,此时需要用到casez,如下例所示,其中,问号的意思是0或1都能匹配,类似计算机语言中的通配符。
虽然很多项目提倡使用case或casez来表述选择器,但究竟是使用if还是case,仍然取决于表达的需要。总体而言,case便于判断是否相等的情况,而if适合判断大于或小于关系,不同情况用不同的表达,可以使Verilog逻辑更加清晰,也更便于维护。
注意 组合逻辑中的if和else if,最后必须跟一句else,使整体逻辑完整。若没有else,则该电路会综合出一个锁存器(Latch)。锁存器不属于10种基本元器件之一。在设计中,凡有寄存需求,应尽量使用触发器,避免使用锁存器,特别要避免不写else引起的隐藏逻辑。