Cours:TP M1102 TP 6 Corr : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
m (Question 1)
m
 
(28 révisions intermédiaires par le même utilisateur non affichées)
Ligne 121 : Ligne 121 :
 
Voici le programme corrigé :
 
Voici le programme corrigé :
 
<source lang=vhdl>
 
<source lang=vhdl>
-- Vérifié OK le 29/09/20
+
-- Vérifié OK le 30/09/20
 
library IEEE;
 
library IEEE;
 
use IEEE.STD_LOGIC_1164.ALL;
 
use IEEE.STD_LOGIC_1164.ALL;
Ligne 235 : Ligne 235 :
 
<big>'''Ce fichier mif doit s'appeler TP6exo2.mif et se trouver dans le répertoire du projet !'''</big> Ce qui décide de cela est la ligne
 
<big>'''Ce fichier mif doit s'appeler TP6exo2.mif et se trouver dans le répertoire du projet !'''</big> Ce qui décide de cela est la ligne
 
<source lang=vhdl>
 
<source lang=vhdl>
 +
-- Pour trouver le nom du fichier mif et son chemin
 
LPM_FILE => "TP6exo2.mif",
 
LPM_FILE => "TP6exo2.mif",
 
</source>
 
</source>
Ligne 259 : Ligne 260 :
 
HEX0[7],Unknown,PIN_D15,7,B7_N0,,3.3-V LVTTL,,,,,
 
HEX0[7],Unknown,PIN_D15,7,B7_N0,,3.3-V LVTTL,,,,,
 
</pre>
 
</pre>
 +
 +
Le fait que l'ensemble des données ci-dessus (fichier .mif) finisse dans un mémoire interne du FPGA est indiqué dans le rapport de compilation (Compilation Report) sous la forme :
 +
<pre>
 +
Total memory bits    128 / 1,677,312 ( < 1 % )
 +
</pre>
 +
Cela vous précise que vous n'utilisez même pas 1% de la mémoire disponible dans votre FPGA.
  
 
==Exercice 3==
 
==Exercice 3==
Ligne 295 : Ligne 302 :
  
 
<source lang=VHDL>
 
<source lang=VHDL>
 +
-- testé 0K le 30/09/20
 
library IEEE;
 
library IEEE;
 
use IEEE.STD_LOGIC_1164.ALL;
 
use IEEE.STD_LOGIC_1164.ALL;
Ligne 392 : Ligne 400 :
 
HEX0[7],Unknown,PIN_D14,7,B7_N0,,3.3-V LVTTL,,,,,
 
HEX0[7],Unknown,PIN_D14,7,B7_N0,,3.3-V LVTTL,,,,,
 
</pre>
 
</pre>
 +
 +
Et enfin le nouveau fichier .mif est :
 +
 +
<pre>
 +
DEPTH = 16;
 +
WIDTH = 8;
 +
 +
ADDRESS_RADIX = HEX;
 +
DATA_RADIX = HEX;
 +
CONTENT
 +
  BEGIN
 +
[0..0f]  :  0;
 +
0000  : 01;
 +
0001  : 02;
 +
0002  : 04;
 +
0003  : 08;
 +
0004  : 10;
 +
0005  : 20;
 +
0006  : 40;
 +
0007  : 80;
 +
0008  : 40;
 +
0009  : 20;
 +
000a  : 10;
 +
000b  : 08;
 +
000c  : 04;
 +
000d  : 02;
 +
000e  : 01;
 +
000f  : ff;
 +
END;
 +
</pre>
 +
 +
===Question 2===
 +
Seul le fichier .mif est à changer :
 +
 +
<pre>
 +
DEPTH = 16;
 +
WIDTH = 8;
 +
 +
ADDRESS_RADIX = HEX;
 +
DATA_RADIX = HEX;
 +
CONTENT
 +
  BEGIN
 +
[0..0f]  :  0;
 +
0000  : 04;
 +
0001  : 02;
 +
0002  : 04;
 +
0003  : 08;
 +
0004  : 04;
 +
0005  : 02;
 +
0006  : 01;
 +
0007  : 02;
 +
0008  : 04;
 +
0009  : 08;
 +
000a  : 10;
 +
000b  : 20;
 +
