18 de abril de 2013

Relógio Digital em VHDL


Boa tarde pessoal!
Reforçando o post de VHDL já existente no blog, segue um projeto de um relogio digital realizado em 2010. Para quem preferir o trabalho inteiro, o mesmo se encontra no site www.ebah.com.br
Espero que vocês façam um excelente uso do material!

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;

entity unidade_seg is
     Port ( clk_in_uni_seg: in std_logic;
                  clk_out_uni_seg: out  std_logic;
                  bcd_uni_seg : out  STD_LOGIC_vector (3 downto 0));
end unidade_seg;

architecture Behavioral of unidade_seg is
                signal uni_seg:  std_logic_vector (3 downto 0):= "0000";
                signal clk_out_tmp_seg : std_logic := '0';
                               begin
                                               process (clk_in_uni_seg)
                                               begin
                                                               IF (clk_in_uni_seg = '1' and clk_in_uni_seg'event) then
                                                                   uni_seg <= uni_seg + "1";
                                                                               IF (uni_seg = 9) then
                                                                                     uni_seg <= "0000";
                                                                                     clk_out_tmp_seg <= '1';
                                                                                end if;
                                                                                              IF (uni_seg = 5) then
                                                                                                   clk_out_tmp_seg <= '0';
                                                                                            end if;
                                                               end if;                                                                                                                                                               end process;
                                               bcd_uni_seg <= uni_seg;
                                               clk_out_uni_seg <= clk_out_tmp_seg;                        
end Behavioral;
Contador 0 a 9 – unidade segundo
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
entity dezena_seg is
Port ( clk_in_dez_seg: in std_logic;
          clk_out_dez_seg : out  std_logic;
          bcd_dez_seg : out  STD_LOGIC_vector (2 downto 0));
end dezena_seg;
architecture Behavioral of dezena_seg is
                signal dez:  std_logic_vector (2 downto 0):= "000";
                signal clk_out_tmp_seg : std_logic := '0';
                               begin
                                               process (clk_in_dez_seg)
                                               begin
                                                               IF (clk_in_dez_seg = '1' and clk_in_dez_seg'event) then
                                                                     dez <= dez + "1";
                                                                              IF (dez = 5) then
                                                                                    dez <= "000";
                                                                                   clk_out_tmp_seg <= '1';
                                                                               end if;
                                                                                              if (dez = 2) then
                                                                                                 clk_out_tmp_seg <= '0';
                                                                                            end if;
                                                               end if;                                                                                                                                                                 end process;
                                               bcd_dez_seg <= dez;
                                               clk_out_dez_seg <= clk_out_tmp_seg;                       
end Behavioral;
Contador 0 a 6 – dezena Segundo
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
entity unidade_min is
Port ( clk_in_uni_min: in std_logic;
          clk_out_uni_min : out  std_logic;
          bcd_uni_min : out  STD_LOGIC_vector (3 downto 0));
end unidade_min;
architecture Behavioral of unidade_min is
                signal uni_min:  std_logic_vector (3 downto 0):= "0000";
                signal clk_out_tmp_min : std_logic := '0';
                               begin
                                               process (clk_in_uni_min)
                                               begin
                                                               IF (clk_in_uni_min = '1' and clk_in_uni_min'event) then
                                                                     uni_min <= uni_min + "1";
                                                                               IF (uni_min = 9) then
                                                                                    uni_min <= "0000";
                                                                                    clk_out_tmp_min <= '1';
                                                                               end if;
                                                                                               if (uni_min = 5) then
                                                                                                  clk_out_tmp_min <= '0';
                                                                                             end if;
                                                               end if;                                                                                                 
                                               end process;
                                               bcd_uni_min <= uni_min;
                                               clk_out_uni_min <= clk_out_tmp_min;                     
end Behavioral;
Contador 0 a 9 unidade minute
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
entity dezena_min is
                 Port ( clk_in_dez_min: in std_logic;
                           clk_out_dez_min : out  std_logic;
                                bcd_dez_min : out  STD_LOGIC_vector (2 downto 0));
end dezena_min;
architecture Behavioral of dezena_min is
                signal dez:  std_logic_vector (2 downto 0):= "000";
                signal clk_out_tmp_min : std_logic := '0';
                               begin
                                               process (clk_in_dez_min)
                                               begin
                                                               IF (clk_in_dez_min = '1' and clk_in_dez_min'event) then
                                                                     dez <= dez + "1";
                                                                               IF (dez = 5) then
                                                                                    dez <= "000";
                                                                                    clk_out_tmp_min <= '1';
                                                                               end if;
                                                                                              if (dez = 2) then
                                                                                                 clk_out_tmp_min <= '0';
                                                                                    end if;
                                                                              end if;                                                                                                                                                 end process;
                                               bcd_dez_min <= dez;
                                               clk_out_dez_min <= clk_out_tmp_min;                     
end Behavioral;
Contador 0 a 6 dezena minuto
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
entity unihora is
                Port ( clk_in_uni_hr: in std_logic;
                          clk_out_uni_hr : out  std_logic;
                          bcd_uni_hr : out  STD_LOGIC_vector (2 downto 0));
end unihora;
architecture Behavioral of unihora is
                signal unihora:  std_logic_vector (2 downto 0):= "000";
                signal clk_out_tmp_hr : std_logic := '0';
                               begin
                                               process (clk_in_uni_hr)
                                               begin
                                                               IF (clk_in_uni_hr = '1' and clk_in_uni_hr'event) then
                                                                     unihora <= unihora + "1";
                                                                              if (unihora = 4) then
                                                                                   unihora <= "000";
                                                                                   clk_out_tmp_hr <= '1';
                                                                              end if;
                                                                                              if (unihora = 2) then
                                                                                                   clk_out_tmp_hr <= '0';
                                                                                            end if;
                                                               end if;                                                                                                 
                                               end process;
                                               bcd_uni_hr <= unihora;
                                               clk_out_uni_hr <= clk_out_tmp_hr;                            
end Behavioral;
Contador 0 a 4 unidade hora
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;
entity dezhora is
                Port ( clk_in_dez_hora: in std_logic;
                          bcd_dez_hora : out  STD_LOGIC_vector (1 downto 0));
end dezhora;
architecture Behavioral of dezhora is
                signal dezhr:  std_logic_vector ( 1 downto 0):= "00";
                               begin
                                               process (clk_in_dez_hora)
                                               begin
                                                               IF (clk_in_dez_hora = '1' and clk_in_dez_hora'event) then
                                                                     dezhr <= dezhr + "1";
                                                                               IF (dezhr = 2) then
                                                                                    dezhr <= "00";
                                                                              end if;
                                                               end if;                                                                                                                                                                 end process;
                                               bcd_dez_hora <= dezhr;
end Behavioral;
Contador 0 a 2 dezena hora
Os códigos descrevem os contadores de a 0 (zero) a 9 correspondente as unidades de segundo e minuto, possuem uma entrada (clk_in) e uma saída de clock (clk_out) respectivamente, também possui uma saída de 4 segmentos para ser acoplado a um decodificador para display de 7 segmentos cujo código esta descrito logo abaixo. O clock de saída é acionado quando o contador chega ao valor máximo, ou seja, o numero nove, proporcionando a borda de subida de clock, a borda de descida acontece quando o contador chega ao valor de numero 5. A saída BCD do relógio é acionada a cada borda de subida de clock e através da lógica descrita mostra os números seqüencialmente na base binária, quando o contador chega ao numero 9 ele então é zerado, ou seja, recebe como saída o valor zero em binário (0000), e depois disso é só um loop de sinal seqüencial a cada linha de código.
Os demais códigos dos contadores descritos são executados da mesma forma, o que diferencia um dos outros são os valores quando eles zeram e quando acontece a borda de descida de clock de saída, basta uma rápida visualização nos códigos para se perceber esta informação.
O código a seguir descreve o projeto do relógio digital chamando todos os componentes criados anteriormente, cada componente esta conectada a um sinal, nomeado antes de chamar os componentes ao projeto, onde então é mostrada a ordem dos componentes que será executado. A entrada da entidade relógio é de apenas um clock, e de saída ele possui seis vetores de oito bits que podem ser conectados diretamente ao display de sete segmentos, pois dentro do código já esta incluso o decodificador do display.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_unsigned.all;
use IEEE.NUMERIC_STD.ALL;

entity relogio is
    port (clk : in std_logic;
                                                seg71: out std_logic_vector (7 downto 0);
                                                seg72: out std_logic_vector (7 downto 0);
                                                seg73: out std_logic_vector (7 downto 0);
                                                seg74: out std_logic_vector (7 downto 0);
                                                seg75: out std_logic_vector (7 downto 0);
                                                seg76: out std_logic_vector (7 downto 0));
end relogio;

                architecture Behavioral of relogio is
                signal bcduniseg :   STD_LOGIC_vector (3 downto 0);
                signal bcddezseg :   STD_LOGIC_vector (2 downto 0);
                signal bcdunimin :   STD_LOGIC_vector (3 downto 0);
                signal bcddezmin :   STD_LOGIC_vector (2 downto 0);
                signal bcdunihr :  STD_LOGIC_vector (2 downto 0);
                signal bcddezhora :   STD_LOGIC_vector (1 downto 0);
                signal clock : std_logic_vector (5 downto 1);

--                                         segmento mostrador:              abcdefgh (h=ponto)
constant num0: STD_LOGIC_vector (7 downto 0) := "00000011"; -- codigo numero 0
constant num1: STD_LOGIC_vector (7 downto 0) := "10011111"; -- codigo numero 1
constant num2: STD_LOGIC_vector (7 downto 0) := "00100101"; -- codigo numero 2
constant num3: STD_LOGIC_vector (7 downto 0) := "00001101"; -- codigo numero 3
constant num4: STD_LOGIC_vector (7 downto 0) := "10011001"; -- codigo numero 4
constant num5: STD_LOGIC_vector (7 downto 0) := "01001001"; -- codigo numero 5
constant num6: STD_LOGIC_vector (7 downto 0) := "11000001"; -- codigo numero 6
constant num7: STD_LOGIC_vector (7 downto 0) := "00011111"; -- codigo numero 7
constant num8: STD_LOGIC_vector (7 downto 0) := "00000001"; -- codigo numero 8
constant num9: STD_LOGIC_vector (7 downto 0) := "00011001"; -- codigo numero 9
constant numn: STD_LOGIC_vector (7 downto 0) := "11111111"; -- apaga tudo

               


                                               component unidade_seg is
                                                                Port ( clk_in_uni_seg: in std_logic;
                                                                          clk_out_uni_seg: out  std_logic;
                                                                          bcd_uni_seg : out  STD_LOGIC_vector (3 downto 0));
                                               end component;

                                               component dezena_seg is
                                                                Port ( clk_in_dez_seg: in std_logic;
                                                                          clk_out_dez_seg : out  std_logic;
                                                                          bcd_dez_seg : out  STD_LOGIC_vector (2 downto 0));
                                               end component;                

                                               component unidade_min is
                                                                Port ( clk_in_uni_min: in std_logic;
                                                                          clk_out_uni_min : out  std_logic;
                                                                          bcd_uni_min : out  STD_LOGIC_vector (3 downto 0));
                                               end component;                                
                                              
                                               component dezena_min is
                                                Port ( clk_in_dez_min: in std_logic;
                                                          clk_out_dez_min : out  std_logic;
                                                          bcd_dez_min : out  STD_LOGIC_vector (2 downto 0));
                                               end component;
                                              
                                              
                                               component unihora is
                                                                Port ( clk_in_uni_hr: in std_logic;
                                                                          clk_out_uni_hr : out  std_logic;
                                                                          bcd_uni_hr : out  STD_LOGIC_vector (2 downto 0));
                                               end component;
                                              
                                               component dezhora is
                                                               Port ( clk_in_dez_hora: in std_logic;
                                                                         bcd_dez_hora : out  STD_LOGIC_vector (1 downto 0));
                                               end component;
                begin                                    
                                              
                                               u1: unidade_seg port map(clk, clock(1), bcduniseg);
                                               u2: dezena_seg port map (clock(1), clock(2), bcddezseg);
                                               u3: unidade_min port map(clock(2), clock(3), bcdunimin);
                                               u4: dezena_min port map (clock(3), clock(4), bcddezmin);
                                               u5: unihora port map(clock(4), clock(5), bcdunihr);
                                               u6: dezhora port map (clock(5), bcddezhora);
                                              
                                              
                                               table_useg: block
                                               begin
                                               seg71 <= num0 when bcduniseg = 0 else
                                                               num1 when bcduniseg = 1 else
                                                               num2 when bcduniseg = 2 else
                                                               num3 when bcduniseg = 3 else
                                                               num4 when bcduniseg = 4 else
                                                               num5 when bcduniseg = 5 else
                                                               num6 when bcduniseg = 6 else
                                                               num7 when bcduniseg = 7 else
                                                               num8 when bcduniseg = 8 else
                                                               num9 when bcduniseg = 9 else
                                                               numn;
                                               end block table_useg;

                                               table_dseg: block
                                               begin
                                               seg72 <=num0 when bcddezseg = 0 else
                                                               num1 when bcddezseg = 1 else
                                                               num2 when bcddezseg = 2 else
                                                               num3 when bcddezseg = 3 else
                                                               num4 when bcddezseg = 4 else
                                                               num5 when bcddezseg = 5 else
                                                               num6 when bcddezseg = 6 else
                                                               num7 when bcddezseg = 7 else
                                                               num8 when bcddezseg = 8 else
                                                               num9 when bcddezseg = 9 else
                                                               numn;
                                               end block table_dseg;
                                              
                                               table_unimin: block
                                               begin
                                               seg73 <=num0 when bcdunimin = 0 else
                                                               num1 when bcdunimin = 1 else
                                                               num2 when bcdunimin = 2 else
                                                               num3 when bcdunimin = 3 else
                                                               num4 when bcdunimin = 4 else
                                                               num5 when bcdunimin = 5 else
                                                               num6 when bcdunimin = 6 else
                                                               num7 when bcdunimin = 7 else
                                                               num8 when bcdunimin = 8 else
                                                               num9 when bcdunimin = 9 else
                                                               numn;
                                               end block table_unimin;

                                               table_dezmin: block
                                               begin
                                                seg74 <=num0 when bcddezmin = 0 else
                                                                num1 when bcddezmin = 1 else
                                                                num2 when bcddezmin = 2 else
                                                                num3 when bcddezmin = 3 else
                                                                num4 when bcddezmin = 4 else
                                                                num5 when bcddezmin = 5 else
                                                                num6 when bcddezmin = 6 else
                                                                num7 when bcddezmin = 7 else
                                                                num8 when bcddezmin = 8 else
                                                                num9 when bcddezmin = 9 else
                                                                numn;
                                               end block table_dezmin;
                                              
                                               table_unihr: block
                                               begin
                                                seg75 <=num0 when bcdunihr = 0 else
                                                                num1 when bcdunihr = 1 else
                                                                num2 when bcdunihr = 2 else
                                                                num3 when bcdunihr = 3 else
                                                                num4 when bcdunihr = 4 else
                                                                numn;
                                               end block table_unihr;
                                              
                                               table_dezhr: block
                                               begin
                                               seg76 <=num0 when bcddezhora = 0 else
                                                               num1 when bcddezhora = 1 else
                                                               num2 when bcddezhora = 2 else
                                                               numn;
                                               end block table_dezhr;
                end Behavioral;
Codigo relogio components


O ultimo código apresentado logo abaixo é o test bench do projeto gerado automaticamente pelo software da Xilinx, nos primeiros testes feitos o contador não contava da forma planejada e descrita na lógica acima, e depois de diversas modificações e testes descobrimos que o test bench estava com uma entrada de clock duplicada, o que gerava uma confusão no projeto, assim que o problema foi resolvido o projeto funcionou exatamente como previsto no inicio.
LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

ENTITY testerelogio IS
END testerelogio;

ARCHITECTURE behavior OF testerelogio IS

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT relogio
    PORT(
         clk : IN  std_logic;
         seg71 : OUT  std_logic_vector(7 downto 0);
         seg72 : OUT  std_logic_vector(7 downto 0);
         seg73 : OUT  std_logic_vector(7 downto 0);
         seg74 : OUT  std_logic_vector(7 downto 0);
         seg75 : OUT  std_logic_vector(7 downto 0);
         seg76 : OUT  std_logic_vector(7 downto 0)
        );
    END COMPONENT;
   

   --Inputs
   signal clk : std_logic := '0';

                --Outputs
   signal seg71 : std_logic_vector(7 downto 0);
   signal seg72 : std_logic_vector(7 downto 0);
   signal seg73 : std_logic_vector(7 downto 0);
   signal seg74 : std_logic_vector(7 downto 0);
   signal seg75 : std_logic_vector(7 downto 0);
   signal seg76 : std_logic_vector(7 downto 0);

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

                -- Instantiate the Unit Under Test (UUT)
   uut: relogio PORT MAP (
          clk => clk,
          seg71 => seg71,
          seg72 => seg72,
          seg73 => seg73,
          seg74 => seg74,
          seg75 => seg75,
          seg76 => seg76
        );

   -- Clock process definitions
   clk_process :process
   begin
                               clk <= '0';
                               wait for clk_period/2;
                               clk <= '1';
                               wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin                  
      -- hold reset state for 100 ns.
      wait for 100 ns;            

      wait for clk_period*10;

      -- insert stimulus here

      wait;
   end process;

END;
Teste bench relogio