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
- A medição do tempo em módulos VHDL é obtida contando os ciclos de clock
- Reduzir a frequência do clock no testbench acelerará a simulação
Ir para o próximo tutorial »
VHDL
- Como criar uma lista de strings em VHDL
- Como criar um testbench orientado por Tcl para um módulo de bloqueio de código VHDL
- Como parar a simulação em um testbench VHDL
- Como criar um controlador PWM em VHDL
- Como gerar números aleatórios em VHDL
- Como criar um buffer de anel FIFO em VHDL
- Como criar um testbench de autoverificação
- Como criar uma lista vinculada em VHDL
- Como usar um procedimento em um processo em VHDL
- Como usar uma função em VHDL