Cours:TP M1102 TP 6 Corr : Différence entre versions
m (→Exercice 2) |
m |
||
(13 révisions intermédiaires par le même utilisateur non affichées) | |||
Ligne 1 : | Ligne 1 : | ||
− | |||
=TP6= | =TP6= | ||
==Exercice 1 : le réveil== | ==Exercice 1 : le réveil== | ||
Ligne 122 : | Ligne 121 : | ||
Voici le programme corrigé : | Voici le programme corrigé : | ||
<source lang=vhdl> | <source lang=vhdl> | ||
− | -- Vérifié OK le | + | -- Vérifié OK le 30/09/20 |
library IEEE; | library IEEE; | ||
use IEEE.STD_LOGIC_1164.ALL; | use IEEE.STD_LOGIC_1164.ALL; | ||
Ligne 303 : | Ligne 302 : | ||
<source lang=VHDL> | <source lang=VHDL> | ||
− | -- testé 0K le | + | -- testé 0K le 30/09/20 |
library IEEE; | library IEEE; | ||
use IEEE.STD_LOGIC_1164.ALL; | use IEEE.STD_LOGIC_1164.ALL; | ||
Ligne 513 : | Ligne 512 : | ||
==Exercice 5== | ==Exercice 5== | ||
===Question 1=== | ===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== | ||
+ | ===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
Sommaire
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.