Cours:TP M1102 TP 4 Corr
Sommaire
TP 4
Exercice 1
Voici donc le compteur qui divise la fréquence. Il est bon de savoir calculer par avance la fréquence de ce genre de compteur :
- compteur 1 bit divise par deux
- compteur 2 bits divise par 4 = 2^2
- compteur 3 bits divise par 8 = 2^3
- ....
- compteur 24 bits (b23,b22,...,b1,b0) divise par 2^24 soit 50000000/2^24 = 2,98 Hz
-- Vérifié le 28/09/20
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;
Le petit fichier de contrainte peut être exprimé par :
To,Direction,Location,I/O Bank,VREF Group,Fitter Location,I/O Standard,Reserved,Current Strength,Slew Rate,Differential Pair,Strict Preservation clk_50MHz,Input,PIN_P11,,,PIN_P11,3.3-V LVTTL,,,,, clk_slow,Unknown,PIN_A8,7,B7_N0,PIN_A8,3.3-V LVTTL,,,,,
Exercice 2
Voici le programme VHDL complet qui comprend deux composants reliés ensemble pour en faire un troisième :
- composant diviseur de fréquence le l'exercice 1
- composant diagramme d'évolution demandé dans l'énoncé
- composant global pour les tests visuels à l’œil
-- Vérifié le 28/09/20
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY compteur IS PORT (
clk: IN std_logic;
q0,q1: OUT std_logic);
END compteur;
ARCHITECTURE arch_compteur OF compteur IS
-- les somposants :
COMPONENT cmpt_exo2 IS PORT (
clk: IN std_logic;
q0,q1: OUT std_logic);
END COMPONENT cmpt_exo2;
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_hologe_lente : std_logic;
BEGIN
i1 : cmpt24bits PORT MAP(
clk_50MHz => clk,
clk_slow => s_hologe_lente);
i2 : cmpt_exo2 PORT MAP (
clk => s_hologe_lente,
q0 => q0,
q1 => q1);
END arch_compteur;
-- diagramme d'évolution demandé
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library ieee;
use ieee.std_logic_1164.all;
ENTITY cmpt_exo2 IS PORT (
clk: IN std_logic;
q0,q1: OUT std_logic);
END cmpt_exo2;
ARCHITECTURE arch_cmpt_exo2 OF cmpt_exo2 IS
SIGNAL q1q0 : std_logic_vector(1 downto 0);
BEGIN
PROCESS (clk) BEGIN -- ou cmpt:PROCESS (clk) BEGIN
IF (clk'EVENT AND clk='1') THEN
q1q0(0) <= NOT q1q0(0);
-- add the second equation here
q1q0(1) <= q1q0(0) XOR q1q0(1);
END IF;
END PROCESS;
-- mise a jour des sorties
q0 <= q1q0(0);
q1 <= q1q0(1);
END arch_cmpt_exo2;
-- 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;
Pour compléter voici 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,Input,PIN_P11,,,PIN_P11,3.3-V LVTTL,,,,, q0,Unknown,PIN_A8,7,B7_N0,PIN_A8,3.3-V LVTTL,,,,, q1,Unknown,PIN_A9,7,B7_N0,,3.3-V LVTTL,,,,,
Exercice 3
Question 1
Un peu long à faire avec des étudiants pour trouver les équations de récurrences. Une version plus simple à réaliser est donnée dans l'exercice suivant.
Voici quand même le
- tableau État présent/État futur
État présent État futur g f e d c b a g+ f+ e+ d+ c+ b+ a+ 1 0 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 1 0 0 1 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 1 1 0 0 0 0 0 1 1 0 0 0 0 0 0 1 1 0 0 1 0 0 1 1 0 0 1 0 0 1 0 0 1 0 0 0 1 0 0 1 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 1 1 1 1 0 0 0 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 0 1 0 0 0 0 1 0 0 0 0 0 0
Pour simplifier l'écriture des équations de récurrences, nous allons utiliser des notations intermédiaires. Ne disposant pas de la possibilité d'écrire les équations logiques correctement dans ce WIKI, nous allons les écrire en VHDL :
zero <= g and not f and not e and not d and not c and not b and not a; --"1000000" pour allumer 0
un <= g and f and e and d and not c and not b and a; --"1111001" pour allumer 1
deux <= not g and f and not e and not d and c and not b and not a; --"0100100" pour allumer 2
trois <= not g and f and e and not d and not c and not b and not a; --"0110000" pour allumer 3
quatre <= not g and not f and e and d and not c and not b and a; --"0011001" pour allumer 4
cinq <= not g and not f and e and not d and not c and b and not a; --"0010010" pour allumer 5
six <= not g and not f and not e and not d and not c and b and not a; --"0000010" pour allumer 6
sept <= g and f and e and d and not c and not b and not a; --"1111000" pour allumer 7
huit <= not g and not f and not e and not d and not c and not b and not a; --"0000000" pour allumer 8
neuf <= not g and not f and e and not d and not c and not b and not a; --"0010000" pour allumer 9
Voici le composant compteur sept segments avec des équations de récurrences :
-- Compteur 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY cmpt7seg IS
PORT(CLK_lent : IN STD_LOGIC;
a,b,c,d,e,f,g : INOUT STD_LOGIC);
-- ou alors : s7segs : out std_logic_vector(6 downto 0));
END cmpt7seg;
ARCHITECTURE arch_cmpt7seg of cmpt7seg is
signal zero,un,deux,trois,quatre,cinq,six,sept,huit,neuf : std_logic;
BEGIN
zero <= g and not f and not e and not d and not c and not b and not a; --"1000000" pour allumer 0
un <= g and f and e and d and not c and not b and a; --"1111001" pour allumer 1
deux <= not g and f and not e and not d and c and not b and not a; --"0100100" pour allumer 2
trois <= not g and f and e and not d and not c and not b and not a; --"0110000" pour allumer 3
quatre <= not g and not f and e and d and not c and not b and a; --"0011001" pour allumer 4
cinq <= not g and not f and e and not d and not c and b and not a; --"0010010" pour allumer 5
six <= not g and not f and not e and not d and not c and b and not a; --"0000010" pour allumer 6
sept <= g and f and e and d and not c and not b and not a; --"1111000" pour allumer 7
huit <= not g and not f and not e and not d and not c and not b and not a; --"0000000" pour allumer 8
neuf <= not g and not f and e and not d and not c and not b and not a; --"0010000" pour allumer 9
PROCESS (clk_lent) BEGIN -- ou cmpt:PROCESS (clk) BEGIN
IF (clk_lent'EVENT AND clk_lent='1') THEN
g <= neuf OR zero OR six;
f <= zero OR un OR deux OR six;
e <= zero OR deux OR trois OR quatre OR six OR huit;
d <= zero OR trois OR six;
c <= un;
b <= quatre OR cinq;
a <= zero OR trois;
END IF;
END PROCESS;
END arch_cmpt7seg;
Et voici donc le programme complet avec l'horloge lente :
-- Vérifié le 28/09/20
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 somposants :
COMPONENT cmpt7seg IS
PORT(CLK_lent : IN STD_LOGIC;
a,b,c,d,e,f,g : OUT STD_LOGIC);
-- ou alors : s7segs : out std_logic_vector(6 downto 0));
END COMPONENT cmpt7seg;
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 : cmpt7seg PORT MAP (
clk_lent => s_horloge_lente,
a => HEX0(0),
b => HEX0(1),
c => HEX0(2),
d => HEX0(3),
e => HEX0(4),
f => HEX0(5),
g => HEX0(6));
END arch_compteur;
-- Compteur 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY cmpt7seg IS
PORT(CLK_lent : IN STD_LOGIC;
a,b,c,d,e,f,g : INOUT STD_LOGIC);
-- ou alors : s7segs : out std_logic_vector(6 downto 0));
END cmpt7seg;
ARCHITECTURE arch_cmpt7seg of cmpt7seg is
signal zero,un,deux,trois,quatre,cinq,six,sept,huit,neuf : std_logic;
BEGIN
zero <= g and not f and not e and not d and not c and not b and not a; --"1000000" pour allumer 0
un <= g and f and e and d and not c and not b and a; --"1111001" pour allumer 1
deux <= not g and f and not e and not d and c and not b and not a; --"0100100" pour allumer 2
trois <= not g and f and e and not d and not c and not b and not a; --"0110000" pour allumer 3
quatre <= not g and not f and e and d and not c and not b and a; --"0011001" pour allumer 4
cinq <= not g and not f and e and not d and not c and b and not a; --"0010010" pour allumer 5
six <= not g and not f and not e and not d and not c and b and not a; --"0000010" pour allumer 6
sept <= g and f and e and d and not c and not b and not a; --"1111000" pour allumer 7
huit <= not g and not f and not e and not d and not c and not b and not a; --"0000000" pour allumer 8
neuf <= not g and not f and e and not d and not c and not b and not a; --"0010000" pour allumer 9
PROCESS (clk_lent) BEGIN -- ou cmpt:PROCESS (clk) BEGIN
IF (clk_lent'EVENT AND clk_lent='1') THEN
g <= neuf OR zero OR six;
f <= zero OR un OR deux OR six;
e <= zero OR deux OR trois OR quatre OR six OR huit;
d <= zero OR trois OR six;
c <= un;
b <= quatre OR cinq;
a <= zero OR trois;
END IF;
END PROCESS;
END arch_cmpt7seg;
-- 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;
Le compilateur de Quartus permet le mélange des "INOUT" et "OUT" comme cela est fait ici :
- un INOUT dans l'entité
- un OUT dans la déclaration du composant associé à l'entité ci-dessus
- un OUT dans le composant global
Tous les compilateurs ne permettent pas cela !!!
Voici pour finir le fichier de contraintes csv 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,,,PIN_P11,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,,,,,
Question 2
Il suffit de forcer l'affichage de zéro quand on active l'entrée Init. Les équations de récurrences sont alors changées comme ci-dessous :
PROCESS (clk_lent) BEGIN -- ou cmpt:PROCESS (clk) BEGIN
IF (clk_lent'EVENT AND clk_lent='1') THEN
g <= neuf OR zero OR six OR Init;
f <= (zero OR un OR deux OR six) AND NOT INIT;
e <= (zero OR deux OR trois OR quatre OR six OR huit) AND NOT INIT;
d <= (zero OR trois OR six) AND NOT INIT;
c <= un AND NOT INIT;
b <= (quatre OR cinq) AND NOT INIT;
a <= (zero OR trois) AND NOT INIT;
END IF;
END PROCESS;
Ainsi quand Init passe à un, g passe à 1 (à cause du OU Init) tandis que f,e,d,c,b et a passent à 0 ( à cause du "et not init") ce qui éteint seulement g et donc affiche 0 !
Exercice 4
Cette façon de procéder est beaucoup plus rapide que celle de l'exercice 3. Il n'y a pas besoin des équations de récurrence mais seulement du diagramme d'évolution.
On vous donne le programme global comportant le compteur 24 bits pour réaliser une horloge lente et le compteur direct sept segments.
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 somposants :
COMPONENT cmpt7seg IS
PORT(CLK : IN STD_LOGIC;
s_7segs : OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END COMPONENT cmpt7seg;
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 : cmpt7seg PORT MAP (
clk_lent => s_horloge_lente,
a => HEX0(0),
b => HEX0(1),
c => HEX0(2),
d => HEX0(3),
e => HEX0(4),
f => HEX0(5),
g => HEX0(6));
END arch_compteur;
-- Compteur 7 segments
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
ENTITY cmpt7seg IS
PORT(CLK : IN STD_LOGIC;
s_7segs : OUT STD_LOGIC_VECTOR(6 DOWNTO 0));
END cmpt7seg;
ARCHITECTURE arch OF cmpt7seg IS -- comment éviter les equations
SIGNAL s7segs : STD_LOGIC_VECTOR(6 DOWNTO 0);
BEGIN
PROCESS(clk) BEGIN
IF (clk'EVENT AND clk='1') THEN
CASE s7segs is --style case when
WHEN "1000000" => s7segs <="1111001"; -- premiere transition
WHEN "1111001" => s7segs <="0100100"; -- deuxieme transition
WHEN "0100100" => s7segs <="0110000"; -- troisieme transition
WHEN "0110000" => s7segs <="0011001";
WHEN "0011001" => s7segs <="0010010";
WHEN "0010010" => s7segs <="0000010";
WHEN "0000010" => s7segs <="1111000";
WHEN "1111000" => s7segs <="0000000";
WHEN "0000000" => s7segs <="0010000";
WHEN "0010000" => s7segs <="1000000"; -- dernière transition
-- dans tous les autres cas on revient sur 8 ce qui utilise 42 LE contre 45 LE pour bouclage à 0 !!!!
WHEN OTHERS => s7segs <="0000000";
END CASE;
END IF;
END PROCESS;
s_7segs <=s7segs;
END arch;
-- 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;
Réaliser un compteur binaire ou décimal avec affichage sur digit(s) sept segments sera une opération classique dans la suite des TPs. Pourtant la technique que l'on utilisera ne sera pas celle qui est présentée ici. Elle sera en général composée de deux composants, un compteur et un transcodeur d'affichage. L'intérêt de cet exercice est donc purement pédagogique !