000c  : 40;
 +
000d  : 80;
 +
000e  : 40;
 +
000f  : ff;
 +
END;
 +
</pre>
 +
 +
=== Information supplémentaire sur les LPM===
 +
Nous donnons pour information l'ensemble de la question 2 entièrement réalisé avec des compteurs '''LPM'''. Notez que <big>'''Ceci est réalisé dans les règles de l'art'''</big> : la même horloge est utilisée par les deux compteurs et la mémoire.
 +
<source lang=vhdl>
 +
--Vérifié OK le 29/09/20
 +
library IEEE;
 +
use IEEE.STD_LOGIC_1164.ALL;
 +
-- pour la mémoire et les deux compteurs
 +
LIBRARY lpm;
 +
USE lpm.lpm_components.ALL;
 +
 +
entity tp6 is port(
 +
  clk_50 : in std_logic;
 +
  hex0 : out std_logic_vector(7 downto 0)); -- changé pour exercice 4
 +
end tp6;
 +
 +
architecture arch_top of tp6 is
 +
  SIGNAL s_clk_slow : std_logic;
 +
  SIGNAL s_eno : std_logic;
 +
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
 +
begin
 +
  -- compteur 24 bits
 +
  ic1: lpm_counter GENERIC MAP (
 +
            LPM_WIDTH => 24
 +
  )
 +
  PORT MAP (CLOCK => clk_50,
 +
            eq(0) => s_eno); -- pas possible avec :(2^24 - 1) = 16777215
 +
 +
  -- compteur 4 bits
 +
  ic2: lpm_counter GENERIC MAP (
 +
            LPM_WIDTH => 4
 +
  )
 +
  PORT MAP (CLOCK => clk_50,
 +
            cnt_en => s_eno,
 +
            q => s_transcod);
 +
  ic3 : lpm_rom GENERIC MAP (
 +
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
 +
                LPM_FILE => "TP6exo2.mif",
 +
LPM_WIDTH => 8,
 +
LPM_WIDTHAD => 4)
 +
PORT MAP (
 +
  outclock => clk_50,
 +
  address => s_transcod,
 +
  q => hex0 -- changé pour exercice 4
 +
  );
 +
end arch_top;
 +
</source>
 +
Notez aussi comme le code est devenu compact.
  
 
==Exercice 5==
 
==Exercice 5==
 +
===Question 1===
 +
 +
Le nouveau fichier VHDL est
 +
<source lang=VHDL>
 +
-- Testé 0K le 1/10/20
 +
library IEEE;
 +
use IEEE.STD_LOGIC_1164.ALL;
 +
 +
entity tp6 is port(
 +
  clk_50 : in std_logic;
 +
  hex0 : out std_logic_vector(6 downto 0));
 +
end tp6;
 +
 +
architecture arch_top of tp6 is
 +
-- compteur 4 bits
 +
