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

1

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 intento la síntesis, las compilaciones de asignación como "aux_signal" dicen que necesita un valor constante.

Ya que necesito una asignación como esa ... ¿hay otra manera de lograr el mismo resultado?

    
pregunta user8469759

2 respuestas

2

El bucle for de Jeff es el enfoque correcto aquí, pero no tiene que integrarlo en un proceso: puede ser una función en su lugar, y la mayoría de las herramientas de síntesis (posiblemente no todas) deben 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 hardware diferente para diferentes valores de Delta. Como Delta varía en tiempo de ejecución, es necesario que el hardware aparezca y desaparezca en tiempo de ejecución.

Mire el bucle aquí: los límites 1 to sig'left son constantes por lo que el hardware está arreglado: en cambio, la condición "if" enmascara cada bit no deseado con una puerta AND: la puerta siempre está ahí, 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 generará si reescribimos el bucle:

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

en el siguiente formulario

  for i in 1 to sig'left loop
    or_result := (or_result or sig(i)) and (i <= mask); 
  end loop;
    
respondido por el Brian Drummond
2

El problema está aquí:

another_signal(to_integer(delta) downto 1)

Los segmentos con límites de variable 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 utilizando 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 puedes usar un proceso, y el tamaño de another_signal es fijo, podrías 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 recomendaría encarecidamente que utilice procesos, incluso para lógica asíncrona.

    
respondido por el scary_jeff

Lea otras preguntas en las etiquetas