5 votos

VHDL operadores de cambio?

Todavía estoy tratando de acostumbrarme a algunas de las peculiaridades de VHDL y estoy teniendo un poco de un problema. En primer lugar, entiendo que los operadores de desplazamiento como rol, ror, ssl, srl, etc. no synthesizeable. El propósito de este laboratorio es el uso de un modelo de oro para comprobar contra un synthesizeable versión de la misma cosa en un testbench.

Ahora, el propósito de este programa es convertir el termómetro de código en los 3 bits del número binario. Así que, en otras palabras, termómetro código "00000001" = "001", "00000011" = "010", "00000111" = "011", etc. Estoy tratando básicamente para contar el número de 1's en la cadena de derecha a izquierda. No habrá ningún caso en el que un '0' se coloca entre la cadena de 1, por lo que el vector "00011101" no es válido y nunca ocurrirá.

He ideado un no-synthesizeable (y hasta ahora, no es de compilación) algoritmo que yo no puedo averiguar cómo conseguir trabajo. Básicamente, la idea es leer el termómetro código, el cambio es a la derecha y a incrementar un contador, hasta que el termómetro código es igual a cero y, a continuación, asignar el valor del contador de 3 bits std_logic_vector. A continuación está el código que he hecho hasta ahora.

library ieee;
use ieee.std_logic_1164.all; 
use ieee.numeric_std.all;

entity therm2bin_g is
    port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
         bin : out std_logic_vector(2 downto 0); -- binary code 
         i : integer range 0 to 7);
end therm2bin_g;    

architecture behavioral_g of therm2bin_g is
begin

golden : process(therm)
begin

    while(therm /= "00000000") loop
        therm <= therm srl 1;
        i = i + 1;      
    end loop;

    bin <= std_logic'(to_unsigned(i,3));

end process golden;
behavioral_g;

8voto

Brian Drummond Puntos 27798

Hay poco sintáctica problemas con este código, pero en general no está lejos y va a ser una manera útil en la distinción entre synthesisable y no synthesisable - que realmente no es lo que usted está esperando!

1) El puerto mapa

port(therm : inout std_logic_vector(6 downto 0); -- thermometer code
     bin : out std_logic_vector(2 downto 0); -- binary code 
     i : integer range 0 to 7);

Puntos a tener en cuenta aquí:

  1. therm y bin tienen un modo y a un tipo; i tiene sólo un tipo. Como bin es sólo una copia de i usted realmente no necesita tanto en la lista de puertos. Usted puede declarar i internamente como una señal, o incluso en el proceso como una variable.
  2. bin representa un número sin signo. Así que el buen estilo es hacerlo sin signo; o, incluso, Entero, y transmitir más de la intención del diseño para el lector. Ambos son perfectamente synthesizable. Entero puede dar un entero de 32 bits, por lo tanto, hacer bin : out natural range 0 to 7; y obtendrá un 3 bits entero sin signo! La lección aquí es que si usted está haciendo un montón de innecesario tipo de conversiones, PARADA: creo, y usted tendrá que encontrar una manera de utilizar el tipo de sistema en lugar de luchar contra ella.
  3. therm ha sido declarado "inout" pero es realmente una entrada para el proceso. (El hecho de que está modificando internamente es un detalle de implementación, que REALMENTE no desea exponer la versión modificada para el mundo exterior!) De hecho, "inout" no hace realmente lo que piensa. Su propósito real es sólo para los buses de datos y similares, donde usted comunicarse en ambos sentidos en la misma señal. Si usted la utiliza como eres, entonces lo que sea que impulsa el valor original en therm seguirá unidad therm, y modificado los valores de los conflictos con que se produzcan "X", es decir, el valor desconocido (O en el hardware real, posiblemente se sobrecaliente y se queme!).

Para eliminar i, hacer bin sin signo o un subtipo de los recursos Naturales, y hacer therm de entrada.

2) Usted necesita una copia local de therm puede modificar. Declarar de forma local como una señal.

