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, the unique or unique0 SystemVerilog keywords, 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 185 simlib.v
1666module \$bmux (A, S, Y);
1667
1668    parameter WIDTH = 0;
1669    parameter S_WIDTH = 0;
1670
1671    input [(WIDTH << S_WIDTH)-1:0] A;
1672    input [S_WIDTH-1:0] S;
1673    output [WIDTH-1:0] Y;
1674
1675    wire [WIDTH-1:0] bm0_out, bm1_out;
1676
1677    generate
1678        if (S_WIDTH > 1) begin:muxlogic
1679            \$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));
1680            \$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));
1681            assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out;
1682        end else if (S_WIDTH == 1) begin:simple
1683            assign Y = S ? A[2*WIDTH-1:WIDTH] : A[WIDTH-1:0];
1684        end else begin:passthru
1685            assign Y = A;
1686        end
1687    endgenerate
1688
1689endmodule
yosys> help $bwmux

Bit-wise multiplexer

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

Properties:

is_evaluable

Simulation model (verilog)
Listing 186 simlib.v
2035module \$bwmux (A, B, S, Y);
2036
2037    parameter WIDTH = 0;
2038
2039    input [WIDTH-1:0] A, B;
2040    input [WIDTH-1:0] S;
2041    output [WIDTH-1:0] Y;
2042
2043    genvar i;
2044    generate
2045        for (i = 0; i < WIDTH; i = i + 1) begin:slices
2046            assign Y[i] = S[i] ? B[i] : A[i];
2047        end
2048    endgenerate
2049
2050endmodule
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 187 simlib.v
1741module \$demux (A, S, Y);
1742
1743    parameter WIDTH = 1;
1744    parameter S_WIDTH = 1;
1745
1746    input [WIDTH-1:0] A;
1747    input [S_WIDTH-1:0] S;
1748    output [(WIDTH << S_WIDTH)-1:0] Y;
1749
1750    genvar i;
1751    generate
1752        for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices
1753            assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0;
1754        end
1755    endgenerate
1756
1757endmodule
yosys> help $mux

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

Properties:

is_evaluable

Simulation model (verilog)
Listing 188 simlib.v
1647module \$mux (A, B, S, Y);
1648
1649    parameter WIDTH = 0;
1650
1651    input [WIDTH-1:0] A, B;
1652    input S;
1653    output [WIDTH-1:0] Y;
1654
1655    assign Y = S ? B : A;
1656
1657endmodule
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 189 simlib.v
1699module \$pmux (A, B, S, Y);
1700
1701    parameter WIDTH = 0;
1702    parameter S_WIDTH = 0;
1703
1704    input [WIDTH-1:0] A;
1705    input [WIDTH*S_WIDTH-1:0] B;
1706    input [S_WIDTH-1:0] S;
1707    output reg [WIDTH-1:0] Y;
1708
1709    integer i;
1710    reg found_active_sel_bit;
1711
1712    always @* begin
1713        Y = A;
1714        found_active_sel_bit = 0;
1715        for (i = 0; i < S_WIDTH; i = i+1)
1716            case (S[i])
1717                1'b1: begin
1718                    Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i);
1719                    found_active_sel_bit = 1;
1720                end
1721                1'b0: ;
1722                1'bx: begin
1723                    Y = 'bx;
1724                    found_active_sel_bit = 'bx;
1725                end
1726            endcase
1727    end
1728
1729endmodule
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 190 simlib.v
1816module \$tribuf (A, EN, Y);
1817
1818    parameter WIDTH = 0;
1819
1820    input [WIDTH-1:0] A;
1821    input EN;
1822    output [WIDTH-1:0] Y;
1823
1824    assign Y = EN ? A : 'bz;
1825
1826endmodule