README.md 8.17 KB

7 Segment display

  1. But du projet
  2. I/O utilisées
  3. Explication de l'algorithme
  4. Résultats

L'ensemble des codes, images et vidéos sont compris dans ce répertoire.

But du projet

Nous avons décider de nous intéresser à l'affichage 7 segments grâce au but suivant:

  • Créer un compteur de 0 à 9999 à l'aide des 4 afficheurs. En cas de dépassement ou d'appuye sur un bouton reset le compteur redémarrera à 0.

I/O utilisées

Tout d'abord, voyons les entrées/sortie que nous avons utilisé.

entity display is
     port {
     clk_fpga : in STD_LOGIC;
     reset : in STD_LOGIC;
     aff : out STD_LOGIC_VECTOR{7 downto 0};
     an : out STD_LOGIC_VECTOR{3 downto 0}
     };
end display;
  • clk_fpga : le signal de clock du fpga

Dans le fichier de contrainte :

   ## Clock signal
   set_property -dict { PACKAGE_PIN W5   IOSTANDARD LVCMOS33 } [get_ports clk_fpga]
   create_clock -add -name sys_clk_pin -period 10.00 -waveform {0 5} [get_ports clk]
  • reset : le signal permettant de remettre le compteur à zéro grâce à un bouton

Dans le fichier de contrainte :

  ## Switches
  set_property -dict { PACKAGE_PIN R2    IOSTANDARD LVCMOS33 } [get_ports reset]
  • aff : un tableau de 8 bits relier à chaque led d'un segment à afficher (en ajoutant le point de l'afficheur)

Dans le fichier de contrainte :

   ##7 Segment Display
   set_property -dict { PACKAGE_PIN W7   IOSTANDARD LVCMOS33 } [get_ports {aff[0]}]
   set_property -dict { PACKAGE_PIN W6   IOSTANDARD LVCMOS33 } [get_ports {aff[1]}]
   set_property -dict { PACKAGE_PIN U8   IOSTANDARD LVCMOS33 } [get_ports {aff[2]}]
   set_property -dict { PACKAGE_PIN V8   IOSTANDARD LVCMOS33 } [get_ports {aff[3]}]
   set_property -dict { PACKAGE_PIN U5   IOSTANDARD LVCMOS33 } [get_ports {aff[4]}]
   set_property -dict { PACKAGE_PIN V5   IOSTANDARD LVCMOS33 } [get_ports {aff[5]}]
   set_property -dict { PACKAGE_PIN U7   IOSTANDARD LVCMOS33 } [get_ports {aff[6]}]

   set_property -dict { PACKAGE_PIN V7   IOSTANDARD LVCMOS33 } [get_ports {aff[7]}]

exemple : aff à "11111110" allumera la led du point de l'afficheur séléctionné.

  • an : un tableau comprenant 4 bits permettant de sélectionner l'un des 4 afficheurs 7 segments

Dans le fichier de contrainte :

   set_property -dict { PACKAGE_PIN U2   IOSTANDARD LVCMOS33 } [get_ports {an[0]}]
   set_property -dict { PACKAGE_PIN U4   IOSTANDARD LVCMOS33 } [get_ports {an[1]}]
   set_property -dict { PACKAGE_PIN V4   IOSTANDARD LVCMOS33 } [get_ports {an[2]}]
   set_property -dict { PACKAGE_PIN W4   IOSTANDARD LVCMOS33 } [get_ports {an[3]}]

exemple : an à "1110" sélectionnera l'afficheur le plus à droite.

Explication de l'algorithme

Les signaux

les signaux utilisés vont nous permettre d'avoir un code propre et plus ou moins factorisé.

   architecture Behavioral of display is

   signal count_an : integer range 3 downto 0 := 0;
   signal clk_enable : integer range 4999 downto 0 := 0;
   signal clk_counter : integer range 2999999 downto 0 := 0;
   constant nb0 : std_logic_vector(7 downto 0) := "11000000";
   constant nb1 : std_logic_vector(7 downto 0) := "11111001";
   constant nb2 : std_logic_vector(7 downto 0) := "10100100";
   constant nb3 : std_logic_vector(7 downto 0) := "10110000";
   constant nb4 : std_logic_vector(7 downto 0) := "10011001";
   constant nb5 : std_logic_vector(7 downto 0) := "10010010";
   constant nb6 : std_logic_vector(7 downto 0) := "10000010";
   constant nb7 : std_logic_vector(7 downto 0) := "11111000";
   constant nb8 : std_logic_vector(7 downto 0) := "10000000";
   constant nb9 : std_logic_vector(7 downto 0) := "10010000";
   constant seg0 : std_logic_vector(3 downto 0) := "1110";
   constant seg1 : std_logic_vector(3 downto 0) := "1101";
   constant seg2 : std_logic_vector(3 downto 0) := "1011";
   constant seg3 : std_logic_vector(3 downto 0) := "0111";
   signal chiffre4 : integer range 9 downto 0 := 0;
   signal chiffre3 : integer range 9 downto 0 := 0;
   signal chiffre2 : integer range 9 downto 0 := 0;
   signal chiffre1 : integer range 9 downto 0 := 0;

   type mynumbers is array(9 downto 0) of std_logic_vector(7 downto 0);
   signal numbers : mynumbers := (nb9,nb8,nb7,nb6,nb5,nb4,nb3,nb2,nb1,nb0);

