0

I am trying to implement a multistage multiplexer that selects the even/odd lines of the input signal at each stage. Let's assume for instance I have 8 inputs [a(0) a(2) a(3) a(4) a(5) a(6) a(7)] and three input signals [s(0) s(1) s(2)]. The multiplexer should behave like this : if s(0) = 0, the first stage passes [a(0) a(2) a(4) a(6)] otherwise it passes the odd elements [a(1) a(3) a(5) a(7)]. To do this I am trying to slice the input signal into odd and even elements like this:

entity mux is
port(
    s       :   in  std_logic_vector(0 to 3);
    vline   :   in  std_logic_vector(0 to 8);
    output  :   out std_logic   
    );
end mux;

architecture multistage of mux32 is

signal level0even   :   std_logic_vector(0 to 3);
signal level0odd    :   std_logic_vector(0 to 3);
signal temp0        :   std_logic_vector(0 to 3);
signal level1even   :   std_logic_vector(0 to 1);
signal level1odd    :   std_logic_vector(0 to 1);
signal temp1        :   std_logic_vector(0 to 1);
signal level2even   :   std_logic;
signal level2odd    :   std_logic;
signal temp2        :   std_logic;

begin
    -- Slicing level0
    for k in 0 to 3 loop
         level0even(k) <= vline(2*k);
         level0odd(k) <= vline(2*k+1);
    end loop;

with s(0) select
    temp0 <= level0even when "0",
             level0odd  when "1",
             "----" when others;

    -- Slicing level1
    for k in 0 to 1 loop
         level1even(k) <= temp0(2*k);
         level1odd(k) <= temp0(2*k+1);
    end loop;

with s(1) select
    temp1 <= level1even when "0",
             level1odd  when "1",
             "----" when others;

[...]

end multistage;

But Multisim gives me the error " Illegal concurrent statement " at the level0 slicing when writing the previous code. The question is: is there a more elegant and compact way to slice the even/odd elements of a vector ?

Plus, I am trying to write the code in a parametric way to use it for a much larger input vector, but I don't know how to do it since I need to declare the temporary vectors (levelxodd/even) one by one. Does anyone have any suggestion on how to do this ?

xhienne
  • 5,738
  • 1
  • 15
  • 34
Ryuzaky
  • 1
  • 1
  • Your code isn't an [Minimal, Complete and Verifiable example](https://stackoverflow.com/help/mcve) there are syntax errors present and not just the [...], loop statements are sequential statements going either in process statements or subprograms. Notice both answers are from those who know that, neither one prove their solutions works. –  Jul 02 '17 at 23:22
  • `temp1 <= [...] "----" when others;`. What would you like to achieve that you are using 'don't care's? By the way "0" -> '0'. first is `std_logic_vector`, second `std_logic`. – JHBonarius Jul 03 '17 at 11:28
  • P.s. you are asking two questions, which would have quite different answers. Better to separate them IMHO. But why are you building the whole multiplexer tree in VHDL? You know that it will be implemented completely different in an FPGA eh? – JHBonarius Jul 03 '17 at 11:37

3 Answers3

0

This in principle a good solution. But... a for loop is a sequential statement - it needs to be inside a process. And to make it parameterisable find out about VHDL generics and/or array attributes.

Matthew Taylor
  • 13,365
  • 3
  • 17
  • 44
0

You can write a function to create a selection of elements:

function even(slv : std_logic_vector) return std_logic_vector is
  variable temp : std_logic_vector(slv'length / 2 downto 0);
begin
  for i in slv'range loop
    if (i mod 2 = 0) then
      temp(i/2) := slv(i);
    end if;
  end loop;
  return temp;
end function;
Paebbels
  • 15,573
  • 13
  • 70
  • 139
0

so you need a multiplexer. An array actually. You can write concurrent loop statements using generate. Example:

array_of_muxes: for k in 0 to 1 generate
    mux_even: level1even(k) <= level0even(2*k) when s(0)='0' else level0odd(2*k);
    mux_odd: level1odd(k) <= level0even(2*k+1) when s(0)='0' else level0odd(2*k+1);
end generate;
JHBonarius
  • 10,824
  • 3
  • 22
  • 41