Lab 3 : Périphérique Liaison Série

Lab 3 : 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.