OpenCores
URL https://opencores.org/ocsvn/saturn/saturn/trunk

Subversion Repositories saturn

[/] [saturn/] [trunk/] [FPGA Concentrateur SIL4/] [fpga_cosil4/] [con_layer2_rx.vhd] - Rev 2

Compare with Previous | Blame | View Log

--============================================================================= 
--  TITRE : CON_LAYER2_RX
--  DESCRIPTION : 
--       Analyse les trames reçues sur le port rx coté concentrateur
--       Décapsule la partie Layer 2 et calcule le CRC
--       Note : les fanions ne sont pas envoyées au module suivant, le CRC oui
--       Le flux sortant est déstuffé
--       Limitation : Il faut au moins 1 pulse de clk_sys au niveau '0' entre 2 
--       pulses de clk_sys à 1 du validant de donnée entrante val_in
--       Le module distribue 2 flux:
--          - un flux à destination du PIC qui ne contient que les trames à 
--             destination du concentrateur et sans le TID du destinataire
--          - un flux à destination de la passerelle qui contient toutes les trames
--             du réseau précédées du TID du destinataire de la trame
--
--  FICHIER :        con_layer2_rx.vhd 
--=============================================================================
--  CREATION 
--  DATE	      AUTEUR	PROJET	REVISION 
--  10/04/2014	DRA	   SATURN	V1.0 
--=============================================================================
--  HISTORIQUE  DES  MODIFICATIONS :
--  DATE	      AUTEUR	PROJET	REVISION 
--=============================================================================
 
LIBRARY IEEE;
USE IEEE.STD_LOGIC_1164.ALL;
USE IEEE.STD_LOGIC_ARITH.ALL;
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
 
entity con_layer2_rx is
   GENERIC (
      nbbit_div : INTEGER := 10);         -- Nombre de bits pour coder le diviseur d'horloge 
   PORT (
      -- Ports système
      clk_sys  : IN  STD_LOGIC;                    -- Clock système
      rst_n    : IN  STD_LOGIC;                    -- Reset général système
      ad_con   : IN  STD_LOGIC_VECTOR(7 DOWNTO 0); -- Adresse logique du Concentrateur (TID)
 
      -- Interfaces ves le module SWITCH
      sw_ena   : OUT  STD_LOGIC;                   -- Indique qu'on est entre 2 trames (autorise le switch du tx)
      dat_in   : IN  STD_LOGIC_VECTOR(7 DOWNTO 0); -- Donnée parallélisée reçue sur port rx
      val_in   : IN  STD_LOGIC;                    -- validant du bus dat_in
      tc_divclk: IN  STD_LOGIC_VECTOR (nbbit_div-1 DOWNTO 0);  -- Diviseur d'horloge pour la durée d'un bit série
 
      -- Flux de données vers le PIC
      sof_pic     : OUT  STD_LOGIC;                   -- Indique au module suivant le début d'une trame en réception
      eof_pic     : OUT  STD_LOGIC;                   -- Indique au module suivant la fin d'une trame en réception
      l2_ok_pic   : OUT  STD_LOGIC;                   -- Indique que la trame reçue est correcte d'un point de vue layer 2
      dat_out_pic : OUT  STD_LOGIC_VECTOR(7 downto 0);-- Données de la couche applicative (épurée de la couche layer 2)
      val_out_pic : OUT  STD_LOGIC;                   -- Validant du bus dat_out
 
      -- Flux de données vers la passerelle
      sof_pas     : OUT  STD_LOGIC;                   -- Indique au module suivant le début d'une trame en réception
      eof_pas     : OUT  STD_LOGIC;                   -- Indique au module suivant la fin d'une trame en réception
      l2_ok_pas   : OUT  STD_LOGIC;                   -- Indique que la trame reçue est correcte d'un point de vue layer 2
      dat_out_pas : OUT  STD_LOGIC_VECTOR(7 downto 0);-- Données de la couche applicative (épurée de la couche layer 2)
      val_out_pas : OUT  STD_LOGIC                    -- Validant du bus dat_out
      );
end con_layer2_rx;
 
