¿Se requiere un valor constante para la indexación de matrices VHDL?

Básicamente tengo una línea como esta en un código vhdl.

entity my_entity is
   port(x : in std_logic_vector;
        y : in std_logic_vector;
        ...);
end entity my_entity;

architecture arch of my_entity is
   -- declarations...
   signal delta : unsigned(...); --correct sizing
   signal aux_signal : std_logic; -- correct sizing
   signal another_signal : unsigned(...); --correct sizing
begin
   delta <= x - y; -- x > y
   aux_signal <= or_reduce(std_logic_vector(another_signal(to_integer(delta) downto 1)));
   -- other stuff
end architecture arch;

la sintaxis está bien (verificada por ncvhdl), sin embargo, cuando pruebo la síntesis, el compilador se queja de una asignación como "aux_signal" diciendo que necesita un valor constante.

Ya que necesito una tarea como esa... ¿hay otra forma de lograr el mismo resultado?

Respuestas (2)

El bucle de Jeff fores el enfoque correcto aquí, pero no tiene que incrustarlo en un proceso: puede ser una función en su lugar, y la mayoría de las herramientas de síntesis (¡posiblemente no todas!) deberían manejarlo correctamente.

function or_reduce_select (sig : unsigned; mask : natural) return std_logic is
  variable or_result : std_logic;
begin
  or_result := '0';
  for i in 1 to sig'left loop
    if i <= mask then
      or_result := or_result or sig(i);
    end if;
  end loop;
  return or_result;
end or_reduce_select;

...

aux_signal <= or_reduce_select(another_signal, to_integer(delta));

EDITAR re: comentarios...
El original requiere un hardware diferente para diferentes valores de Delta. Como Delta varía en el tiempo de ejecución, requiere que el hardware aparezca y desaparezca en el tiempo de ejecución.

Mire el ciclo aquí: los límites 1 to sig'leftson constantes, por lo que el hardware es fijo: en cambio, la condición "si" enmascara cada bit no deseado con una puerta AND: la puerta siempre está allí, su otra entrada es variable en tiempo de ejecución. Por lo tanto, esta forma es físicamente realizable en hardware, mientras que la forma original no lo es.

Quizás sea más fácil visualizar el hardware que esto generará si reescribimos el ciclo:

  for i in 1 to sig'left loop
    if i <= mask then
      or_result := or_result or sig(i);
    end if;
  end loop;

en la siguiente forma

  for i in 1 to sig'left loop
    or_result := (or_result or sig(i)) and (i <= mask); 
  end loop;
¿Puedo preguntar por qué la función y el bucle funcionan en tal caso mientras que la asignación concurrente no lo hace? Me falta la lógica detrás de esto.
La llamada de función ES una asignación concurrente (o también se puede usar en un proceso)
Ok ... entonces no entiendo el problema con mi declaración por qué en lugar de incrustarlo (o de manera equivalente ...) funciona. No entiendo qué tipo de problema evitas de esta manera y por qué puedes evitarlo de esta manera.
Jeff respondió el problema con su declaración actual. Requiere hardware diferente para diferentes valores de Delta. Como Delta varía en el tiempo de ejecución, requiere que el hardware aparezca y desaparezca en el tiempo de ejecución. Mire el ciclo aquí: los límites 1 to sig'leftson constantes, por lo que el hardware es fijo: en cambio, la condición "si" enmascara cada bit no deseado con una puerta AND: la puerta siempre está allí, su otra entrada es variable en tiempo de ejecución. Por lo tanto, esta forma es físicamente realizable en hardware, mientras que la forma original no lo es.

El problema está aquí:

another_signal(to_integer(delta) downto 1)

Los segmentos con límites de variables de tiempo de ejecución no son compatibles con la síntesis. ¿Cómo se traduciría esto en hardware real?

Podría lograr una función similar usando un bucle dentro de un proceso:

process (delta, another_signal)
  variable or_result : std_logic;
begin
  or_result := '0';
  for i in 1 to another_signal'left loop
    if (i <= to_integer(delta)) then
      or_result := or_result or another_signal(i);
    end if;
  end loop;
  aux_signal <= or_result;
end process;

Si no puede usar un proceso y el tamaño de another_signales fijo, puede escribir algo como:

aux_signal <= another_signal(1) when delta = 1 else
              or_reduce(another_signal(2 downto 1) when delta = 2 else
              or_reduce(another_signal(3 downto 1) when delta = 3 else
              or_reduce(another_signal(4 downto 1) when delta = 4 else
              '0';

Le recomiendo encarecidamente que utilice procesos, incluso para la lógica asíncrona.

Es un diseño combinatorio, me gustaría evitar el proceso (incluso si el proceso no sintetiza ningún FF o registro). ¿Puedo usar una función en su lugar?
¿Por qué demonios querrías evitar usar la processconstrucción?
No te enojes conmigo xD. Solo porque estoy acostumbrado a usar el proceso generalmente con diseños secuenciales.
@Lukkio Edité para agregar una posible solución para el caso de 'no usar un proceso'.
Entonces, en el segundo caso, ¿necesariamente tengo que usar "listado" de todos los casos? Pensé que era más fácil...
¿Sería posible usar una función de cambio de tamaño (basada en el valor delta) y luego or_reduce en el resultado? (desde este enlace )
¿Es correcto su proceso? quiero decir que haces una asignación de señal allí en términos de que la asignación es semánticamente correcta (para lo que debo hacer)?
Creo que usar resizedaría como resultado el mismo problema de que el parámetro no sea constante. Actualicé la respuesta para mostrar un proceso completo.
Probé tu proceso... no funciona. Internamente tiene una sentencia if como <code>if delta < 3</code> y esa línea me da el mismo error...