Périphérique Liaison Série

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 :

serial.vhd

Seuls le registre sérialisateur et le séquenceur sont à compléter.


uart.svg

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.

capture_serial.png


transcript de test

Decodeur

decodeur.svg

library IEEE;
use IEEE.std_logic_1164.all;

entity decodeur is
port(	E  :		in 	std_logic_vector(1 downto 0);
	S0,S1,S2 : 	out 	std_logic);
end decodeur;

architecture arch_decodeur of decodeur is
begin
	S0<='1' when E="00" else '0';
	S1<='1' when E="01" else '0';
	S2<='1' when E="10" else '0';
end arch_decodeur;

Détecteur de Parité

detecteur_parite.svg

library IEEE;
use IEEE.std_logic_1164.all;

entity detecteur_parite is
port(	E : in std_logic_vector( 7 downto 0);
	par : out std_logic);
end detecteur_parite;

architecture arch_detecteur_parite of detecteur_parite is
begin

par <= E(0) xor E(1) xor E(2) xor E(3) xor E(4) xor E(5) xor E(6) xor E(7);

end arch_detecteur_parite;

Compteur

compteur.svg

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity compteur is
port( 	clk,raz,ce		:	in  std_logic;
	count 			: 	out std_logic_vector(3 downto 0));
end compteur;

architecture arch_compteur of compteur is
signal count_int : unsigned (3 downto 0);
begin
process(clk)
	begin	
	if rising_edge(clk) then
		if raz='1' then count_int <= (others => '0');
		elsif ce='1' then			
			if count_int="1111" then count_int <= (others => '0'); -- fin de comptage
			else count_int <= count_int + 1; -- "+"(unsigned,int)
			end if;
		end if;
	end if;
end process;

count <= std_logic_vector(count_int); -- count copie de count_int

end arch_compteur;

Registre Tampon

registre_tampon.svg

library IEEE;
use IEEE.std_logic_1164.all;

entity registre_tampon is
port( 	clk,reset,load	:	in std_logic;
	d_in 		: 	in std_logic_vector(7 downto 0);
	d_out 		: 	out std_logic_vector(7 downto 0));
end registre_tampon;

architecture arch_registre_tampon of registre_tampon is
begin
	process(clk,reset)
		begin
		if reset='1' then d_out <= (others => '0');
		elsif rising_edge(clk) then 
			if load='1' then d_out <= d_in;
			end if;
		end if;
	end process;
end arch_registre_tampon;

Registre de Contrôle

registre_ctl.svg

library IEEE;
use IEEE.std_logic_1164.all;

entity registre_ctl is
port( 	clk,raz,load	:	in std_logic;
	d_in 		: 	in std_logic_vector(7 downto 0);
	d_out 		: 	out std_logic);
end registre_ctl;

architecture arch_registre_ctl of registre_ctl is
begin
	process(clk)
		begin
		if rising_edge(clk) then 
			if raz='1' then d_out <= '0';
			elsif load='1' then d_out <= d_in(0);
			end if;
		end if;
	end process;
end arch_registre_ctl;

Registre d’état

registre_etat.svg

library IEEE;
use IEEE.std_logic_1164.all;

entity registre_etat is
port( 	clk,raz,set	:	in std_logic;
	d_out 		: 	out std_logic_vector(7 downto 0));
end registre_etat;

architecture arch_registre_etat of registre_etat is

begin
	process(clk)
		begin
		
		if rising_edge(clk) then 
			if raz='1' then d_out <= (others => '0');
			elsif set='1' then d_out(0) <= '1'; d_out(7 downto 1) <= (others => '0');
			end if;
		end if;
	end process;

end arch_registre_etat;

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

registre_serialisateur.svg

library IEEE;
use IEEE.std_logic_1164.all;
use IEEE.numeric_std.all;

entity reg_serialisateur is
port( raz, clk, load, rotate : in std_logic;
	d_in : in std_logic_vector(8 downto 0);
	TX : out std_logic);
end reg_serialisateur;

architecture arch_reg_serialisateur of reg_serialisateur is

--************************************
--	A COMPLETER	
--************************************

begin

--************************************
--	A COMPLETER	
--************************************

end arch_reg_serialisateur;

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.

sequenceur.svg

library IEEE;
use IEEE.std_logic_1164.all;

entity sequenceur_serial is
port( clk, reset, start,  ld_t: in std_logic;
	comptage : in std_logic_vector (3 downto 0);
	set_st, raz_st, raz_ctl,  raz_ser, ld_ser, ser, raz_count, ce : out std_logic);
end sequenceur_serial;

architecture arch_sequenceur_serial of sequenceur_serial is

--************************************
--	A COMPLETER	
--************************************

begin

--************************************
--	A COMPLETER	
--************************************

end arch_sequenceur_serial;

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;