architecture  rtl of con_layer2_rx is
   -- Buffer prenant la valeur du flux de sortie
   SIGNAL dat_out_buf: STD_LOGIC_VECTOR(7 downto 0);
 
   -- Timer de réception entre 2 mots reçus. Le compteur doit pouvoir mesurer 16 bits. 
   -- La durée de 1 bit est codé sur nbbit_div
   SIGNAL cpt_timer: STD_LOGIC_VECTOR(nbbit_div+4-1 DOWNTO 0);  
   SIGNAL timeout  : STD_LOGIC;                     -- Indique que la timer s'est écoulé
 
   SIGNAL fanion_recu : STD_LOGIC;                  -- A 1 pour mémoriser qu'on a reçu un fanion
   SIGNAL rec_encours : STD_LOGIC;                  -- A 1 pour indiquer qu'une trame est en cours d'analyse          
   SIGNAL crc      : STD_LOGIC_VECTOR(15 downto 0); -- Valeur dynamique du crc
   SIGNAL val_crc  : STD_LOGIC;                     -- Pour mettre à jour le CRC avec un octet de plus
   SIGNAL init_crc : STD_LOGIC;                     -- Initialise le calcul du CRC
 
   SIGNAL cpt_byt  : STD_LOGIC_VECTOR(1 downto 0);  -- Pour compter les premiers octets reçus dans la trame
   SIGNAL adest_ok : STD_LOGIC;                     -- A 1 lorsque la trame s'adresse à ce MIO
   SIGNAL eof      : STD_LOGIC;                     -- Pour générer le signal de fin de trame
   SIGNAL l2_ok    : STD_LOGIC;                     -- Pour générer le signal de bonne trame
 
   -- Machine d'état de gestion du module
   TYPE layer2_rx_type IS (idle_st, rec_st, destuf_st, endnok_st, endok_st, newdat_st);
   SIGNAL fsm_layer2_rx       : layer2_rx_type;
 
   -- Module de calcul du CRC16
	COMPONENT crc16
   GENERIC (
      poly : STD_LOGIC_VECTOR(15 downto 0) := x"1021"
      );
	PORT(
		clk_sys  : IN std_logic;
		rst_n    : IN std_logic;
		data     : IN std_logic_vector(7 downto 0);
		val      : IN std_logic;
		init     : IN std_logic;          
		crc      : OUT std_logic_vector(15 downto 0)
		);
	END COMPONENT;
 
