Diseño de Sistemas Digitales con VHDL: Contadores, Máquinas de Estados y Aplicaciones Prácticas

Enviado por Chuletator online y clasificado en Informática y Telecomunicaciones

Escrito el en español con un tamaño de 9,65 KB

Registro y Contador Universal: Solución "Todo en Uno"

Uso: Este patrón es ideal si se requiere implementar un registro, un contador ascendente/descendente o un acumulador.

Parámetros a modificar:

  • El valor de N (ancho de bits).
  • El tipo de datos: UNSIGNED o SIGNED.
  • La lógica interna dentro del bloque if (operaciones de suma, resta o carga).
library IEEE;
use IEEE.STD_LOGIC_1164.all;
use IEEE.NUMERIC_STD.all; -- ¡Indispensable para contadores!

entity Universal_Counter is
    generic (N: INTEGER := 8); -- Cambia 8 por el valor requerido
    port (
        Reset : in  STD_LOGIC;
        Clock : in  STD_LOGIC;
        Load  : in  STD_LOGIC; -- Señal de carga (opcional)
        Up    : in  STD_LOGIC; -- Control arriba/abajo (opcional)
        Data  : in  UNSIGNED(N-1 downto 0); -- Entrada de datos
        Q_out : out UNSIGNED(N-1 downto 0)  -- Salida
    );
end Universal_Counter;

