Electronic – VHDL: Demultiplexing a signal to one of many outputs while driving unused outputs to ‘0’

fpgaprogrammable-logicvhdlvivado

I'm attempting to create synthesisable VHDL that will demultiplex a one-bit continuous signal stream to one of many outputs. The outputs that aren't being sent this stream should be set to '0'. See image below for an idea of what I'm trying to achieve.

Demux Diagram

The code I've written to create this functionality is:

send_s         <= (line_select_s => prbs_i(0), others => '0');

where 'prbs_i(0)' is the signal stream.

Unfortunately this is unsynthesisable in Vivado, giving the error:

[Synth 8-211] could not evaluate expression: aggregate choice expression

Is there a proper way to do this? The VHDL simulates fine but will not synthesise.

Best Answer

The problem with your code is that an assignment of the form:

a <= (3 => '0', others => '1');

must use constants for the offsets being assigned (in this case, 3).

If you need the offset being set to vary, you have to split it into two assignments. Note that this will only work inside a process; with a pair of concurrent assignments, you would encounter a multiple driver problem.

process (line_select_s, prbs_i)
begin
  send_s <= (others => '0');
  send_s(line_select_s) <= prbs_i(0);
end process;

This works because although we start by assigning '0' to the whole vector, the last assignment to a particular signal in a process will take priority.

An alternative is to use a loop:

process (line_select_s, prbs_i)
begin
  send_s <= (others => '0');
  for i in send_s'range loop
    if (i = line_select_s) then
      send_s(i) <= prbs_i(0);
    end if;
  end loop;
end process;

This has the advantage that if your select signal can represent an offset larger than the width of your target vector, no error will be produced in simulation. An example scenario would be a 3-bit select signal, but a target vector with only 5 elements; the first method would produce an error if the select signal represented 6, 7, or 8, but the second would not.

As a side note, you may want to make a process like this synchronous if you want to get the best performance (in terms of maximum operating frequency) out of your design.