Search code examples
genericsvhdlmux

Generic MUX and DEMUX using Generics


It seems to be solved with the current process:

process(sel, X)
begin
    -- set all to 0
    mux_out <= (others => zero);
    -- Set input in correct line
    mux_out(to_integer(unsigned(sel))) <= X;
end process;

I will test more cases with the TestBench and write here the results, thanks again to everyone for the help :)

==== PREVIOUS POST ======= I have implemented the DEMUX by following Paebbles example:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.MATH_REAL.ALL;
use IEEE.NUMERIC_STD.ALL;

entity DeMUX_1toX_N_bits is
  generic (
    PORTS  : POSITIVE  := 4;
    BITS   : POSITIVE  := 8 );
  port (
    sel  : in  STD_LOGIC_VECTOR(integer(ceil(log2(real(PORTS)))) - 1 downto 0);
     X    : in  STD_LOGIC_VECTOR(BITS - 1 downto 0);
    Y    : out  STD_LOGIC_VECTOR((BITS * PORTS) - 1 downto 0)  
    );
end;

architecture rtl of DeMUX_1toX_N_bits is
  type T_SLVV is array(NATURAL range <>) of STD_LOGIC_VECTOR(BITS - 1 downto 0);
  signal mux_out : T_SLVV(PORTS - 1 downto 0);
  begin
  gen : for i in 0 to PORTS - 1 generate
    -- connect Output FLAT VECTOR to the correct T_SLVV lines
     Y(((i + 1) * BITS) - 1 downto (i * BITS)) <=  mux_out(i);
  end generate;

  mux_out(to_integer(unsigned(sel))) <= X;
end;

The Synthesis Tool tells me " Found 1-bit latch for signal mux_out<3><6>. Latches may be generated from incomplete case or if statements. We do not recommend the use of latches in FPGA/CPLD designs, as they may lead to timing problems."

So to solve this i should assign explicitly '0' to all other output bits?

Thanks again for all the help :) This way of coding is really powerful but also complex :)

================== Previous POST ====

I'm developing a VHDL project (for FPGA) as an university lab. I'm stuck on the design of a mux and a demux parametrized both in data size and number of ports. In particular I can't find a way to write a dynamic code (With / Select statements? )

I have in mind something like this :

use IEEE.STD_LOGIC_1164.ALL;

entity generic_mux is
GENERIC (  inputs: INTEGER := 4;              -- number of inputs
           size : INTEGER := 8);              -- size of each input
Port (
  -- ???  how can i define the input data ports if i don't know the exact number?
);
end generic_mux;

architecture arc of generic_mux is
begin
  -- how can i use the select as an address? The With/Select needs a         
  -- defined number of cases...
  --   ???
end arc;

Thanks in advance for your help.


Solution

  • Using VHDL-2008 it can be done like:

    library ieee;
    use ieee.std_logic_1164.all;
    
    package mux_p is
      type slv_array_t is array (natural range <>) of std_logic_vector;
    end package;
    
    package body mux_p is
    end package body;
    
    
    library ieee;
    use ieee.std_logic_1164.all;
    use work.mux_p;
    
    entity mux is
      generic(
        LEN : natural;   -- Bits in each input
        NUM : natural);  -- Number of inputs
      port(
        v_i   : in  mux_p.slv_array_t(0 to NUM - 1)(LEN - 1 downto 0);
        sel_i : in  natural range 0 to NUM - 1;
        z_o   : out std_logic_vector(LEN - 1 downto 0));
    end entity;
    
    architecture syn of mux is
    begin
      z_o <= v_i(sel_i);
    end architecture;
    

    The sel_i should also be std_logic_vector, with a length derived from NUM, but the above shows the code that is related to the mux.

    Usage example of the mux can be:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity mdl is
      port(
        a_i   : in  std_logic_vector(1 downto 0);
        b_i   : in  std_logic_vector(1 downto 0);
        c_i   : in  std_logic_vector(1 downto 0);
        sel_i : in  natural;
        z_o   : out std_logic_vector(1 downto 0));
    end entity;
    
    architecture syn of mdl is
    begin
      mux_e : entity work.mux
        generic map(
          LEN => 2,
          NUM => 3)
        port map(
          v_i(0) => a_i,
          v_i(1) => b_i,
          v_i(2) => c_i,
          sel_i  => sel_i,
          z_o    => z_o);
    end architecture;