architecture behavioral_g of therm2bin_g is
   therm_int : std_logic_vector(6 downto 0);
begin

Y i debe ser declarado localmente. Podría ser una señal demasiado, pero vamos a hacer una variable en el proceso de cambio.

golden : process(therm)
variable i : integer := 0;
-- yes, it is important to initialise it!
begin

3) El bucle.

En primer lugar, debemos copiar la entrada en el interior de la señal, entonces podemos modificar en el bucle.

therm_int <= therm;
while (therm_int /= "00000000") loop
    therm_int <= therm_int srl 1;
    i := i + 1;      
end loop;

Para simplificar, se podría hacer therm_int sin firmar y escribir while therm_int /= 0 loop (perdiendo el tonto de estilo C paréntesis en el proceso)

Hay otro problema aquí. Pensar en un proceso como un pequeño programa en C (pero sin algunos de C tonto "características") - de las variables de trabajo más bien como esperaba PERO las señales son esencialmente diseñado para la comunicación entre procesos en paralelo en un sistema de procesamiento. Si usted piensa en C términos, el equivalente más cercano es un tubo abierto en stdout y bucle de nuevo en stdin! Usted puede escribir en una tubería, pero no pasa nada hasta que un chorro de agua...

En VHDL, el color sólo ocurrirá cuando el proceso se suspende a sí mismo. Como está escrito, no puede suspender a sí mismo hasta que el bucle termina y llega a "end process". Y no puede terminar el bucle hasta "therm_int = 0". Y no puede cambiar el valor visto en therm_int hasta que se suspende ... esto es un bucle infinito.

Para entender por qué VHDL señales de trabajar de esta manera, ver este Q&A

La manera más simple de la ronda de esto es hacer therm_int otra variable de proceso y el uso de la variable de asignación := en lugar de la asignación de señal <= .

Y ahora debería funcionar.

4) la Síntesis.

Pero lo que no synthesisable al respecto?

Sólo esto: Se utiliza un while bucle en lugar de un for de bucle!

Pensar que por un momento: no se puede prever, en general, el número de ciclos que una while bucle va a tomar. Para la síntesis, que significa que usted tiene que generar una desconocida cantidad de hardware!

Pero se puede colocar un límite superior en las iteraciones, y generar hardware para atender a que el límite superior. De hecho, una for bucle automáticamente es limitada, y las herramientas de síntesis puede manejar eso.

Para escribir el bucle como

therm_int <= therm;
for j in therm_int'range loop  
   if therm_int /= 0 then
      therm_int := therm_int srl 1;
      i := i + 1;   
   end if;   
end loop;

y sintetizarla. Notas : for j in therm_int'range loop; la razón por la j? Así no queremos ocultar su i variable! Y tenga en cuenta que therm_int'range automáticamente equivale a (6 downto 0) o sin embargo usted declaró therm_int. Este bombproofs el código en contra de los cambios en el tamaño de therm_int o accidental desbordamientos de búfer. Es un pequeño ejemplo de lo que quiero decir utilizando el tipo de sistema en lugar de luchar contra ella.

Mientras estamos en ello, vamos a eliminar el cambio, el cual es innecesario!

for j in therm_int'reverse_range loop  
   if therm_int (j) = '1' then
      i := j;   -- last assignment is most significant '1' bit
   end if;   
end loop;

Como está escrito, este reunirán para generar suficiente hardware para implementar la tarea en un solo ciclo de reloj. En general, lo que llevaría a más lentos ciclos de reloj, y se desea ración de la obra (tal vez una sola iteración del bucle por reloj). Pero esa es otra historia...

1voto

pacmanlikespie Puntos 9

Solo hay siete salidas posibles, u ocho si incluye 000, por lo que solo hay siete (ocho) entradas posibles. Solo usaría una tabla de búsqueda, o una declaración de cambio si tiene una disponible.

i-Ciencias.com

I-Ciencias es una comunidad de estudiantes y amantes de la ciencia en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X