COMPONENT cmpt4bits IS
 +
  PORT(clk : IN STD_LOGIC;
 +
      cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
 +
END COMPONENT;
 +
-- compteur 24 bits pour l'horloge lente
 +
COMPONENT cmpt24bits IS
 +
  PORT(clk_50MHz : IN STD_LOGIC;
 +
    clk_slow : OUT STD_LOGIC);
 +
END COMPONENT;
 +
COMPONENT rams_21a is
 +
    port (clk : in std_logic;
 +
          en    : in std_logic;
 +
          addr : in std_logic_vector(3 downto 0);
 +
          data : out std_logic_vector(7 downto 0));
 +
end COMPONENT rams_21a;
 +
  SIGNAL s_clk_slow : std_logic;
 +
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
 +
begin
 +
  lent: cmpt24bits port map(
 +
          clk_50MHz => clk_50,
 +
          clk_slow => s_clk_slow);
 +
  cmpt: cmpt4bits port map(
 +
          clk => s_clk_slow,
 +
          cnt => s_transcod);
 +
  ic3 : rams_21a PORT MAP (
 +
  clk => s_clk_slow,
 +
  en => '1',
 +
  addr => s_transcod,
 +
  data(6 downto 0) => hex0
 +
  );
 +
end arch_top;
 +
-- 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;
 +
 +
library IEEE;
 +
use IEEE.STD_LOGIC_1164.ALL;
 +
use ieee.std_logic_arith.all;
 +
use ieee.std_logic_unsigned.all;
 +
ENTITY cmpt4bits IS
 +
  PORT(clk : IN STD_LOGIC;
 +
    cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
 +
END cmpt4bits;
 +
 +
ARCHITECTURE arch_cmpt4bits OF cmpt4bits IS
 +
  signal cmpt : std_logic_vector(3 downto 0);
 +
BEGIN
 +
  process(clk) begin
 +
    if rising_edge(clk) then
 +
      cmpt <= cmpt + 1;
 +
    end if;
 +
  end process;
 +
  cnt <= cmpt; 
 +
END arch_cmpt4bits;
 +
 +
--
 +
-- ROMs Using Block RAM Resources.
 +
-- VHDL code for a ROM with registered output (template 1)
 +
--
 +
library ieee;
 +
use ieee.std_logic_1164.all;
 +
use ieee.std_logic_unsigned.all;
 +
entity rams_21a is
 +
    port (clk : in std_logic;
 +
          en    : in std_logic;
 +
          addr : in std_logic_vector(3 downto 0);
 +
          data : out std_logic_vector(7 downto 0));
 +
end rams_21a;
 +
architecture syn of rams_21a is
 +
  type rom_type is array (0 to 15) of std_logic_vector (7 downto 0);
 +
-- contenu de la ROM
 +
  signal ROM : rom_type:=
 +
    (X"40", X"79", X"24", X"30", X"19", X"12",
 +
    X"02", X"78", X"00", X"10", X"08", X"03",
 +
    X"46", X"21", X"06", X"0E");
 +
begin
 +
    process (clk)
 +
    begin
 +
        if (clk'event and clk = '1') then
 +
            if (en = '1') then
 +
                  data <= ROM(conv_integer(addr));
 +
            end if;
 +
        end if;
 +
    end process;
 +
end syn;
 +
 +
</source>
 +
 +
Mais le rapport de compilation donne :
 +
 +
<pre>
 +
Total memory bits      0 / 1,677,312 ( 0 % )
 +
</pre>
 +
 +
ce qui indique que le compilateur n'a pas utilisé de mémoire interne pour réaliser cette mémoire !
 +
 +
===Question 2===
 +
Vous n'avez qu'à changer le fichier de contraintes pour que les sorties se fassent sur les leds. '''ATTENTION''' cependant la taille de le sortie sur 7 segments est à adpter pour les 8 leds.
 +
 +
Le contenu de la mémoire est à changer aussi.
 +
 +
===Question 3===
 +
Cette question dispose de son corrigé accessible tout le temps et présente dans l'énoncé.
 +
 +
Gilles Millon m'a proposé une autre solution. Je ne sais plus s'il l'a réalisée en pratique, mais si c'est le cas il peut la mettre ici.
  
 
==Exercice 6==
 
==Exercice 6==
 +
===Question 1===
 +
Il y a 9 valeurs possibles pour les sorties : 0,1,2,3,4,5,6,7,8 leds allumées. On doit donc choisir un bis d'adresse de 4 bits. Cela revient donc à utiliser le même type de mémoire que ce que l'on a utilisé jusqu'à présent :
 +
<source lang = VHDL>
 +
lpm_rom GENERIC MAP (
 +
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
 +
                LPM_FILE => "TP6exo2.mif",
 +
LPM_WIDTH => 8, -- 8 bits de données
 +
LPM_WIDTHAD => 4) -- 4 bits de bus d'adresse
 +
</source>
 +
 +
===Question 2 et 3===
 +
On a plutôt utilisé un compteur qui compte de 0 à 15 et on préfère doubler quelques affichage. Cela revient à peu près à ne pas tenir compte du poids faible. A peu près car ce n'est pas vrai pour 0 et pour 8. Voici donc le contenu de la mémoire :
 +
<pre>
 +
DEPTH = 16;
 +
WIDTH = 8;
 +
 +
ADDRESS_RADIX = HEX;
 +
DATA_RADIX = HEX;
 +
CONTENT
 +
  BEGIN
 +
[0..0f]  :  0;
 +
0000  : 00;
 +
0001  : 01;
 +
0002  : 01;
 +
0003  : 03;
 +
0004  : 03;
 +
0005  : 07;
 +
0006  : 07;
 +
0007  : 0f;
 +
0008  : 0f;
 +
0009  : 1f;
 +
000a  : 1f;
 +
000b  : 3f;
 +
000c  : 3f;
 +
000d  : 7f;
 +
000e  : 7f;
 +
000f  : ff;
 +
END;
 +
</pre>
 +
 +
Et voici le programme VHDL correspondant :
 +
<source lang=vhdl>
 +
--testé OK le 1/10/20
 +
library IEEE;
 +
use IEEE.STD_LOGIC_1164.ALL;
 +
-- pour la mémoire
 +
LIBRARY lpm;
 +
USE lpm.lpm_components.ALL;
 +
 +
entity tp6 is port(
 +
  clk_50 : in std_logic;
 +
  hex0 : out std_logic_vector(7 downto 0)); -- changé pour exercice 4
 +
end tp6;
 +
 +
architecture arch_top of tp6 is
 +
COMPONENT cmpt4bits IS
 +
  PORT(clk : IN STD_LOGIC;
 +
      cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
 +
END COMPONENT;
 +
COMPONENT cmpt24bits IS
 +
  PORT(clk_50MHz : IN STD_LOGIC;
 +
    clk_slow : OUT STD_LOGIC);
 +
END COMPONENT;
 +
  SIGNAL s_clk_slow : std_logic;
 +
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
 +
begin
 +
  lent: cmpt24bits port map(
 +
          clk_50MHz => clk_50,
 +
          clk_slow => s_clk_slow);
 +
  cmpt: cmpt4bits port map(
 +
          clk => s_clk_slow,
 +
          cnt => s_transcod);
 +
  ic3 : lpm_rom GENERIC MAP (
 +
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
 +
                LPM_FILE => "TP6exo2.mif",
 +
LPM_WIDTH => 8,
 +
LPM_WIDTHAD => 4)
 +
PORT MAP (
 +
  outclock => s_clk_slow,
 +
  address => s_transcod,
 +
  q => hex0 -- changé pour exercice 4
 +
  );
 +
end arch_top;
 +
-- 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;
 +
 +
library IEEE;
 +
use IEEE.STD_LOGIC_1164.ALL;
 +
use ieee.std_logic_arith.all;
 +
use ieee.std_logic_unsigned.all;
 +
ENTITY cmpt4bits IS
 +
  PORT(clk : IN STD_LOGIC;
 +
    cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
 +
END cmpt4bits;
 +
 +
ARCHITECTURE arch_cmpt4bits OF cmpt4bits IS
 +
  signal cmpt : std_logic_vector(3 downto 0);
 +
BEGIN
 +
  process(clk) begin
 +
    if rising_edge(clk) then
 +
      cmpt <= cmpt + 1;
 +
    end if;
 +
  end process;
 +
  cnt <= cmpt; 
 +
END arch_cmpt4bits;
 +
</source>
 +
 +
===Question 4===
 +
Il est simple de réaliser un compteur/décompteur avec des LPM. Si on veut le faire en VHDL, cela a été fait avec un compteur/décompteur décimal en exercice 4 du TP 5.
 +
 +
Ainsi,
 +
<source lang=VHDL>
 +
      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;
 +
</source>
 +
doit se simplifier en :
 +
<source lang=VHDL>
 +
      if(rising_edge(Clock)) then
 +
        if EN='1' then
 +
          if du='1' then
 +
            cmpt <= cmpt + 1;
 +
          else
 +
            cmpt <= cmpt - 1;
 +
          end if; --if du='1'
 +
        end if; --if EN='1'
 +
    end if;-- if(rising_edge(Clock))
 +
</source>
 +
si on retire la gestion du reset. La gestion du '''EN''' pourrait elle aussi être retirée.

Version actuelle datée du 21 juillet 2021 à 13:56

TP6

Exercice 1 : le réveil

Il n'y a pas grand chose à dire sur la correction à part que l'on n'utilise pas l'horloge 50 MHz directement mais le 3Hz que l'on sait fabriquer depuis le tp 3.

-- Vérifié OK le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY tp6 IS PORT (
  clk, key, trip : IN std_logic;
  Led0: OUT std_logic);
END tp6;

ARCHITECTURE arch_tp6 OF tp6 IS
-- les composants :
COMPONENT SequSonnerie IS
  PORT(                  
        clock,Key,Trip,ena :IN std_logic;
        Ring :OUT std_logic
        );
END COMPONENT SequSonnerie;

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 : SequSonnerie PORT MAP (
         clock => s_horloge_lente,
			Key => Key,
			Trip => Trip,
			ena => '1',
         Ring => led0);
END arch_tp6;

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY SequSonnerie IS
  PORT(                  
        clock,Key,Trip,ena :IN std_logic;
        Ring :OUT std_logic
        );
END SequSonnerie;

ARCHITECTURE arch_SequSonnerie  OF SequSonnerie IS
  TYPE typetat IS (Armed, Off, Ringing); 
  SIGNAL etatp, etatf : typetat;
  BEGIN
-- partie séquentielle
    PROCESS (clock) BEGIN  -- 1er process
	 IF Clock ='1' AND Clock'EVENT THEN
	   IF ena = '1' then
            etatp <= etatf;
		END IF;
     END IF;
    END PROCESS;
    PROCESS(etatp) BEGIN --2eme process
        CASE etatp IS
             WHEN Off => IF key ='1' THEN etatf <= Armed; 
                         ELSE etatf <= Off;
                      END IF;  
             WHEN Armed => IF Key = '0' THEN 
                            etatf <= Off;
	                   ELSIF Trip ='1' THEN 
                             etatf <= Ringing;
	                   ELSE etatf <= Armed;
	                  END IF; 
             WHEN Ringing => IF Key ='0' THEN 
                                 etatf <= Off; 
                            ELSE etatf <= Ringing;
			    END IF; 
	        END CASE;
    END PROCESS;
-- partie combinatoire
   Ring <= '1' WHEN etatp=Ringing ELSE
           '0';
END arch_SequSonnerie;

-- 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;

Voici 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,,,,,

Key,Unknown,PIN_C10,7,B7_N0,PIN_C10,3.3-V LVTTL,,,,,
Trip,Unknown,PIN_C11,7,B7_N0,PIN_C11,3.3-V LVTTL,,,,,

LED0,Unknown,PIN_A8,7,B7_N0,PIN_A8,3.3-V LVTTL,,,,,

Exercice 2

Voici le programme corrigé :

-- Vérifié OK le 30/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- pour la mémoire
LIBRARY lpm;
USE lpm.lpm_components.ALL;

entity tp6 is port(
  clk_50 : in std_logic;
  hex0 : out std_logic_vector(6 downto 0));
end tp6;

architecture arch_top of tp6 is
COMPONENT cmpt4bits IS
  PORT(clk : IN STD_LOGIC;
       cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT;
COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC;
    clk_slow : OUT STD_LOGIC);
END COMPONENT;
  SIGNAL s_clk_slow : std_logic;
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
begin
  lent: cmpt24bits port map(
           clk_50MHz => clk_50,
           clk_slow => s_clk_slow);
  cmpt: cmpt4bits port map(
           clk => s_clk_slow,
           cnt => s_transcod);
  ic3 : lpm_rom GENERIC MAP (
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
                LPM_FILE => "TP6exo2.mif",
		LPM_WIDTH => 8,
		LPM_WIDTHAD => 4)
		PORT MAP (
		  outclock => s_clk_slow,
		  address => s_transcod,
		  q(6 downto 0) => hex0
		  );
end arch_top;
-- 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;

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

Nous donnons maintenant le fichier mif :

DEPTH = 16;
WIDTH = 8;

ADDRESS_RADIX = HEX;
DATA_RADIX = HEX;
CONTENT
  BEGIN
[0..0f]   :  0;
0000  : 40;
0001  : 79;
0002  : 24;
0003  : 30;
0004  : 19;
0005  : 12;
0006  : 02;
0007  : 78;
0008  : 00;
0009  : 10;
000a  : 08;
000b  : 03;
000c  : 46;
000d  : 21;
000e  : 06;
000f  : 0e;
END;

Ce fichier mif doit s'appeler TP6exo2.mif et se trouver dans le répertoire du projet ! Ce qui décide de cela est la ligne

-- Pour trouver le nom du fichier mif et son chemin
LPM_FILE => "TP6exo2.mif",

dans l'instanciation de la mémoire. Ceci peut naturellement être changé.

Vient maintenant le fichier de contraintes :

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

clk_50,Input,PIN_P11,,,,3.3-V LVTTL,,,,,

Key,Unknown,PIN_C10,7,B7_N0,PIN_C10,3.3-V LVTTL,,,,,
Trip,Unknown,PIN_C11,7,B7_N0,PIN_C11,3.3-V LVTTL,,,,,

LED0,Unknown,PIN_A8,7,B7_N0,PIN_A8,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,,,,,

Le fait que l'ensemble des données ci-dessus (fichier .mif) finisse dans un mémoire interne du FPGA est indiqué dans le rapport de compilation (Compilation Report) sous la forme :

Total memory bits    128 / 1,677,312 ( < 1 % )

Cela vous précise que vous n'utilisez même pas 1% de la mémoire disponible dans votre FPGA.

Exercice 3

Seul le fichier .mif est à changer par rapport à l'exercice 2. Voici le nouveau contenu :

DEPTH = 16;
WIDTH = 8;

ADDRESS_RADIX = HEX;
DATA_RADIX = HEX;
CONTENT
  BEGIN
[0..0f]   :  0;
0000  : 03;
0001  : 23;
0002  : 2b;
0003  : 71;
0004  : 23;
0005  : 63;
0006  : 2f;
0007  : 7f;
0008  : 08;
0009  : 7f;
000a  : 07;
000b  : 23;
000c  : 63;
000d  : 12;
000e  : 7f;
000f  : 7f;
END;

Exercice 4

Question 1

Le fichier VHDL est changé de manière très mineure par rapport à celui de l'exercice 2. Les sorties s'appellent toujours HEX0 sont sur 8 bits maintenant et sont maintenant destinées aux leds.

-- testé 0K le 30/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- pour la mémoire
LIBRARY lpm;
USE lpm.lpm_components.ALL;

entity tp6 is port(
  clk_50 : in std_logic;
  hex0 : out std_logic_vector(7 downto 0)); -- changé pour exercice 4
end tp6;

architecture arch_top of tp6 is
COMPONENT cmpt4bits IS
  PORT(clk : IN STD_LOGIC;
       cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT;
COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC;
    clk_slow : OUT STD_LOGIC);
END COMPONENT;
  SIGNAL s_clk_slow : std_logic;
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
begin
  lent: cmpt24bits port map(
           clk_50MHz => clk_50,
           clk_slow => s_clk_slow);
  cmpt: cmpt4bits port map(
           clk => s_clk_slow,
           cnt => s_transcod);
  ic3 : lpm_rom GENERIC MAP (
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
                LPM_FILE => "TP6exo2.mif",
		LPM_WIDTH => 8,
		LPM_WIDTHAD => 4)
		PORT MAP (
		  outclock => s_clk_slow,
		  address => s_transcod,
		  q => hex0 -- changé pour exercice 4
		  );
end arch_top;
-- 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;

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

Le nouveau fichier de contrainte est :

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

clk_50,Input,PIN_P11,,,,3.3-V LVTTL,,,,,

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

Et enfin le nouveau fichier .mif est :

DEPTH = 16;
WIDTH = 8;

ADDRESS_RADIX = HEX;
DATA_RADIX = HEX;
CONTENT
  BEGIN
[0..0f]   :  0;
0000  : 01;
0001  : 02;
0002  : 04;
0003  : 08;
0004  : 10;
0005  : 20;
0006  : 40;
0007  : 80;
0008  : 40;
0009  : 20;
000a  : 10;
000b  : 08;
000c  : 04;
000d  : 02;
000e  : 01;
000f  : ff;
END;

Question 2

Seul le fichier .mif est à changer :

DEPTH = 16;
WIDTH = 8;

ADDRESS_RADIX = HEX;
DATA_RADIX = HEX;
CONTENT
  BEGIN
[0..0f]   :  0;
0000  : 04;
0001  : 02;
0002  : 04;
0003  : 08;
0004  : 04;
0005  : 02;
0006  : 01;
0007  : 02;
0008  : 04;
0009  : 08;
000a  : 10;
000b  : 20;
000c  : 40;
000d  : 80;
000e  : 40;
000f  : ff;
END;

Information supplémentaire sur les LPM

Nous donnons pour information l'ensemble de la question 2 entièrement réalisé avec des compteurs LPM. Notez que Ceci est réalisé dans les règles de l'art : la même horloge est utilisée par les deux compteurs et la mémoire.

--Vérifié OK le 29/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- pour la mémoire et les deux compteurs
LIBRARY lpm;
USE lpm.lpm_components.ALL;

entity tp6 is port(
  clk_50 : in std_logic;
  hex0 : out std_logic_vector(7 downto 0)); -- changé pour exercice 4
end tp6;

architecture arch_top of tp6 is
  SIGNAL s_clk_slow : std_logic;
  SIGNAL s_eno : std_logic;
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
begin
  -- compteur 24 bits
  ic1: lpm_counter GENERIC MAP (
            LPM_WIDTH => 24
  )
  PORT MAP (CLOCK => clk_50,
            eq(0) => s_eno); -- pas possible avec :(2^24 - 1) = 16777215

  -- compteur 4 bits
  ic2: lpm_counter GENERIC MAP (
            LPM_WIDTH => 4
  )
  PORT MAP (CLOCK => clk_50,
            cnt_en => s_eno,
            q => s_transcod);
  ic3 : lpm_rom GENERIC MAP (
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
                LPM_FILE => "TP6exo2.mif",
		LPM_WIDTH => 8,
		LPM_WIDTHAD => 4)
		PORT MAP (
		  outclock => clk_50,
		  address => s_transcod,
		  q => hex0 -- changé pour exercice 4
		  );
end arch_top;

Notez aussi comme le code est devenu compact.

Exercice 5

Question 1

Le nouveau fichier VHDL est

-- Testé 0K le 1/10/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity tp6 is port(
  clk_50 : in std_logic;
  hex0 : out std_logic_vector(6 downto 0));
end tp6;

architecture arch_top of tp6 is
-- compteur 4 bits
COMPONENT cmpt4bits IS
  PORT(clk : IN STD_LOGIC;
       cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT;
-- compteur 24 bits pour l'horloge lente
COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC;
    clk_slow : OUT STD_LOGIC);
END COMPONENT;
COMPONENT rams_21a is 
    port (clk : in std_logic; 
           en    : in std_logic; 
           addr : in std_logic_vector(3 downto 0); 
           data : out std_logic_vector(7 downto 0)); 
end COMPONENT rams_21a;
  SIGNAL s_clk_slow : std_logic;
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
begin
  lent: cmpt24bits port map(
           clk_50MHz => clk_50,
           clk_slow => s_clk_slow);
  cmpt: cmpt4bits port map(
           clk => s_clk_slow,
           cnt => s_transcod);
  ic3 : rams_21a PORT MAP (
		  clk => s_clk_slow,
		  en => '1',
		  addr => s_transcod,
		  data(6 downto 0) => hex0
		  );
end arch_top;
-- 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;

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

-- 
-- ROMs Using Block RAM Resources. 
-- VHDL code for a ROM with registered output (template 1) 
-- 
library ieee; 
use ieee.std_logic_1164.all; 
use ieee.std_logic_unsigned.all; 
entity rams_21a is 
    port (clk : in std_logic; 
           en    : in std_logic; 
           addr : in std_logic_vector(3 downto 0); 
           data : out std_logic_vector(7 downto 0)); 
end rams_21a; 
architecture syn of rams_21a is 
  type rom_type is array (0 to 15) of std_logic_vector (7 downto 0);
 -- contenu de la ROM 
  signal ROM : rom_type:= 
    (X"40", X"79", X"24", X"30", X"19", X"12", 
     X"02", X"78", X"00", X"10", X"08", X"03", 
     X"46", X"21", X"06", X"0E"); 
begin 
    process (clk) 
    begin 
        if (clk'event and clk = '1') then 
             if (en = '1') then 
                  data <= ROM(conv_integer(addr)); 
             end if; 
         end if; 
    end process; 
end syn;

Mais le rapport de compilation donne :

Total memory bits       0 / 1,677,312 ( 0 % )

ce qui indique que le compilateur n'a pas utilisé de mémoire interne pour réaliser cette mémoire !

Question 2

Vous n'avez qu'à changer le fichier de contraintes pour que les sorties se fassent sur les leds. ATTENTION cependant la taille de le sortie sur 7 segments est à adpter pour les 8 leds.

Le contenu de la mémoire est à changer aussi.

Question 3

Cette question dispose de son corrigé accessible tout le temps et présente dans l'énoncé.

Gilles Millon m'a proposé une autre solution. Je ne sais plus s'il l'a réalisée en pratique, mais si c'est le cas il peut la mettre ici.

Exercice 6

Question 1

Il y a 9 valeurs possibles pour les sorties : 0,1,2,3,4,5,6,7,8 leds allumées. On doit donc choisir un bis d'adresse de 4 bits. Cela revient donc à utiliser le même type de mémoire que ce que l'on a utilisé jusqu'à présent :

lpm_rom GENERIC MAP (
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
                LPM_FILE => "TP6exo2.mif",
		LPM_WIDTH => 8, -- 8 bits de données
		LPM_WIDTHAD => 4) -- 4 bits de bus d'adresse

Question 2 et 3

On a plutôt utilisé un compteur qui compte de 0 à 15 et on préfère doubler quelques affichage. Cela revient à peu près à ne pas tenir compte du poids faible. A peu près car ce n'est pas vrai pour 0 et pour 8. Voici donc le contenu de la mémoire :

DEPTH = 16;
WIDTH = 8;

ADDRESS_RADIX = HEX;
DATA_RADIX = HEX;
CONTENT
  BEGIN
[0..0f]   :  0;
0000  : 00;
0001  : 01;
0002  : 01;
0003  : 03;
0004  : 03;
0005  : 07;
0006  : 07;
0007  : 0f;
0008  : 0f;
0009  : 1f;
000a  : 1f;
000b  : 3f;
000c  : 3f;
000d  : 7f;
000e  : 7f;
000f  : ff;
END;

Et voici le programme VHDL correspondant :

--testé OK le 1/10/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-- pour la mémoire
LIBRARY lpm;
USE lpm.lpm_components.ALL;

entity tp6 is port(
  clk_50 : in std_logic;
  hex0 : out std_logic_vector(7 downto 0)); -- changé pour exercice 4
end tp6;

architecture arch_top of tp6 is
COMPONENT cmpt4bits IS
  PORT(clk : IN STD_LOGIC;
       cnt : OUT STD_LOGIC_VECTOR(3 DOWNTO 0));
END COMPONENT;
COMPONENT cmpt24bits IS
  PORT(clk_50MHz : IN STD_LOGIC;
    clk_slow : OUT STD_LOGIC);
END COMPONENT;
  SIGNAL s_clk_slow : std_logic;
  SIGNAL s_transcod : std_logic_vector(3 downto 0);
begin
  lent: cmpt24bits port map(
           clk_50MHz => clk_50,
           clk_slow => s_clk_slow);
  cmpt: cmpt4bits port map(
           clk => s_clk_slow,
           cnt => s_transcod);
  ic3 : lpm_rom GENERIC MAP (
                LPM_ADDRESS_CONTROL => "UNREGISTERED",
                LPM_FILE => "TP6exo2.mif",
		LPM_WIDTH => 8,
		LPM_WIDTHAD => 4)
		PORT MAP (
		  outclock => s_clk_slow,
		  address => s_transcod,
		  q => hex0 -- changé pour exercice 4
		  );
end arch_top;
-- 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;

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

Question 4

Il est simple de réaliser un compteur/décompteur avec des LPM. Si on veut le faire en VHDL, cela a été fait avec un compteur/décompteur décimal en exercice 4 du TP 5.

Ainsi,

      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;

doit se simplifier en :

      if(rising_edge(Clock)) then
        if EN='1' then
          if du='1' then
            cmpt <= cmpt + 1;
          else
            cmpt <= cmpt - 1;	
          end if; --if du='1'
        end if; --if EN='1'
     end if;-- if(rising_edge(Clock))

si on retire la gestion du reset. La gestion du EN pourrait elle aussi être retirée.