architecture Behavioral of Universal_Counter is
begin
    process(Reset, Clock)
        -- Variable interna para poder leer y escribir en el mismo ciclo
        variable v_Count: UNSIGNED(N-1 downto 0); 
    begin
        -- 1. Reset Asíncrono (Prioridad absoluta)
        if (Reset = '1') then
            v_Count := (others => '0');

        -- 2. Flanco de Reloj
        elsif (Clock = '1' and Clock'EVENT) then
            -- Aquí va la lógica del ejercicio:
            if (Load = '1') then
                v_Count := Data;       -- Carga paralela
            elsif (Up = '1') then
                v_Count := v_Count + 1; -- Cuenta arriba
            else
                v_Count := v_Count - 1; -- Cuenta abajo
            end if;
        end if;

        -- 3. Asignación a la salida (fuera de los ifs, pero dentro del process)
        Q_out <= v_Count;
    end process;
end Behavioral;

Máquina de Estados Finitos (FSM) Estilo E3

Uso: Recomendado para controladores, semáforos y detectores de secuencia.

architecture Behavioral of Mi_FSM is
    -- Define tus estados aquí con nombres claros
    type states is (S_Idle, S_Espera, S_Activo, S_Fin);
    variable state: states; -- Usamos variable según los requerimientos de diseño
begin
    process(Reset, Clock)
    begin
        -- 1. Reset
        if (Reset = '1') then
            state := S_Idle;
            -- Resetear salidas (opcional pero recomendado)
            Salida1 <= '0';
            Salida2 <= '0';

        -- 2. Reloj
        elsif (Clock = '1' and Clock'EVENT) then
            
            -- IMPORTANTE: Valores por defecto (para no repetir código)
            -- Así solo escribes cuando la señal vale '1'
            Salida1 <= '0';
            Salida2 <= '0';

            -- 3. Máquina de Estados
            case state is
                when S_Idle =>
                    if (Entrada_Start = '1') then
                        state := S_Activo; -- Transición
                    end if;

                when S_Activo =>
                    Salida1 <= '1'; -- Salida específica de este estado
                    if (Entrada_Fin = '1') then
                        state := S_Fin;
                    end if;

                when S_Fin =>
                    Salida2 <= '1';
                    state := S_Idle; -- Vuelta al inicio automática

                when others =>
                    state := S_Idle; -- Recuperación de errores
            end case;
        end if;
    end process;
end Behavioral;

Máquina de Estados con Operaciones Complejas

Uso: Problemas complejos como el Multiplicador o la Raíz Cuadrada. Combina estados con sumas, restas y desplazamientos.

Estructura Clave:

  • Declara variables para tus registros de datos (A, B, Resultado) justo después de process(...).
  • Usa := para asignar valores a esas variables.
  • Realiza las operaciones matemáticas dentro de los estados del CASE.
architecture Behavioral of Algoritmo is
begin
    process(Reset, Clock)
        -- Variables de DATOS (Registros internos)
        variable Reg_A : UNSIGNED(7 downto 0);
        variable Reg_B : UNSIGNED(7 downto 0);

        -- Variable de ESTADO
        type states is (S_Load, S_Operate, S_Done);
        variable state: states;
    begin
        if (Reset = '1') then
            state := S_Load;
            Reg_A := (others => '0');

        elsif (Clock = '1' and Clock'EVENT) then
            case state is
                when S_Load =>
                    if (Start = '1') then
                        Reg_A := UNSIGNED(Entrada_Dato_A); -- Cargar dato
                        Reg_B := UNSIGNED(Entrada_Dato_B);
                        state := S_Operate;
                    end if;

                when S_Operate =>
                    -- Aquí se implementa la lógica matemática
                    Reg_A := Reg_A + Reg_B;       -- Ejemplo: Sumar
                    -- Reg_A := Reg_A srl 1;      -- Ejemplo: Desplazar a la derecha

                    if (Reg_A > 100) then         -- Condición de salida
                        state := S_Done;
                    end if;

                when S_Done =>
                    Done_Flag <= '1';             -- Avisar finalización
                    Salida_Resultado <= STD_LOGIC_VECTOR(Reg_A);
                    state := S_Load;              -- Volver a empezar

            end case;
        end if;
    end process;
end Behavioral;

Caso Práctico: Robot Aspirador (Vacuum Cleaner Robot)

Propose a VHDL description of a vacuum cleaner robot with inputs ‘start’, ‘object’, ‘stop’ and ‘batlow’ and outputs ‘go’, ‘turn’ and ‘redlight’, all of 1 bit. The robot works with a clock of 5 Hz. It waits until start=‘1’ with all the outputs to ‘0’. In the next cycle it puts go=‘1’ until object=‘1’. Then, go=‘0’ and turn=‘1’ and in the next cycle it goes back to go=‘1’ and turn=‘0’. This repeats until stop=‘1’. Whenever batlow=‘1’, go=‘0’, turn=‘0’ and redlight=‘1’.

library IEEE;
use IEEE.STD_LOGIC_1164.all;
-- No se requiere numeric_std al no haber contadores ni operaciones aritméticas.

entity VacuumBot is
    port (
        reset   : in  STD_LOGIC;
        clock   : in  STD_LOGIC;
        start   : in  STD_LOGIC;  -- Botón de encendido
        object  : in  STD_LOGIC;  -- Sensor de objeto
        stop    : in  STD_LOGIC;  -- Botón de parada
        batlow  : in  STD_LOGIC;  -- Sensor de batería baja
        go      : out STD_LOGIC;  -- Motor avance
        turn    : out STD_LOGIC;  -- Motor giro
        redlight: out STD_LOGIC   -- Luz de error
    );
end VacuumBot;

architecture Behavioral of VacuumBot is
begin
    -- Proceso único para control de estados y salidas
    process(reset, clock)
        -- Paso 2: Definir el TYPE con los estados del diagrama
        type states is (idle, move, roll, error);
        -- Uso de VARIABLE para el estado (estilo FSMD)
        variable state: states;
    begin
        -- Reset Asíncrono (Pág. 69)
        if (reset = '1') then
            state := idle;
            go <= '0'; turn <= '0'; redlight <= '0'; 

        -- Detección de flanco de reloj (Pág. 69)
        elsif (clock = '1' and clock'EVENT) then

            -- ASIGNACIONES POR DEFECTO (Pág. 74)
            -- Evita la inferencia de Latches y simplifica el código.
            go <= '0'; 
            turn <= '0'; 
            redlight <= '0';

            -- Paso 4: Traducción del Diagrama de Estados (CASE)
            case state is
                -- ESTADO IDLE (Pág. 70)
                when idle =>
                    -- Prioridad 1: Stop (Permanece en idle)
                    if (stop = '1') then
                        state := idle;
                    -- Prioridad 2: Batería baja
                    elsif (batlow = '1') then
                        state := error;
                    -- Prioridad 3: Start
                    elsif (start = '1') then
                        state := move;
                    end if;

                -- ESTADO MOVE (Pág. 71)
                when move =>
                    go <= '1'; -- Acción: Avanzar

                    if (stop = '1') then
                        state := idle;
                    elsif (batlow = '1') then
                        state := error;
                    elsif (object = '1') then -- Detección de obstáculo
                        state := roll;
                    end if;

                -- ESTADO ROLL (Pág. 72)
                when roll =>
                    turn <= '1'; -- Acción: Girar

                    if (stop = '1') then
                        state := idle;
                    elsif (batlow = '1') then
                        state := error;
                    else
                        -- Retorno automático al movimiento si no hay incidencias
                        state := move; 
                    end if;

                -- ESTADO ERROR (Pág. 73)
                when error =>
                    redlight <= '1'; -- Acción: Alerta visual

                    -- Salida del estado de error mediante stop
                    if (stop = '1') then
                        state := idle;
                    end if;

            end case;
        end if;
    end process;
end Behavioral;

Entradas relacionadas: