Manufaturação industrial
Internet das coisas industrial | Materiais industriais | Manutenção e reparo de equipamentos | Programação industrial |
home  MfgRobots >> Manufaturação industrial >  >> Industrial programming >> VHDL

Aproveitando Procedimentos In-Process para Design de FSM em VHDL Mais Limpo

Em VHDL, um procedimento pode conduzir sinais externos desde que o sinal permaneça em seu escopo. Embora um procedimento declarado em uma arquitetura não tenha acesso a sinais externos — porque esses sinais não são visíveis em tempo de compilação — um procedimento definido dentro de um processo pode ler e escrever livremente qualquer sinal que o processo possa ver.

Usar procedimentos in-process é uma maneira eficaz de organizar lógica repetitiva em máquinas de estado ou protocolos complexos. Encapsulando ações comuns — como uma transição de estado temporizada — dentro de um procedimento, você reduz código boilerplate, melhora a legibilidade e torna a intenção de cada passo cristalina.

Por exemplo, em um controlador de semáforo, renomear operações para ChangeState(ToState, Minutes, Seconds) diz ao leitor exatamente o que o código está fazendo sem mergulhar nas atribuições de variáveis subjacentes.

Exercício Prático

Em um tutorial anterior, usamos uma função impura para conduzir um sinal Counter e determinar mudanças de estado. No entanto, não podíamos mover a atribuição State para essa função porque VHDL exige um valor de retorno para toda chamada de função. Em vez disso, um procedimento — desprovido de valor de retorno — se encaixa perfeitamente para este caso de uso.

Abaixo está o testbench e módulo completos que demonstram um FSM de semáforo conduzido por um procedimento in-process.

Testbench

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T23_ProcedureInProcessTb is end entity; architecture sim of T23_ProcedureInProcessTb is constant ClockFrequencyHz : integer := 100; -- 100 Hz constant ClockPeriod : time := 1000 ms / ClockFrequencyHz; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal NorthRed : std_logic; signal NorthYellow : std_logic; signal NorthGreen : std_logic; signal WestRed : std_logic; signal WestYellow : std_logic; signal WestGreen : std_logic; begin i_TrafficLights : entity work.T23_TrafficLights(rtl) generic map(ClockFrequencyHz => ClockFrequencyHz) port map ( Clk => Clk, nRst => nRst, NorthRed => NorthRed, NorthYellow => NorthYellow, NorthGreen => NorthGreen, WestRed => WestRed, WestYellow => WestYellow, WestGreen => WestGreen); Clk <= not Clk after ClockPeriod / 2; process is begin wait until rising_edge(Clk); wait until rising_edge(Clk); nRst <= '1'; wait; end process; end architecture;

Módulo Semáforo

library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T23_TrafficLights is generic(ClockFrequencyHz : integer); port( Clk : in std_logic; nRst : in std_logic; NorthRed : out std_logic; NorthYellow : out std_logic; NorthGreen : out std_logic; WestRed : out std_logic; WestYellow : out std_logic; WestGreen : out std_logic); end entity; architecture rtl of T23_TrafficLights is type t_State is (NorthNext, StartNorth, North, StopNorth, WestNext, StartWest, West, StopWest); signal State : t_State; signal Counter : integer range 0 to ClockFrequencyHz * 60; begin process(Clk) is procedure ChangeState(ToState : t_State; Minutes : integer := 0; Seconds : integer := 0) is variable TotalSeconds : integer; variable ClockCycles : integer; begin TotalSeconds := Seconds + Minutes * 60; ClockCycles := TotalSeconds * ClockFrequencyHz - 1; if Counter = ClockCycles then Counter <= 0; State <= ToState; end if; end procedure; begin if rising_edge(Clk) then if nRst = '0' then State <= NorthNext; Counter <= 0; NorthRed <= '1'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '1'; WestYellow <= '0'; WestGreen <= '0'; else NorthRed <= '0'; NorthYellow <= '0'; NorthGreen <= '0'; WestRed <= '0'; WestYellow <= '0'; WestGreen <= '0'; Counter <= Counter + 1; case State is when NorthNext => NorthRed <= '1'; WestRed <= '1'; ChangeState(StartNorth, Seconds => 5); when StartNorth => NorthRed <= '1'; NorthYellow <= '1'; WestRed <= '1'; ChangeState(North, Seconds => 5); when North => NorthGreen <= '1'; WestRed <= '1'; ChangeState(StopNorth, Minutes => 1); when StopNorth => NorthYellow <= '1'; WestRed <= '1'; ChangeState(WestNext, Seconds => 5); when WestNext => NorthRed <= '1'; WestRed <= '1'; ChangeState(StartWest, Seconds => 5); when StartWest => NorthRed <= '1'; WestRed <= '1'; WestYellow <= '1'; ChangeState(West, Seconds => 5); when West => NorthRed <= '1'; WestGreen <= '1'; ChangeState(StopWest, Minutes => 1); when StopWest => NorthRed <= '1'; WestYellow <= '1'; ChangeState(NorthNext, Seconds => 5); end case; end if; end if; end process; end architecture;

Forma de Onda

A simulação permanece idêntica ao FSM original — apenas o código se tornou mais mantenível e fácil de entender.

Análise

Ao mover a lógica de tempo e mudança de estado para um único procedimento, preservamos o comportamento do módulo enquanto melhoramos dramaticamente a legibilidade. O procedimento garante implementação consistente onde quer que seja chamado.

Principais Conclusões

VHDL

  1. Introdução ao VHDL: Construindo sua Primeira Porta AND
  2. Exemplo de Procedure VHDL: Incrementando um Standard Logic Vector
  3. Como o Molibdênio Molda a Indústria Moderna: Usos, Benefícios e Dinâmica de Fornecimento
  4. Criando Listas de Strings em VHDL: Boas Práticas e Exemplo
  5. Usando Funções Impuras em VHDL: Melhorando Legibilidade e Manutenibilidade de FSM
  6. Dominando Funções VHDL: Guia Prático para Design Eficiente
  7. Usando Procedimentos em VHDL: Simplifique seu Design com Código Reutilizável
  8. Construindo um Temporizador Confiável em VHDL: Contando Ciclos de Clock até Horas
  9. Construindo um Processo Disparado por Clock em VHDL: Guia Prático
  10. Dominando Técnicas de Retificadora de Ferramentas e Cortadores: Guia Prático