Cours:TP M1102 TP 5 Corr

De troyesGEII
Révision datée du 21 juillet 2021 à 14:55 par SergeMoutou (discussion | contributions)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à : navigation, rechercher

TP 5

Exercice 1

L'exercice 1 a déjà été corrigé dans Corrigé du TP4 (Exercice 4). Il ne sera donc réalisé en TP5 que s'il ne l'a pas été en TP 4.

Exercice 2

Question 1

On vous présente plusieurs corrections de cet exercice. L'enseignant les présentera toutes ou en choisira quelques unes.

Comme on utilise le même fichier de contraintes dans les trois façons de faire ci-dessous, on vous donne ce fichier ici :

To,Direction,Location,I/O Bank,VREF Group,Fitter Location,I/O Standard,Reserved,Current Strength,Slew Rate,Differential Pair,Strict Preservation

clk,Input,PIN_P11,,,,3.3-V LVTTL,,,,,

Leds8[0],Unknown,PIN_A8,7,B7_N0,PIN_A8,3.3-V LVTTL,,,,,
Leds8[1],Unknown,PIN_A9,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[2],Unknown,PIN_A10,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[3],Unknown,PIN_B10,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[4],Unknown,PIN_D13,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[5],Unknown,PIN_C13,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[6],Unknown,PIN_E14,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[7],Unknown,PIN_D14,7,B7_N0,,3.3-V LVTTL,,,,,

Première façon : on fait tout soi-même

Le compteur 8 bits utilisé ici était donné dans le TP4. On a simplement modifié le nom de son horloge.

