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

Gerar exemplo de debouncer de declaração


A instrução generate em VHDL pode duplicar automaticamente um bloco de código para encerramentos com sinais, processos e instâncias idênticos. É um loop for para a região de arquitetura que pode criar processos encadeados ou instâncias de módulo.



Ao contrário de um loop for regular, que só pode existir em um processo ou subprograma, a instrução generate é colocada diretamente na região de arquitetura do arquivo VHDL. Quando usado em conjunto com genéricos, torna-se uma ferramenta poderosa para projetar módulos VHDL personalizáveis ​​que permitem a reutilização em projetos.

Gerar sintaxe de instrução


A sintaxe do comando generate é a seguinte:
[label :] for <constant_name> in <range> generate
  [declarations_local_to_each_loop_iteration]
[begin]
  <processes_and_instantiations>
end generate [label];

As partes entre colchetes são opcionais. Assim, você pode omitir a região declarativa e o begin palavra-chave se você não quiser declarar nenhum objeto local. O placeholder representa um intervalo de inteiros padrão usando to ou downto .

Debouncer de switch de um bit


Antes de começarmos com a instrução generate, apresentarei um módulo simples que usaremos como exemplo ao longo deste artigo. É um debouncer capaz de depurar uma única entrada de switch.

Para torná-lo utilizável para qualquer velocidade de clock, adicionei uma entrada genérica chamada timeout_cycles . Essa constante especifica quantos ciclos de clock o tempo limite será depois que a entrada do switch for alterada. O debouncer ignorará qualquer alteração adicional no valor do switch durante o período de tempo limite.

A lista abaixo mostra a entidade do debouncer módulo. Há um interruptor saltitante entrada, e depois há o switch_debounced limpo resultado.
entity debouncer is
  generic (
    timeout_cycles : positive
    );
  port (
    clk : in std_logic;
    rst : in std_logic;
    switch : in std_logic;
    switch_debounced : out std_logic
  );
end debouncer;

O módulo debouncer conta com um contador inteiro para atingir o período de tempo limite. O comprimento do contador sinal segue a constante genérica. É isso que a duração do tempo limite especificada durante a instanciação faz.

Porque precisamos ler o valor do switch_debounced output internamente, eu declarei um shadow signal chamado debounced , que usaremos em seu lugar. Essa é uma solução mais limpa do que a outra opção, que é definir inout modo em switch_debounce na entidade.

Por fim, implementamos o comportamento de debounce em um único processo, conforme mostrado no código abaixo.
architecture rtl of debouncer is

  signal debounced : std_logic;
  signal counter : integer range 0 to timeout_cycles - 1;

begin

  -- Copy internal signal to output
  switch_debounced <= debounced;

  DEBOUNCE_PROC : process(clk)
  begin
    if rising_edge(clk) then
      if rst = '1' then
        counter <= 0;
        debounced <= switch;
        
      else
        
        if counter < timeout_cycles - 1 then
          counter <= counter + 1;
        elsif switch /= debounced then
          counter <= 0;
          debounced <= switch;
        end if;

      end if;
    end if;
  end process;

end architecture;

A forma de onda abaixo mostra uma simulação do debounce módulo no ModelSim. Podemos ver que o switch_debounced a saída segue o switch entrada, mas ignora o comportamento de salto imediato após a primeira mudança - ele debounce o sinal.



Use o formulário abaixo para baixar o código VHDL deste artigo. Ao inserir seu endereço de e-mail, você receberá um arquivo Zip contendo todo o projeto ModelSim com testbenches e um script de execução rápida. Você receberá atualizações futuras do VHDLwhiz e poderá cancelar a assinatura a qualquer momento.




Gerar loop for com instanciações


Para fazer um debouncer para um array de switches, usaremos uma instrução generate para criar várias instâncias do nosso módulo debouncer de um bit.

A lista abaixo mostra a entidade do nosso novo módulo debouncer de vetor ou array. É semelhante ao debouncer de um bit, mas há uma entrada genérica adicional:switch_count . Ele especifica quantas instâncias do módulo debouncer devem ser criadas. Deve haver um para cada switch.

Além disso, renomeei a entrada e a saída do switch para as versões plurais da palavra, e agora elas são vetores em vez de bits únicos.
entity debouncer_gen_inst is
  generic (
    switch_count : positive;
    timeout_cycles : positive
    );
  port (
    clk : in std_logic;
    rst : in std_logic;
    switches : in std_logic_vector(switch_count - 1 downto 0);
    switches_debounced : out std_logic_vector(switch_count - 1 downto 0)
  );
