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 153 simlib.v
1544module \$bmux (A, S, Y);
1545
1546    parameter WIDTH = 0;
1547    parameter S_WIDTH = 0;
1548
1549    input [(WIDTH << S_WIDTH)-1:0] A;
1550    input [S_WIDTH-1:0] S;
1551    output [WIDTH-1:0] Y;
1552
1553    wire [WIDTH-1:0] bm0_out, bm1_out;
1554
1555    generate
1556        if (S_WIDTH > 1) begin:muxlogic
1557            \$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));
1558            \$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));
1559            assign Y = S[S_WIDTH-1] ? bm1_out : bm0_out;
1560        end else if (S_WIDTH == 1) begin:simple
1561            assign Y = S ? A[2*WIDTH-1:WIDTH] : A[WIDTH-1:0];
1562        end else begin:passthru
1563            assign Y = A;
1564        end
1565    endgenerate
1566
1567endmodule
yosys> help $bwmux

Bit-wise multiplexer

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

Properties:

is_evaluable

Simulation model (verilog)
Listing 154 simlib.v
1913module \$bwmux (A, B, S, Y);
1914
1915    parameter WIDTH = 0;
1916
1917    input [WIDTH-1:0] A, B;
1918    input [WIDTH-1:0] S;
1919    output [WIDTH-1:0] Y;
1920
1921    genvar i;
1922    generate
1923        for (i = 0; i < WIDTH; i = i + 1) begin:slices
1924            assign Y[i] = S[i] ? B[i] : A[i];
1925        end
1926    endgenerate
1927
1928endmodule
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 155 simlib.v
1619module \$demux (A, S, Y);
1620
1621    parameter WIDTH = 1;
1622    parameter S_WIDTH = 1;
1623
1624    input [WIDTH-1:0] A;
1625    input [S_WIDTH-1:0] S;
1626    output [(WIDTH << S_WIDTH)-1:0] Y;
1627
1628    genvar i;
1629    generate
1630        for (i = 0; i < (1 << S_WIDTH); i = i + 1) begin:slices
1631            assign Y[i*WIDTH+:WIDTH] = (S == i) ? A : 0;
1632        end
1633    endgenerate
1634
1635endmodule
yosys> help $mux

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

Properties:

is_evaluable

Simulation model (verilog)
Listing 156 simlib.v
1525module \$mux (A, B, S, Y);
1526
1527    parameter WIDTH = 0;
1528
1529    input [WIDTH-1:0] A, B;
1530    input S;
1531    output [WIDTH-1:0] Y;
1532
1533    assign Y = S ? B : A;
1534
1535endmodule
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 157 simlib.v
1577module \$pmux (A, B, S, Y);
1578
1579    parameter WIDTH = 0;
1580    parameter S_WIDTH = 0;
1581
1582    input [WIDTH-1:0] A;
1583    input [WIDTH*S_WIDTH-1:0] B;
1584    input [S_WIDTH-1:0] S;
1585    output reg [WIDTH-1:0] Y;
1586
1587    integer i;
1588    reg found_active_sel_bit;
1589
1590    always @* begin
1591        Y = A;
1592        found_active_sel_bit = 0;
1593        for (i = 0; i < S_WIDTH; i = i+1)
1594            case (S[i])
1595                1'b1: begin
1596                    Y = found_active_sel_bit ? 'bx : B >> (WIDTH*i);
1597                    found_active_sel_bit = 1;
1598                end
1599                1'b0: ;
1600                1'bx: begin
1601                    Y = 'bx;
1602                    found_active_sel_bit = 'bx;
1603                end
1604            endcase
1605    end
1606
1607endmodule
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 158 simlib.v
1694module \$tribuf (A, EN, Y);
1695
1696    parameter WIDTH = 0;
1697
1698    input [WIDTH-1:0] A;
1699    input EN;
1700    output [WIDTH-1:0] Y;
1701
1702    assign Y = EN ? A : 'bz;
1703
1704endmodule