Preview only show first 10 pages with watermark. For full document please download

Relatórios Taed

Relatórios dos Lab 01 ao 05

   EMBED


Share

Transcript

UNIVERSIDADE FEDERAL DO CEARÁ DEPARTAMENTO DE ENGENHARIA ELÉTRICA TÉCNICAS AVANÇADAS DE ELETRÔNICA DIGITAL Relatórios dos Laboratórios 01 ao 05 Turma 01A José Roberto Pereira dos Santos - 336371 Professor Paulo Praça Fortaleza, dezembro de 2015 Sumário Laboratório 01 – Descrição de circuitos digitais com comandos concorrentes ......................2 Laboratório 02 – Circuitos Sequenciais ....................................................................................6 Laboratório 03 – Divisores de Frequência .............................................................................11 Laboratório 04 – Teclado PS/2 ................................................................................................17 Laboratório 05 – Sensor de distância ultrassônico HC-SR04 ...............................................21 Laboratório 01 – Descrição de circuitos digitais com comandos concorrentes 1) Apresente uma solução para um multiplexador de 4 canais utilizando o comando WITH/SELECT. entity q1 is port (e: in bit_vector(3 downto 0); s: in bit_vector(1 downto 0); x: out bit); end q1; -- entradas do mux -- vetor de seletoras -- saída do mux architecture mux of q1 is begin with s select x <= e(0) when "00", e(1) when "01", e(2) when "10", e(3) when others; end mux; -- de acordo com o vetor de seletoras ‘s’, transmitir uma das entradas ‘e’ para o saída ‘x’ 2) Descreva um circuito codificador de prioridade 8x3 semelhante ao CI 74148. O circuito deverá ter oito entradas numeradas de 0 a 7 e três saídas para indicar o binário correspondente ao número da entrada ativada. Neste circuito a entrada 7 tem maior prioridade. Há diferença em utilizar o comando WHEN/ELSE ao invés do WITH/SELECT? Por quê? Figura 1 - Tabela verdade para o codificador de prioridade entity q2 is port (e: in bit_vector (7 downto 0); x: out bit_vector (2 downto 0)); end q2; architecture pri of q2 is begin x<="111" when e(7) = "110" when e(6) = "101" when e(5) = "101" when e(5) = "100" when e(4) = "011" when e(3) = "010" when e(2) = "001" when e(1) = "000"; end pri; '1' '1' '1' '1' '1' '1' '1' '1' else else else else else else else else -- entradas -- saídas -- testa primeiramente o bit mais significativo ‘e(7)’ da entrada ‘e’, caso seja 1 define a saída para 111 independente dos outros bits de entrada. -- depois testa o próximo bit mais significativo e assim sucessivamente seguindo a tabela verdade. 2 Para utilizar o comando with/select neste código seria necessário listar todos as possíveis combinações de entrada (28 – 1 possibilidades). Utilizando o comando when/else essa tarefa é simplificada, pois mesmo sendo um comando concorrente, o when/else apresenta uma característica sequencial que nos permite testar a prioridade dos bits mais significativos para definir a saída. 3) Desenvolva um código VHDL de um decodificador hexadecimal para display de sete segmentos. Obs.: No FPGA os displays de 7 segmentos são do tipo ANODO comum, ou seja, para acenderem precisam de um nível lógico BAIXO no pino do segmento. O esquema da pinagem dos displays é mostrado na figura 1. entity q3 is port (e: in bit_vector(3 downto 0); s: out bit_vector(6 downto 0)); end q3; -- entradas -- display de saída architecture display of q3 is CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT i00 i01 i02 i03 i04 i05 i06 i07 i08 i09 i10 i11 i12 i13 i14 i15 i16 : : : : : : : : : : : : : : : : : BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector --GFE..A := "1000000"; := "1111001"; := "0100100"; := "0110000"; := "0011001"; := "0010010"; := "0000010"; := "1111000"; := "0000000"; := "0010000"; := "0001000"; := "0000011"; := "1000110"; := "0100001"; := "0000110"; := "0001110"; := "1111111"; -constantes representando os dígitos (0 a 9) e os hexa (A a F) que serão envidas ao display. -- os 7 bits de cada constante correspondem aos pinos GFEDCBA do display de 7 seg. begin with e select s<=i00 when "0000", i01 when "0001", i02 when "0010", i03 when "0011", i04 when "0100", i05 when "0101", i06 when "0110", i07 when "0111", i08 when "1000", i09 when "1001", i10 when "1010", i11 when "1011", i12 when "1100", i13 when "1101", i14 when "1110", i15 when "1111", i16 when others; end display; --compara qual constante representa o valor binário na entrada ‘e’, e envia a constante selecionada para a saída ‘s’. 3 4) A partir da declaração de entidade mostrada a seguir desenvolva um código de um deslocador de bits que segue a seguinte lógica:  A partir de uma entrada de 2 bits ajustada nas chaves do kit, o usuário deverá especificar o número de bits que serão deslocados no caso, de 0 até 3 bits;  Os bits deslocados serão de um vetor de 4 posições criado pelo usuário;  Os deslocamentos sempre ocorrerão para a direita;  O resultado armazenado no vetor “resultado” deverá aparecer nos leds do kit sendo o led mais à esquerda o MSB. entity deslocador is port (vetor: in bit_vector (0 to 3); entrada : in bit_vector (1 downto 0); resultado : out bit_vector (3 downto 0)); -- entidade fornecida na questão. end deslocador; architecture desl of deslocador is begin resultado <= vetor when entrada= "00" else vetor(2)&vetor(1)&vetor(0)&vetor(4) when entrada="01" else vetor(1)&vetor(0)&vetor(4)&vetor(3) when entrada="10" else vetor(0)&vetor(4)&vetor(3)&vetor(2) when entrada="11"; end desl; -- utiliza o comando when para deslocar o número de bits de acordo com o valor de entrada; o vetor resultado é formado pela aglutinação de cada um dos bits do vetor de entrada através da utilização do operador &. 5) Projete um decodificador de displays de 7 segmentos que escolha um dos quatro displays do kit, especificado por duas chaves, para receber o hexadecimal decodificado que também será aferido por chaves do módulo. Figura 2 – Esquemático da questão 5 4 entity q5 is port (e: in bit_vector(3 downto 0); d0,d1,d2,d3: out bit_vector(6 downto 0); sel: in bit_vector (1 downto 0)); end q5; architecture display of q5 is CONSTANT i00 : BIT_vector := CONSTANT i01 : BIT_vector := CONSTANT i02 : BIT_vector := CONSTANT i03 : BIT_vector := CONSTANT i04 : BIT_vector := CONSTANT i05 : BIT_vector := CONSTANT i06 : BIT_vector := CONSTANT i07 : BIT_vector := CONSTANT i08 : BIT_vector := CONSTANT i09 : BIT_vector := CONSTANT i10 : BIT_vector := CONSTANT i11 : BIT_vector := CONSTANT i12 : BIT_vector := CONSTANT i13 : BIT_vector := CONSTANT i14 : BIT_vector := CONSTANT i15 : BIT_vector := CONSTANT i16 : BIT_vector := Signal A : bit_vector (6 downto begin with e select A<=i00 when "0000", i01 when "0001", i02 when "0010", i03 when "0011", i04 when "0100", i05 when "0101", i06 when "0110", i07 when "0111", i08 when "1000", i09 when "1001", i10 when "1010", i11 when "1011", i12 when "1100", i13 when "1101", i14 when "1110", i15 when "1111", i16 when others; s0 s1 s2 s3 <= <= <= <= A A A A when when when when sel sel sel sel = = = = "00"; "01"; "10"; "11"; "1000000"; "1111001"; "0100100"; "0110000"; "0011001"; "0010010"; "0000010"; "1111000"; "0000000"; "0010000"; "0001000"; "0000011"; "1000110"; "0100001"; "0000110"; "0001110"; "1111111"; 0); -- entradas -- displays saída -- seletoras -constantes representando os dígitos (0 a 9) e os hexa (A a F) que serão envidas ao sinal ‘A’. -- sinal A que será enviado aos displays. --compara qual constante representa o valor binário na entrada ‘e’, e envia a constante selecionada para o sinal ‘A’. --seleciona o display de acordo com as seletoras ‘sel’. end display; 5 Laboratório 02 – Circuitos Sequenciais 1) Desenvolva um código VHDL que descreva o comportamento de um circuito comparador de magnitude de 4 bits semelhante ao CI 7485. Utilize a tabela abaixo para implementar a lógica do circuito. Dica: declare as duas entradas a serem comparadas como um vetor de bits. Figura 3 - Tabela de funcionamento do CI 7485 entity q1 is port (A,B : in bit_vector (3 downto 0); X end q1; : out bit_vector (2 downto 0)); architecture prio of q1 is begin X <= "100" when AB; end prio; 2) --Vetores de entrada e a saída X; Cada bit de X representa uma das condições presentes na figura 3 (menor, igual e maior). --comando When/else testa a relação entre A e B, e seta o corresponde bit da saída X. O módulo dispõe de três osciladores na placa, um de 24 MHz, outro de 27 MHz e um terceiro de 50 MHz. O exemplo de contador do quadro a seguir implementa um divisor de frequência com período de 5,12 us. Este valor é encontrado conforme equação (1). 𝑇𝑐𝑜𝑛𝑡𝑎𝑑𝑜𝑟 = 𝑇𝑐𝑙𝑜𝑐𝑘 𝑥 𝑁 (1) Onde, Tcontador é o período desejado do divisor de frequência; Tclock representa o período do clock principal do kit, neste exemplo, 20 ns (1/50 MHz); N é o inteiro declarado como “limite” no código abaixo. É possível reescrever a equação (1) em função da frequência: 6 𝑓𝑐𝑜𝑛𝑡𝑎𝑑𝑜𝑟 = 𝑓𝑐𝑙𝑜𝑐𝑘 𝑁 (2) Desenvolva um código gerador de onda quadrada com período de 100 ms. Neste tipo de onda a saída do novo clock deverá ficar em nível lógico alto metade do período total e a outra metade, em nível baixo. Coloque a saída do divisor em um led do kit para a constatação do funcionamento do circuito. entity q2 is generic (limite : integer := 5000000); port (clk : in bit; --clock de 50 MHz flag : out bit := '0'); end q2; -- Para o clock de 50MHz encontra-se N=5*106 quando se quer um período de 100 ms. architecture contador of q2 is begin process (clk) variable aux : integer range 1 to limite := 1; Begin if (clk'event and clk = '0') then if (aux > limite) then aux := 0; elsif (aux < limite/2) then aux := aux +1; flag <='1'; else aux := aux + 1; flag <='0'; end if; end if; end process; end contador; --A variável ‘aux’ será o contador; --dá sequência ao process apenas na borda de descida do clock; -O auxiliar incrementa com passo 1 até o valor limite; enquanto ele for menor que limite/2, a saída flag ficará em alta, e durante a outra metade do tempo, flag será 0; Ou seja gera-se uma onda quadrada. 7 3) Descreva um circuito registrador de deslocamento em anel de 4 bits que desloque para a direita um bit do vetor a cada borda ativa de clock que deve ocorrer a cada 0,5 segundos. Utilize o pino de 24 MHz do módulo. Obs.: declare um sinal do tipo bit_vector de 4 bits com o valor inicial de “1000” e uma entrada na chave do kit para dar início aos deslocamentos para a direita, como um enable do circuito. Utilize leds. entity q3 is generic (limite : integer := 12000000); port (clk : in bit; --clk de 24MHz d0,d1,d2,d3: out bit_vector(6 downto 0); enable:in bit; saida: out bit_vector(3 downto 0); flag : buffer bit := '0'); -- para o clock de 24MHz, o limite será 1,2*107 para corresponder a uma onda com período de 0.5s; end q3; architecture imp of q3 is begin signal v: bit_vector :=”1000”; onda: process (clk) variable aux : integer range 1 to limite := 1; begin if (clk'event and clk = '1') then if (aux > limite) then aux := 0; elsif (aux < limite/2) then aux := aux +1; flag <='1'; else aux := aux + 1; flag<='0'; end if; --gera a onda quadrada com período de 0.5s; end if; end process onda; desloc: process (flag,enable) variable cont: integer range 0 to 4:=1; begin if(enable=’1’) then if (flag'event and flag = '1') then if(cont=1) then saida<=v(0)&v(3)&v(2)&v(1); elsif(cont=2) then saida<=v(1)&v(0)&v(3)&v(2); elsif(cont=3) then saida<=v(2)&v(1)&v(0)&v(3); else saida<=v(3)&v(2)&v(1)&v(0); endif; cont:=cont+1; endif; endif; end process desloc; --Se enable é ‘1’ (maior prioridade) desloca os bits do sinal v para a direita a cada 0.5s. end imp; 8 4) Utilizando seus conhecimentos nas descrições de circuitos divisores de frequência e registradores de deslocamento em anel, descreva um circuito em VHDL que escreva uma palavra de quatro caracteres, cada caractere em um display, e faça esses caracteres girarem nos displays de acordo com a borda de subida ocasionada por um oscilador de 1 Hz. A figura 1 mostra como o circuito deverá se comportar. Figura 4 - Exemplo de Loop de caracteres. entity q4 is generic (limite : integer := 50000000); port (clk : in bit; d0,d1,d2,d3: out bit_vector(6 downto 0); flag : buffer bit := '0'); end q4; --para período de 1s, limite será 5*107; --4 displays de saída; --‘flag’ foi declarado como buffer para ser usado na lista de sensibilidade do process. architecture display of q4 is --constantes correspondentes a cada letra da palavra ‘FPGA’ CONSTANT CONSTANT CONSTANT CONSTANT i00 i01 i02 i03 : : : : BIT_vector BIT_vector BIT_vector BIT_vector := := := := "0001110"; "0001100"; "1000010"; "0001000"; --F --P --G --A begin onda: process (clk) variable aux : integer range 1 to limite := 1; 9 begin if (clk'event and clk = '1') then --o process ‘onda’ gera a onda quadrada com período de 1s; if (aux > limite) then aux := 0; elsif (aux < limite/2) then aux := aux +1; flag <='1'; else aux := aux + 1; flag<='0'; end if; end if; end process onda; fpga: process (flag) variable cont: integer range 0 to 4:=1; -- inicia o process fpga sempre que o flag varia begin if (flag'event and flag = '1') then if(cont=1) then d0<=i03; d1<=i02; d2<=i01; d3<=i00; elsif(cont=2) then d0<=i02; d1<=i01; d2<=i00; d3<=i03; elsif(cont=3) then d0<=i01; d1<=i00; d2<=i03; d3<=i02; else d0<=i00; d1<=i03; d2<=i02; d3<=i01; cont:=0; end if; cont:=cont+1; end if; end process fpga; --Nas bordas de descida do flag, ou seja, a cada 1s, o process fpga executa o resto do código. --O contador cont define quais letras serão enviadas para cada display de acordo com a figura 4. end display; 10 Laboratório 03 – Divisores de Frequência 1) Desenvolva um VHDL de um contador de 4 bits a uma frequência de 3 Hz. O terminal “max_cont” deverá indicar que a contagem chegou ao limite. entity max_cont is generic (limite : integer := 9000000); port (clk : in bit; -- clock 27 MHz count : out integer range 0 to 15 :=0; flag : buffer bit := '0'); end max_cont; architecture contador of max_cont is begin um: process (clk) variable aux : integer range 0 to limite := 1; Begin -- Escolheu-se o clock de 27MHz; para uma frequência de 3Hz o limite deve ser 9*10^6. count é o contador de 4 bits (Inteiro de 16 valores). Flag é o led opcional para visualização do clock; -- process já previamente apresentado para geração de onda quadrada com a frequência desejada. if (clk'event and clk = '0') then if (aux > limite) then aux := 0; elsif (aux < limite/2) then aux := aux +1; flag <='1'; else aux := aux + 1; flag <='0'; end if; end if; end process um; dois: process (flag) variable aux2 : integer range 0 to 16 := 0; begin if(flag'event and flag ='1') then aux2:=aux2 + 1; end if; -O process ‘dois’ é ativado a cada variação de flag (onda quadrada gerada no process um). Assim, nas bordas de subida, ou seja a cada 1/3 s, o contador count será incrementado em 1 através do aux2. count<=aux2; end process dois; end contador; 2) Desenvolva um VHDL de um contador de 4 bits a uma frequência de 10 Hz com a entidade declarada a seguir. O terminal “max_cont” deverá indicar que a contagem chegou ao limite. entity Contador_livre is generic (n : integer := 4); port (reset, clk : in bit; max_cont : out bit; q : out natural range 0 to n-1); end Contador_livre; 11 entity contador_livre2 is generic (limite : integer := 5000000); port (clk : in bit; -- clock de 50 MHz do kit count : out integer range 0 to 15 :=0; max_cont: out bit := '0'; flag : buffer bit := '0'); --como a frequência agora será de 10Hz, o limite será De 5*106 com um clock de 50MHz; end contador_livre2; architecture contador of contador_livre2 is begin um: process (clk) variable aux : integer range 0 to limite := 0; Begin if (clk'event and clk = '0') then if (aux > limite) then aux := 0; elsif (aux < limite/2) then aux := aux +1; flag <='1'; else aux := aux + 1; flag <='0'; end if; end if; end process um; dois: process (flag) variable aux2 : integer range 0 to 15 := 0; begin if(flag'event and flag ='1') then aux2:=aux2 + 1; end if; -- o diferencial para esse programa é adição de max_cont que será setado quando o contador atingir o seu limite 15. count<=aux2; if aux2=15 then max_cont<='1'; else max_cont<='0'; end if; end process dois; end contador; 3) As contagens devem ser decodificada para os displays de 7 segmentos do kit. Para essa parte do projeto usou-se o esquemático de blocos, onde o VHDL da questão 2 foi transformado em um bloco e sua saída (max_cont) foi então conectada ao bloco 2 (VHDL que se segue) como sendo a entrada do mesmo. 12 entity display is port (e: in bit; s0,s1: out bit_vector(6 downto 0)); end display; -- ‘e’ será a entrada que receberá o sinal max_cont do programa anterior; --‘s0’ e ‘s1’ são os displays de 7 segmentos; architecture disp of display is CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT i00 i01 i02 i03 i04 i05 i06 i07 i08 i09 : : : : : : : : : : BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector BIT_vector := := := := := := := := := := "1000000"; "1111001"; "0100100"; "0110000"; "0011001"; "0010010"; "0000010"; "1111000"; "0000000"; "0010000"; begin um: process(e) variable var: integer range 0 to 9:=0; variable var2: integer range 0 to 9:=0; begin if (e'event and e = '0') then var:=var+1; if var > 9 then var2:= var2+1; var:= 0; end if; if var2 > 9 then var2 :=0; end if; -- constantes do display de 7 seg. -- as duas variáveis (‘var’ e ‘var2’) tem limite 9 e são inicializadas em 0 fornecendo uma contagem no display de 00 até 99. -- Na borda de descida da entrada e, a variável ‘var’ receberá +1. Quando esta atinge o máximo 9, a variável ‘var2’ será então incrementada em 1 e ‘var’ será zerada. Quando ‘var2’ atinge o máximo ela é zerada. end if; case var is when when when when when when when when when when 0 1 2 3 4 5 6 7 8 9 => => => => => => => => => => s0 s0 s0 s0 s0 s0 s0 s0 s0 s0 <= <= <= <= <= <= <= <= <= <= i00; i01; i02; i03; i04; i05; i06; i07; i08; i09; -- transmite os valores de ‘var’ para o primeiro display ‘s0’. end case; 13 case var2 is when when when when when when when when when when 0 1 2 3 4 5 6 7 8 9 => => => => => => => => => => s1 s1 s1 s1 s1 s1 s1 s1 s1 s1 <= <= <= <= <= <= <= <= <= <= i00; i01; i02; i03; i04; i05; i06; i07; i08; i09; -- envia o valor de var2 para o segundo display s1. end case; end process um; end disp; 4) Descreva em VHDL o hardware de um relógio digital com minutos e segundos mostrados no display de sete segmentos. O circuito deve ter ainda botões de configuração como start/stop, reset, ajuste de minutos (incrementa-decrementa). Durante o ajuste de minutos o relógio deve permanecer pausado. Para esta questão optou-se por utilizar o código do clock já previamente implementado, fazendo-se as devidas alterações para que ele possua frequência de 1 Hz, ou seja, período de 1s. Outra observação é que a chaves para ajuste de minutos não foram implementadas. Figura 5 - Diagrama de blocos para o relógio 14 entity display is port( d0,d1,d2,d3 : out bit_vector (6 downto 0); statop,reset,inc,dec,clk : in bit ); end display; --declaração dos displays de saída; --entradas: reset, clock, start/stop, incremento e decremento; architecture dis of display is CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT signal signal signal signal c1: c2: c3: c4: i00 i01 i02 i03 i04 i05 i06 i07 i08 i09 := "1000000"; := "1111001"; : BIT_vector := : BIT_vector := : BIT_vector := : BIT_vector := : BIT_vector := : BIT_vector := : BIT_vector := : BIT_vector := "0100100"; "0110000"; "0011001"; "0010010"; "0000010"; "1111000"; "0000000"; "0010000"; --constantes representando os dígitos de 0 a 9 que serão enviadas para os displays de 7 segmentos. -- sinais que receberão os valores dos contadores, pois estes são variáveis internas do process; integer; integer; integer range 0 to 10 :=0; integer range 0 to 7 :=0; Begin um: process (clk) variable count1: variable count2: variable count3: variable count4: integer integer integer integer range range range range 0 0 0 0 to to to to 10; 7; 10; 7; begin if(reset = '0') then if(clk'event and clk = '0') then if (statop = '1') then count1 := count1+1; if (count1 = 10) then count2 := count2+1; count1 := 0; if (count2 = 6) then count3 := count3+1; count2 := 0; if (count3 = 10) then count4 := count4+1; count3 := 0; if(count4 = 6) then count4 := 0; end if; end if; end if; --contadores que representam os valores dos segundos e minutos; 1 contador para cada display. --testa se o reset não está ativado e continua a execução na borda de descida do clock; depois testa se a chave start/stop é ‘1’ o que indica que pode prosseguir com a execução; caso start/stop é ‘0’ nada é feito e o relógio para. --incrementa os contadores, iniciando pelo menos significativo ( ultimo digito dos segundos); quando ele atinge o valor máximo 9, o contador1 é zerado e o próximo contador é incrementado; repete-se o mesmo processo para os 4 contadores; end if; end if; end if; else count1 count2 count3 count4 end if; := := := := 0; 0; 0; 0; -- caso a chave reset esteja ativado (valor ‘1’), todos os contadores são zerados; 15 -- os contadores são transferidos para os sinais c1,c2,c3,c4. --fim do process. c1 <= count1; c2 <= count2; c3 <= count3; c4 <= count4; end process um; with c1 select d0 <= i00 i01 i02 i03 i04 i05 i06 i07 i08 i09 i09 when when when when when when when when when when when 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, others; --comandos with/select que verificam o valor do contador (agora nos sinais C) e enviam a constante correspondente a esse valor para o display de 7 segmentos. with contador2 select d1 <= i00 when 0, i01 when 1, i02 when 2, i03 when 3, i04 when 4, i05 when 5, i06 when 6, i06 when others; with c3 select d2 <= i00 when 0, i01 when 1, i02 when 2, i03 when 3, i04 when 4, i05 when 5, i06 when 6, i07 when 7, i08 when 8, i09 when 9, i09 when others; with c4 select d3 <= i00 when 0, i01 when 1, i02 when 2, i03 when 3, i04 when 4, i05 when 5, i06 when 6, i06 when others; end dis; 16 Laboratório 04 – Teclado PS/2 1) Compilar o código fornecido no Roteiro para recepção de dados do teclado PS/2. LIBRARY IEEE; USE IEEE.STD_LOGIC_1164.ALL; USE IEEE.STD_LOGIC_ARITH.ALL; USE IEEE.STD_LOGIC_UNSIGNED.ALL; ENTITY teclado IS PORT ( rst : IN STD_LOGIC; -- Sinal de Reset clock_tec : IN STD_LOGIC; -- Sinal de Clock do Teclado dados_tec : IN STD_LOGIC; -- Sinal de Dados do Teclado scan_code: OUT STD_LOGIC_VECTOR (7 DOWNTO 0)); -- Valor Lido (Tabela ScanCode) END teclado; ARCHITECTURE leitura OF teclado IS SIGNAL contador : NATURAL RANGE 0 TO 32 := 0; -- Nº de bits lidos na AÇÃO COMPLETA SIGNAL byte : STD_LOGIC_VECTOR (7 DOWNTO 0); -- ScanCode enviado pelo teclado BEGIN ler_scancodes: PROCESS (clock_tec, rst) -- Processo que lê scancode do teclado quando pressionado BEGIN IF (rst = '0') THEN -- Se o reset for pressionado, zera tudo. contador <= 0; scan_code <= "00000000"; ELSIF ((clock_tec'EVENT) AND (clock_tec = '0')) THEN -- Os dados são lidos na borda de descida. contador <= contador + 1; -- Incremento inicial do contador (START Bit) -- Inicio da transferência, bit a bit, de dados do teclado: CASE contador IS WHEN 0 => null; -- START Bit ('0'). WHEN 1 TO 8 => -- Primeiros 8 bits da palavra de dados contador <= contador + 1; -- Contador é incrementado em 1, e byte(contador - 1) <= dados_tec; -- byte vai recebendo os dados do teclado WHEN 9 => -- Bit de Paridade ('1'). contador <= contador + 1; -- Contador é incrementado em 1, e scan_code <= byte; -- scan_code recebe o byte completo (Dados). WHEN 10 => IF (dados_tec = '1') THEN -- Se STOP Bit é igual a '1' contador <= contador + 1; -- Contador é incrementado em 1. ELSE null; -- Caso contrário não é o bit de parada END IF; WHEN 11 => -- Fim da transmissão da ação de PRESSIONAR TECLA IF (dados_tec = '0') THEN -- Teclado deve gerar um pulso igual a '0'(ACK) contador <= contador + 1; -- Contador incrementa 1. ELSE null; END IF; WHEN 12 TO 20 => -- Intervalo de pulsos para uma nova palavra. contador <= contador + 1; -- Apenas é incrementado o contador. 17 WHEN 21 => IF (dados_tec = '1') THEN -- Fim do intervalo de 10 bits. contador <= contador +1; ELSE null; END IF; WHEN 22 => IF (dados_tec = '0') THEN -- START Bit, da ação de SOLTAR TECLA contador <= contador + 1; ELSE null; END IF; WHEN 23 TO 31 => -- bits gerados na ação de SOLTAR TECLA (não interessa) contador <= contador + 1; WHEN 32 => IF (dados_tec = '1') THEN -- STOP Bit, da ação de SOLTAR TECLA contador <= 0; -- Reinicia o contador. ELSE null; END IF; END CASE; END IF; END PROCESS ler_scancodes; END leitura; 2) Desenvolva um código VHDL para o bloco “converter_codigo” que receba o scan_code proveniente do programa implementado anteriormente no bloco “teclado” e mostre nos displays de 7 segmentos do kit o valor em HEXA da tecla pressionada no teclado PS/2. Como cada tecla corresponde a dois caracteres em Hexa, serão utilizados apenas dois displays do kit. Além disso optou-se em mandar o código recebido pelo teclado para um conjunto de leds com o objetivo de verificar se alguma informação estava sendo recebida de fato. Figura 6 - Diagrama de blocos 18 entity converter_codigo is port( scan_cod: in bit_vector(7 downto 0); d0,d1: out bit_vector(6 downto 0); leds: out bit_vector (7 downto 0)); end converter_codigo; --bloco que converterá o codigo recebido do teclado para o display de 7 segmentos. architecture display of converter_codigo is CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT CONSTANT --GFE..A i00 : BIT_vector i01 : BIT_vector i02 : BIT_vector i03 : BIT_vector i04 : BIT_vector i05 : BIT_vector i06 : BIT_vector i07 : BIT_vector i08 : BIT_vector i09 : BIT_vector i10 : BIT_vector i11 : BIT_vector i12 : BIT_vector i13 : BIT_vector i14 : BIT_vector i15 : BIT_vector i16 : BIT_vector := := := := := := := := := := := := := := := := := "1000000"; "1111001"; "0100100"; "0110000"; "0011001"; "0010010"; "0000010"; "1111000"; "0000000"; "0010000"; "0001000"; "0000011"; "1000110"; "0100001"; "0000110"; "0001110"; "1111111"; -- constantes contendo a informação necessária para representar os dígitos (0 a 9) e os hexa (A a F) nos displays de 7 segmentos. begin leds<=scan_cod; with scan_cod(3)&scan_cod(2)&scan_cod(1)&scan_cod(0) select d0 <=i00 when "0000", i01 when "0001", i02 when "0010", i03 when "0011", i04 when "0100", i05 when "0101", i06 when "0110", i07 when "0111", i08 when "1000", i09 when "1001", i10 when "1010", i11 when "1011", i12 when "1100", i13 when "1101", i14 when "1110", i15 when "1111", i16 when others; with scan_cod(7)&scan_cod(6)&scan_cod(5)&scan_cod(4) select d1 <=i00 when "0000", i01 when "0001", i02 when "0010", i03 when "0011", i04 when "0100", i05 when "0101", i06 when "0110", i07 when "0111", i08 when "1000", i09 when "1001", i10 when "1010", -código recebido pelo teclado é enviado para os leds (parte opcional). -aglutina os 4 primeiros bits recebidos do teclado e envia a constante correspondente para o primeiro display (d0). Por exemplo, ao receber “0010” do teclado, que corresponde ao valor hexadecimal 2, a constante i02 será enviada para o display d0. --mesmo do item anterior, só que agora os 4 últimos bits serão enviados para o display d1. 19 i11 i12 i13 i14 i15 i16 when when when when when when "1011", "1100", "1101", "1110", "1111", others; end display; 20 Laboratório 05 – Sensor de distância ultrassônico HC-SR04 1) Digite o código do Anexo A e acompanhe a explicação do professor. Esse código mostra como implementar o uso do sensor ultrassônico HC-SR04. Neste código iremos acionar dois LEDs no qual um aceso representará 5 cm e os dois acesos representarão 10 cm distância entre o sensor e o obstáculo. Entity q1 is port(Clk_50: in bit; -- Clock de 50 MHz Echo: in bit; -- Sinal de Echo do sensor Trigger: out bit; -- Sinal de trigger para o sensor Saida: out bit_vector (1 downto 0)); -- Saida para os LEDs End q1; Architecture codigo of q1 is Type estado is (parado, triggando, medindo); -- Declarando o tipo "estado" Signal status : estado := parado; -- Sinal do tipo "estado" Signal clk_us : bit := '0'; -- Sinal para o clock de 1us Signal distancia : integer range 0 to 500; -- Sinal que armazena o valor da distancia medida Begin clkus: process(Clk_50) -- Divisor de frequencia para gerar o clock de 1uz. variable cont : integer range 0 to 50 :=0; begin if Clk_50'event and Clk_50='1' then cont:=cont+1; if cont=50 then cont:=0; elsif cont<=24 then clk_us<='0'; else clk_us<='1'; end if; end if; end process; process(Echo,clk_us) variable cont_tempoH: integer :=0; -- Variavel que contará o tempo em alto do sinal de Echo variable cont_us: integer :=0; -- Variavel que contará o tempo em alto do sinal de trigger variable sample_rate: integer:=0; -- Variavel que adicionará um atraso no programa. 21 begin if(clk_us'event and clk_us ='1') then -- A cada 1uz testa-se a variavel "status" case status is when parado => Trigger<='0'; cont_tempoH:=0; cont_us:=0; sample_rate:=sample_rate+1; -- Trigger automatico com atraso if sample_rate=60000 then sample_rate:=0; status<=triggando; Trigger<='1'; end if; when triggando => cont_us:=cont_us+1; if cont_us>=10 then Trigger <='0'; cont_us:=0; status<= medindo; end if; when medindo => if Echo='1'then cont_tempoH:=cont_tempoH+1; elsif Echo='0' then if cont_tempoH = 0 then cont_tempoH:=0; else distancia<= cont_tempoH/58; status<=parado; end if; end if; end case; -- Essa parte do programa diz respeito ao acionamento dos leds. if distancia > 10 then -- Se a distância for maior que 10cm, dois -- leds são acesos. Saida <= "11"; elsif distancia > 5 then –- Se a distância for maior que 5cm, e menor -- que 10, apenas um led é aceso. Saida <= "01"; Else -- Se a distância for menor que 5cm, os -- leds serão apagados. Saida <= "00"; end if; end if; end process; end codigo; 22 2) Tendo como base o código do Anexo A, implemente um código no qual o sensor detectará um obstáculo entre 2 e 18 centímetros de distância. De acordo com essa distância medida, os LEDS do módulo FPGA devem acender de forma gradual, ou seja, um LED a cada 2 cm. Entity q2 is port(Clk_50: in bit; -- Clock de 50 MHz Echo: in bit; -- Sinal de Echo do sensor Trigger: out bit; -- Sinal de trigger para o sensor Saida: out bit_vector (8 downto 0)); end q2; -- A entidade possui a mesma estrutura da questão anterior. -- ‘Saida’ será um vetor de 9 posições que comandará os leds conforme solicitado na questão. architecture codigo of q2 is if ( distancia > 18) then Saida <= "111111111"; elsif (distancia > 16) then Saida <= "011111111"; elsif (distancia > 14) then Saida <= "001111111"; elsif (distancia > 12) then Saida <= "000111111"; elsif (distancia > 10) then Saida <= "000011111"; elsif (distancia > 8) then Saida <= "000001111"; elsif (distancia > 6) then Saida <= "000000111"; elsif (distancia > 4) then Saida <= "000000011"; elsif (distancia > 2) then Saida <= "000000001"; else Saida <= "000000000"; end if; --mesma arquitecture da questão anterior, acrescentando o seguinte código com if/else e retirando a parte onde os dois leds sao acesos. -A cada dois cm de distancia um led da saída será comandado a ser aceso ou apagado, de acordo com a distância detectado pelo sensor. end codigo; 23 3) Utilizando o código feito em no item 2 mostre a distância medida nos displays de 7 segmentos. Para a realização desse projeto usou-se blocos, como mostrado na Figura 1 a seguir: Figura 7 - Diagrama de blocos para implementação do programa da questão 3. O bloco dito como ‘Sensor’ corresponde ao VHDL da questão 2. O código nomeado como Display está mostrado abaixo. entity display is port(d1,d2: out bit_vector (6 downto 0); entrada: in bit_vector (8 downto 0)); end display; architecture conf of display is CONSTANT i00 : BIT_vector := "1000000"; CONSTANT i01 : BIT_vector := "1111001"; CONSTANT i02 : BIT_vector := "0100100"; CONSTANT i04 : BIT_vector := "0011001"; CONSTANT i06 : BIT_vector := "0000010"; CONSTANT i08 : BIT_vector := "0000000"; begin process (entrada) begin case entrada is when "000000000" => d1 <= i00; d2 <= i00; when "000000001" => d1 <= i02; d2 <= i00; when "000000011" => d1 <= i04; d2 <= i00; when "000000111" => d1 <= i06; d2 <= i00; when "000001111" => d1 <= i08; d2 <= i00; when "000011111" => d1 <= i00; d2 <= i01; when "000111111" => d1 <= i02; d2 <= i01; when "001111111" => d1 <= i04; d2 <= i01; when "011111111" => d1 <= i06; d2 <= i01; when "111111111" => d1 <= i08; d2 <= i01; when others => d1 <= i00; d2 <= i00; end case; end process; end conf; -- ‘d1’ e ‘d2’ são os dois displays que mostrarão a distância em cm. ‘entrada’ é um vetor que receberá a saída do programa da questão 2. -- constantes dos displays de 7 segmentos, referentes aos dígitos 0,1,2,4,6,8; -- A cada mudança da entrada, o novo valor é convertido para o display de 7 segmentos e a distância é mostrada. 24