Revisão 2: Quartus e Circuitos Sequenciais

Objetivos

  1. Rever blocos construtivos sequenciais.

Contextualização

Os circuitos sequenciais tem como característica principal possuŕem “memória”. O circuito base da lógica sequencial é o latch. Porém, o latch depende somente de suas entradas para modificar a sua saída.

Latch S/R e sua Tabela da Verdade
Latch S/R e sua Tabela da Verdade

Para aumentar o controle sobre o funcionamento do latch, seu circuito foi modificado para que armazenasse a sua entrada somente através do controle de um sinal de gatilho ou clock. Mais especificamente, a transferência ocorrerá somente na borda de subida, ou de descida, do sinal de clock. O resultado dessa modificação é o flip flop e este é o principal bloco construtivo da lógica sequencial.

Flip Flop Tipo Construído com 3 Latchs S/R
Flip Flop Tipo Construído com 3 Latchs S/R

1 - Se o Clock for 0:

Flip Flop com Sinal de Clock em 0
Flip Flop com Sinal de Clock em 0

2 - Se o sinal Dado for 1 e o Clock passar de 0 para 1:

Flip Flop com Sinal de Clock em 1 e Dado em 1
Flip Flop com Sinal de Clock em 1 e Dado em 1

3 - Se o sinal Dado for 0 e o Clock passar de 0 para 1:

Flip Flop com Sinal de Clock em 1 e Dado em 0
Flip Flop com Sinal de Clock em 1 e Dado em 0

Contextualização: Blocos Construtivos Sequenciais

Caso ainda esteja com dificuldades de lembrar sobre o VHDL, o livro Free Range VHDL tem um resumo rápido no seu item 6.7 (Review of Almost Everything Up to Now).

Se as dúvidas ainda persistirem, leia o capítulo 3 (VHDL Design Units) do Free Range VHDL.

Os principais circuitos da lógica sequencial são:

Para relembrar o funcionamento do flip flop, leia as 3 primeiras páginas do capítulo 7 do Free Range VHDL, Using VHDL for Sequential Circuits, até o início do exemplo 15.

Um flip flop, em VHDL, utiliza a construção sequencial process(<lista_sensibilidade>). Essa construção possui uma lista de sensibilidade, listada dentro dos parênteses, que, quando houver variação de qualquer sinal dessa lista, a sequência de comandos dentro da construção process() será executada sequencialmente. Repare como é similar ao sinal de Clock de um Flip Flop.

Nos templates do Quartus, temos o seguinte modelo para um flip flop:

Simbolo do Flip Flop Tipo D
Simbolo do Flip Flop Tipo D

Para que seja um flip flop, devemos utilizar um sinal de entrada e outro de saída, ambos do tipo std_logic. O clock também deve ser std_logic.

Funcionamento:

Esse código fica aguardando uma variação no sinal de clock. Quando ocorre a variação, o código dentro da cláusula begin é disparado.

Que, por sua vez, verifica se a transição do sinal foi de subida (rising_edge()) ou de descida (falling_edge()) e, caso seja a transição desejada, dispara o código dentro da construção if.

A construção if faz a atribuição do sinal de entrada (data) para a saída do flip flop (register_variable).

Dessa forma, enquanto não houver outra transição do sinal de clock, na borda definida pelo if, o sinal de saída ficará estável, ou seja, memorizado.

Um registrador é a interligação, em paralelo, de vários flip flops de forma que haja uma entrada e uma saída para cada flip flop e o sinal de clock seja comum a todos.

Nos templates do Quartus, temos o seguinte modelo para um registrador (note que é o mesmo do flip flop):

Simbolo de um Registrador de 8 bits
Simbolo de um Registrador de 8 bits

Para que seja um registrador, devemos utilizar o sinal de entrada e o de saída, ambos do tipo std_logic_vector (esse vetor deve ter a mesma quantidade que os total de bits a serem armazenados). O clock deve ser std_logic.

