VHDL - conversión de tipos y sustracción de enteros

3

Estoy preparando un programa en VHDL y me quedé atascado en la conversión de tipos. Intenté buscar en Google y también aquí en el intercambio de pila, pero estoy bastante confundido ya que una respuesta contradice a la otra y ninguna de las cuales puedo trabajar. Pero finalmente a la cuestión mía: Tengo que mostrar los relojes digitales ordinarios. Obtuve de mi profesor decodificador para la visualización de 7 segmentos que toma como entrada std_logic_vector(3 downto 0) . Y mi parte es proporcionar datos (más específicamente un conjunto de dígitos) para mostrar. La mayoría del trabajo ya está hecho, pero estoy luchando para convertir mis variables, por ejemplo. minutos (es std_logic_vector(4 downto 0) ) a dos dígitos decimales. He hecho la separación de esta manera:

if (min >= 50) then
  d3 <= 5;
  d4 <= min - 50;
elsif (min >= 40) then
  d3 <= 4;
  d4 <= min - 40;
elsif 
...
end if;

(El valor máximo de min es 59 y si alcanza este máximo, se restablece a 0 y el contador de horas obtiene +1, al igual que los relojes normales). Así, d3 debería mostrar decenas de minutos y d4 unidades de minutos. Como probablemente ya hayas adivinado, ya que min tiene una longitud de 5, no puedo compilarlo ( d4 acepta una longitud de 4 tops). Por lo tanto, mi idea es convertir min a entero, restar el número (por ejemplo, 50) y volver a convertir a std_logic_vector con la longitud correcta (el valor real estaría en el rango de 0 a 9, por lo tanto no hay problema con la longitud de cuatro bits). Intenté realizar algo como esto:

d4 <= std_logic_vector(unsigned(integer(unsigned(min)) - 50));

pero sin éxito. Siempre había terminado con errores como función desconocida, falta de coincidencia de tipo o sin sobrecarga coincidente para el método, sin importar qué combinación probé. Aparentemente obtuve algún error trivial, pero no lo veo. Yo uso esos:

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

Por favor, ¿puedes indicarme la dirección correcta? Me estoy quedando sin ideas.

Muchas gracias por tu tiempo, Michal

EDITAR: Las declaraciones de entradas, salidas y variables solicitadas son:

port (sw2, sw1, sw0: in std_logic;  -- input switches
        clock:       in std_logic;
        reset:       in std_logic;
        d0, d1, d2, d3, d4, d5, d6, d7: out std_logic_vector(3 downto 0);  -- outputs for eight units of 7segment display decoders
        dp0, dp1, dp2, dp3, dp4, dp5, dp6, dp7: out std_logic);  -- outputs for decimal points

  attribute loc : string; 
  attribute loc of sw0   : signal is "P7";
  attribute loc of sw1   : signal is "P9";
  attribute loc of sw2   : signal is "P10";
  attribute loc of clock : signal is "P2"; 
  attribute loc of reset : signal is "P11"; 

end main_1048;

architecture main_1048arch of main_1048 is
begin
process(sw2, sw1, sw0, clock, reset)
variable yrs: std_logic_vector(11 downto 0);
variable min, sec: std_logic_vector(4 downto 0);
variable hrs, day, mth: std_logic_vector(3 downto 0);
begin

EDIT2: Después de eliminar libs std_logic_arith a std_logic_unsigned según lo sugerido por Brian Drummond y redefinir las variables, ahora son natural s. Los nuevos errores fueron No hay sobrecarga correspondiente para "-". Según las especificaciones que encontré, "-" debería funcionar:

function "-" (L: NATURAL; R: UNSIGNED) return UNSIGNED;
  -- Result subtype: UNSIGNED(R'LENGTH-1 downto 0).
  -- Result: Subtracts an UNSIGNED vector, R, from a non-negative INTEGER, L.

Por lo tanto, la edición final fue a d4 <= std_logic_vector(min - to_unsigned(50,4)); (con la declaración variable min: natural range 0 to 59; ) y esto (respecto a encasillamiento) funciona.

¡Gracias a todos por su ayuda!

    
pregunta Rao

2 respuestas

3

Primero elimine las bibliotecas no estándar std_logic_arith y std_logic_unsigned , dejando std_logic y numeric_std.

Además de ser no estándar, causan problemas a través de una regla VHDL que, si se ven dos definiciones de un tipo (o procedimiento u operador o lo que sea), como unsigned o <= , VHDL intentará descubra cuál fue su intención (por ejemplo, por los tipos de parámetros del operador, porque los operadores sobrecargados son legales).

Pero si dos definiciones son visibles e indistinguibles, se considera que ambas están ocultas. Esto hace que el problema sea reparado en lugar de permitir que el compilador elija uno, probablemente incorrecto, al azar.

Así que solo con las bibliotecas estándar, las cosas se vuelven mucho más simples.

Ahora, otra regla básica es que si estás luchando con muchas conversiones de tipos, algo se declara del tipo incorrecto, lo que apunta a un error de diseño.

Voy a adivinar el error: min debe declararse como unsigned pero no lo es. (Ditto d3 etc). Representa un número sin firmar en forma de bit (std_logic). Así lo declaran como tal.

Arregla eso y mira que pasa. Pero primero, busque la fuente del paquete numeric_std (la especificación del paquete, no se moleste con el cuerpo del paquete). Verá una gran cantidad de operadores que permiten que unsigned y integer interactúen directamente.

Entonces esperaría que su fragmento de código funcione directamente, sin conversiones de tipo.

Si realmente no necesita los bits de min , vaya más allá y declare que es un subtipo de natural con un rango de 0 a 59. No hay razón para no hacerlo, incluso para la síntesis, y para puertos en un componente.

Por lo general, es apropiado usar unsigned (o incluso std_logic_vector si debe) para puertos en el nivel más alto, donde necesita conectar cada bit a un pin FPGA. Pero internamente, conviértase a los tipos más apropiados para el diseño tan pronto como pueda.

    
respondido por el Brian Drummond
1

Utilizando la información que ha proporcionado, asumo que está utilizando funciones de conversión de tipo incorrectas.
Suponiendo que min y d4 son std_logic_vector s, la línea para calcular d4 debería tener el siguiente aspecto:

d4 <= std_logic_vector(to_unsigned(to_integer(unsigned(min)) - 50, d4'length));

Al convertir entre los tipos unsigned y integer , las funciones to_unsigned() y to_integer() son tus amigos. El segundo argumento de to_unsigned() es la longitud del valor unsigned resultante.

    
respondido por el damage

Lea otras preguntas en las etiquetas