Verilog conditional (ternary) operator

The simplest way to implement "narrow" multiplexers in Verilog is to use the conditional (?:) operator:

// 2-to-1 mux; the A control selects either B or C
assign Q = A? B:C;

B and C are m-bit expressions (for example, 10-bit buses); this statement implements an (m x (2-to-1)) multiplexer.

This operator is particularly convenient, because it can be used in an expression, and so can form the right-hand-side of a continuous assignment. This is therefore a compact way of driving a net ("wire") without the overhead of the procedural if statement.

A Verilog mux described in this way is essentially identical to one described using an if-else statement, although the two will simulate differently when the control expression (A) contains metavalues. The synthesised hardware, however, will probably be identical; in particular, both are likely to be implemented as priority encoders once the control width exceeds a small value.

In practice, the conditional operator tends to be used for 2:1 multiplexers only, because:

  1. wider multiplexers are likely to be implemented as priority encoders. However, XST implements the 8:1 code below as efficiently as any other style here, and does not use a priority encoder.
  2. the code for cascaded conditional operators is generally less readable than the alternatives.

There is a widespread opinion that a multiplexer implemented using the conditional operator is better than other implementations because it propagates X values, so making it easier to find errors in a simulation. The reasoning is that the control expression is treated differently from the control expression in, for example, an if statement. If A contains metavalues, the corresponding bits of B and C are combined in a way that simulates X propagation from the control input through the multiplexer. However, in practice, this is of little use, for these reasons (1):

  1. Procedural if and case statements don't have this functionality, and it's not practical to build a complete device using only the conditional operator
  2. The X propagation is "optimistic". In some circumstances, a gate-level description will propagate X's while the conditional operator will not (see Mux #4 below). The behavioural code in Mux #5 below is even more pessimistic than the gate-level version, and is arguably a much better way to carry out X propagation.


module MUX8TO1(input [2:0] SEL, input [7:0] I, output O);
   assign O =
          (SEL == 0)? I[0] : 
          (SEL == 1)? I[1] : 
          (SEL == 2)? I[2] : 
          (SEL == 3)? I[3] : 
          (SEL == 4)? I[4] : 
          (SEL == 5)? I[5] : 
          (SEL == 6)? I[6] : I[7];