Slice even/odd elements in VHDL

1.5k Views Asked by At

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 ?

3

There are 3 best solutions below

1
Matthew Taylor On

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.

0
Paebbels On

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;
0
JHBonarius On

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;