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:
- 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.
- 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):
- 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
- 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 : (SEL == 1)? I : (SEL == 2)? I : (SEL == 3)? I : (SEL == 4)? I : (SEL == 5)? I : (SEL == 6)? I : I; endmodule