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 188 simlib.v
1689module \$bmux (A, S, Y);
1690
1691    parameter WIDTH = 0;
1692    parameter S_WIDTH = 0;
1693
1694    input [(WIDTH << S_WIDTH)-1:0] A;
1695    input [S_WIDTH-1:0] S;
1696    output [WIDTH-1:0] Y;
1697
1698    wire [WIDTH-1:0] bm0_out, bm1_out;
1699
1700    generate
1701        if (S_WIDTH > 1) begin:muxlogic
1702            \$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));
1703            \$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));
1704            assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out;
1705        end else if (S_WIDTH == 1) begin:simple
1706            assign Y = S ? A[2*WIDTH-1:WIDTH] : A[WIDTH-1:0];
1707        end else begin:passthru
1708            assign Y = A;
1709        end
1710    endgenerate
1711
1712endmodule
yosys> help $bwmux

Bit-wise multiplexer

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

Properties:

is_evaluable

Simulation model (verilog)
Listing 189 simlib.v
2058module \$bwmux (A, B, S, Y);
2059
2060    parameter WIDTH = 0;
2061
2062    input [WIDTH-1:0] A, B;
2063    input [WIDTH-1:0] S;
2064    output [WIDTH-1:0] Y;
2065
2066    genvar i;
2067    generate
2068        for (i = 0; i < WIDTH; i = i + 1) begin:slices
2069            assign Y[i] = S[i] ? B[i] : A[i];
2070        end
2071    endgenerate
2072
2073endmodule
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 190 simlib.v
1764module \$demux (A, S, Y);
1765
1766    parameter WIDTH = 1;
1767    parameter S_WIDTH = 1;
1768
1769    input [WIDTH-1:0] A;
1770    input [S_WIDTH-1:0] S;
1771    output [(WIDTH << S_WIDTH)-1:0] Y;
1772
1773    genvar i;
1774    generate
1775        for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices
1776            assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0;
1777        end
1778    endgenerate
1779
1780endmodule
yosys> help $mux

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

Properties:

is_evaluable

Simulation model (verilog)
Listing 191 simlib.v
1670module \$mux (A, B, S, Y);
1671
1672    parameter WIDTH = 0;
1673
1674    input [WIDTH-1:0] A, B;
1675    input S;
1676    output [WIDTH-1:0] Y;
1677
1678    assign Y = S ? B : A;
1679
1680endmodule
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 192 simlib.v
1722module \$pmux (A, B, S, Y);
1723
1724    parameter WIDTH = 0;
1725    parameter S_WIDTH = 0;
1726
1727    input [WIDTH-1:0] A;
1728    input [WIDTH*S_WIDTH-1:0] B;
1729    input [S_WIDTH-1:0] S;
1730    output reg [WIDTH-1:0] Y;
1731
1732    integer i;
1733    reg found_active_sel_bit;
1734
1735    always @* begin
1736        Y = A;
1737        found_active_sel_bit = 0;
1738        for (i = 0; i < S_WIDTH; i = i+1)
1739            case (S[i])
1740                1'b1: begin
1741                    Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i);
1742                    found_active_sel_bit = 1;
1743                end
1744                1'b0: ;
1745                1'bx: begin
1746                    Y = 'bx;
1747                    found_active_sel_bit = 'bx;
1748                end
1749            endcase
1750    end
1751
1752endmodule
yosys> help $tribuf

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

Simulation model (verilog)
Listing 193 simlib.v
1839module \$tribuf (A, EN, Y);
1840
1841    parameter WIDTH = 0;
1842
1843    input [WIDTH-1:0] A;
1844    input EN;
1845    output [WIDTH-1:0] Y;
1846
1847    assign Y = EN ? A : 'bz;
1848
1849endmodule