end debouncer_gen_inst;

Na arquitetura, é hora de usar a instrução generate. Funciona como um loop for regular, apenas com a palavra “generate” substituindo a palavra “loop”. Mas, ao contrário de um loop for regular, ele pode conter instanciações de módulo.

O loop for é executado em tempo de compilação e gera uma instância do módulo debouncer para cada iteração. Mas como a constante “i” será diferente para cada iteração, podemos usá-la para mapear as entradas e saídas dos debouncers para bits individuais nos vetores de switch, conforme mostrado abaixo.
architecture rtl of debouncer_gen_inst is
begin

  MY_GEN : for i in 0 to switch_count - 1 generate

    DEBOUNCER : entity work.debouncer(rtl)
    generic map (
      timeout_cycles => timeout_cycles
    )
    port map (
      clk => clk,
      rst => rst,
      switch => switches(i),
      switch_debounced => switches_debounced(i)
    );

  end generate;

end architecture;

Observe que é opcional rotular a instrução generate, mas pode ser sensato fazê-lo. O rótulo aparece na hierarquia do simulador e no log de síntese, facilitando a identificação da instância específica durante a depuração.

A forma de onda abaixo mostra uma simulação do vetor debouncer. Podemos ver que o rótulo “MY_GEN” reaparece aqui, com índices adicionados para cada uma das oito instâncias do debouncer.



Este testbench altera apenas a entrada do switch número 3, é isso que você vê na forma de onda e por isso expandi apenas o grupo MY_GEN(3).

Você pode executar este exemplo rapidamente em seu computador se tiver o ModelSim instalado. Use o formulário abaixo para baixar o código fonte e o projeto ModelSim!




Gerar for loop contendo processos


No último exemplo deste artigo, usaremos uma instrução de geração para fazer uma série de processos idênticos. Em vez de criar instâncias do módulo debouncer de um bit, retirei o código VHDL dele. A entidade é a mesma do exemplo anterior, assim como o comportamento, mas a implementação é diferente.

Podemos ver que movi o processo DEBOUNCE_PROC dentro da instrução generate e alterei um pouco no código abaixo. Desta vez estou declarando dois sinais locais dentro do comando generate:debounced e contador .

Cada iteração do loop for criará uma cópia adicional dos sinais e do processo. O uso desses nomes de sinal dentro do processo fará referência àqueles com escopo definido para o gabinete dessa iteração de loop específica.

Por fim, estou atribuindo o debounced std_logic sinal para o bit correto do switches_debounced saída do módulo usando uma instrução concorrente acima do processo.
architecture rtl of debouncer_gen_proc is
begin

  MY_GEN : for i in 0 to switch_count - 1 generate

    signal debounced : std_logic;
    signal counter : integer range 0 to timeout_cycles - 1;

  begin

    switches_debounced(i) <= debounced;

    DEBOUNCE_PROC : process(clk)
    begin
      if rising_edge(clk) then
        if rst = '1' then
          counter <= 0;
          debounced <= switches(i);

        else

          if counter < timeout_cycles - 1 then
            counter <= counter + 1;
          elsif switches(i) /= debounced then
            counter <= 0;
            debounced <= switches(i);
          end if;

        end if;
      end if;
    end process;

  end generate;

end architecture;

Eu omiti a forma de onda de simulação porque ela parece exatamente a mesma do exemplo anterior usando instanciação de módulo. O comportamento é idêntico.

Você pode baixar todo o código usando o formulário abaixo. Ao inserir seu endereço de e-mail, você se inscreve nas atualizações do VHDLwhiz. Mas não se preocupe, há um link de cancelamento de inscrição em todos os e-mails que eu envio.





Deixe um comentário abaixo se você tiver outro aplicativo útil para gerar declarações para compartilhar! ?

VHDL

  1. Declaração de Procedimento - Exemplo de VHDL
  2. Registros - Exemplo de VHDL
  3. Variáveis ​​- Exemplo de VHDL
  4. Circuito com interruptor
  5. Opções de análise
  6. Tipos de troca
  7. Instrução C# switch
  8. Instrução C# break
  9. C# continue declaração
  10. Instrução C++ Switch Case com EXEMPLO