0

I'm writing a flexible MUX, it has a generic which determines the number of selection lines but also the number of inputs and outputs to the system. If, for example, size = 3; The system will have 8 inputs, 64 outputs and 3 selection lines. This creates 2^size MUXes and I need to set them each time the selection bits change (they are global).

So far I have this:

library ieee ;
use ieee.std_logic_1164.all ;
use ieee.std_logic_unsigned.all ;

entity mux is
    generic ( size : positive := 3 ) ;
    port    ( din  : in  std_logic_vector (((2**size)-1) downto 0) ;
              sel  : in  std_logic_vector (size-1 downto 0) ;
              y    : out std_logic_vector (((2**(size*2))-1) downto 0) ) ;
end mux ;

architecture arc_mux of mux is
begin

    process(sel)
    begin

    end process ;

end arc_mux ;

What I would like to do is go over the inputs in a loop ( 0 to ((2**size)-1) ) and adjust the correct output to the value stored in that place. The thing is that I need to use the value of sel for this as an offset to i * 2**size but the libraries I can use in this exercise won't allow me to use the + operator to just add that value to i * 2**size. Any suggestions?

user34920
  • 227
  • 3
  • 6
  • 12
  • I keep getting stuck on the term "mux", this isn't a [multiplexer](http://en.wikipedia.org/wiki/Multiplexer "multiplexer"), rather a demultiplexer. Regardless there are attributes you can use (e.g. 'RANGE,'LENGTH, 'LEFT and `RIGHT) to relate characteristics of array types. The idea being after you declare subtypes for your port signals you can relate to actual values without reconstruction. Index bounds and lengths are all closely related to integers and the math is available in library standard. Perhaps you should show what is failing? Simulation or synthesis? Actual error messages? –  Apr 26 '14 at 22:58

1 Answers1

0

The error you might get in the for loop should tell you something to the effect that a universal integer bound must be a numerical literal or an attribute. A rule relaxed in the 2008 version of VHDL.

With your port definitions producing a synthesis eligible description isn't too hard. You can either use din'reverse_range or create an array subtype with the range you need for the loop or specify the type of the implicit loop variable as integer:

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

entity demux is
    generic ( size: positive := 3);
    port ( 
        din:    in  std_logic_vector (2**size-1 downto 0);
        sel:    in  std_logic_vector (size-1 downto 0);
        y:      out std_logic_vector (2**(size*2)-1 downto 0) 
    );
end entity;

architecture foo of demux is

begin

PROC:
    process(sel, din)
        -- subtype sel_range is std_logic_vector (0 to 2**size-1);
    begin

    SLCT:
        -- for i in sel_range'range loop
        for i in integer range 0 to 2**size-1 loop
            if i = to_integer(unsigned(sel)) then
                y(i*din'length+din'length-1 downto i*din'length) <= din;
            else
                y(i*din'length+din'length-1 downto i*din'length) <= (others => '0');
            end if;
        end loop;
    end process ;

end architecture;

This code uses the VHDL-93 library numeric_std and a type conversion to unsigned to compare i to sel. You could use the Synopsys library could as easily be used. The use of a loop and assigning a value to the y index range allows synthesis.

The iterations through the for loop will be replicated (in parallel) in hardware. The assigned slices of y are dependent on i and din'length which is static.

This example analyzes, elaborates and simulates.

demux_tb simulation

If you were intending to latch the 'y' value and sequentially update y slices based on sel, simply leaving din off the process sensitivity list isn't enough. It isn't a synthesis eligible construct, and it operates on any event on sel. Note I added din to the process sensitivity list. If you intend addressable latches or registers you'd need a clock or separate latch enable because the rise and fall times for sel elements aren't necessarily equal, should you generate an enable through a gate. You can get glitches in real hardware implementations. (Your language "...adjust the correct output to the value stored in that place" is unclear).

Your port declarations are a good example of more parentheses than are actually needed based on operator precedence.

You might also note that the length of din is unnecessarily tied to the the number of sel bits which is why din'reverse_length would work. Yes there needs to be a relationship between din length and y length, and y length is related to size. y'LEFT would otherwise be 2**size*din'LENGTH-1. This would imply a second generic for the size of din. It'd also change the for loop statement's y assignment slice bounds math.