Showing results for 
Show  only  | Search instead for 
Did you mean: 
Registered: ‎04-26-2012

I can't generate a generic Multiplexer

Hello, everybody. This is my first question on this forum, so please correct me if I make some mistake.


I'm trying to create a multiplexer, but my wish is to make it as generic as possible. This is, with a generic input width and an arbitrary number of signals, to avoid to individually create all options for a large instance. I don't know how to "dynamically create" port inputs, so what I do is to combine all signals in a large input vector.


What I try to do is using the MUXF7 primitive, a 2-input 1-output multiplexer, and replicate it for the number of inputs and the data bit width. To replicate for more than two inputs, the outputs of each multiplexer connect to a new stage of half the size (in number of util signals) until only 1 signal remains.

I guess it is better understood looking at the code.

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_misc.all;
use ieee.numeric_std.all;
use ieee.math_real.all;

library unisim;
use unisim.vcomponents.all;

-- Entity declaration.
entity gmuxer is
        WIDTH: integer := 8;
        NINPT: integer := 64
        chnsel: in std_logic_vector((integer(ceil(LOG2(real(NINPT))))-1) downto 0);
        datain: in std_logic_vector((NINPT*WIDTH-1) downto 0);
        dataout: out std_logic_vector((WIDTH-1) downto 0);
        tst: out std_logic
end entity;
-- Architecture declaration.
architecture behavioral of gmuxer is
    constant LOG2_NINPT: integer := integer(ceil(LOG2(real(NINPT))));
    subtype datawrd is std_logic_vector((WIDTH-1) downto 0);
    type mux_dat is array (0 to LOG2_NINPT, 0 to (NINPT-1)) of datawrd;
    signal mux_flow: mux_dat;

    for i in 1 to NINPT generate
        mux_flow(0,i-1) <= datain((i*WIDTH-1) downto ((i-1)*WIDTH));
    end generate;
    for i in 1 to LOG2_NINPT generate
        for j in 0 to ((NINPT/(2**i))-1) generate
            for k in 0 to (WIDTH-1) generate
                MUXF7_inst: MUXF7
                port map(
                    O => mux_flow(i,j)(k),
                    I0 => mux_flow(i-1,2*j)(k),
                    I1 => mux_flow(i-1,2*j+1)(k),
                    S => chnsel(i-1)
            end generate;
        end generate;
    end generate;
--    process(mux_flow,chnsel)
--    variable selector: std_logic;
--    begin
--        output_stg_rep:
--        for i in 1 to LOG2_NINPT loop
--            selector := chnsel(i-1);
--            output_inp_rep:
--            for j in 0 to ((NINPT/(2**i))-1) loop
--                output_dat_rep:
--                for k in 0 to (WIDTH-1) loop
--                    case selector is
--                        when '1' =>
--                            mux_flow(i,j)(k) <= mux_flow(i-1,2*j)(k);
--                        when '0' =>
--                            mux_flow(i,j)(k) <= mux_flow(i-1,2*j+1)(k);
--                        when others =>
--                            --mux_flow(i,j)(k) <= mux_flow(i,j)(k);
--                    end case;
--                end loop;
--            end loop;
--        end loop;
--    end process;
    dataout <= std_logic_vector(mux_flow(LOG2_NINPT,0));
    tst <= AND_REDUCE(datain);
    --tst <= datain(0);
end architecture;


I'm working in a project for Virtex 5 FPGA. However, when I synthesize the project and try to view the RTL it is empty. I repeated the design using a process but the problem occurs again.

Do anyone know what my error is or if there is a better way to implement my idea?



0 Kudos
3 Replies
Registered: ‎07-21-2009

Simple code is good.

Readable (understandable) code is good.

Code with a predictable translation into hardware is good.


'Generic' code which is not simple and not readable...  not so good.  Even if it synthesises correctly.


To what end are you torturing yourself in this way?


-- Bob Elkind

README for newbies is here:

1. Read the manual or user guide. Have you read the manual? Can you find the manual?
2. Search the forums (and search the web) for similar topics.
3. Do not post the same question on multiple forums.
4. Do not post a new topic or question on someone else's thread, start a new thread!
5. Students: Copying code is not the same as learning to design.
6 "It does not work" is not a question which can be answered. Provide useful details (with webpage, datasheet links, please).
7. You are not charged extra fees for comments in your code.
8. I am not paid for forum posts. If I write a good post, then I have been good for nothing.
Registered: ‎09-09-2010

"To what end are you torturing yourself in this way?"



To O/P:

Just write code that infers the multiplexing functionality, and let the tools take care of the low-level details. They are actually quite good at that sort of thing now!


"If it don't work in simulation, it won't work on the board."
Registered: ‎02-25-2008

There is zero point in making a generic multiplexor. Absolutely none. The tools are pretty good at sorting out what you need without resorting to bizarre stuff.


Here are a couple of pro tips, though.


a) The width of each input vector can be arbitrary, and you don't even need a WIDTH generic to set it. Something like this (a two-input mux for clarity) solves the width problem neatly using unconstrained vectors on the port list. Note that it doesn't have to be its own entity (I rarely, if ever, create separate entities just for muxes):


entity Mux2To1 is

    port (

        InA     : in std_logic_vector;

        InB     : in std_logic_vector;

        Select  : in std_logic;

        OutData : out std_logic_vector);

end entity Mux2To1;


architecture mux of Mux2To1 is


    TheMux : process (InA, InB, Select) is

        MuxSelect : if Select = '0' then

            OutData <= InA;


            OutData <= InB;

        end if MuxSelect;

    end process TheMux;

end architecture mux;


The size of the InA, InB and OutData vectors is set when the entity is instantiated. The port map's actuals (the signals on the right-hand side of each => in the port map) have to have known widths, and those known widths set the size of those vectors in that instance. You can have several instances of the same entity, each with different width ports.


(And if you do need to know the size of the vectors in the mux entity, you can use the 'length attribute.)


b) The mux select doesn't have to be a std_logic_vector. It can be a natural (with a range), for clarity. Here's some fun with attributes and subtypes.


architecture multiplex of foo is


    constant WIDTH : natural := 32;

    subtype muxdata_t is std_logic_vector(WIDTH-1 downto 0);

    constant NUMINPUTS : natural := 10;

    subtype select_t is natural range 0 to NUMINPUTS-1;

    signal MuxSelect : select_t;

    type muxinputs_t is array (select_t'range) of muxdata_t;

    signal MuxInputs : muxinputs_t;

    signal MuxOutput : muxdata_t;



    --  ... assign to various MuxInputs as necessary 


    -- the mux:

    MuxOutput <= MuxInputs(MuxSelect);


    -- etc

end architecture multiplex;


So there are lots of ways to do this. But let the tools do the work.

----------------------------Yes, I do this for a living.