Como criar um processo cronometrado em VHDL
A grande maioria dos designs de VHDL usa lógica com clock , também conhecido como lógica síncrona ou lógica sequencial . Um processo cronometrado é acionado apenas por um sinal de relógio mestre, não quando qualquer um dos outros sinais de entrada muda.
O bloco de construção básico da lógica com clock é um componente chamado flip-flop . Existem diferentes variantes dele, e neste tutorial vamos focar no flip-flop acionado por borda positiva com reset negativo:
O flip-flop é um circuito sample-and-hold, o que significa que ele copia o valor da entrada para a saída quando a borda de subida do sinal de clock chega. A saída é então mantida estável no valor amostrado até a próxima borda de subida do clock, ou até que o sinal de reset seja pulsado.
Esta postagem do blog faz parte da série de tutoriais básicos de VHDL.
Todos os processos cronometrados são acionados simultaneamente e lerão suas entradas de uma só vez. Ao mesmo tempo, eles produzirão os resultados da última iteração. O sinal de relógio cria efetivamente intervalos de tempo no fluxo de dados. Isso torna gerenciável para o designer criar lógica complexa e profunda. Ele ou ela pode quebrar as ações do algoritmo em eventos que acontecem nos ciclos do relógio.
Flip-flops ou arrays de flip-flops às vezes são chamados de registros , é a mesma coisa.
A lista de sensibilidade para processos com clock geralmente contém apenas o sinal de clock. Isso ocorre porque um processo com clock é acionado apenas por um flanco no sinal de clock, os outros sinais de entrada não farão com que ele acorde.
Este é um modelo para criar um processo cronometrado com redefinição síncrona:
process(Clk) is
begin
if rising_edge(Clk) then
if nRst = '0' then
<reset all output signals here>
else
<main logic here>
end if;
end if;
end process;
Exercício
Neste tutorial em vídeo vamos aprender como criar um processo com clock em VHDL:
O código final para o flip-flop testbench :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T17_ClockedProcessTb is end entity; architecture sim of T17_ClockedProcessTb is constant ClockFrequency : integer := 100e6; -- 100 MHz constant ClockPeriod : time := 1000 ms / ClockFrequency; signal Clk : std_logic := '1'; signal nRst : std_logic := '0'; signal Input : std_logic := '0'; signal Output : std_logic; begin -- The Device Under Test (DUT) i_FlipFlop : entity work.T17_FlipFlop(rtl) port map( Clk => Clk, nRst => nRst, Input => Input, Output => Output); -- Process for generating the clock Clk <= not Clk after ClockPeriod / 2; -- Testbench sequence process is begin -- Take the DUT out of reset nRst <= '1'; wait for 20 ns; Input <= '1'; wait for 22 ns; Input <= '0'; wait for 6 ns; Input <= '1'; wait for 20 ns; -- Reset the DUT nRst <= '0'; wait; end process; end architecture;
O código final para o módulo do flip-flop :
library ieee; use ieee.std_logic_1164.all; use ieee.numeric_std.all; entity T17_FlipFlop is port( Clk : in std_logic; nRst : in std_logic; -- Negative reset Input : in std_logic; Output : out std_logic); end entity; architecture rtl of T17_FlipFlop is begin -- Flip-flop with synchronized reset process(Clk) is begin if rising_edge(Clk) then if nRst = '0' then Output <= '0'; else Output <= Input; end if; end if; end process; end architecture;
A janela de forma de onda no ModelSim depois que pressionamos executar e ampliamos a linha do tempo:
Análise
Podemos ver pela forma de onda que o sinal de saída é atualizado apenas em cada borda de subida do sinal de clock. O sinal de entrada é amostrado apenas quando o sinal do relógio muda de '0' para '1'. A queda negativa do sinal de entrada começando em cerca de 45 ns é completamente perdida. Ele não é copiado para a saída porque está entre duas bordas ascendentes do relógio e, portanto, é ignorado.
Esta animação ilustra como a saída reage à mudança dos sinais de entrada e clock:
As linhas verticais indicam como o sinal de entrada é relativo às bordas ascendentes do clock.
Preste atenção especial ao pulso positivo no sinal de entrada a partir de 20 ns. É síncrono com o relógio e exatamente um período de relógio. A saída não reage instantaneamente, é atrasada por um período de clock.
Quando eu estava aprendendo VHDL, achei isso particularmente difícil de entender. A borda de subida do clock é síncrona com a borda de subida da entrada, então como o flip-flop pode escolher um valor ou outro?
O simulador usa passos de tempo para modelar eventos de maneira previsível e os sinais se propagam em tempo zero. Como o flip-flop lê a entrada exatamente no mesmo intervalo de tempo em que atualiza a saída, ele vê o valor antigo da entrada e o copia para a saída.
Leia mais sobre as etapas de tempo do VHDL aqui:Ciclos delta explicados
Devo acrescentar a esta resposta que isso não é realmente como funciona. No mundo físico, um sinal precisa de tempo para se propagar, não sabemos exatamente quando ele chega ao flip-flop. Esses atrasos de propagação são estimados automaticamente para nós pelo processo de software (local e rota) que converte o código VHDL em uma netlist.
Na realidade, a entrada deve ser mantida estável por alguns nanossegundos antes e depois da borda ascendente do clock:
Esses períodos de tempo críticos são conhecidos como tempo de configuração e espera. Felizmente, isso não é algo que você normalmente deve levar em consideração. Ao trabalhar puramente com lógica cronometrada, esses problemas são tratados pelo software que transforma o código VHDL em uma netlist.
Retirada
- Processos bloqueados com reinicialização sincronizada têm apenas o sinal do relógio na lista de sensibilidade
- O
if rising_edge(Clk)
garante que o processo só acorde nas bordas ascendentes do relógio - Em um design síncrono, as coisas só acontecem na borda do relógio ativa
Faça o Basic VHDL Quiz – parte 3 »
ou
Vá 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