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