Multiplexers

Multiplexers are generated by the Verilog HDL frontend for ?:-expressions. Multiplexers are also generated by the proc pass to map the decision trees from RTLIL::Process objects to logic.

The simplest multiplexer cell type is $mux. Cells of this type have a WITDH parameter and data inputs A and B and a data output Y, all of the specified width. This cell also has a single bit control input S. If S is 0 the value from the input A is sent to the output, if it is 1 the value from the B input is sent to the output. So the $mux cell implements the function Y = S ? B : A.

The $pmux cell is used to multiplex between many inputs using a one-hot select signal. Cells of this type have a WIDTH and a S_WIDTH parameter and inputs A, B, and S and an output Y. The S input is S_WIDTH bits wide. The A input and the output are both WIDTH bits wide and the B input is WIDTH*S_WIDTH bits wide. When all bits of S are zero, the value from A input is sent to the output. If the \(n\)‘th bit from S is set, the value \(n\)‘th WIDTH bits wide slice of the B input is sent to the output. When more than one bit from S is set the output is undefined. Cells of this type are used to model “parallel cases” (defined by using the parallel_case attribute or detected by an optimization).

The $tribuf cell is used to implement tristate logic. Cells of this type have a WIDTH parameter and inputs A and EN and an output Y. The A input and Y output are WIDTH bits wide, and the EN input is one bit wide. When EN is 0, the output is not driven. When EN is 1, the value from A input is sent to the Y output. Therefore, the $tribuf cell implements the function Y = EN ? A : 'bz.

Behavioural code with cascaded if-then-else- and case-statements usually results in trees of multiplexer cells. Many passes (from various optimizations to FSM extraction) heavily depend on these multiplexer trees to understand dependencies between signals. Therefore optimizations should not break these multiplexer trees (e.g. by replacing a multiplexer between a calculated signal and a constant zero with an $and gate).

yosys> help $bmux

Binary-encoded multiplexer

Selects between ‘slices’ of A where each value of S corresponds to a unique slice.

Properties:

is_evaluable

Simulation model (verilog)
Listing 174 simlib.v
1658module \$bmux (A, S, Y);
1659
1660    parameter WIDTH = 0;
1661    parameter S_WIDTH = 0;
1662
1663    input [(WIDTH << S_WIDTH)-1:0] A;
1664    input [S_WIDTH-1:0] S;
1665    output [WIDTH-1:0] Y;
1666
1667    wire [WIDTH-1:0] bm0_out, bm1_out;
1668
1669    generate
1670        if (S_WIDTH > 1) begin:muxlogic
1671            \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm0 (.A(A[(WIDTH << (S_WIDTH - 1))-1:0]), .S(S[S_WIDTH-2:0]), .Y(bm0_out));
1672            \$bmux #(.WIDTH(WIDTH), .S_WIDTH(S_WIDTH-1)) bm1 (.A(A[(WIDTH << S_WIDTH)-1:WIDTH << (S_WIDTH - 1)]), .S(S[S_WIDTH-2:0]), .Y(bm1_out));
1673            assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out;
1674        end else if (S_WIDTH == 1) begin:simple
1675            assign Y = S ? A[2*WIDTH-1:WIDTH] : A[WIDTH-1:0];
1676        end else begin:passthru
1677            assign Y = A;
1678        end
1679    endgenerate
1680
1681endmodule
yosys> help $bwmux

Bit-wise multiplexer

Equivalent to a series of 1-bit wide $mux cells.

Properties:

is_evaluable

Simulation model (verilog)
Listing 175 simlib.v
2027module \$bwmux (A, B, S, Y);
2028
2029    parameter WIDTH = 0;
2030
2031    input [WIDTH-1:0] A, B;
2032    input [WIDTH-1:0] S;
2033    output [WIDTH-1:0] Y;
2034
2035    genvar i;
2036    generate
2037        for (i = 0; i < WIDTH; i = i + 1) begin:slices
2038            assign Y[i] = S[i] ? B[i] : A[i];
2039        end
2040    endgenerate
2041
2042endmodule
yosys> help $demux

Demultiplexer i.e routing single input to several outputs based on select signal. Unselected outputs are driven to zero.

Properties:

is_evaluable

Simulation model (verilog)
Listing 176 simlib.v
1733module \$demux (A, S, Y);
1734
1735    parameter WIDTH = 1;
1736    parameter S_WIDTH = 1;
1737
1738    input [WIDTH-1:0] A;
1739    input [S_WIDTH-1:0] S;
1740    output [(WIDTH << S_WIDTH)-1:0] Y;
1741
1742    genvar i;
1743    generate
1744        for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices
1745            assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0;
1746        end
1747    endgenerate
1748
1749endmodule
yosys> help $mux

Multiplexer i.e selecting between two inputs based on select signal.

Properties:

is_evaluable

Simulation model (verilog)
Listing 177 simlib.v
1639module \$mux (A, B, S, Y);
1640
1641    parameter WIDTH = 0;
1642
1643    input [WIDTH-1:0] A, B;
1644    input S;
1645    output [WIDTH-1:0] Y;
1646
1647    assign Y = S ? B : A;
1648
1649endmodule
yosys> help $pmux

Priority-encoded multiplexer

Selects between ‘slices’ of B where each slice corresponds to a single bit of S. Outputs A when all bits of S are low.

Properties:
Simulation model (verilog)
Listing 178 simlib.v
1691module \$pmux (A, B, S, Y);
1692
1693    parameter WIDTH = 0;
1694    parameter S_WIDTH = 0;
1695
1696    input [WIDTH-1:0] A;
1697    input [WIDTH*S_WIDTH-1:0] B;
1698    input [S_WIDTH-1:0] S;
1699    output reg [WIDTH-1:0] Y;
1700
1701    integer i;
1702    reg found_active_sel_bit;
1703
1704    always @* begin
1705        Y = A;
1706        found_active_sel_bit = 0;
1707        for (i = 0; i < S_WIDTH; i = i+1)
1708            case (S[i])
1709                1'b1: begin
1710                    Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i);
1711                    found_active_sel_bit = 1;
1712                end
1713                1'b0: ;
1714                1'bx: begin
1715                    Y = 'bx;
1716                    found_active_sel_bit = 'bx;
1717                end
1718            endcase
1719    end
1720
1721endmodule
yosys> help $tribuf

A tri-state buffer. This buffer conditionally drives the output with the value of the input based on the enable signal.

Properties:

is_evaluable

Simulation model (verilog)
Listing 179 simlib.v
1808module \$tribuf (A, EN, Y);
1809
1810    parameter WIDTH = 0;
1811
1812    input [WIDTH-1:0] A;
1813    input EN;
1814    output [WIDTH-1:0] Y;
1815
1816    assign Y = EN ? A : 'bz;
1817
1818endmodule