BEGIN
   --------------------------------------------
   -- Timer entre la réception de 2 mots consécutifs
   --------------------------------------------
   timer : PROCESS(clk_sys, rst_n)
   BEGIN
      IF (rst_n = '0') THEN
         cpt_timer <= (others => '0');
         timeout <= '0';
      ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
         IF (val_in = '1') THEN
         -- Pour chaque mot reçu
            cpt_timer <= (others => '0');    -- Le timer est réinitialisé
            timeout <= '0';
         ELSE
            cpt_timer <= cpt_timer + 1;
            IF (cpt_timer = (tc_divclk & "0000")) THEN
            -- Lorsque le compteur a mesuré un temps équivalent à 16 bits
               timeout <= '1';               -- On déclare un timeout
            END IF;
         END IF;
      END IF;
   END PROCESS;
 
   --------------------------------------------
   -- Machine d'état d'analyse du flux
   --------------------------------------------
   -- Le déclenchement du timeout annule la réception d'une trame 
   man_fsm : PROCESS(clk_sys, rst_n)
   BEGIN
      IF (rst_n = '0') THEN
         fsm_layer2_rx <= idle_st;
         init_crc <= '1';
         val_crc <= '0';
         val_out_pic <= '0';
         val_out_pas <= '0';
         cpt_byt <= "00";
         eof <= '0';
         sof_pic <= '0';           
         sof_pas <= '0';           
         l2_ok <= '0';
         adest_ok <= '0';
         rec_encours <= '0';
         fanion_recu <= '0';         
         dat_out_buf <= (others => '0');
      ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
         CASE fsm_layer2_rx IS
            WHEN idle_st =>
            -- Etat transitoire de remise à 0
               init_crc <= '1';
               val_crc <= '0';
               val_out_pic <= '0';
               val_out_pas <= '0';
               cpt_byt <= "00";
               eof <= '0';
               sof_pic <= '0';           
               sof_pas <= '0';           
               l2_ok <= '0';
               adest_ok <= '0';
               rec_encours <= '0';
               fanion_recu <= '0';
               fsm_layer2_rx <= rec_st;
 
            WHEN rec_st =>
            -- Etat d'attente des caractères
               val_out_pic <= '0';
               val_out_pas <= '0';
               sof_pic <= '0';           
               sof_pas <= '0';           
               val_crc <= '0';
               init_crc <= '0';
               IF (val_in = '1') THEN
               -- Sur chaque donnée reçue
                  IF (dat_in = x"7E") THEN
                  -- Si on reçoit un fanion
                     fanion_recu <= '1';           -- On mémorisele fait qu'on en a déjà reçu 1
                     IF (rec_encours = '1') THEN
                     -- Si on reçoit un fanion et qu'on a déjà reçu 1 octet, alors c'est le fanion de fin de trame
                        IF (crc(15 downto 0) = x"470F") THEN
                        -- Si le crc est égal au magic number, on valide la trame
                           fsm_layer2_rx <= endok_st;
                        ELSE
                        -- Sinon on annule la trame
                           fsm_layer2_rx <= endnok_st;
                        END IF;
                     -- Tant qu'on a reçu aucun octet, on ne traite que les fanions
                     END IF;
                  ELSIF (fanion_recu = '1') THEN
                  -- Si on reçoit un acaratère autre qu'un fanion et qu'on a déjà reçu un fanion auparavant
                     rec_encours <= '1';           -- On commence la réception d'une trame
                     IF (dat_in = x"7D") THEN
                     -- Si c'est un mot de bourage, on va attendre le mot suivant
                        fsm_layer2_rx <= destuf_st;
                     ELSE
                     -- Si c'est une donnée normale, on la traite
                        dat_out_buf <= dat_in;     -- On mémorise la donnée à traiter pour l'état suivant
                        fsm_layer2_rx <= newdat_st;
                     END IF;
                  END IF;
               ELSIF (timeout = '1') THEN
               -- Si on a une condition de timeout
                  IF (rec_encours = '1') THEN
                  -- Si on recevait une trame, on l'annule
                     fsm_layer2_rx <= endnok_st;
                  ELSIF (fanion_recu = '1') THEN
                  -- Si on a juste reçue des fanions, on remet tout à 0
                     fsm_layer2_rx <= idle_st;
                  END IF;
               END IF;
 
            WHEN newdat_st =>
            -- Etat de traitement d'un nouveau caractère reçu (hors Fanion)
               IF (timeout = '1') THEN
               -- Si le timeout arrive ici
                  fsm_layer2_rx <= endnok_st;  -- On annule la trame
               ELSE
                  fsm_layer2_rx <= rec_st;     -- Sinon on va attendre le mot suivant
                  val_crc <= '1';              -- La valeur reçues doit être prise en comtpe dans le CRC
                  val_out_pas <= '1';          -- Coté passerelle on ne fait pas de filtrage on envoie tout au module suivant
                  val_out_pic <= adest_ok;     -- Coté PIC on envoie que ce qui est à destination et on envoie pas le TID 
 
                  IF (cpt_byt = "00") THEN    
                     sof_pas <= '1';           -- Le premier octet indique également le début de trame au module suivant coté passerelle
                     IF ((dat_out_buf = ad_con) OR (dat_out_buf = x"F0") OR (dat_out_buf = x"FF")) THEN
                     -- Le Concentrateur peut être adressé directement (ad_con) ou bien en multicast (F0h ou FFh)
                        adest_ok <= '1';
                     ELSE
                        adest_ok <=  '0';
                     END IF;
                  END IF;
                  IF (cpt_byt = "01") THEN    
                     sof_pic <= adest_ok;      -- Le 2ème octet indique le début de trame au module suivant coté PIC
                  END IF;
                  IF (cpt_byt /= "10") THEN
                  -- On ne compte que les 2 premiers octets
                     cpt_byt <= cpt_byt + 1;
                  END IF;
               END IF;
 
            WHEN destuf_st =>
            -- Etat de gestion du destuffing. On a reçu un caratère 7Dh
               IF (timeout = '1') THEN
                  fsm_layer2_rx <= endnok_st;
               ELSE
                  IF (val_in = '1') THEN
                  -- On attend le caractère suivant et suivant le cas de stuffing on fourni la bonne donnée
                     IF (dat_in = x"5E") THEN
                        dat_out_buf <= x"7E";
                        fsm_layer2_rx <= newdat_st;
                     ELSIF (dat_in = x"5D") THEN
                        dat_out_buf <= x"7D";
                        fsm_layer2_rx <= newdat_st;
                     ELSE
                        fsm_layer2_rx <= endnok_st;
                     END IF;
                  END IF;
               END IF;
 
            WHEN endnok_st =>
            -- Cas de réception d'une mauvaise trame
               eof <= '1';          -- On indique la fin de réception au module suivant pour que l'information trame erronée soit
                                    -- reportée pour comptage
               l2_ok <= '0';        -- On indique qu'il y'a eu un problème
               rec_encours <= '0';  -- On est plus en réception de trame
               fanion_recu <= '0';
               fsm_layer2_rx <= idle_st;
 
            WHEN endok_st =>
            -- Cas de réception d'une bonne trame
               eof <= '1';          -- On indique la fin de réception car l'information bonne trame est
                                    -- utilisée pour vérouiller l'autobaudrate
               l2_ok <= '1';        -- On indique que la trame est bonne
               rec_encours <= '0';  -- On est plus en réception de trame
               fanion_recu <= '0';
               fsm_layer2_rx <= idle_st;
 
            WHEN OTHERS =>
               fsm_layer2_rx <= idle_st;
         END CASE;
      END IF;
   END PROCESS;
   dat_out_pic <= dat_out_buf;         -- Flux de données déstuffé vers le PIC
   eof_pic     <= eof;                 -- Find e trame PIC
   l2_ok_pic   <= l2_ok;               -- Bonne trmae PIC
   dat_out_pas <= dat_out_buf;         -- Flux de données déstuffé vers la passerelle
   eof_pas     <= eof;                 -- Find e trame Passerelle
   l2_ok_pas   <= l2_ok;               -- Bonne trmae Passerelle
   sw_ena <=  NOT(rec_encours OR fanion_recu);   -- Le switch est autorisé entre 2 trames (i.e. lorsqu'une réception n'est pas en cours)
 
   --------------------------------------------
   -- Calcul du crc16
   --------------------------------------------
	inst_crc16: crc16
   GENERIC MAP (
      poly => x"1021"   -- CCITT16
      )
   PORT MAP(
		clk_sys => clk_sys,
		rst_n => rst_n,
		data => dat_out_buf,
		val => val_crc,
		init => init_crc,
		crc => crc
	);
 
end rtl;
 
 

Compare with Previous | Blame | View Log

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.