Decodificador de Senha
O projeto apresentado nesse artigo tem como objetivo implementar sistema que lerá um teclado e, quando a sequência correta de digitos for digitada, acenderá um LED durante 15s.
O projeto foi desenvolvido em VHDL e testado via testbench no modelsim-Altera. Esse projeto é um exemplo de logica sequencial.
O equipamento utilizado foi:
- 1x Kit CPLD_7064;
- 1x placa teclado matricial;
- 1x placa de LEDs;
Descrição de Funcionamento
O decodificador de senha é baseado na leitura de teclado e, caso seja inserido a sequencia correta, sinaliza através de um LED, que ficará aceso por 15 segundos e depois desligará. A leitura de teclado é baseada na varredura de teclado matricial, a qual será utilizada como componente (caso não saiba como criar um componente em VHDL, siga as instruções da animação abaixo).
Descrição em VHDL
Serão utilizadas apenas 10 portas, 7 para as linhas e colunas do teclado, 1 para o clock, 1 para reset e uma para a saida. Abaixo segue a declaração da entity:
1 2 3 4 5 6 7 8 9 |
entity DECODIFICADOR_SENHA is port ( CLK, RESETn : in std_logic; F, E, D : in std_logic; K, J, H, G : out std_logic; SAIDA : out std_logic := '0' ); end entity; |
Dentro da arquitetura teremos que declarar o componente da leitura do teclado e o sinal auxiliar TECLA para o registro da tecla pressionada.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
signal TECLA : std_logic_vector(3 downto 0); COMPONENT teclado PORT ( CLOCK : IN STD_LOGIC; F : IN STD_LOGIC; E : IN STD_LOGIC; D : IN STD_LOGIC; K : OUT STD_LOGIC; J : OUT STD_LOGIC; H : OUT STD_LOGIC; G : OUT STD_LOGIC; TECLA : OUT STD_LOGIC_VECTOR(3 DOWNTO 0) ); END COMPONENT; |
Depois de declarar o componente, é feita a sua instanciação. Lembrando que é necessario que os signals/valores atribuidos sejam do mesmo tipo e do mesmo tamanho.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
begin TECLADO_INST: TECLADO port map ( CLOCK => CLK, F => F, E => E, D => D, K => K, J => J, H => H, G => G, TECLA => TECLA ); |
O process principal será sensível a variação do clock e do reset. Dentro do process são declaradas as variaveis que auxiliaram no controle do programa.
1 2 3 4 5 6 7 8 |
process (CLK, RESETn) variable VALOR_SAIDA : std_logic := '0'; variable DIGITO : integer range 0 to 4 := 0; variable SENHA : std_logic_vector(15 downto 0) := x"FFFF"; variable CONT : integer range 0 to 31 := 0; variable CONTA : integer range 0 to 1024 := 0; variable FLAG : std_logic := '0'; |
A primeira condição testada dentro do process é se o botão de reset está pressionado, caso esteja, os signals e variables do programa voltam aos valores iniciais.
1 2 3 4 5 6 7 |
if RESETn = '0' then -- Reset do programa DIGITO := 0; SENHA := x"FFFF"; VALOR_SAIDA := '0'; FLAG := '0'; CONTA := 0; CONT := 0; |
Em seguida, é declarada a parte principal do programa, chamada a cada pulso de clock. A primeiramente verifica-se se a saída está ativa. Quando ela está ativa, incrementa-se a variable CONTA, responsável por limitar o tempo em que a saída ficará ativa, nesse caso 15 segundos, com um clock de 64Hz, o que da 960 contagens.
1 2 3 4 5 6 |
if VALOR_SAIDA = '1' then -- Quando está aberto CONTA := CONTA + 1; -- incrementa o contador do tempo da saida e if CONTA = 960 then -- verifica se ja passou o tempo para que a saída seja fechada. VALOR_SAIDA := '0'; CONTA := 0; end if; |
A variable CONT é responsável pela proteção contra o ruído de trepidação. A FLAG é indica se o botão anteriormente pressionado foi solto, para evitar que seja registrado mais de uma vez. Juntando essas duas variable mais o signal TECLA, que indica qual a tecla pressionada, constroi-se a condição necessária para a que seja registrado um valor na variable SENHA. O valor da senha pode ser modificado alterando o valor presente no if, neste caso a senha é colocada como x”0123″.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
elsif CONT = 31 and TECLA /= "1111" and FLAG = '0' then -- FLAG := '1'; CONT := 0; SENHA (3 downto 0) := TECLA; -- Depois que foi dado o inicio ao registro das teclas, registra-se -- as teclas no 4 bits menos significativos do signal SENHA. DIGITO := DIGITO + 1; -- DIGITO faz a contagem de quantas teclas ja foram digitadas if DIGITO = 4 then -- Depois da quarta tecla ser digitada, o programa compara a senha digitada DIGITO := 0; -- com a senha programada, caso a senha esteja correta a saida assume '1' if SENHA = x"0123" then VALOR_SAIDA := '1'; end if; SENHA := x"FFFF"; -- No final, o signal que registra a senha e a FLAG_INICIO são apagados else -- Caso ainda não tenha sido digitada as quatro teclas, SENHA é rotacionado for i in 15 downto 4 loop -- 4 vezes. SENHA(i) := SENHA(i - 4); end loop; end if; |
A variable digito tem o objetivo de contar quantas teclas ja foram pressionadas e quando ja tiverem sido inseridas 4 teclas faz-se a verificação da senha, caso esteja correta a saida é habilitada. Depois disso, as variáveis são resetadas.
Fora do controle das teclas pressionadas, ocorre o incremento de CONT a cada pulso de clock.
1 2 3 |
if CONT < 31 then CONT := CONT + 1; end if; |
Por ultimo, o programa verifica se as teclas do teclado estão soltas para fazer o controle da variable FLAG e atribui VALOR_SAIDA à SAIDA.
1 2 3 4 5 |
if TECLA = "1111" then -- Detecta que o botão já foi solto; FLAG := '0'; end if; SAIDA <= VALOR_SAIDA; |
Simulação
A simulação é feita através de um testbench que emula o pressionamento de uma sequência de teclas para averiguar o funcionamento do decodificador. Para que a simulação seja mais suscinta, diminui-se os limites de CONT e CONTA. Para este teste, modificou-se o limite de CONT para 1 e o de CONTA para 30.
As instruções do testbench iniciam com a geração do clock:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
gera_clock: process begin RESETn <= '0'; wait for 5ms; RESETn <= '1'; for cont in 0 to 1000 loop CLK <= '1'; wait for 5 ms; CLK <= '0'; wait for 5 ms; end loop; wait; end process; |
No outro processo são emulados o pressionamento dos botões. Abaixo segue a declaração para o pressionamento das primeiras teclas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
process begin F <= 'H'; E <= 'H'; D <= 'H'; -- Pressionamento da Tecla '0' wait for 80ms; wait until G = '0'; E <= '0'; wait for 15 ms ; E <= 'H'; -- Pressionamento da Tecla '1' wait for 80 ms; wait until K = '0'; F <= '0'; wait for 15 ms ; F <= 'H'; -- Pressionamento da Tecla '2' wait for 80 ms; wait until K= '0'; E <= '0'; wait for 15 ms ; E <= 'H'; -- Pressionamento da Tecla '3' wait for 80 ms; wait until K= '0'; D <= '0'; wait for 15 ms ; D <= 'H'; wait for 1500ms; |
As formas de onda encontradas na simulação mostram o funcionamento correto do programa.
Figura 1: Resultados da Simulação.
Estrutura Física
O projeto é composto do kit CPLD_7064, um teclado matricial e uma placa de LEDs. O teclado funcionará como entrada de dados para a verificação da senha e a placa de LEDs, que apresentará a saída. O componente utilizado foi o EPM7064, da família MAX7000S.
Montagem e Roteamento
A placa de LEDs será conectada a CON1 e o LED escolhido para será o L0, portanto o pino correspondente no CPLD é o 14. O teclado será conectado a CON2 e tem a ordem de conexão segundo a imagem abaixo. Vale lembrar que o seletor de clock de baixa frequência deve estar na posição 64Hz.
Figura 3: Ilustração da conexão entre o teclado e o kit CPLD feita no Fritzing.
Figura 4 : Ilustração das conexões das placas periféricas com o kit CPLD feita no Fritzing.
Figura 5: Pin Planner com os pinos atribuidos.
Gravação e Teste
A gravação ocorre seguindo o tutorial do Quartus II. Para testar, pressiona-se as teclas e, caso a sequencia seja a correspondente a senha, o LED da saída acende. Esse mesmo algorítimo poderia ser usado para outras finalidades, como, por exemplo, uma fechadura acionada por senha, porém seria necessário implementar a comunicação entre o CPLD e a fechadura.