Périphérique Liaison Série
L’objectif de cet exercice est de décrire en partie un périphérique liaison série simplifié de type UART.
On considère les hypothèses simplificatrices suivantes :
- Le Débit sur la ligne correspond à l’horloge du périphérique
- On considère uniquement l’envoi des données (et pas la réception)
Un Décodeur permet, à partir de l’adresse figurant sur le bus d’adresses, de sélectionner un registre afin de charger une donnée
présente sur le bus de données ou de forcer la valeur de ce bus.
Les registres accessibles par l’utilisateur (le microcprocesseurs) sont :
- Le registre tampon : Permet de stocker une donnée en vue de la transmettre
- Le registre de Contrôle : Le bit de poids faible est le bit start : La donnée présente dans le registre tampon doit être sérialisée
- Le registre d’état : Permet d’indiquer au microprocesseur que le registre tampon contient une donnée qui n’a pas encore été envoyée.
Le bit de parité est fourni par le détecteur de parité (1 pour un nombre impair de 1 dans la donnée à envoyer).
Fichier Source :
Seuls le registre sérialisateur et le séquenceur sont à compléter.
COMMENT TESTER ?
- L’utilisateur de la liaison série est le processeur.
- C’est ce dernier qui doit écrire dans les registres ou lire le contenu de registres afin d’envoyer une donnée sur la liaison série.
- La sélections de ces registres se fait en envoyant une adresse sur le bus d’adresses.
Rappelons une procédure classique pour écrire une donnée sur une liaison série :
- Consultation du registre d’état : Tant que le registre tampon n’est pas libre, attente.
- Si le registre Tampon est libre, on peut écrire dedans.
- Sélection du registre contrôle pour donner ordre de sérialiser.
transcript de test
Decodeur
|
|
|
Détecteur de Parité
|
|
|
Compteur
|
|
|
Registre Tampon
|
|
|
Registre de Contrôle
|
|
|
Registre d’état
|
|
|
Registre Sérialisateur
Ce composant synchrone revient à gérer un signal interne de 11 bits (Parite / Donnée / 0 / 1)
La Sortie TX correspond au bit de poids faible de ce registre (1 à l’état de repos)
L’affectation de TX doit se faire en parallèle du process pour que TX corresponde à une copie de ce bit de poids faible.
Le chargement de la donnée et du bits de parité a lieu lorsque load=‘1’.
Tant que rotate=‘1’, on doit observer une rotation des bits du registre de telle sorte que chaque bit défile par la cas 0 (correspondant à TX).
La rotation peut se faire par une boucle for, ou plus simplement avec la fonction rotate_right disponible dans numeric_std
|
|
|
Séquenceur
Proposer un diagramme d’états, et la description VHDL correspondante pour le fonctionnement suivant :
- Initialement, le compteur doit être remis à zéro
- Si un chargement du tampon est demandé, le registre d’état doit être forcé à 1
- Si un Start est demandé :
- la donnée présente dans le tampon doit être copiée dans le registre sérialisateur
- Le Registre d’Etat doit être remis à zéro
- Les données doivent être sérialisée sur TX
Proposer un nouveau diagramme d’états permettant de prendre en compte le chargement d’une donnée dans le tampon alors qu’une sérialisation est en cours.
|
|
|
Sérialisateur et mu0
Relier le sérialisateur au processeur mu0 (lab2) ( an ajoutant au passage un décodeur pour le bus d’adresse ) ; modifier le programme dans la mémoire de mu0 pour montrer le bon fonctionnement de l’ensemble.
Eléments de Correction
serialisateur.vhd
--**********************************************************************************************
-- DESCRIPTION DU REGISTRE TAMPON
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity reg_tampon is
port( d_in:in std_logic_vector(7 downto 0);
clk: in std_logic;
loadt: in std_logic;
tampon:out std_logic_vector(7 downto 0));
end reg_tampon;
architecture arch_tampon of reg_tampon is
begin
process(clk)
begin
if (rising_edge(clk)) then
if (loadt='1') then tampon<=d_in;
end if;
end if;
end process;
end arch_tampon;
--**********************************************************************************************
-- DESCRIPTION DU REGISTRE D'ETAT
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity registre_etat is
port ( s, r, clk: in std_logic;
st: out std_logic);
end registre_etat;
architecture arch_registre_etat of registre_etat is
begin
process(clk)
begin
if (rising_edge(clk))
then if (s='1') then st<='1';
elsif (r='1') then st<='0';
end if;
end if;
end process;
end arch_registre_etat;
--**********************************************************************************************
-- DESCRIPTION DU DETECTEUR DE PARITE
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity detecteur is
port (tampon : in std_logic_vector(7 downto 0);
par: out std_logic);
end detecteur;
architecture arch_detecteur of detecteur is
begin
process(tampon)
variable loopxor : std_logic;
begin
loopxor := '0';
for i in 0 to 7 loop
loopxor := loopxor xor tampon(i);
end loop;
par<=loopxor;
end process;
end arch_detecteur;
--**********************************************************************************************
-- DESCRIPTION DU REGISTRE A DECALLAGE
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity registre_decalage is
port( reset, par, clk, decal, loadd : in std_logic;
tampon : in std_logic_vector(7 downto 0);
ligne : out std_logic);
end registre_decalage;
architecture arch_decal of registre_decalage is
signal interne : std_logic_vector(10 downto 0);
begin
process(clk, reset)
begin
if reset='1' then
interne <= "11111111111";
elsif (rising_edge(clk)) then
if (loadd='1') then
interne(10)<=par;
interne(9 downto 2) <= tampon;
interne(1)<='0';
interne(0)<='1';
elsif (decal='1') then
interne <= std_logic_vector(rotate_right(unsigned(interne),1));
end if;
end if;
end process ;
ligne <= interne(0);
end arch_decal;
--**********************************************************************************************
-- DESCRIPTION DE L'UNITE DE CONTROLE
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity compteur_seq is
port(
raz_count , clk, count_enable : in std_logic;
compt_10 : out std_logic
);
end compteur_seq;
architecture arch_compteur_seq of compteur_seq is
signal compteur : integer range 0 to 11;
begin
process(clk)
begin
if raz_count='0' then
if rising_edge(clk) then
if count_enable = '1' then
if compteur =11 then compteur <= 0; else compteur <= compteur+1; end if;
end if;
end if;
else compteur <= 0;
end if;
end process;
compt_10 <= '1' when compteur=11 else '0';
end arch_compteur_seq;
--**********************************************************************************************
-- DESCRIPTION DE L'UNITE DE CONTROLE
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
entity unite_controle is
port( clk, reset, dval, st, compt_10 : in std_logic;
s,r,loadt, decal, loadd, raz_compteur, ce_compteur : out std_logic);
end unite_controle;
architecture arch_controle of unite_controle is
type etat_correlateur is (repos, chargement, done, serial);
signal etat_cr, etat_sv : etat_correlateur;
begin
etat_cr <= repos when reset ='1' else
etat_sv when rising_edge(clk) else
etat_cr;
process(etat_cr,dval, st, compt_10)
begin
s<= '0';
r<= '0';
loadt<= '0';
decal<= '0';
loadd<= '0';
raz_compteur <= '0';
ce_compteur <= '0';
etat_sv <=etat_cr ;
case etat_cr is
when repos =>if dval='1' then etat_sv<=chargement; else etat_sv<=repos; end if;
raz_compteur <= '1';
when chargement =>if st='1' then etat_sv<=done; else etat_sv <= chargement; end if;
loadt <= '1' ;
s <= '1';
when done =>etat_sv<=serial;
loadd <= '1';
r <= '1';
when serial =>if compt_10='1' then etat_sv<=repos; else etat_sv<=serial; end if;
decal <= '1';
ce_compteur <= '1';
end case;
end process;
end arch_controle;
--**********************************************************************************************
--**********************************************************************************************
--
-- DESCRIPTION DU SERIALISATEUR
--
--**********************************************************************************************
--**********************************************************************************************
library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;
use work.all;
entity serialisateur is
port(d_in : std_logic_vector(7 downto 0);
dval, clk, reset : in std_logic;
ligne : out std_logic);
end serialisateur;
architecture arch_serialisateur of serialisateur is
signal tampon : std_logic_vector(7 downto 0);
signal s, r, st, loadt, decal, loadd, par, compt_10, raz_compteur, ce_compteur : std_logic;
begin
tamp : entity reg_tampon port map(
d_in => d_in,
clk => clk,
loadt => loadt,
tampon => tampon );
uc : entity unite_controle port map(
clk => clk,
reset => reset,
dval => dval,
st => st,
compt_10 => compt_10,
s => s,
r => r,
loadt => loadt,
decal => decal,
loadd => loadd,
raz_compteur => raz_compteur,
ce_compteur => ce_compteur);
compt_seq : entity compteur_seq port map(
raz_count => raz_compteur,
clk => clk,
count_enable => ce_compteur,
compt_10 => compt_10);
reg_dec : entity registre_decalage port map(
reset => reset,
par => par,
clk => clk,
decal => decal,
loadd => loadd,
tampon => tampon,
ligne => ligne);
det : entity detecteur port map (
tampon => tampon,
par => par);
reg_etat : entity registre_etat port map (
s => s,
r => r,
clk => clk,
st => st);
end arch_serialisateur;