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

Como criar um temporizador em VHDL


Em tutoriais anteriores, usamos o wait for instrução para atrasar o tempo na simulação. Mas e os módulos de produção? O wait for declaração não pode ser usada para isso. Isso só funciona em simulação porque não podemos simplesmente dizer aos elétrons em um circuito para pausar por um determinado tempo. Então, como podemos acompanhar o tempo em um módulo de design?

A resposta é simplesmente contar os ciclos de clock. Todo projeto digital tem acesso a um sinal de clock que oscila em uma frequência fixa e conhecida. Portanto, se soubermos que a frequência de clock é de 100 MHz, podemos medir um segundo contando cem milhões de ciclos de clock.

Esta postagem do blog faz parte da série de tutoriais básicos de VHDL.

Para contar segundos em VHDL, podemos implementar um contador que conta o número de períodos de relógio que passam. Quando este contador atinge o valor da frequência do clock, 100 milhões por exemplo, sabemos que passou um segundo e é hora de incrementar outro contador. Vamos chamar isso de contador de segundos.

Para contar os minutos, podemos implementar outro contador de minutos que é incrementado após 60 segundos. Da mesma forma, podemos criar um contador de horas para contar horas, incrementando quando 60 minutos se passaram.

Podemos continuar essa abordagem para contar dias, semanas e meses também. Estamos limitados pelos recursos físicos disponíveis na tecnologia subjacente, bem como pelo comprimento do contador versus a frequência do relógio.

À medida que o comprimento dos contadores aumenta, obviamente consome mais recursos. Mas também reagirá mais lentamente porque a cadeia de eventos se torna mais longa.

Exercício


Neste tutorial em vídeo vamos aprender como criar um módulo timer em VHDL:



O código final para o timer testbench :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T18_TimerTb is
end entity;

architecture sim of T18_TimerTb is

    -- We're slowing down the clock to speed up simulation time
    constant ClockFrequencyHz : integer := 10; -- 10 Hz
    constant ClockPeriod      : time := 1000 ms / ClockFrequencyHz;

    signal Clk     : std_logic := '1';
    signal nRst    : std_logic := '0';
    signal Seconds : integer;
    signal Minutes : integer;
    signal Hours   : integer;

begin

    -- The Device Under Test (DUT)
    i_Timer : entity work.T18_Timer(rtl)
    generic map(ClockFrequencyHz => ClockFrequencyHz)
    port map (
        Clk     => Clk,
        nRst    => nRst,
        Seconds => Seconds,
        Minutes => Minutes,
        Hours   => Hours);

    -- Process for generating the clock
    Clk <= not Clk after ClockPeriod / 2;

    -- Testbench sequence
    process is
    begin
        wait until rising_edge(Clk);
        wait until rising_edge(Clk);

        -- Take the DUT out of reset
        nRst <= '1';

        wait;
    end process;

end architecture;

O código final para o módulo do temporizador :
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;

entity T18_Timer is
generic(ClockFrequencyHz : integer);
port(
    Clk     : in std_logic;
    nRst    : in std_logic; -- Negative reset
    Seconds : inout integer;
    Minutes : inout integer;
    Hours   : inout integer);
end entity;

architecture rtl of T18_Timer is

    -- Signal for counting clock periods
    signal Ticks : integer;

begin

    process(Clk) is
    begin
        if rising_edge(Clk) then

            -- If the negative reset signal is active
            if nRst = '0' then
                Ticks   <= 0;
                Seconds <= 0;
                Minutes <= 0;
                Hours   <= 0;
            else

                -- True once every second
                if Ticks = ClockFrequencyHz - 1 then
                    Ticks <= 0;

                    -- True once every minute
                    if Seconds = 59 then
                        Seconds <= 0;

                        -- True once every hour
                        if Minutes = 59 then
                            Minutes <= 0;

                            -- True once a day
                            if Hours = 23 then
                                Hours <= 0;
                            else
                                Hours <= Hours + 1;
                            end if;

                        else
                            Minutes <= Minutes + 1;
                        end if;

                    else
                        Seconds <= Seconds + 1;
                    end if;

                else
                    Ticks <= Ticks + 1;
                end if;

            end if;
        end if;
    end process;

end architecture;

A forma de onda ampliou o Seconds sinal:


A forma de onda ampliou o Minutes sinal:


A forma de onda aumentou o zoom no Hours sinal:





Análise


Para executar uma simulação de 50 horas, demos o comando run 50 hr no console do ModelSim. Cinquenta horas é uma simulação muito longa e, portanto, tivemos que diminuir a frequência do relógio no banco de testes para 10 Hz. Se tivéssemos deixado em 100 MHz, a simulação levaria dias. Tais adaptações às vezes são necessárias para nos permitir simular um projeto.

Clicamos com o botão direito do mouse na linha do tempo na forma de onda e selecionamos “Grid, Timeline &Cursor Control”. Ao alterar a unidade de tempo de ns para segundos, minutos e horas, pudemos ver que o cronômetro estava realmente funcionando em tempo real.

O tempo do temporizador é ligeiramente deslocado do tempo de simulação devido à reinicialização do módulo no início da simulação. É visível na primeira forma de onda, onde a marca de 60 segundos na linha do tempo está um pouco antes, quando o sinal de segundos chega a 0.

Observe que na simulação, os valores do contador são atualizados em tempo zero na borda de subida do relógio. No mundo real, o valor do contador precisará de algum tempo para se propagar do primeiro bit do contador ao último. À medida que aumentamos o comprimento dos contadores, consumimos o tempo disponível de um período do relógio.



Se o comprimento acumulado de todos os contadores em cascata se tornar muito longo, um erro será produzido na etapa de local e rota após a compilação. Quanto tempo um contador pode ser implementado antes de consumir todo o período de clock depende da arquitetura FPGA ou ASIC e da velocidade do clock.

Uma velocidade de clock aumentada significa que a cadeia do contador será mais longa. Isso também significa que o tempo do período do relógio será mais curto, dando à cadeia do contador ainda menos tempo para ser concluída.


Retirada


Ir para o próximo tutorial »

VHDL

  1. Como criar uma lista de strings em VHDL
  2. Como criar um testbench orientado por Tcl para um módulo de bloqueio de código VHDL
  3. Como parar a simulação em um testbench VHDL
  4. Como criar um controlador PWM em VHDL
  5. Como gerar números aleatórios em VHDL
  6. Como criar um buffer de anel FIFO em VHDL
  7. Como criar um testbench de autoverificação
  8. Como criar uma lista vinculada em VHDL
  9. Como usar um procedimento em um processo em VHDL
  10. Como usar uma função em VHDL