Examples: MUX 4→1

Complete implementation of a 4-to-1 multiplexer in different VHDL styles.

The Multiplexer (MUX)

A multiplexer selects one input out of N based on a selection signal.

MUX 4→1 schematic: 4 inputs selected by i_sel → output o_y

Truth table of a 4→1 MUX:

i_selo_y
"00"i_d0
"01"i_d1
"10"i_d2
"11"i_d3

Style 1: Conditional Concurrent Assignment

The most compact solution for small MUXes.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
 
entity mux4to1 is
  port (
    i_d0  : in  std_logic;
    i_d1  : in  std_logic;
    i_d2  : in  std_logic;
    i_d3  : in  std_logic;
    i_sel : in  std_logic_vector(1 downto 0);
    o_y   : out std_logic
  );
end entity mux4to1;
 
architecture rtl of mux4to1 is
begin
  o_y <= i_d0 when i_sel = "00" else
         i_d1 when i_sel = "01" else
         i_d2 when i_sel = "10" else
         i_d3;
end architecture rtl;

Style 2: Selected Assignment (with/select)

architecture rtl of mux4to1 is
begin
  with i_sel select o_y <=
    i_d0 when "00",
    i_d1 when "01",
    i_d2 when "10",
    i_d3 when others;
end architecture rtl;

Style 3: Process with case

Most readable for complex MUXes or in sequential context.

architecture rtl of mux4to1 is
begin
  p_mux : process(i_d0, i_d1, i_d2, i_d3, i_sel)
  begin
    case i_sel is
      when "00"   => o_y <= i_d0;
      when "01"   => o_y <= i_d1;
      when "10"   => o_y <= i_d2;
      when others => o_y <= i_d3;
    end case;
  end process p_mux;
end architecture rtl;

MUX on a Data Bus (std_logic_vector)

In practice, MUXes often operate on buses.

entity mux4to1_bus is
  generic (
    g_WIDTH : integer := 8
  );
  port (
    i_d0  : in  std_logic_vector(g_WIDTH-1 downto 0);
    i_d1  : in  std_logic_vector(g_WIDTH-1 downto 0);
    i_d2  : in  std_logic_vector(g_WIDTH-1 downto 0);
    i_d3  : in  std_logic_vector(g_WIDTH-1 downto 0);
    i_sel : in  std_logic_vector(1 downto 0);
    o_y   : out std_logic_vector(g_WIDTH-1 downto 0)
  );
end entity mux4to1_bus;
 
architecture rtl of mux4to1_bus is
begin
  with i_sel select o_y <=
    i_d0 when "00",
    i_d1 when "01",
    i_d2 when "10",
    i_d3 when others;
end architecture rtl;

The generic g_WIDTH makes the component parameterizable: one description, multiple instantiations with different widths.


Registered MUX (pipeline)

To improve timing performance, you can register the MUX output.

architecture rtl of mux4to1_reg is
  signal r_out : std_logic;
begin
  p_mux_reg : process(i_clk)
  begin
    if rising_edge(i_clk) then
      if i_rst = '1' then
        r_out <= '0';
      else
        case i_sel is
          when "00"   => r_out <= i_d0;
          when "01"   => r_out <= i_d1;
          when "10"   => r_out <= i_d2;
          when others => r_out <= i_d3;
        end case;
      end if;
    end if;
  end process p_mux_reg;
 
  o_y <= r_out;
end architecture rtl;

The output o_y is now synchronous: it changes only on the rising clock edge. This introduces one cycle of latency but improves timing.


Style Summary

StyleAdvantagesDisadvantages
when/elseCompact, readableImplicit priority (cascade)
with/selectNo priority, clearSingle selection input
process/caseFlexible, readableMore verbose

For pure MUXes (no priority), with/select is the recommended style.