Interested In VHDL Training? Click Here

0 votes
in VHDL by (240 points)

How do you implement a multiplexer or MUX in VHDL?

4 Answers

0 votes
by (1.8k points)

VHDL Multiplexer (MUX)

Quick Syntax

output <= input1 when mux_sel = "000" else
input2 when mux_sel = "001" else
input3 when mux_sel = "010" else
....more options here...
(others => '0');

Purpose

A multiplexer, or MUX for short, is simply a way to select between multiple inputs to a common output. It is one of the most common things that you will code in VHDL and is used frequently.

With that in mind, you often see:
1) asynchronous MUX, or one that is not clocked: implemented as concurrent
2) asynchronous MUX, or one that is not clocked: implemented as an unclocked process
3) synchronous MUX, or one that is clocked: implemented as a clocked process

You will typically see people calling asynchronous the same as concurrent, which is the way it's implemented. However, you can also have an asynchronous MUX in a process that is not clocked. You will also see them calling a synchronous a clocked MUX, since that is the way they are implemented.

Which one you use is usually determined by the needs of the design. When it comes to routing and timing, the tools will have an easier time of routing a clocked MUX, since it allows it to more easily fit things in the part instead of stuffing logic in between clocked signals.

Keep in mind that many times you will see asynchronous MUXes used even though the output and inputs are to and from clocked signals. The tools will put timing constraints on these based on the clock domain constraints, so you need to be thoughtful here. Don't make the mux be a clock domain crossing since that's not good design practice.

Also, it sticks levels of logic in between clocked signals when you do that, which makes it harder to meet timing on higher frequency designs.

Examples

Note that we include the else others at the end even though all select states are covered. It's just good design practice to do so. Read on to find out why. Some will debate whether it's necessary.

Here are some great examples of asynchronous/concurrent MUXes. First up is a 2 to 1 MUX:
output <= input1 when mux_sel = '0' else
input2 when mux_sel = '1' else
(others => '0');
Here's a 4 to 1 MUX:
output <= input1 when mux_sel = "00" else
input2 when mux_sel = "01" else
input3 when mux_sel = "10" else
input4 when mux_sel = "11" else
(others => '0');
Here are some great examples of synchronous/clocked MUXes. First up is a 2 to 1 MUX:
MUX : process (clk,mux_sel)
begin
if rising_edge(clk) then
case mux_sel is
when "0" =>
output <= input_1;
when "1" =>
output <= input_2;
when others =>
output <= (others => '0');
end case ;
end if;
end process;
Here's a 4 to 1 MUX:
MUX : process (clk,mux_sel)
begin
if rising_edge(clk) then
case mux_sel is
when "00" =>
output <= input_1;
when "01" =>
output <= input_2;
when "10" =>
output <= input_3;
when "11" =>
output <= input_4;
when others =>
output <= (others => '0');
end case ;
end if;
end process;
If you want an asynchronous/unclocked MUX but in a process, just remove the if rising_edge(clk) statement from the above examples.

Best Practices

1. MUXes are very common, so get comfortable with using them.

2. A clocked MUX in a process will give you better timing and routing, so try to use them for higher frequency designs. Your logic needs to account for the extra clock delay of course on the output of the MUX.

3. It's smart to use an else others to have a catch all in case the select signal doesn't cover all cases. Even if your design does, you always have the risk of someone coming in behind you and removing one of the options down the road.

4. Make sure that the output, inputs, and select are on the same clock domain, unless the MUX is purely asynchronous. Otherwise, use proper clock domain crossing practices.

5. Don't manually MUX clock signals. Use the device's intended primitives for that. Consult the documentation for your FPGA part family to see what the best way to do it is in your situation.
0 votes
by (700 points)

There many ways to implement a MUX in VHDL. The most common and recommended method involves using the "case" statement.

Example :

signal select : std_logic_vector ( 2 downto 0 ) ;
signal input_0 : std_logic_vector ( 15 downto 0 ) ;
signal input_1 : std_logic_vector ( 15 downto 0 ) ;
signal input_2 : std_logic_vector ( 15 downto 0 ) ;
signal input_3 : std_logic_vector ( 15 downto 0 ) ;
signal input_4 : std_logic_vector ( 15 downto 0 ) ;
signal input_5 : std_logic_vector ( 15 downto 0 ) ;
signal input_6 : std_logic_vector ( 15 downto 0 ) ;
signal input_7 : std_logic_vector ( 15 downto 0 ) ;
signal output : std_logic_vector ( 15 downto 0 ) ;

my_mux : process
(
select ,
input_0 ,
input_1 ,
input_2 ,
input_3 ,
input_4 ,
input_5 ,
input_6 ,
input_7 ,
) is
begin
case select is
when "000" =>
output <= input_0 ;
when "001" =>
output <= input_1 ;
when "010" =>
output <= input_2 ;
when "011" =>
output <= input_3 ;
when "100" =>
output <= input_4 ;
when "101" =>
output <= input_5 ;
when "110" =>
output <= input_6 ;
when "111" =>
output <= input_7 ;
end case ;
end process my_mux ;
0 votes
by (700 points)

It depends on the context. There are several ways: using concurrent assignments and using sequential assignments.

Sequential:

process (sel, in0, in1)
begin
if sel = '0' then
o <= in0;
else
o <= in1;
end if;
end process;
Concurrent:

1. o <= in0 when sel = '0' else in1;
2. with sel select b <=
in0 when '0',
in1 when others;
0 votes
by (700 points)

As in all programming languages, in VHDL there are multiple ways to implement something. It is important to understand the concept behind how a MUX works, the implementation can then be according to the developers style and requirements. A mux is basically a selector. It takes multiple signals as an input and also a 'select signal'. The selection of the input signal that goes to the output depends on the value of the 'select' signal.

This clearly is a case of conditional programming and thus can be implemented by one of the conditional statements in VHDL e.g case-when statement, if-elseif statement etc. An example implementation of MUX is given below. It is a MUX with four inputs and one output. The select signal (variable i_sel ) determines which of the four inputs appears on the output.

library ieee;
use ieee.std_logic_1164.all;

entity Mux4_1 is
port (
i_sel : in std_logic_vector(1 downto 0);
in1 : in std_logic;
in2 : in std_logic;
in3 : in std_logic;
in4 : in std_logic;
out_data : out std_logic
);
end entity Mux4_1;

architecture RTL of Mux4_1 is
begin
out_data <= in1 when i_sel = "00" else
in2 when i_sel = "01" else
in3 when i_sel ="10" else
in4;
end architecture RTL;
The output of the mux is signal in1 when value of variable i_sel is '00'. Similarly, output is in2 and in3 when value of i_sel is '01' and '10' respectively. If neither of these cases is true i.e. value of i_sel is '11', the output is in4.

Want to improve your VHDL skills?

Click Here - Sign Up For VHDL Training

© 2022 by Hardware Coder. User contributions are licensed under cc by-sa 4.0 with attribution required. Attribution means a link to the question, answer, user, etc on this site.

This site is owned and operated by Hardware Coder in McKinney, Texas.

Send Us A Message
About Us

By using this site, you agree to the following:

Privacy Policy
Terms and Conditions
DMCA Policy
Earnings Disclaimer
Legal Disclaimer

...