On a:

  • count_an : compte pour effectuer les opérations sur les afficheurs un par un.
  • clk_enable : diviser la clock pour l'affichage et évite les recouvrements.
  • clk_counter : divise la clock pour le compteur et lui évite de compter bien trop rapidement.
  • nb* : représentation des chiffres par leurs segments.
  • seg* : attribue chaque segment à une valeur constante.
  • chiffre* : variable représentant le chiffre en * position
  • numbers : associe la représentation logique d'un chiffre à un entier.

Les process

  • 1er process :
   begin

   -- display process
   process(clk_fpga)
   begin
      if clk_fpga'event and clk_fpga = '1' then
         if clk_enable = 4999 then
            clk_enable <= 0;
            if count_an = 0 then
               aff <= numbers(chiffre4); 
               an <= seg0;
               count_an <= count_an + 1;
            elsif count_an = 1 then
               aff <= numbers(chiffre3); 
               an <= seg1;
               count_an <= count_an + 1;
            elsif count_an = 2 then
               aff <= numbers(chiffre2);
               an <= seg2;       
               count_an <= count_an + 1;
            elsif count_an = 3 then 
               aff <= numbers(chiffre1);
               an <= seg3;
               count_an <= 0;
            end if;
         else
            clk_enable <= clk_enable + 1;
        end if;   
      end if;    
   end process; 

Ce premier processus permet à chaque tick de clock + diviseur d'afficher un chiffre sur le premier afficheur. Au prochain tick sur le second puis le 3ème et enfin le 4ème. Ensuite l'algorithme boucle.

le diviseur (clk_enable) ralentit la cadence de switch entre afficheur. Si l'on ne divise du fait de la vitesse les chiffres ne s'affichent pas correctement.

Ainsi la logique et l'électronique étant ici très rapide devant la fréquence de perception de l'oeil humain, l'utilisateur à l'impression que l'affichage et statique et que rien ne clignote.

  • 2ème processus :
   -- process counter
   process(clk_fpga)
   begin
      if clk_fpga'event and clk_fpga = '1' then
         if clk_counter = 2999999 then 
            clk_counter <= 0; 
            if reset = '1' then 
               chiffre1 <= 0;
               chiffre2 <= 0;
               chiffre3 <= 0;
               chiffre4 <= 0;
            else if chiffre4 = 9 then
               chiffre4 <= 0; 
               if chiffre3 = 9 then 
                  chiffre3 <= 0;
                  if chiffre2 = 9 then 
                     chiffre2 <= 0;
                        if chiffre1 = 9 then 
                           chiffre1 <= 0;
                        else 
                           chiffre1 <= chiffre1 + 1;
                        end if;
                  else 
                     chiffre2 <= chiffre2 + 1;
                  end if;
               else 
                  chiffre3 <= chiffre3 + 1;
               end if;
            else 
               chiffre4 <= chiffre4 + 1;
            end if;
         else 
            clk_counter <= clk_counter + 1;
         end if;
      end if;
   end process;
   end Behavioral;

Ce processus permet de compter avec un diviseur de la clock de base. Lorsque le chiffre tout à droite et à 9 et qu'il doit être incrémenter alors il passe à 0. Si le chiffre à sa gauche n'est pas à 9 alors il est incrémenter sinon il passe à 0 et on regarde le chiffre de gauche en suivant le même algorithme.

Si on a 9999 ou un 1 logique sur reset alors tout les chiffres repassent à 0.

Résultats

  • Nous avons dans un premier temps essayer d'afficher sur les 4 afficheurs sans recouvrement. C'est pour cela qu'il a fallu baisser la clock.

img1

  • Ensuite il a fallu donner du sens à ce que nous affichions. C'est pourquoi nous avons tenté d'afficher 1 2 3 4.

img2

  • Enfin il a fallu implémanter un simple algorithme pour le compteur.

counter