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?
El bucle de Jeff for
es 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'left
son 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;
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_signal
es 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.
process
construcción?resize
daría como resultado el mismo problema de que el parámetro no sea constante. Actualicé la respuesta para mostrar un proceso completo.
usuario8469759
usuario_1818839
usuario8469759
usuario_1818839
1 to sig'left
son 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.