Abaixo, temos o registrador genérico da nossa biblioteca de componentes. Note que a largura dos dados (número de bits) é definida pelo generic.

Por ser genérico, esse registrador possui mais dois sinais de controle:


library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity registradorGenerico is
    generic (
        larguraDados : natural := 8
    );
    port (DIN : in std_logic_vector(larguraDados-1 downto 0);
       DOUT : out std_logic_vector(larguraDados-1 downto 0);
       ENABLE : in std_logic;
       CLK,RST : in std_logic
        );
end entity;

architecture comportamento of registradorGenerico is
begin
    -- In Altera devices, register signals have a set priority.
    -- The HDL design should reflect this priority.
    process(RST, CLK)
    begin
        -- The asynchronous reset signal has the highest priority
        if (RST = '1') then
            DOUT <= (others => '0');    -- Código reconfigurável.
        else
            -- At a clock edge, if asynchronous signals have not taken priority,
            -- respond to the appropriate synchronous signal.
            -- Check for synchronous reset, then synchronous load.
            -- If none of these takes precedence, update the register output
            -- to be the register input.
            if (rising_edge(CLK)) then
                if (ENABLE = '1') then
                        DOUT <= DIN;
                end if;
            end if;
        end if;
    end process;
end architecture;

Funcionamento:

O funcionamento do registrador é o mesmo do flip flop, diferindo somente na quantidade de dados transferida da entrada para a saída. A forma como o reset é implementado, permite que seja alterada a quantidade de bits do registrador sem precisar alterar o código.

O comando DOUT <= (others => ‘0’); verifica qual a quantidade de bits utilizada e ajusta a atribuição para essa quantidade.

Atividade:

Crie um projeto no Quartus e instancie o registrador mostrado no código acima. Faça alterações na definição do generic e veja o resultado no RTL Viewer.

Simule o funcionamento para se familiarizar com o componente. Certifique que os sinais de controle estão funcionando (tanto o enable quanto o reset).


Pipeline

O pipeline é uma sequência de circuitos combinacionais separados por registradores, chamados de registradores de etapa ou fronteira. Essa técnica permite dividir o tempo de propagação do circuito combinacional em etapas distintas e, consequentemente, é possível aumentar o clock (velocidade) do circuito. Essa é a utilização mais comum no projeto de processadores.

Pipeline de 8 bits
Pipeline de 8 bits

A criação de um pipeline vazio permite adicionar um atraso de propagação de um período de clock por etapa do pipeline.

Pipeline de 8 bits Vazio
Pipeline de 8 bits Vazio

Esse tipo de circuito funciona devido ao tempo de propagação entre a entrada e a saída do registrador após a ativação do clock. Esse tempo de propagação é maior do que a janela de tempo da ocorrência do clock, impedindo o sinal de entrada do primeiro registrador consiga alcançar a entrada o segundo registrador em tempo hábil para ser memorizado durante um mesmo clock.

Para observar o efeito dos dados atravessando o pipeline, vamos montar o circuito abaixo e, através das chaves, alimentar com a sequência binária: 0x0, pulso de clock, 0x1, pulso de clock, 0x2 pulso de clock, 0x3 e pulso de clock. Poderemos ver o funcionamento através da simulação do Quartus.

Pipeline
Pipeline

Contadores

Um projeto de contador que não é tão usual em práticas digitais mas é muito usado no projeto de processadores, está mostrado abaixo. Ele conta o número de vezes que o botão KEY 0 foi pressionado.

Contador com Somador
Contador com Somador

Novamente, esse tipo de circuito depende da característica do flip-flop (ou registrador) de amostrar o valor de entrada durante uma janela de tempo muito estreita (a transição do clock).

Vamos montar o circuito abaixo e, através das chaves, verificar a carga de um valor e a contagem subsequente. Poderemos ver o funcionamento através da simulação do Quartus.

Contador com Somador e Carga de Valor
Contador com Somador e Carga de Valor