VHDL: ¿Se puede usar una señal como un índice para un agregado?

1

¿Es legal usar una señal entera en lugar de un literal entero como un índice en una asociación nombrada? Quiero hacerlo para crear un decodificador, como este:

reg_clk_en <= (write_reg => '1', others => '0');

donde reg_clk_en es un std_logic_vector y write_reg es un integer (con un rango de 0 a 31).

De lo que he leído en Renerta sobre Aggregates y Expressions , creo que esto debería ser legal: write_reg es una cláusula legal choices porque es una nombre , que es una expresión simple . Sin embargo, no estoy seguro de entender esta cita:

  

Un valor de expresión simple se puede aplicar solo en matrices y debe pertenecer a un rango discreto de un tipo de matriz. Una expresión simple especifica el elemento en el valor de índice correspondiente.

La primera oración parece decir que está bien usar un índice de enteros siempre que el objetivo de la asignación agregada sea una matriz, y el valor del entero esté dentro del rango del tipo de matriz. La segunda oración parece confirmar que la expresión array(index) se refiere al elemento de array en index , pero esto es tan obvio que sospecho que lo estoy interpretando mal.

La razón por la que pregunto es que Vivado rechaza mi fragmento de código inicial con el siguiente mensaje:

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

Conozco otras formas de especificar un decodificador, pero ninguna tan concisa. Lo más importante es que me gustaría entender por qué que el fragmento de código es problemático para Vivado. Si no es VHDL legal, ¿qué es incorrecto?

    
pregunta odougs

3 respuestas

2

Estás combinando sintaxis legal y semántica.

Su agregado utiliza la asociación de elementos.

¿Qué elemento de reg_clk_en tiene el nombre write_reg ?

Ver IEEE Std 1076-2008 9.3.3 Agregados, opciones de nota simple_expression y elemento _simple_name en el BNF, párrafo:

element_association ::=  
    [ choices => ] expression  

choices ::= choice { | choice }  

choice ::= 
      simple_expression
    | discrete_range
    | element_simple_name
    | others

Existe un requisito de que un índice en un agregado sea localmente estático (determinado en el momento del análisis), lo que le impide utilizar un valor de señal. Ese requisito se encuentra en 9.3.3.3 Agregados de matrices, párrafo 7:

  

Aparte de una asociación de elemento final con otras opciones de una sola elección, el resto (si existe) de las asociaciones de elementos de un agregado de matriz debe ser todas posicionales o todas nombradas. Se permite que una asociación nombrada de un agregado de matriz tenga una opción que no sea localmente estática, o también una opción que sea un rango nulo, solo si el agregado incluye una asociación de un solo elemento y esta asociación de elementos tiene un opción única . Otra opción es localmente estática si la restricción de índice aplicable es localmente estática.

Si sigues el BNF desde simple_expression hasta el primario:

simple_expression ::=
     [ sign ] term { adding_operator term }

term ::=
     factor { multiplying_operator factor }

factor ::=
     primary [ ** primary ]
   | abs primary
   | not primary
   | logical_operator primary

primary ::= 
     name 
   | literal
   | aggregate
   | function_call
   | qualified_expression 
   | type_conversion
   | allocator
   | ( expression )

encontramos tu nombre. Puede mirar a través de 9.4.2. Las primarias localmente estáticas y determinar las señales no se mencionan, mientras que una constante es (9.4.2 b).

Entonces, vemos que su agregado no es elegible para ser tomado como el valor proporcionado por la evaluación de la expresión simple que es un nombre de señal. Si se declara como una constante sería:

library ieee;
use ieee.std_logic_1164.all;

entity foo is
end entity;

architecture fum of foo is
    signal reg_clk_en: std_logic_vector(7 downto 0);
    constant write_reg: natural := 3;
begin
    reg_clk_en <= (write_reg => '1', others => '0');
end architecture;

Esto analiza, elabora y simula (sin hacer nada particularmente interesante).

La única otra posible evaluación del nombre como índice sería como el nombre del elemento de un registro, teniendo en cuenta que su fragmento de código no es un ejemplo mínimo, completo y verificable (sin declaraciones).

9.3.3 Agregados, 9.3.3.1 General, párrafo 5:

  

Una asociación de elemento con una opción que es un nombre simple de elemento solo se permite en un agregado de registro. Una asociación de elementos con una opción que es una expresión simple o un rango discreto solo se permite en un agregado de matriz: una expresión simple especifica el elemento en el valor de índice correspondiente, mientras que un rango discreto especifica los elementos en cada uno de los valores de índice en el distancia. ...

Suponiendo que es un tipo de matriz, el estándar nos dice que una señal no se puede usar como un índice para un agregado de la manera que ha intentado.

No siempre se puede confiar en los recursos no autoritativos para definir completamente la semántica aceptable.

    
respondido por el user8352
1

Lo importante a tener en cuenta es que las declaraciones VHDL dentro de un proceso se aplican secuencialmente para crear el resultado. Esto no es lo mismo que la ejecución secuencial; lo que significa es que las asignaciones posteriores reemplazan por completo a las anteriores (reconectan los circuitos, a diferencia de las declaraciones concurrentes en las que los controladores múltiples necesitan resolución como Wired-OR / wired-AND). En su caso, puede escribir:

PROCESS (write_reg)
BEGIN
    reg_clk_en <= (others => '0'); -- all elements become '0' ...
    reg_clk_en(write_reg) <= '1';  --                         ... except write_reg
END PROCESS;

que tiene la semántica prevista y funciona correctamente cuando write_reg NO es un constant o generic .

Por supuesto, esto fallará cuando write_reg esté fuera de reg_clk_en'RANGE . En la simulación obtendrás un error, mientras que en la síntesis obtendrás resultados impredecibles (tal vez el sintetizador determinó que podría ignorar los bits superiores, por ejemplo, y terminas con un decodificador de módulo).

    
respondido por el Ben Voigt
-1
reg_clk_en <= (write_reg => '1', others => '0');

El primer error que veo es que ha declarado que write_reg es de tipo entero & lo estás asignando '1', que es un tipo de bit.

y por qué quieres usar agregados si quieres hacer lo que estás tratando.

Supongamos que reg_clk_en es std_logic_vector (9 downto 0)

entonces solo puedes hacer:

reg_clk_en(9 downto 4) <= std_logic_vector(to_unsigned(write_reg,6));
reg_clk_en(3 downto 0) <= (OTHERS => '0');                       
    
respondido por el rahdirs

Lea otras preguntas en las etiquetas