-- Testé le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY compteur IS PORT (
  clk: IN std_logic;
  Leds8: OUT std_logic_vector(7 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS
-- les composants :
COMPONENT cmpt8bits IS
  PORT(clk : IN STD_LOGIC;
    cnt : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT cmpt8bits;

COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END COMPONENT cmpt24bits;
-- LE FIL INTENE
SIGNAL s_horloge_lente : std_logic;
BEGIN
  i1 : cmpt24bits PORT MAP(
      clk_50MHz => clk,
      clk_slow => s_horloge_lente);
	 
  i2 : cmpt8bits PORT MAP (
         clk => s_horloge_lente,
	 cnt => leds8);
END arch_compteur;

-- Compteur 8 bits
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt8bits IS
  PORT(clk : IN STD_LOGIC;
    cnt : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END cmpt8bits;
 
ARCHITECTURE arch_cmpt8bits OF cmpt8bits IS
  signal cmpt : std_logic_vector(7 downto 0);
BEGIN
  process(clk) begin
    if rising_edge(clk) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  cnt <= cmpt;  
END arch_cmpt8bits;

-- horloge lente 3 Hz
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END cmpt24bits;
 
ARCHITECTURE arch_cmpt24bits OF cmpt24bits IS
  signal cmpt : std_logic_vector(23 downto 0);
BEGIN
  process(clk_50MHz) begin
    if rising_edge(clk_50MHz) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  clk_slow <= cmpt(23);  -- partie combinatoire de construction de l'horloge lente
END arch_cmpt24bits;

Deuxième façon : on utilise les LPM

En principe les LPM ne sont présentés qu'en question 4. Nous en donnons ici une première utilisation.

-- Testé correct le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
LIBRARY lpm; -- for LPM
USE lpm.lpm_components.ALL;

ENTITY compteur IS PORT (
  clk: IN std_logic;
  Leds8: OUT std_logic_vector(7 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS

  -- LE FIL INTENE
  SIGNAL s_horloge_lente : std_logic;

BEGIN
  -- compteur 24 bits
  ic1: lpm_counter GENERIC MAP (
            LPM_WIDTH => 24
  )
  PORT MAP (CLOCK => clk,
            q(23) => s_horloge_lente);
  -- compteur 8 bits
  ic2: lpm_counter GENERIC MAP (
            LPM_WIDTH => 8
  )
  PORT MAP (CLOCK => s_horloge_lente,
            q => Leds8);
END arch_compteur;

Remarquez comme cette façon de faire est compacte. Mais on va vous présenter encore plus compact dans la suite.

Troisième façon : on remarque que le problème est de créer deux compteurs cascdés que l'on peut regrouper

-- Testé correct le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
LIBRARY lpm; -- for LPM
USE lpm.lpm_components.ALL;

ENTITY compteur IS PORT (
  clk: IN std_logic;
  Leds8: OUT std_logic_vector(7 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS

  -- LE FIL INTENE
  SIGNAL s_horloge_lente : std_logic;

BEGIN
  -- compteur 24 bits
  ic1: lpm_counter GENERIC MAP (
            LPM_WIDTH => 32
  )
  PORT MAP (CLOCK => clk,
            q(31 downto 24) => Leds8);  
END arch_compteur;

Non seulement cette façon de faire est la plus compacte, mais en plus c'est elle qui respecte au mieux les règles des horloges dans un FPGA.

Question 2 et 3

Même s'il est intéressant pédagogiquement de présenter d'abord la question 2 puis la question 3, nous allons faire directement la correction de la question 3.

-- Vérifié OK le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY compteur IS PORT (
  clk: IN std_logic;
  HEX0,HEX1: OUT std_logic_vector(6 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS
-- les composants :
COMPONENT cmpt8bits IS
  PORT(clk : IN STD_LOGIC;
    cnt : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END COMPONENT cmpt8bits;

COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END COMPONENT cmpt24bits;

COMPONENT transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END COMPONENT transcod7segs;

-- LES FILS INTERNES
SIGNAL s_horloge_lente : std_logic;
SIGNAL s_cmpt8 : std_logic_vector(7 downto 0);
BEGIN
  i1 : cmpt24bits PORT MAP(
      clk_50MHz => clk,
      clk_slow => s_horloge_lente);
	 
  i2 : cmpt8bits PORT MAP (
         clk => s_horloge_lente,
	 cnt => s_cmpt8);
  i3 : transcod7segs PORT MAP(
           e => s_cmpt8(3 DOWNTO 0),
           s7segs => HEX0);
  i4 : transcod7segs PORT MAP(
           e => s_cmpt8(7 DOWNTO 4),
           s7segs => HEX1);
END arch_compteur;

-- Compteur 8 bits
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt8bits IS
  PORT(clk : IN STD_LOGIC;
    cnt : OUT STD_LOGIC_VECTOR(7 DOWNTO 0));
END cmpt8bits;
 
ARCHITECTURE arch_cmpt8bits OF cmpt8bits IS
  signal cmpt : std_logic_vector(7 downto 0);
BEGIN
  process(clk) begin
    if rising_edge(clk) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  cnt <= cmpt;  
END arch_cmpt8bits;

-- horloge lente 3 Hz
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END cmpt24bits;
 
ARCHITECTURE arch_cmpt24bits OF cmpt24bits IS
  signal cmpt : std_logic_vector(23 downto 0);
BEGIN
  process(clk_50MHz) begin
    if rising_edge(clk_50MHz) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  clk_slow <= cmpt(23);  -- partie combinatoire de construction de l'horloge lente
END arch_cmpt24bits;

-- transcodeur pour affichage 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END transcod7segs;
ARCHITECTURE arch of transcod7segs IS 
BEGIN
  with e select
             --gfedcba
    s7segs <= "1000000" when "0000",
              "1111001" when "0001",
              "0100100" when "0010",
              "0110000" when "0011",
              "0011001" when "0100",
              "0010010" when "0101",
              "0000010" when "0110",
              "1111000" when "0111",
              "0000000" when "1000",
              "0010000" when "1001",
              "0001000" when "1010",
              "0000011" when "1011",
              "1000110" when "1100",
              "0100001" when "1101",
              "0000110" when "1110",
              "0001110" when others;
END;

Et avec son fichier de contraintes associé :

To,Direction,Location,I/O Bank,VREF Group,Fitter Location,I/O Standard,Reserved,Current Strength,Slew Rate,Differential Pair,Strict Preservation

clk,Input,PIN_P11,,,,3.3-V LVTTL,,,,,

Leds8[0],Unknown,PIN_A8,7,B7_N0,PIN_A8,3.3-V LVTTL,,,,,
Leds8[1],Unknown,PIN_A9,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[2],Unknown,PIN_A10,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[3],Unknown,PIN_B10,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[4],Unknown,PIN_D13,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[5],Unknown,PIN_C13,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[6],Unknown,PIN_E14,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[7],Unknown,PIN_D14,7,B7_N0,,3.3-V LVTTL,,,,,

HEX0[0],Unknown,PIN_C14,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[1],Unknown,PIN_E15,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[2],Unknown,PIN_C15,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[3],Unknown,PIN_C16,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[4],Unknown,PIN_E16,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[5],Unknown,PIN_D17,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[6],Unknown,PIN_C17,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[7],Unknown,PIN_D15,7,B7_N0,,3.3-V LVTTL,,,,,

HEX1[0],Unknown,PIN_C18,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[1],Unknown,PIN_D18,6,B6_N0,,3.3-V LVTTL,,,,,
HEX1[2],Unknown,PIN_E18,6,B6_N0,,3.3-V LVTTL,,,,,
HEX1[3],Unknown,PIN_B16,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[4],Unknown,PIN_A17,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[5],Unknown,PIN_A18,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[6],Unknown,PIN_B17,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[7],Unknown,PIN_A16,7,B7_N0,,3.3-V LVTTL,,,,,

Question 4

La question 4 qui utilise les LPM se trouve corrigée en question 1. Il suffit de remplacer les compteurs 24 et 8 bits par deux LPM ou mieux par un seul de 32 bits dans la correction de la question 3.

Exercice 3

Question 1

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY compteur IS PORT (
  clk: IN std_logic;
  HEX0: OUT std_logic_vector(6 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS
-- les composants :
component CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
--         ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end component CounterBCD;

COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END COMPONENT cmpt24bits;

COMPONENT transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END COMPONENT transcod7segs;

-- LES FILS INTERNES
SIGNAL s_horloge_lente : std_logic;
SIGNAL s_digit0BCD : std_logic_vector(3 downto 0);
BEGIN
  i1 : cmpt24bits PORT MAP(
      clk_50MHz => clk,
      clk_slow => s_horloge_lente);
	 
  i2 : CounterBCD PORT MAP (
         EN => '1',
 	 Clock => s_horloge_lente,
 	 Reset => '0',
--         ENO : out std_logic;
 	 Output => s_digit0BCD);

  i3 : transcod7segs PORT MAP(
           e => s_digit0BCD,
           s7segs => HEX0);
END arch_compteur;

-- Compteur 4 bits BCD
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
--         ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end CounterBCD;
 
architecture Behavioral of CounterBCD is
   signal cmpt: std_logic_vector(3 downto 0);
begin   process(Clock,Reset)
   begin
      if Reset='1' then
         cmpt <= "0000";
      elsif(rising_edge(Clock)) then
 	 if EN='1' then
	    if cmpt="1001" then
	       cmpt<="0000";
	    else
	       cmpt <= cmpt + 1;
	    end if;
         end if;
      end if;
   end process;
   Output <= cmpt;
end Behavioral;


-- horloge lente 3 Hz
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END cmpt24bits;
 
ARCHITECTURE arch_cmpt24bits OF cmpt24bits IS
  signal cmpt : std_logic_vector(23 downto 0);
BEGIN
  process(clk_50MHz) begin
    if rising_edge(clk_50MHz) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  clk_slow <= cmpt(23);  -- partie combinatoire de construction de l'horloge lente
END arch_cmpt24bits;

-- transcodeur pour affichage 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END transcod7segs;
ARCHITECTURE arch of transcod7segs IS 
BEGIN
  with e select
             --gfedcba
    s7segs <= "1000000" when "0000",
              "1111001" when "0001",
              "0100100" when "0010",
              "0110000" when "0011",
              "0011001" when "0100",
              "0010010" when "0101",
              "0000010" when "0110",
              "1111000" when "0111",
              "0000000" when "1000",
              "0010000" when "1001",
              "0001000" when "1010",
              "0000011" when "1011",
              "1000110" when "1100",
              "0100001" when "1101",
              "0000110" when "1110",
              "0001110" when others;
END;

Question 2

Commençons par détailler le compteur BCD cascadable :

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
         ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end CounterBCD;
 
architecture Behavioral of CounterBCD is
   signal cmpt: std_logic_vector(3 downto 0);
   SIGNAL s_en_cmpt : std_logic_vector(4 downto 0);
begin   
  process(Clock,Reset) begin
      if Reset='1' then
         cmpt <= "0000";
      elsif(rising_edge(Clock)) then
 	 if EN='1' then
	    if cmpt="1001" then
	       cmpt<="0000";
	    else
	       cmpt <= cmpt + 1;
	    end if;
         end if;
      end if;
   end process;
   Output <= cmpt;
   s_en_cmpt <= en & cmpt; -- operateur '&' est une concatenation
  with s_en_cmpt select
    ENO <= '1' when "11001", -- EN actif et on est arrivé à (1001)=9
           '0' when others;
end Behavioral;

La réalisation du compteur BCD cascadable est primordiale et surtout la façon de faire est du VHDL correct.

  • présence d'un signal d'entrée EN qui bloque le fonctionnement du compteur s'il est à 0
  • présence d'un signal de sortie ENO qui passe à un lorque le compteur est arrivé à 9 (et s'il est autorisé à compter

Cascader des compteurs avec ce type de signaux consiste à relier la sortie ENO à l'entrée EN de l'étage suivant.

Venons-en maintenant au programme complet :

-- Vérifié OK le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY compteur IS PORT (
  clk: IN std_logic;
  HEX0,HEX1: OUT std_logic_vector(6 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS
-- les composants :
component CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
         ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end component CounterBCD;

COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END COMPONENT cmpt24bits;

COMPONENT transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END COMPONENT transcod7segs;

-- LES FILS INTERNES
SIGNAL s_horloge_lente : std_logic;
SIGNAL s_digit0BCD : std_logic_vector(3 downto 0);
SIGNAL s_digit1BCD : std_logic_vector(3 downto 0);
SIGNAL s_eno : std_logic;
BEGIN
  i1 : cmpt24bits PORT MAP(
      clk_50MHz => clk,
      clk_slow => s_horloge_lente);
	 
  i2 : CounterBCD PORT MAP (
         EN => '1',
 	      Clock => s_horloge_lente,
 	      Reset => '0',
         ENO => s_eno,
 	      Output => s_digit0BCD);
  i3 : CounterBCD PORT MAP (
         EN => s_eno,
 	      Clock => s_horloge_lente,
 	      Reset => '0',
         ENO => open,
 	      Output => s_digit1BCD);
  i4 : transcod7segs PORT MAP(
           e => s_digit0BCD,
           s7segs => HEX0);
  i5 : transcod7segs PORT MAP(
           e => s_digit1BCD,
           s7segs => HEX1);
END arch_compteur;

-- Compteur 4 bits BCD
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
         ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end CounterBCD;
 
architecture Behavioral of CounterBCD is
   signal cmpt: std_logic_vector(3 downto 0);
	SIGNAL s_en_cmpt : std_logic_vector(4 downto 0);
begin   process(Clock,Reset)
   begin
      if Reset='1' then
         cmpt <= "0000";
      elsif(rising_edge(Clock)) then
 	 if EN='1' then
	    if cmpt="1001" then
	       cmpt<="0000";
	    else
	       cmpt <= cmpt + 1;
	    end if;
         end if;
      end if;
   end process;
   Output <= cmpt;
	s_en_cmpt <= en & cmpt; -- operateur '&' est une concatenation
  with s_en_cmpt select
    ENO <= '1' when "11001",
           '0' when others;
end Behavioral;


-- horloge lente 3 Hz
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END cmpt24bits;
 
ARCHITECTURE arch_cmpt24bits OF cmpt24bits IS
  signal cmpt : std_logic_vector(23 downto 0);
BEGIN
  process(clk_50MHz) begin
    if rising_edge(clk_50MHz) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  clk_slow <= cmpt(23);  -- partie combinatoire de construction de l'horloge lente
END arch_cmpt24bits;

-- transcodeur pour affichage 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END transcod7segs;
ARCHITECTURE arch of transcod7segs IS 
BEGIN
  with e select
             --gfedcba
    s7segs <= "1000000" when "0000",
              "1111001" when "0001",
              "0100100" when "0010",
              "0110000" when "0011",
              "0011001" when "0100",
              "0010010" when "0101",
              "0000010" when "0110",
              "1111000" when "0111",
              "0000000" when "1000",
              "0010000" when "1001",
              "0001000" when "1010",
              "0000011" when "1011",
              "1000110" when "1100",
              "0100001" when "1101",
              "0000110" when "1110",
              "0001110" when others;
END;

Exercice 4

Première version : on écrit absolument tout en VHDL

Seule la gestion de la sortie ENO est plus complexe dans un compteur/décompteur. Mais les étudiants disposent d'un lien qui leur donne la solution. Voici donc le programme complet :

-- Testé OK le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY compteur IS PORT (
  clk: IN std_logic;
  DU : in std_logic; -- down / up = 0 / 1
  HEX0,HEX1: OUT std_logic_vector(6 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS
-- les composants :
component CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
	 du: in std_logic;
    ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end component CounterBCD;

COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END COMPONENT cmpt24bits;

COMPONENT transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END COMPONENT transcod7segs;

-- LES FILS INTERNES
SIGNAL s_horloge_lente : std_logic;
SIGNAL s_digit0BCD : std_logic_vector(3 downto 0);
SIGNAL s_digit1BCD : std_logic_vector(3 downto 0);
SIGNAL s_eno : std_logic;
BEGIN
  i1 : cmpt24bits PORT MAP(
      clk_50MHz => clk,
      clk_slow => s_horloge_lente);
	 
  i2 : CounterBCD PORT MAP (
         EN => '1',
			du => DU,
 	      Clock => s_horloge_lente,
 	      Reset => '0',
         ENO => s_eno,
 	      Output => s_digit0BCD);
  i3 : CounterBCD PORT MAP (
         EN => s_eno,
			du => DU,
 	      Clock => s_horloge_lente,
 	      Reset => '0',
         ENO => open,
 	      Output => s_digit1BCD);

  i4 : transcod7segs PORT MAP(
           e => s_digit0BCD,
           s7segs => HEX0);
  i5 : transcod7segs PORT MAP(
           e => s_digit1BCD,
           s7segs => HEX1);
END arch_compteur;

-- Compteur 4 bits BCD
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

entity CounterBCD is
   port( EN: in std_logic;
 	 Clock: in std_logic;
 	 Reset: in std_logic;
	 du: in std_logic;
    ENO : out std_logic;
 	 Output: out std_logic_vector(3 downto 0));
end CounterBCD;
 
architecture Behavioral of CounterBCD is
   signal cmpt: std_logic_vector(3 downto 0);
	signal s_en_cmpt:  std_logic_vector(5 downto 0);
begin   process(Clock,Reset)
   begin
      if Reset='1' then
         cmpt <= "0000";
      elsif(rising_edge(Clock)) then
 	     if EN='1' then
	       if du='1' then
	         if cmpt="1001" then
	           cmpt<="0000";
	         else
	           cmpt <= cmpt + 1;
	         end if;
		    else 
	         if cmpt="0000" then
	           cmpt<="1001";
	         else
	           cmpt <= cmpt - 1;
	         end if;	
          end if;
        end if;
     end if;
   end process;
	-- sortie du comptage
   Output <= cmpt;
	-- gestion combinatoire de la sortie ENO
   s_en_cmpt <= en & du & cmpt;
   with s_en_cmpt select
     ENO <= '1' when "111001",
	         '1' when "100000",
            '0' when others;
				
end Behavioral;


-- horloge lente 3 Hz
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END cmpt24bits;
 
ARCHITECTURE arch_cmpt24bits OF cmpt24bits IS
  signal cmpt : std_logic_vector(23 downto 0);
BEGIN
  process(clk_50MHz) begin
    if rising_edge(clk_50MHz) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  clk_slow <= cmpt(23);  -- partie combinatoire de construction de l'horloge lente
END arch_cmpt24bits;

-- transcodeur pour affichage 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END transcod7segs;
ARCHITECTURE arch of transcod7segs IS 
BEGIN
  with e select
             --gfedcba
    s7segs <= "1000000" when "0000",
              "1111001" when "0001",
              "0100100" when "0010",
              "0110000" when "0011",
              "0011001" when "0100",
              "0010010" when "0101",
              "0000010" when "0110",
              "1111000" when "0111",
              "0000000" when "1000",
              "0010000" when "1001",
              "0001000" when "1010",
              "0000011" when "1011",
              "1000110" when "1100",
              "0100001" when "1101",
              "0000110" when "1110",
              "0001110" when others;
END;

ainsi que le fichier de contraintes associé :

To,Direction,Location,I/O Bank,VREF Group,Fitter Location,I/O Standard,Reserved,Current Strength,Slew Rate,Differential Pair,Strict Preservation

clk,Input,PIN_P11,,,,3.3-V LVTTL,,,,,

DU,Input,PIN_C10,7,B7_N0,PIN_C10,3.3-V LVTTL,,,,,

Leds8[0],Unknown,PIN_A8,7,B7_N0,PIN_A8,3.3-V LVTTL,,,,,
Leds8[1],Unknown,PIN_A9,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[2],Unknown,PIN_A10,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[3],Unknown,PIN_B10,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[4],Unknown,PIN_D13,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[5],Unknown,PIN_C13,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[6],Unknown,PIN_E14,7,B7_N0,,3.3-V LVTTL,,,,,
Leds8[7],Unknown,PIN_D14,7,B7_N0,,3.3-V LVTTL,,,,,

HEX0[0],Unknown,PIN_C14,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[1],Unknown,PIN_E15,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[2],Unknown,PIN_C15,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[3],Unknown,PIN_C16,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[4],Unknown,PIN_E16,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[5],Unknown,PIN_D17,7,B7_N0,,3.3-V LVTTL,,,,,
HEX0[6],Unknown,PIN_C17,7,B7_N0,,3.3-V LVTTL,,,,,

HEX1[0],Unknown,PIN_C18,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[1],Unknown,PIN_D18,6,B6_N0,,3.3-V LVTTL,,,,,
HEX1[2],Unknown,PIN_E18,6,B6_N0,,3.3-V LVTTL,,,,,
HEX1[3],Unknown,PIN_B16,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[4],Unknown,PIN_A17,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[5],Unknown,PIN_A18,7,B7_N0,,3.3-V LVTTL,,,,,
HEX1[6],Unknown,PIN_B17,7,B7_N0,,3.3-V LVTTL,,,,,

Deuxième version en LPM

L'utilisation des LPM pour faire compteur décompteur est simple. Mais pour les cascader vous êtes obligé de faire un travail combinatoire par vous-même. Ce qui diminue franchement sa simplicité.

Voici le programme en LPM BCD (uniquement pour les compteur BCD):

-- testé OK le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
LIBRARY lpm; -- for LPM
USE lpm.lpm_components.ALL;

ENTITY compteur IS PORT (
  clk: IN std_logic;
  DU : in std_logic; -- down / up = 0 / 1
  EN : in std_logic;
  HEX0,HEX1: OUT std_logic_vector(6 downto 0));
END compteur;

ARCHITECTURE arch_compteur OF compteur IS

-- les composants :
COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END COMPONENT cmpt24bits;

COMPONENT transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END COMPONENT transcod7segs;

-- LES FILS INTERNES
SIGNAL s_horloge_lente : std_logic;
SIGNAL s_digit0BCD : std_logic_vector(3 downto 0);
SIGNAL s_digit1BCD : std_logic_vector(3 downto 0);
signal s_en_cmpt:  std_logic_vector(3 downto 0);
SIGNAL s_eno,s_eno0, s_eno9 : std_logic;
BEGIN
  i1 : cmpt24bits PORT MAP(
      clk_50MHz => clk,
      clk_slow => s_horloge_lente);
  i2 : lpm_counter GENERIC MAP (
    LPM_WIDTH => 4,
    LPM_MODULUS => 10 -- pour BCD
  )
  PORT MAP (
    CLOCK => s_horloge_lente,
    updown => DU,
    cnt_en => EN,
    eq(9) => s_eno9, -- détection de la valeur 9
    eq(0) => s_eno0, -- détection de la valeur 0
    q => s_digit0BCD);	
 
-- **** voici le calcul combinatoire à faire pour cascader : *****
    s_en_cmpt <= en & DU & s_eno9 & s_eno0;
    with s_en_cmpt select
     s_eno <= '1' when "1110",
              '1' when "1001",
              '0' when others;
-- fin du calcul
  i3 : lpm_counter GENERIC MAP (
    LPM_WIDTH => 4,
    LPM_MODULUS => 10 -- pour BCD
  )
  PORT MAP (
    CLOCK => s_horloge_lente,
    cnt_en => s_eno,
    updown => DU,
    q => s_digit1BCD);	

  i4 : transcod7segs PORT MAP(
           e => s_digit0BCD,
           s7segs => HEX0);
  i5 : transcod7segs PORT MAP(
           e => s_digit1BCD,
           s7segs => HEX1);
END arch_compteur;

-- horloge lente 3 Hz
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
ENTITY cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC; -- une seule entrée
    clk_slow : OUT STD_LOGIC); -- une seule sortie
END cmpt24bits;
 
ARCHITECTURE arch_cmpt24bits OF cmpt24bits IS
  signal cmpt : std_logic_vector(23 downto 0);
BEGIN
  process(clk_50MHz) begin
    if rising_edge(clk_50MHz) then
      cmpt <= cmpt + 1;
    end if;
  end process;
  clk_slow <= cmpt(23);  -- partie combinatoire de construction de l'horloge lente
END arch_cmpt24bits;

-- transcodeur pour affichage 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY transcod7segs IS PORT(
  e : in std_logic_vector(3 downto 0);
  s7segs : out std_logic_vector(6 downto 0));
END transcod7segs;
ARCHITECTURE arch of transcod7segs IS 
BEGIN
  with e select
             --gfedcba
    s7segs <= "1000000" when "0000",
              "1111001" when "0001",
              "0100100" when "0010",
              "0110000" when "0011",
              "0011001" when "0100",
              "0010010" when "0101",
              "0000010" when "0110",
              "1111000" when "0111",
              "0000000" when "1000",
              "0010000" when "1001",
              "0001000" when "1010",
              "0000011" when "1011",
              "1000110" when "1100",
              "0100001" when "1101",
              "0000110" when "1110",
              "0001110" when others;
END;

On a ajouté la ligne :

EN,Unknown,PIN_C11,7,B7_N0,PIN_C11,3.3-V LVTTL,,,,,

aux contraintes.