1 |
2 |
DavidRAMBA |
--=============================================================================
|
2 |
|
|
-- TITRE : COM_EXEC
|
3 |
|
|
-- DESCRIPTION :
|
4 |
|
|
-- Exécute les actions codées dans la trame applicative
|
5 |
|
|
-- Gère des registres Internes (zone d'adresse de 0 à 7F)
|
6 |
|
|
-- Gère les écritures et lectures des registres externes
|
7 |
|
|
-- (zone d'adresse de 80 à FF)
|
8 |
|
|
|
9 |
|
|
-- FICHIER : com_exec.vhd
|
10 |
|
|
--=============================================================================
|
11 |
|
|
-- CREATION
|
12 |
|
|
-- DATE AUTEUR PROJET REVISION
|
13 |
|
|
-- 10/04/2014 DRA SATURN V1.0
|
14 |
|
|
--=============================================================================
|
15 |
|
|
-- HISTORIQUE DES MODIFICATIONS :
|
16 |
|
|
-- DATE AUTEUR PROJET REVISION
|
17 |
|
|
--=============================================================================
|
18 |
|
|
|
19 |
|
|
LIBRARY IEEE;
|
20 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
21 |
|
|
USE IEEE.STD_LOGIC_ARITH.ALL;
|
22 |
|
|
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
|
23 |
|
|
|
24 |
|
|
ENTITY com_exec IS
|
25 |
|
|
GENERIC (
|
26 |
|
|
freq_clksys : INTEGER := 48; -- Fréquence de l'horloge système en MHz
|
27 |
|
|
reg_typemio : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"10"; -- Type du MIO
|
28 |
|
|
reg_version : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"10"; -- Version du MIO
|
29 |
|
|
ad_ref : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"80"; -- Adresse des registre à transmettre sur synchro
|
30 |
|
|
sz_ref : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"04" -- Nombre d'octets à transmetrte sur synchro
|
31 |
|
|
);
|
32 |
|
|
PORT (
|
33 |
|
|
-- Ports système
|
34 |
|
|
clk_sys : IN STD_LOGIC; -- Clock système
|
35 |
|
|
rst_n : IN STD_LOGIC; -- Reset général système
|
36 |
|
|
tid : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Adresse affectée au MIO (8F au reset)
|
37 |
|
|
iid : IN STD_LOGIC_VECTOR(63 downto 0);-- Adresse IID du composant
|
38 |
|
|
sync_lock : OUT STD_LOGIC; -- Indique qu'on est calé sur une synchro
|
39 |
|
|
|
40 |
|
|
-- Interfaces vers le bloc métier
|
41 |
|
|
datout_write: OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données à écrire sur l'interface externe
|
42 |
|
|
datout_read : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données lues sur l'interface externe
|
43 |
|
|
ad_out : OUT STD_LOGIC_VECTOR(6 DOWNTO 0); -- Adresse d'écriture et de lecture des données externes
|
44 |
|
|
wr_out : OUT STD_LOGIC; -- Signal d'écriture sur l'interface externe
|
45 |
|
|
rd_out : OUT STD_LOGIC; -- Signal de lecture sur l'interface externe
|
46 |
|
|
|
47 |
|
|
-- Interfaces vers les modules layer2_rx
|
48 |
|
|
activity1 : IN STD_LOGIC; -- 1 pulse indique qu'il y'a de l'activité sur le port de com 1
|
49 |
|
|
activity2 : IN STD_LOGIC; -- 1 pulse indique qu'il y'a de l'activité sur le port de com 2
|
50 |
|
|
|
51 |
|
|
-- Interfaces vers le module frame_store1
|
52 |
|
|
datin1 : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données utiles de la couche applicative (commande, @, data)
|
53 |
|
|
socin1 : IN STD_LOGIC; -- Indique que l'octet sur datin1 est le 1er d'une commande
|
54 |
|
|
rd_datin1 : OUT STD_LOGIC; -- Signal de lecture d'un nouvel octet applicatif
|
55 |
|
|
new_frame1 : IN STD_LOGIC; -- 1 Pulse indique qu'une nouvelle trame est disponible
|
56 |
|
|
l7_ok1 : IN STD_LOGIC; -- 1 Pulse indique que la nouvelle trame est conforme du point de vue layer 7
|
57 |
|
|
l7_overflow1: IN STD_LOGIC; -- Indique un débordement de la mémoire de frame_store
|
58 |
|
|
com_dispo1 : IN STD_LOGIC; -- A 1 tant qu'il y'a des données de commande à traiter dans la DPRAM
|
59 |
|
|
|
60 |
|
|
-- Interfaces vers le module frame_store2
|
61 |
|
|
datin2 : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données utiles de la couche applicative (commande, @, data)
|
62 |
|
|
socin2 : IN STD_LOGIC; -- Indique que l'octet sur datin2 est le 1er d'une commande
|
63 |
|
|
rd_datin2 : OUT STD_LOGIC; -- Signal de lecture d'un nouvel octet applicatif
|
64 |
|
|
new_frame2 : IN STD_LOGIC; -- 1 Pulse indique qu'une nouvelle trame est disponible
|
65 |
|
|
l7_ok2 : IN STD_LOGIC; -- 1 Pulse indique que la nouvelle trame est conforme du point de vue layer 7
|
66 |
|
|
l7_overflow2: IN STD_LOGIC; -- Indique un débordement de la mémoire de frame_store
|
67 |
|
|
com_dispo2 : IN STD_LOGIC; -- A 1 tant qu'il y'a des données de commande à traiter dans la DPRAM
|
68 |
|
|
|
69 |
|
|
-- Interfaces ver le module layer2_tx
|
70 |
|
|
datsent : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Flux de données applicatives à émettre
|
71 |
|
|
-- La première donnée du flux qui suit le sof est l'@ de destination
|
72 |
|
|
valsent : OUT STD_LOGIC; -- validant du bus datsent
|
73 |
|
|
sof : OUT STD_LOGIC; -- Indique le début d'une trame à émettre
|
74 |
|
|
eof : OUT STD_LOGIC; -- Indique le dernier octet de la trame à émettre
|
75 |
|
|
datsent_free: IN STD_LOGIC; -- Indique que le module layer2_tx a pris en compte l'octet datsent
|
76 |
|
|
clr_fifo_tx : OUT STD_LOGIC; -- Signal de purge de la FIFO Tx
|
77 |
|
|
|
78 |
|
|
-- Interface vers les modules switch
|
79 |
|
|
copy_ena1 : OUT STD_LOGIC; -- Autorise la copie de Rx1 sur Tx2
|
80 |
|
|
copy_ena2 : OUT STD_LOGIC; -- Autorise la copie de Rx2 sur Tx1
|
81 |
|
|
|
82 |
|
|
-- Interface de pilotage du module SPI
|
83 |
|
|
reload_fpgan: OUT STD_LOGIC; -- Ordre de reconfiguration du FPGA
|
84 |
|
|
spitx_dat : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data + commande à sérialiser
|
85 |
|
|
spitx_val : OUT STD_LOGIC; -- Validant de spitx_dat
|
86 |
|
|
spirx_dat : IN STD_LOGIC_VECTOR(7 DOWNTO 0); -- Data reçue
|
87 |
|
|
spirx_val : IN STD_LOGIC; -- Indique des données dispo dans spirx_val
|
88 |
|
|
spirx_next : OUT STD_LOGIC; -- Lit un octet de plus dans spirx_val
|
89 |
|
|
spi_typecom : OUT STD_LOGIC; -- Type de commande à éxécuter
|
90 |
|
|
spi_execcom : OUT STD_LOGIC; -- Ordre d'exécution d'une commande
|
91 |
|
|
spi_busy : IN STD_LOGIC; -- Indique que le module SPI est occupé
|
92 |
|
|
spi_nbread : OUT STD_LOGIC_VECTOR(7 DOWNTO 0); -- Nombre d 'octets à lire avec une commande de lecture
|
93 |
|
|
spi_rstn : OUT STD_LOGIC -- Reset du module SPI
|
94 |
|
|
);
|
95 |
|
|
END com_exec;
|
96 |
|
|
|
97 |
|
|
ARCHITECTURE rtl OF com_exec IS
|
98 |
|
|
CONSTANT typ_sync : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"00"; -- Type pour trame de synchronisation
|
99 |
|
|
CONSTANT typ_reqnoseq : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"08"; -- Type pour trame de requête non sécuritaire
|
100 |
|
|
CONSTANT typ_repnoseq : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"80"; -- Type pour trame de réponse non sécuritaire
|
101 |
|
|
CONSTANT typ_atttid : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"3C"; -- Type pour trame d'attribution de TID
|
102 |
|
|
CONSTANT com_write : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"01"; -- Commande d'écriture dans une requête non sec
|
103 |
|
|
CONSTANT com_read : STD_LOGIC_VECTOR(7 DOWNTO 0) := x"02"; -- Commande de lecture dans une requête non sec
|
104 |
|
|
|
105 |
|
|
|
106 |
|
|
-- Définition des adresses des registres internes
|
107 |
|
|
CONSTANT adreg_mac : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(0, 7);
|
108 |
|
|
CONSTANT adreg_iid : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(8, 7);
|
109 |
|
|
CONSTANT adreg_typ : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(16, 7);
|
110 |
|
|
CONSTANT adreg_ver : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(17, 7);
|
111 |
|
|
CONSTANT adreg_verpic: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(18, 7);
|
112 |
|
|
CONSTANT adreg_tid : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(19, 7);
|
113 |
|
|
CONSTANT adreg_sid : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(20, 7);
|
114 |
|
|
-- CONSTANT adreg_outrep: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(23, 7);
|
115 |
|
|
CONSTANT adreg_tcyc : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(24, 7);
|
116 |
|
|
CONSTANT adreg_status: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(25, 7);
|
117 |
|
|
--CONSTANT adreg_cnfrep: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(26, 7);
|
118 |
|
|
--CONSTANT adreg_cnfcyc: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(27, 7);
|
119 |
|
|
CONSTANT adreg_adref : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(28, 7);
|
120 |
|
|
CONSTANT adreg_szref : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(29, 7);
|
121 |
|
|
CONSTANT adreg_toco1 : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(30, 7);
|
122 |
|
|
CONSTANT adreg_toco2 : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(31, 7);
|
123 |
|
|
--CONSTANT adreg_seq : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(32, 7);
|
124 |
|
|
CONSTANT adreg_toac1 : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(33, 7);
|
125 |
|
|
CONSTANT adreg_toac2 : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(34, 7);
|
126 |
|
|
CONSTANT adreg_sync : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(35, 7);
|
127 |
|
|
CONSTANT adreg_for : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(36, 7);
|
128 |
|
|
CONSTANT adreg_conf : STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(37, 7);
|
129 |
|
|
CONSTANT adreg_loadfpga: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(124, 7);
|
130 |
|
|
CONSTANT adreg_spinbr: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(125, 7);
|
131 |
|
|
CONSTANT adreg_spictl: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(126, 7);
|
132 |
|
|
CONSTANT adreg_spidat: STD_LOGIC_VECTOR(6 DOWNTO 0) := CONV_STD_LOGIC_VECTOR(127, 7);
|
133 |
|
|
|
134 |
|
|
-- Définition des registres internes
|
135 |
|
|
SIGNAL reg_tid : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
136 |
|
|
SIGNAL reg_config : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
137 |
|
|
SIGNAL reg_status : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
138 |
|
|
SIGNAL reg_adref : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
139 |
|
|
SIGNAL reg_szref : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
140 |
|
|
SIGNAL reg_cpttoco1 : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
141 |
|
|
SIGNAL reg_cpttoco2 : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
142 |
|
|
SIGNAL reg_cpttoac1 : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
143 |
|
|
SIGNAL reg_cpttoac2 : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
144 |
|
|
SIGNAL reg_cptsync : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
145 |
|
|
SIGNAL reg_cptfor : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
146 |
|
|
SIGNAL reg_tcyc : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
147 |
|
|
SIGNAL reg_spinbr : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
148 |
|
|
SIGNAL reg_spictl : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
149 |
|
|
SIGNAL reg_loadfpga : STD_LOGIC_VECTOR(7 DOWNTO 0);
|
150 |
|
|
|
151 |
|
|
-- Signaux de gestion du cycle
|
152 |
|
|
SIGNAL synchro : STD_LOGIC; -- 1 Pulse sur réception d'1 trame de synchro valide
|
153 |
|
|
SIGNAL start_cycle : STD_LOGIC; -- 1 Pulse indique le début d'un cycle (sur synhcro ou timer interne)
|
154 |
|
|
SIGNAL tc_tcyc : STD_LOGIC_VECTOR(15 DOWNTO 0); -- Pour calculer reg_tcyc * 100
|
155 |
|
|
SIGNAL mescycle : STD_LOGIC_VECTOR(16 DOWNTO 0); -- compteur de mesure de périodes de 10us
|
156 |
|
|
SIGNAL mes10us : STD_LOGIC_vector(10 DOWNTO 0); -- Compteur de période de clk_sys pour mesurer 10us
|
157 |
|
|
SIGNAL synchro_lock : STD_LOGIC; -- A 0 tant qu'on a pas reçu une première synchro
|
158 |
|
|
SIGNAL win_syncbefore: STD_LOGIC; -- Signal de validité d'une syncro en avance (dernier quart d'un cycle de com)
|
159 |
|
|
SIGNAL win_syncafter : STD_LOGIC; -- Signal de validité d'une synchro en retard (premier quart d'un cycle de com)
|
160 |
|
|
SIGNAL synchro_miss : STD_LOGIC; -- 1 Pulse à 1 indique qu'on a pas reçu de trame de synhcro sur une durée de 1.125xTcyc
|
161 |
|
|
SIGNAL cpt_seq : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Compteur de numéro de cycle de communication en cours
|
162 |
|
|
SIGNAL mem_sync : STD_LOGIC; -- Pour mémoriser le fait que le start_cycle est issue d'une trame de synchro
|
163 |
|
|
|
164 |
|
|
-- Signaux de gestion des monitoring
|
165 |
|
|
SIGNAL mem_activity1 : STD_LOGIC; -- Pour mémoriser une activité sur le port 1 entre 2 synchros
|
166 |
|
|
SIGNAL mem_activity2 : STD_LOGIC; -- Pour mémoriser une activité sur le port 2entre 2 synchros
|
167 |
|
|
SIGNAL err_toco : STD_LOGIC; -- 1 Pulse indique une trame réçue sur un port mais pas sur l'autre
|
168 |
|
|
SIGNAL voie_toco : STD_LOGIC; -- 0 pour err_toco sur le port 1, 1 pour err_toco sur le port 2
|
169 |
|
|
|
170 |
|
|
-- Signaux d'interprétation et d'exécution des commandes
|
171 |
|
|
SIGNAL datin : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Données applicatives à traiter (voie 1 ou 2 multiplexée)
|
172 |
|
|
SIGNAL rd_com : STD_LOGIC; -- Ordre de fetch d'un nouvel octet de donnée applicative
|
173 |
|
|
SIGNAL com_dispo : STD_LOGIC; -- Multiplexage de com_dispo 1 ou 2 selon la voie
|
174 |
|
|
SIGNAL rd_combuf : STD_LOGIC; -- Buffer provisoire pour multiplexer rd_com
|
175 |
|
|
SIGNAL sel_voie : STD_LOGIC; -- A 0 si on traite la voie 1, a 1 si on traite la voie 2
|
176 |
|
|
SIGNAL typ_field : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Pour mémoriser le type de trame
|
177 |
|
|
SIGNAL seq_field : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Pour mémoriser le champ SEQ de la trmae de synhcro
|
178 |
|
|
SIGNAL com_field : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Pour mémoriser le champ COM d'une trame de requête non secu
|
179 |
|
|
--SIGNAL ad_source : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Pour mémoriser l'adresse de l'expéditeur de la commande
|
180 |
|
|
SIGNAL oldcom1 : STD_LOGIC_vector(9 DOWNTO 0); -- Pour stocker jusqu'à 3 commandes
|
181 |
|
|
SIGNAL oldcom2 : STD_LOGIC_vector(9 DOWNTO 0); -- MSB = voie de réception de la commande, MSB - 1 : le registre est libre (0) ou occupé (1)
|
182 |
|
|
SIGNAL oldcom3 : STD_LOGIC_vector(9 DOWNTO 0); -- 8 LSB : champs TYP de la commande enregistrée
|
183 |
|
|
SIGNAL store_com : STD_LOGIC; -- 1 pulse pour enregistrer la commande en cours dans un oldcomx
|
184 |
|
|
SIGNAL delete_com : STD_LOGIC; -- 1 pulse pour effacer la commande en cours des oldcomx
|
185 |
|
|
SIGNAL com_recue : STD_LOGIC; -- A 1 si la commande en cours a déjà été enregistrée dans un oldcomx
|
186 |
|
|
SIGNAL synchro_valide: STD_LOGIC; -- A 1 si la commande en cours est une synchrone valide
|
187 |
|
|
SIGNAL iid_temp : STD_LOGIC_vector(63 DOWNTO 0); -- Registre à décalage pour la réception de l'adresse IID
|
188 |
|
|
SIGNAL cpt_byt : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Compteur d'octets en émission ou réception
|
189 |
|
|
SIGNAL wr : STD_LOGIC; -- Signal d'écriture d'un octet à l'adresse ad_buf
|
190 |
|
|
SIGNAL rd : STD_LOGIC; -- Signal de lecture d'un octet à l'adresse ad_buf
|
191 |
|
|
SIGNAL rd_r : STD_LOGIC; -- Pour retarder le signal rd de 1 cycle
|
192 |
|
|
SIGNAL ad_buf : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Adresse de lecture ou d'écriture
|
193 |
|
|
SIGNAL wr_int : STD_LOGIC; -- Signal d'écriture si ad_buf pointe sur un registre interne
|
194 |
|
|
SIGNAL rd_int : STD_LOGIC; -- Signal de lecture si ad_buf pointe sur un registre interne
|
195 |
|
|
SIGNAL dataread : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Multiplexeur pour la lecture
|
196 |
|
|
SIGNAL memadbuf7 : STD_LOGIC; -- Pour latcher le MSB du adbus lors d'une lecture
|
197 |
|
|
SIGNAL datawrite : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Pour latcher les données à écrire
|
198 |
|
|
SIGNAL datint_read : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Multiplexeur pour la lecture des registres internes
|
199 |
|
|
SIGNAL socin : STD_LOGIC; -- Multiplexage des signaux socinx
|
200 |
|
|
SIGNAL synchro_outwin: STD_LOGIC; -- A 1 sur une synchro en dehors des fenêtres autorisées
|
201 |
|
|
-- Signaux de gestion des SYNC absents
|
202 |
|
|
SIGNAL cpt_syncmiss : STD_LOGIC_VECTOR(7 DOWNTO 0); -- Compteur de trames de synhcro absentes
|
203 |
|
|
|
204 |
|
|
-- Machine d'état de gestion du module
|
205 |
|
|
TYPE comexec_type IS (idle_st, rectyp_st, getadsrce_st, attribtid_st, purgesidsync_st, getseq_st, purgecrcsync_st, getadbuf_st, getnr_st, getcom_st,
|
206 |
|
|
writebyt_st, startframe_st, sendseq_st, sendcom_st, sendsrce_st, sendadr_st, sendnr_st, senddata_st,
|
207 |
|
|
sendstatus_st, endframe_st,purgecom_st);
|
208 |
|
|
SIGNAL fsm_comexec : comexec_type;
|
209 |
|
|
|
210 |
|
|
|
211 |
|
|
|
212 |
|
|
begin
|
213 |
|
|
--------------------------------------------
|
214 |
|
|
-- Affectation des sorties de configuration du module
|
215 |
|
|
--------------------------------------------
|
216 |
|
|
sync_lock <= synchro_lock; -- Indique que le module est calé sur une synchro
|
217 |
|
|
tid <= reg_tid; -- Adresse attribuée au MIO à destination des autres modules
|
218 |
|
|
copy_ena1 <= reg_config(0); -- Autorisation de recopie du port 1 sur le port 2
|
219 |
|
|
copy_ena2 <= reg_config(1); -- Autorisationd e recopie du port 2 sur le port 1
|
220 |
|
|
clr_fifo_tx <= '0'; -- On n'utilsie pas le clr des FIFO Tx pour l'instant
|
221 |
|
|
spi_typecom <= reg_spictl(0); -- Type de commande sur le port SPI PROM
|
222 |
|
|
spi_execcom <= reg_spictl(3); -- Lance l'exécution d'une commande SPI PROM
|
223 |
|
|
spi_rstn <= reg_spictl(4); -- Reset du module SPI PROM
|
224 |
|
|
spi_nbread <= reg_spinbr; -- Nombre d'octets à lire avec une commande lecture en PROM FPGA
|
225 |
|
|
|
226 |
|
|
--------------------------------------------
|
227 |
|
|
-- Gestion du signal de reprogrammation du FPGA
|
228 |
|
|
--------------------------------------------
|
229 |
|
|
gest_progb : PROCESS(clk_sys, rst_n)
|
230 |
|
|
BEGIN
|
231 |
|
|
IF (rst_n = '0') THEN
|
232 |
|
|
reload_fpgan <= '1';
|
233 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
234 |
|
|
IF (reg_spictl(4) = '0') THEN
|
235 |
|
|
-- Tant que le reset du module SPI est actif
|
236 |
|
|
reload_fpgan <= '1'; -- On fait rien
|
237 |
|
|
ELSIF (reg_loadfpga = x"31") THEN
|
238 |
|
|
-- Si le module SPI est actif et qu'on trouve la valeur magique dan le registre
|
239 |
|
|
reload_fpgan <= '0'; -- On force la reprogrammation
|
240 |
|
|
END IF;
|
241 |
|
|
END IF;
|
242 |
|
|
END PROCESS;
|
243 |
|
|
|
244 |
|
|
--------------------------------------------
|
245 |
|
|
-- Gestion des bus d'accès mémoire
|
246 |
|
|
-- interne (module SPI inclus)
|
247 |
|
|
-- externe
|
248 |
|
|
--------------------------------------------
|
249 |
|
|
ad_out <= ad_buf(6 DOWNTO 0); -- Bus d'accès aux registres externes (7 bits de long)
|
250 |
|
|
datout_write <= datawrite; -- Donnée à écrire dans un registre externe
|
251 |
|
|
wr_int <= wr AND NOT(ad_buf(7)); -- On écrit un registre interne selon le MSB de l'@
|
252 |
|
|
-- On lit un registre interne selon le MSB de l'@
|
253 |
|
|
rd_int <= rd AND datsent_free AND NOT(ad_buf(7)); -- On ne lit rien si le module destination n'est pas prêt
|
254 |
|
|
wr_out <= wr AND ad_buf(7); -- On écrit un registre externe selon le MSB de l'@
|
255 |
|
|
-- On lit un registre externe selon le MSB de l'@
|
256 |
|
|
rd_out <= rd AND datsent_free AND ad_buf(7); -- On ne lit rien si le module destination n'est pas prêt
|
257 |
|
|
|
258 |
|
|
-- On écrit dans la FIFO de commande SPI si signal d'écriture à l'adresse de la FIFO
|
259 |
|
|
spitx_val <= wr_int WHEN (ad_buf(6 DOWNTO 0) = adreg_spidat) ELSE '0';
|
260 |
|
|
spitx_dat <= datawrite; -- la donnée est directement sur le bus d'écriture (passe pas par un regditre)
|
261 |
|
|
|
262 |
|
|
-- On fetche un octet de plus dans la FIFO de lecture SPI si signal de lecture à l'adresse de la FIFO
|
263 |
|
|
spirx_next<= rd_int WHEN (ad_buf(6 DOWNTO 0) = adreg_spidat) ELSE '0';
|
264 |
|
|
|
265 |
|
|
--------------------------------------------
|
266 |
|
|
-- Gestion de la lecture sur le bus interne
|
267 |
|
|
--------------------------------------------
|
268 |
|
|
gest_readint : PROCESS(clk_sys, rst_n)
|
269 |
|
|
BEGIN
|
270 |
|
|
IF (rst_n = '0') THEN
|
271 |
|
|
datint_read <= (others => '0');
|
272 |
|
|
memadbuf7 <= '0';
|
273 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
274 |
|
|
IF (rd_int = '1') THEN
|
275 |
|
|
CASE ad_buf(6 DOWNTO 0) IS
|
276 |
|
|
-- Décodage du registre lu en focntion de l'adresse du registre
|
277 |
|
|
WHEN adreg_mac | adreg_mac+1 | adreg_mac+2 | adreg_mac+3 |
|
278 |
|
|
adreg_mac+4 | adreg_mac+5 | adreg_mac+6 | adreg_mac+7 => datint_read <= x"FF";
|
279 |
|
|
WHEN adreg_iid => datint_read <= iid( 7 DOWNTO 0);
|
280 |
|
|
WHEN adreg_iid+1 => datint_read <= iid(15 DOWNTO 8);
|
281 |
|
|
WHEN adreg_iid+2 => datint_read <= iid(23 DOWNTO 16);
|
282 |
|
|
WHEN adreg_iid+3 => datint_read <= iid(31 DOWNTO 24);
|
283 |
|
|
WHEN adreg_iid+4 => datint_read <= iid(39 DOWNTO 32);
|
284 |
|
|
WHEN adreg_iid+5 => datint_read <= iid(47 DOWNTO 40);
|
285 |
|
|
WHEN adreg_iid+6 => datint_read <= iid(55 DOWNTO 48);
|
286 |
|
|
WHEN adreg_iid+7 => datint_read <= iid(63 DOWNTO 56);
|
287 |
|
|
WHEN adreg_typ => datint_read <= reg_typemio;
|
288 |
|
|
WHEN adreg_ver => datint_read <= reg_version;
|
289 |
|
|
WHEN adreg_verpic => datint_read <= x"00";
|
290 |
|
|
WHEN adreg_tid => datint_read <= reg_tid;
|
291 |
|
|
WHEN adreg_sid | adreg_sid+1 | adreg_sid+2 => datint_read <= x"FF";
|
292 |
|
|
WHEN adreg_tcyc => datint_read <= reg_tcyc;
|
293 |
|
|
WHEN adreg_status => datint_read <= reg_status;
|
294 |
|
|
WHEN adreg_adref => datint_read <= reg_adref;
|
295 |
|
|
WHEN adreg_szref => datint_read <= reg_szref;
|
296 |
|
|
WHEN adreg_toco1 => datint_read <= reg_cpttoco1;
|
297 |
|
|
WHEN adreg_toco2 => datint_read <= reg_cpttoco2;
|
298 |
|
|
WHEN adreg_toac1 => datint_read <= reg_cpttoac1;
|
299 |
|
|
WHEN adreg_toac2 => datint_read <= reg_cpttoac2;
|
300 |
|
|
WHEN adreg_sync => datint_read <= reg_cptsync;
|
301 |
|
|
WHEN adreg_for => datint_read <= reg_cptfor;
|
302 |
|
|
WHEN adreg_conf => datint_read <= reg_config;
|
303 |
|
|
WHEN adreg_spinbr => datint_read <= reg_spinbr;
|
304 |
|
|
WHEN adreg_spictl => datint_read <= spirx_val & reg_spictl(6 DOWNTO 4) & spi_busy & reg_spictl(2 DOWNTO 0);
|
305 |
|
|
WHEN adreg_spidat => datint_read <= spirx_dat;
|
306 |
|
|
WHEN OTHERS => datint_read <= reg_status;
|
307 |
|
|
END CASE;
|
308 |
|
|
END IF;
|
309 |
|
|
IF (rd = '1') THEN
|
310 |
|
|
-- sur une lecture, que ce soit interne ou externe
|
311 |
|
|
memadbuf7 <= ad_buf(7); -- On mémrosie quelle zone mémoire était lue
|
312 |
|
|
END IF;
|
313 |
|
|
END IF;
|
314 |
|
|
END PROCESS;
|
315 |
|
|
-- Lorsqu'on lit une donnée, on multiplexe soit le bus externe, soit les registres internes selon le MSB de l'adresse de lecture
|
316 |
|
|
dataread <= datout_read WHEN memadbuf7 = '1' ELSE datint_read;
|
317 |
|
|
|
318 |
|
|
--------------------------------------------
|
319 |
|
|
-- Gestion des écritures dans les registres internes de configuration
|
320 |
|
|
-- L'écriture dans les registres internes de status est gérée au cas par cas.
|
321 |
|
|
--------------------------------------------
|
322 |
|
|
gest_wrreg : PROCESS(clk_sys, rst_n)
|
323 |
|
|
BEGIN
|
324 |
|
|
IF (rst_n = '0') THEN
|
325 |
|
|
reg_config <= x"03";
|
326 |
|
|
reg_adref <= ad_ref;
|
327 |
|
|
reg_szref <= sz_ref;
|
328 |
|
|
reg_tcyc <= x"FF";
|
329 |
|
|
reg_spinbr <= x"00";
|
330 |
|
|
reg_loadfpga <= x"00";
|
331 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
332 |
|
|
IF (wr_int = '1') THEN
|
333 |
|
|
CASE ad_buf(6 DOWNTO 0) IS
|
334 |
|
|
-- Mise à jour du registre en focntion du décodage de l'adresse du registre
|
335 |
|
|
WHEN adreg_conf =>
|
336 |
|
|
reg_config <= datawrite;
|
337 |
|
|
WHEN adreg_adref =>
|
338 |
|
|
reg_adref <= datawrite;
|
339 |
|
|
WHEN adreg_szref =>
|
340 |
|
|
reg_szref <= datawrite;
|
341 |
|
|
WHEN adreg_tcyc =>
|
342 |
|
|
reg_tcyc <= datawrite;
|
343 |
|
|
WHEN adreg_loadfpga =>
|
344 |
|
|
IF (reg_spictl(4) = '1') THEN
|
345 |
|
|
-- On autorise la mise à jour du registre que si le reste SPI est relaché
|
346 |
|
|
reg_loadfpga <= datawrite;
|
347 |
|
|
END IF;
|
348 |
|
|
WHEN adreg_spinbr =>
|
349 |
|
|
reg_spinbr <= datawrite;
|
350 |
|
|
WHEN OTHERS =>
|
351 |
|
|
NULL;
|
352 |
|
|
END CASE;
|
353 |
|
|
END IF;
|
354 |
|
|
IF (wr_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_spictl) THEN
|
355 |
|
|
reg_spictl <= datawrite;
|
356 |
|
|
ELSE
|
357 |
|
|
-- On s'assure que le pulse de commande du SPI ne dure qu'un seul cycle
|
358 |
|
|
reg_spictl(3) <= '0';
|
359 |
|
|
END IF;
|
360 |
|
|
END IF;
|
361 |
|
|
END PROCESS;
|
362 |
|
|
|
363 |
|
|
----------------------------------
|
364 |
|
|
-- Gestion du registre de status
|
365 |
|
|
----------------------------------
|
366 |
|
|
gest_stat : PROCESS(clk_sys, rst_n)
|
367 |
|
|
BEGIN
|
368 |
|
|
IF (rst_n = '0') THEN
|
369 |
|
|
-- Par défaut le bit REP est à 1
|
370 |
|
|
reg_status <= x"80";
|
371 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
372 |
|
|
IF (rd_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_status) OR
|
373 |
|
|
(fsm_comexec = sendstatus_st AND datsent_free = '1') THEN
|
374 |
|
|
-- Le registre status est resetté à chaque lecture
|
375 |
|
|
reg_status <= x"00";
|
376 |
|
|
ELSE
|
377 |
|
|
IF (err_toco = '1') THEN
|
378 |
|
|
-- Gestion du bit CNR (trame non reçue sur un des ports)
|
379 |
|
|
reg_status(0) <= '1';
|
380 |
|
|
END IF;
|
381 |
|
|
-- Bit ESE non implémenté
|
382 |
|
|
IF (start_cycle = '1' AND mem_activity1 = '0') THEN
|
383 |
|
|
-- Gestion du bit NA1 (pas d'activité sur le port 1)
|
384 |
|
|
reg_status(2) <= '1';
|
385 |
|
|
END IF;
|
386 |
|
|
IF (start_cycle = '1' AND mem_activity2 = '0') THEN
|
387 |
|
|
-- Gestion du bit NA2 (pas d'activité sur le port 2)
|
388 |
|
|
reg_status(3) <= '1';
|
389 |
|
|
END IF;
|
390 |
|
|
IF (synchro_miss = '1') THEN
|
391 |
|
|
-- Gestion du bit NTS (pas de trame de synhcro)
|
392 |
|
|
reg_status(4) <= '1';
|
393 |
|
|
END IF;
|
394 |
|
|
IF (new_frame1 = '1' AND l7_ok1 = '0') OR
|
395 |
|
|
(new_frame2 = '1' AND l7_ok2 = '0') THEN
|
396 |
|
|
-- Gestion du bit BFO (format de trame non supporté)
|
397 |
|
|
reg_status(5) <= '1';
|
398 |
|
|
END IF;
|
399 |
|
|
reg_status(6) <= sel_voie;
|
400 |
|
|
reg_status(7) <= '0';
|
401 |
|
|
END IF;
|
402 |
|
|
END IF;
|
403 |
|
|
END PROCESS;
|
404 |
|
|
|
405 |
|
|
--------------------------------------------
|
406 |
|
|
-- Gestion de la synchro
|
407 |
|
|
--------------------------------------------
|
408 |
|
|
gest_sync : PROCESS(clk_sys, rst_n)
|
409 |
|
|
BEGIN
|
410 |
|
|
IF (rst_n = '0') THEN
|
411 |
|
|
cpt_syncmiss <= (others => '0');
|
412 |
|
|
synchro_lock <= '0';
|
413 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
414 |
|
|
IF (synchro_outwin = '1' AND synchro_lock = '1') THEN
|
415 |
|
|
-- Sur synchro en dehors de la fenêtre alors qu'on est déjà locké
|
416 |
|
|
cpt_syncmiss <= (others => '0'); -- On annule le compteur de trame de sync manquante
|
417 |
|
|
synchro_lock <= '0'; -- On se délocke de la synchro d'avant
|
418 |
|
|
ELSE
|
419 |
|
|
IF (synchro = '1') THEN
|
420 |
|
|
-- Sur chaque trame de synchro traitée
|
421 |
|
|
synchro_lock <= '1';
|
422 |
|
|
cpt_syncmiss <= (others => '0');
|
423 |
|
|
ELSIF (synchro_miss = '1') THEN
|
424 |
|
|
-- Sur chaque cycle sans trame de synchro
|
425 |
|
|
IF (cpt_syncmiss /= x"FF") THEN
|
426 |
|
|
-- On comtpe de 0 à 255 et on s'arrêt de compter
|
427 |
|
|
cpt_syncmiss <= cpt_syncmiss + 1;
|
428 |
|
|
ELSE
|
429 |
|
|
synchro_lock <= '0'; -- On considère qu'on a perdu la synchro au bout de 255 cycles sans synchro
|
430 |
|
|
END IF;
|
431 |
|
|
END IF;
|
432 |
|
|
END IF;
|
433 |
|
|
END IF;
|
434 |
|
|
END PROCESS;
|
435 |
|
|
|
436 |
|
|
--------------------------------------------
|
437 |
|
|
-- Gestion du temps de cycle de communication
|
438 |
|
|
--------------------------------------------
|
439 |
|
|
gest_cycle : PROCESS(clk_sys, rst_n)
|
440 |
|
|
BEGIN
|
441 |
|
|
IF (rst_n = '0') THEN
|
442 |
|
|
mes10us <= (others => '0');
|
443 |
|
|
mescycle <= CONV_STD_LOGIC_VECTOR(1, mescycle'LENGTH);
|
444 |
|
|
tc_tcyc <= (OTHERS => '0');
|
445 |
|
|
start_cycle <= '0';
|
446 |
|
|
win_syncbefore <= '0';
|
447 |
|
|
win_syncafter <= '0';
|
448 |
|
|
synchro_miss <= '0';
|
449 |
|
|
cpt_seq <= (others => '0');
|
450 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
451 |
|
|
--tc_tcyc <= reg_tcyc * 100; -- reg_tcyc est en périodes de 1ms mais la mesure se fait en périodes de 10us
|
452 |
|
|
tc_tcyc <= EXT(reg_tcyc & "000000", tc_tcyc'LENGTH) + EXT(reg_tcyc & "00000", tc_tcyc'LENGTH) + EXT(reg_tcyc & "00", tc_tcyc'LENGTH);
|
453 |
|
|
IF (synchro = '1') THEN
|
454 |
|
|
-- Si on a reçu une trame de synchro valide
|
455 |
|
|
mes10us <= (others => '0'); -- Compteur de durée de 10us
|
456 |
|
|
mescycle <= CONV_STD_LOGIC_VECTOR(1, mescycle'LENGTH); -- Compteur de périodes de 10us (compte de 1 à TCYC)
|
457 |
|
|
start_cycle <= '1'; -- On indique au module un début de cycle
|
458 |
|
|
win_syncbefore <= '0'; -- On a plus besoin de la fenêtre de validité de synchro en avance
|
459 |
|
|
win_syncafter <= '1'; -- Par contre, onpeut recevoir une synchro en retard
|
460 |
|
|
synchro_miss <= '0';
|
461 |
|
|
cpt_seq <= seq_field; -- Le numéro de cycle est celui de la commande
|
462 |
|
|
ELSE
|
463 |
|
|
IF (mes10us = CONV_STD_LOGIC_VECTOR(freq_clksys*10-1, mes10us'length)) THEN
|
464 |
|
|
-- Toutes les 10 us
|
465 |
|
|
mes10us <= (others => '0');
|
466 |
|
|
IF (mescycle = ('0' & tc_tcyc) + ("0000" & tc_tcyc(tc_tcyc'LEFT DOWNTO 3))) THEN
|
467 |
|
|
-- Si on a mesuré 1.125xTCYC
|
468 |
|
|
win_syncbefore <= '0'; -- Les fenêtres de validité sont annulées
|
469 |
|
|
win_syncafter <= '0';
|
470 |
|
|
-- On remet le compteur à 0.125xTCYC pour mesure 1 TCYC entre 0.125 et 1.125TCYC
|
471 |
|
|
mescycle <= ("0000" & tc_tcyc(tc_tcyc'LEFT DOWNTO 3)) + 1;
|
472 |
|
|
synchro_miss <= '1'; -- On indique qu'on a manqué une synchro sur la période précédente
|
473 |
|
|
start_cycle <= '1'; -- On démarre un cycle sur ordre interne (pas de trame de synchro)
|
474 |
|
|
ELSE
|
475 |
|
|
-- Si on a pas encore atteind le 1.125xTCYC
|
476 |
|
|
mescycle <= mescycle + 1;
|
477 |
|
|
IF (mescycle = ('0' & tc_tcyc) - ("0000" & tc_tcyc(tc_tcyc'LEFT DOWNTO 3))) THEN
|
478 |
|
|
-- Si on est à 0.875x TCYC
|
479 |
|
|
win_syncbefore <= '1'; -- On active le signal de validité en avance de la synchro
|
480 |
|
|
win_syncafter <= '0'; -- Par contre la synchro en retard ne serait pas valide
|
481 |
|
|
ELSIF (mescycle = ('0' & tc_tcyc)) THEN
|
482 |
|
|
-- Si on est pile à TCYC
|
483 |
|
|
win_syncbefore <= '0';
|
484 |
|
|
win_syncafter <= '1'; -- On active le signal de validité en retard de la synchro
|
485 |
|
|
cpt_seq <= cpt_seq + 1; -- On est dans le numéro de cycle suivant
|
486 |
|
|
ELSIF (mescycle = ("0000" & tc_tcyc(tc_tcyc'LEFT DOWNTO 3))) THEN
|
487 |
|
|
-- Si on est pile à 0.125xTCYC
|
488 |
|
|
win_syncafter <= '0'; -- On annule le signal de validité en retard de la synchro
|
489 |
|
|
END IF;
|
490 |
|
|
END IF;
|
491 |
|
|
ELSE
|
492 |
|
|
-- pour tous les autres états dans le cycle
|
493 |
|
|
start_cycle <= '0'; -- On assure que les signaux ne durent qu'un clk
|
494 |
|
|
synchro_miss <= '0';
|
495 |
|
|
mes10us <= mes10us + 1;
|
496 |
|
|
END IF;
|
497 |
|
|
END IF;
|
498 |
|
|
END IF;
|
499 |
|
|
END PROCESS;
|
500 |
|
|
|
501 |
|
|
--------------------------------------------
|
502 |
|
|
-- Gestion des compteurs de monitoring
|
503 |
|
|
--------------------------------------------
|
504 |
|
|
-- Compteur de trames avec un mauvais format (champs invalides, CRC faux, ...)
|
505 |
|
|
gest_for : PROCESS(clk_sys, rst_n)
|
506 |
|
|
BEGIN
|
507 |
|
|
IF (rst_n = '0') THEN
|
508 |
|
|
reg_cptfor <= (others => '0');
|
509 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
510 |
|
|
IF (rd_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_for) THEN
|
511 |
|
|
-- Le registre est remis à 0 ou à 1 lors d'une lecture selon la condition de génération
|
512 |
|
|
IF (new_frame1 = '1' AND l7_ok1 = '0') OR (new_frame2 = '1' AND l7_ok2 = '0') THEN
|
513 |
|
|
reg_cptfor(0) <= '1';
|
514 |
|
|
ELSE
|
515 |
|
|
reg_cptfor(0) <= '0';
|
516 |
|
|
END IF;
|
517 |
|
|
reg_cptfor(7 DOWNTO 1) <= "0000000";
|
518 |
|
|
ELSIF (reg_cptfor /= x"FF") THEN
|
519 |
|
|
IF (new_frame1 = '1' AND l7_ok1 = '0') OR
|
520 |
|
|
(new_frame2 = '1' AND l7_ok2 = '0') THEN
|
521 |
|
|
-- Sur réception d'une nouvelle trame avec un mauvais format quel que soit le port
|
522 |
|
|
reg_cptfor <= reg_cptfor + 1;
|
523 |
|
|
END IF;
|
524 |
|
|
END IF;
|
525 |
|
|
END IF;
|
526 |
|
|
END PROCESS;
|
527 |
|
|
|
528 |
|
|
-- Compteur d'absence de trame de synchro
|
529 |
|
|
gest_abssync : PROCESS(clk_sys, rst_n)
|
530 |
|
|
BEGIN
|
531 |
|
|
IF (rst_n = '0') THEN
|
532 |
|
|
reg_cptsync <= (others => '0');
|
533 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
534 |
|
|
IF (rd_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_sync) THEN
|
535 |
|
|
-- Le registre est remis à 0 ou à 1 lors d'une lecture selon la condition de génération
|
536 |
|
|
reg_cptsync <= "0000000" & synchro_miss;
|
537 |
|
|
ELSIF (reg_cptsync /= x"FF") THEN
|
538 |
|
|
IF (synchro_miss = '1') THEN
|
539 |
|
|
reg_cptsync <= reg_cptsync + 1;
|
540 |
|
|
END IF;
|
541 |
|
|
END IF;
|
542 |
|
|
END IF;
|
543 |
|
|
END PROCESS;
|
544 |
|
|
|
545 |
|
|
-- Compteur de cycles sans activité sur le port 1
|
546 |
|
|
gest_toac1 : PROCESS(clk_sys, rst_n)
|
547 |
|
|
BEGIN
|
548 |
|
|
IF (rst_n = '0') THEN
|
549 |
|
|
reg_cpttoac1 <= (others => '0');
|
550 |
|
|
mem_activity1 <= '1';
|
551 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
552 |
|
|
IF (rd_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_toac1) THEN
|
553 |
|
|
-- Le registre est remis à 0 ou à 1 lors d'une lecture selon la condition de génération
|
554 |
|
|
IF (start_cycle = '1' AND mem_activity1 = '0') THEN
|
555 |
|
|
reg_cpttoac1(0) <= '1';
|
556 |
|
|
ELSE
|
557 |
|
|
reg_cpttoac1(0) <= '0';
|
558 |
|
|
END IF;
|
559 |
|
|
reg_cpttoac1(7 DOWNTO 1) <= "0000000";
|
560 |
|
|
ELSIF (reg_cpttoac1 /= x"FF") THEN
|
561 |
|
|
IF (start_cycle = '1' AND mem_activity1 = '0') THEN
|
562 |
|
|
-- A chaque début de cycle, si on a pas eu du tout d'activité
|
563 |
|
|
reg_cpttoac1 <= reg_cpttoac1 + 1;
|
564 |
|
|
END IF;
|
565 |
|
|
END IF;
|
566 |
|
|
IF (activity1 = '1') THEN
|
567 |
|
|
-- Bascule JK de mémorisation d'activité
|
568 |
|
|
mem_activity1 <= '1';
|
569 |
|
|
ELSIF (start_cycle = '1') THEN
|
570 |
|
|
-- Remise à 0 à chaque début de cycle
|
571 |
|
|
mem_activity1 <= '0';
|
572 |
|
|
END IF;
|
573 |
|
|
END IF;
|
574 |
|
|
END PROCESS;
|
575 |
|
|
|
576 |
|
|
-- Compteur de cycles sans activité sur le port 2
|
577 |
|
|
gest_toac2 : PROCESS(clk_sys, rst_n)
|
578 |
|
|
BEGIN
|
579 |
|
|
IF (rst_n = '0') THEN
|
580 |
|
|
reg_cpttoac2 <= (others => '0');
|
581 |
|
|
mem_activity2 <= '1';
|
582 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
583 |
|
|
IF (rd_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_toac2) THEN
|
584 |
|
|
-- Le registre est remis à 0 ou à 1 lors d'une lecture selon la condition de génération
|
585 |
|
|
IF (start_cycle = '1' AND mem_activity2 = '0') THEN
|
586 |
|
|
reg_cpttoac2(0) <= '1';
|
587 |
|
|
ELSE
|
588 |
|
|
reg_cpttoac2(0) <= '0';
|
589 |
|
|
END IF;
|
590 |
|
|
reg_cpttoac2(7 DOWNTO 1) <= "0000000";
|
591 |
|
|
ELSIF (reg_cpttoac2 /= x"FF") THEN
|
592 |
|
|
IF (start_cycle = '1' AND mem_activity2 = '0') THEN
|
593 |
|
|
reg_cpttoac2 <= reg_cpttoac2 + 1;
|
594 |
|
|
END IF;
|
595 |
|
|
END IF;
|
596 |
|
|
IF (activity2 = '1') THEN
|
597 |
|
|
mem_activity2 <= '1';
|
598 |
|
|
ELSIF (start_cycle = '1') THEN
|
599 |
|
|
mem_activity2 <= '0';
|
600 |
|
|
END IF;
|
601 |
|
|
END IF;
|
602 |
|
|
END PROCESS;
|
603 |
|
|
|
604 |
|
|
-- Compteur de trames reçues sur le port 2 mais pas sur le port 1 durant le cycle
|
605 |
|
|
gest_toco1 : PROCESS(clk_sys, rst_n)
|
606 |
|
|
BEGIN
|
607 |
|
|
IF (rst_n = '0') THEN
|
608 |
|
|
reg_cpttoco1 <= (others => '0');
|
609 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
610 |
|
|
IF (rd_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_toco1) THEN
|
611 |
|
|
-- Sur lecture du registre, remise à 0 ou à 1 du compteur selon la condition de généraltion de l'évènement
|
612 |
|
|
IF (err_toco = '1' AND voie_toco = '0') THEN
|
613 |
|
|
reg_cpttoco1(0) <= '1';
|
614 |
|
|
ELSE
|
615 |
|
|
reg_cpttoco1(0) <= '0';
|
616 |
|
|
END IF;
|
617 |
|
|
reg_cpttoco1(7 DOWNTO 1) <= "0000000";
|
618 |
|
|
ELSIF (reg_cpttoco1 /= x"FF") THEN
|
619 |
|
|
IF (err_toco = '1' AND voie_toco = '0') THEN
|
620 |
|
|
-- Si on a une trame absente (err_toco) sur le voie 1 (voie_toco)
|
621 |
|
|
reg_cpttoco1 <= reg_cpttoco1 + 1;
|
622 |
|
|
END IF;
|
623 |
|
|
END IF;
|
624 |
|
|
END IF;
|
625 |
|
|
END PROCESS;
|
626 |
|
|
|
627 |
|
|
-- Compteur de trames reçues sur le port 1 mais pas sur le port 2 durant le cycle
|
628 |
|
|
gest_toco2 : PROCESS(clk_sys, rst_n)
|
629 |
|
|
BEGIN
|
630 |
|
|
IF (rst_n = '0') THEN
|
631 |
|
|
reg_cpttoco2 <= (others => '0');
|
632 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
633 |
|
|
IF (rd_int = '1' AND ad_buf(6 DOWNTO 0) = adreg_toco2) THEN
|
634 |
|
|
IF (err_toco = '1' AND voie_toco = '1') THEN
|
635 |
|
|
reg_cpttoco2(0) <= '1';
|
636 |
|
|
ELSE
|
637 |
|
|
reg_cpttoco2(0) <= '0';
|
638 |
|
|
END IF;
|
639 |
|
|
reg_cpttoco2(7 DOWNTO 1) <= "0000000";
|
640 |
|
|
ELSIF (reg_cpttoco2 /= x"FF") THEN
|
641 |
|
|
IF (err_toco = '1' AND voie_toco = '1') THEN
|
642 |
|
|
-- Si on a une trame absente (err_toco) sur le voie 2 (voie_toco)
|
643 |
|
|
reg_cpttoco2 <= reg_cpttoco2 + 1;
|
644 |
|
|
END IF;
|
645 |
|
|
END IF;
|
646 |
|
|
END IF;
|
647 |
|
|
END PROCESS;
|
648 |
|
|
|
649 |
|
|
--------------------------------------------
|
650 |
|
|
-- multiplexage des données selon si on traite la voie 1 ou la voie 2
|
651 |
|
|
--------------------------------------------
|
652 |
|
|
datin <= datin1 WHEN (sel_voie = '0') ELSE datin2; -- Sélection de la donnée à traiter
|
653 |
|
|
socin <= socin1 WHEN (sel_voie = '0') ELSE socin2; -- Sélection du signal soc selon la voie
|
654 |
|
|
rd_datin1 <= rd_combuf WHEN (sel_voie = '0') ELSE '0';-- On lit un octet de plus dans le bon buffer
|
655 |
|
|
rd_datin2 <= rd_combuf WHEN (sel_voie = '1') ELSE '0';
|
656 |
|
|
com_dispo <= com_dispo1 WHEN (sel_voie = '0') ELSE com_dispo2; -- Il y'a une commande dispo sur la voie sélectionnée
|
657 |
|
|
|
658 |
|
|
-- Condition de lecture dans une méoire de commande. Si on est en purge, on lit jusqu'à la trame suivante
|
659 |
|
|
-- ou bien que la méoire soit vide
|
660 |
|
|
rd_combuf <= rd_com AND com_dispo AND NOT(socin) WHEN (fsm_comexec = purgecom_st) ELSE
|
661 |
|
|
rd_com AND com_dispo;
|
662 |
|
|
|
663 |
|
|
--------------------------------------------
|
664 |
|
|
-- Mémorisation des commandes déjà reçues dans le cycle
|
665 |
|
|
-- Format des oldcom
|
666 |
|
|
-- MSB : Voie où la commande a été reçue
|
667 |
|
|
-- MSB-1 : Le oldcom est occupé (une commande est mémorisée)
|
668 |
|
|
-- 8 LSB : champs de la commande
|
669 |
|
|
-- Les oldcom sont gérés comme une FIFO (oldcom1 est le premier remplit)
|
670 |
|
|
--------------------------------------------
|
671 |
|
|
mem_oldcom : PROCESS(clk_sys, rst_n)
|
672 |
|
|
BEGIN
|
673 |
|
|
IF (rst_n = '0') THEN
|
674 |
|
|
oldcom1 <= (others => '0');
|
675 |
|
|
oldcom2 <= (others => '0');
|
676 |
|
|
oldcom3 <= (others => '0');
|
677 |
|
|
err_toco <= '0';
|
678 |
|
|
voie_toco <= '0';
|
679 |
|
|
mem_sync <= '0';
|
680 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
681 |
|
|
IF (synchro = '1') THEN
|
682 |
|
|
-- mem_sync est une bascule JK de mémorisation de réception d'une trame de synchro dans le cycle en cours
|
683 |
|
|
mem_sync <= '1';
|
684 |
|
|
ELSIF (start_cycle = '1') THEN
|
685 |
|
|
-- A chaque début de cycle (qu'il soit sur réception de synchro ou timer)
|
686 |
|
|
mem_sync <= '0';
|
687 |
|
|
END IF;
|
688 |
|
|
IF (start_cycle = '1') THEN
|
689 |
|
|
-- Au début d'un cycle
|
690 |
|
|
IF (mem_sync = '1') THEN
|
691 |
|
|
-- Si ce cycle a été induit par une trame de synchro
|
692 |
|
|
-- On utilise typ_sync (en dur) au lieu de typ_field car typ_field est écrasé pour la trame réflexe
|
693 |
|
|
oldcom1 <= sel_voie & '1' & typ_sync; -- On mémorise la commande
|
694 |
|
|
oldcom2(8) <= '0'; -- Au début d'un cycle initié par une trame de synchro
|
695 |
|
|
oldcom3(8) <= '0'; -- On purge les FIFO oldcom
|
696 |
|
|
END IF;
|
697 |
|
|
IF (oldcom1(8) = '1') THEN
|
698 |
|
|
-- Si la première case mémoire n'était pas vide
|
699 |
|
|
err_toco <= '1'; -- Ca veut dire qu'une commande d'une cycle précédent n'a pas eu sa jumelle
|
700 |
|
|
voie_toco <= NOT(oldcom1(9)); -- On va incrémenter le compteur opposé au port
|
701 |
|
|
ELSE
|
702 |
|
|
err_toco <= '0';
|
703 |
|
|
END IF;
|
704 |
|
|
ELSIF (store_com = '1') THEN
|
705 |
|
|
-- Sur réception d'un ordre de stockage de la commande, on cherche la première case vide
|
706 |
|
|
IF (oldcom1(8) = '0') THEN
|
707 |
|
|
oldcom1 <= sel_voie & '1' & typ_field;
|
708 |
|
|
ELSIF (oldcom2(8) = '0') THEN
|
709 |
|
|
oldcom2 <= sel_voie & '1' & typ_field;
|
710 |
|
|
ELSIF (oldcom3(8) = '0') THEN
|
711 |
|
|
oldcom3 <= sel_voie & '1' & typ_field;
|
712 |
|
|
ELSE
|
713 |
|
|
-- Si pas de case vide, on jette la plus vieille et on stoke à la fin de la file
|
714 |
|
|
oldcom1 <= oldcom2;
|
715 |
|
|
oldcom2 <= oldcom3;
|
716 |
|
|
oldcom3 <= sel_voie & '1' & typ_field;
|
717 |
|
|
END IF;
|
718 |
|
|
err_toco <= '0';
|
719 |
|
|
ELSIF (delete_com = '1') THEN
|
720 |
|
|
-- Sur réception d'un ordre d'effacement (i.e. la commande en cours a déjà été reçue, donc on l'efface de la mémoire)
|
721 |
|
|
IF (oldcom1 = NOT(sel_voie) & '1' & typ_field) THEN
|
722 |
|
|
-- En principe, il faut que ce soit la première disponible car elles arrivent forcément dans le même ordre sur les 2 ports
|
723 |
|
|
oldcom1 <= oldcom2; -- On efface la première en recopiant la 2ème et la 3ème
|
724 |
|
|
oldcom2 <= oldcom3;
|
725 |
|
|
oldcom3(8) <= '0'; -- On vide la 3ème case
|
726 |
|
|
err_toco <= '0';
|
727 |
|
|
ELSIF (oldcom2 = NOT(sel_voie) & '1' & typ_field) THEN
|
728 |
|
|
-- Si la commande en cours est stockée en 2ème position, ça veut dire que la commande stockée
|
729 |
|
|
-- en première position a été perdue sur l'autre port
|
730 |
|
|
oldcom1 <= oldcom3; -- On jette les 2 premières mémoires
|
731 |
|
|
oldcom2(8) <= '0';
|
732 |
|
|
oldcom3(8) <= '0';
|
733 |
|
|
err_toco <= '1'; -- On indique l'erreur
|
734 |
|
|
voie_toco <= NOT(oldcom1(9)); -- et sur quelle voie il y'a eu l'erreur
|
735 |
|
|
ELSIF (oldcom3 = NOT(sel_voie) & '1' & typ_field) THEN
|
736 |
|
|
-- Si la commande en cours est stockée en 3ème position, ça veut dire que les commandes stockées
|
737 |
|
|
-- en première et deuxième position ont été perdues sur l'autre port. On a donc 2 erreurs à enregistrer
|
738 |
|
|
-- On purge la mémoire 1 et 3 et on indiquee une erreur. On garde la mémoire 2 en mémoire 1 pour traiter l'erreur
|
739 |
|
|
-- à la prochaine commande ou au début du cycle suivant
|
740 |
|
|
oldcom1 <= oldcom2; -- On purge donc toutes les mémoires
|
741 |
|
|
oldcom2(8) <= '0';
|
742 |
|
|
oldcom3(8) <= '0';
|
743 |
|
|
err_toco <= '1'; -- On indique l'erreur
|
744 |
|
|
voie_toco <= NOT(oldcom1(9)); -- et sur quelle voie il y'a eu l'erreur
|
745 |
|
|
END IF;
|
746 |
|
|
ELSE
|
747 |
|
|
err_toco <= '0'; -- Pour assurer qu'il ne dure qu'un seul cycle
|
748 |
|
|
END IF;
|
749 |
|
|
END IF;
|
750 |
|
|
END PROCESS;
|
751 |
|
|
|
752 |
|
|
--------------------------------------------
|
753 |
|
|
-- Machine d'état de gestion du module
|
754 |
|
|
--------------------------------------------
|
755 |
|
|
-- Une commande est déjà reçue sur l'autre port si elle dans une des 3 cases mémoires
|
756 |
|
|
com_recue <= '1' WHEN ((oldcom1 = NOT(sel_voie) & '1' & datin) OR
|
757 |
|
|
(oldcom2 = NOT(sel_voie) & '1' & datin) OR
|
758 |
|
|
(oldcom3 = NOT(sel_voie) & '1' & datin)) ELSE '0';
|
759 |
|
|
|
760 |
|
|
-- Une trame de synchro est valide si c'est la première (synchro_lock = '0') ou bien si elle est
|
761 |
|
|
-- dans la fenêtre de validité en avance avec SEQ = cpt_seq+1 ou bien si elle est dans la
|
762 |
|
|
-- fenêtre de validité en retard avec SEQ = cpt_seq
|
763 |
|
|
synchro_valide <= '1' WHEN (typ_field = typ_sync AND
|
764 |
|
|
(synchro_lock = '0' OR
|
765 |
|
|
(win_syncbefore = '1' AND datin = cpt_seq + 1) OR
|
766 |
|
|
(win_syncafter = '1' AND datin = cpt_seq))) ELSE '0';
|
767 |
|
|
|
768 |
|
|
man_fsm : PROCESS(clk_sys, rst_n)
|
769 |
|
|
BEGIN
|
770 |
|
|
IF (rst_n = '0') THEN
|
771 |
|
|
fsm_comexec <= idle_st;
|
772 |
|
|
sel_voie <= '1';
|
773 |
|
|
cpt_byt <= (others => '0');
|
774 |
|
|
reg_tid <= x"8F";
|
775 |
|
|
wr <= '0';
|
776 |
|
|
rd <= '0';
|
777 |
|
|
rd_r <= '0';
|
778 |
|
|
ad_buf <= (others => '0');
|
779 |
|
|
--ad_source <= (others => '0'); -- Inutilisé car les TID sdestination sont en dur (multicast)
|
780 |
|
|
store_com <= '0';
|
781 |
|
|
delete_com <= '0';
|
782 |
|
|
synchro_outwin <= '0';
|
783 |
|
|
rd_com <= '0';
|
784 |
|
|
sof <= '0';
|
785 |
|
|
eof <= '0';
|
786 |
|
|
datsent <= (others => '0');
|
787 |
|
|
valsent <= '0';
|
788 |
|
|
datawrite <= (others => '0');
|
789 |
|
|
synchro <= '0';
|
790 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
791 |
|
|
CASE fsm_comexec IS
|
792 |
|
|
WHEN idle_st =>
|
793 |
|
|
-- Etat d'attente de données disponibles dans les modules frame_ana
|
794 |
|
|
wr <= '0';
|
795 |
|
|
rd <= '0';
|
796 |
|
|
synchro <= '0';
|
797 |
|
|
store_com <= '0';
|
798 |
|
|
delete_com <= '0';
|
799 |
|
|
synchro_outwin <= '0';
|
800 |
|
|
sof <= '0';
|
801 |
|
|
eof <= '0';
|
802 |
|
|
valsent <= '0';
|
803 |
|
|
IF (com_dispo1 = '1' AND (com_dispo2 = '0' OR sel_voie = '1')) THEN
|
804 |
|
|
-- On s'assure qu'on traite par alternance une voie et puis l'autre. On traite la voie 1 que si y'a
|
805 |
|
|
-- des données a traiter et que soit la voie 2 est vide soit on a traité la voie 2 au coup d'avant
|
806 |
|
|
sel_voie <= '0'; -- Sélection de la voie de traitement
|
807 |
|
|
rd_com <= '1'; -- On demande un octet de plus par anticipation
|
808 |
|
|
fsm_comexec <= rectyp_st;
|
809 |
|
|
ELSIF (com_dispo2 = '1') THEN
|
810 |
|
|
-- Si on des données dans la voie 2
|
811 |
|
|
sel_voie <= '1'; -- Sélection de la voie à traiter
|
812 |
|
|
rd_com <= '1';
|
813 |
|
|
fsm_comexec <= rectyp_st;
|
814 |
|
|
ELSE
|
815 |
|
|
rd_com <= '0';
|
816 |
|
|
END IF;
|
817 |
|
|
|
818 |
|
|
WHEN rectyp_st =>
|
819 |
|
|
-- Etat d'enregistrement du type de commande
|
820 |
|
|
typ_field <= datin; -- Mémorise la partie typ
|
821 |
|
|
IF (com_recue = '0') THEN
|
822 |
|
|
-- Si on a pas déjà reçu cette com dans ce cycle
|
823 |
|
|
fsm_comexec <= getadsrce_st; --
|
824 |
|
|
IF (datin /= typ_sync) THEN
|
825 |
|
|
-- Si c'est pas une synchro, on l'enregistre. La synchro est mémorisée lors du start_cycle
|
826 |
|
|
store_com <= '1';
|
827 |
|
|
END IF;
|
828 |
|
|
ELSE
|
829 |
|
|
-- Si on a déjà reçu cette commande
|
830 |
|
|
delete_com <= '1'; -- On efface la commande des mémoires
|
831 |
|
|
fsm_comexec <= purgecom_st;-- On va purger la mémoire sans faire l'action associée
|
832 |
|
|
END IF;
|
833 |
|
|
|
834 |
|
|
WHEN getadsrce_st =>
|
835 |
|
|
-- Etat de récupération de l'adresse source de la commande
|
836 |
|
|
--ad_source <= datin;
|
837 |
|
|
store_com <= '0';
|
838 |
|
|
delete_com <= '0';
|
839 |
|
|
-- On va traiter la commande en fonction de son type
|
840 |
|
|
IF (typ_field = typ_sync) THEN
|
841 |
|
|
-- Si c'est une trame de synchro
|
842 |
|
|
cpt_byt <= x"01";
|
843 |
|
|
fsm_comexec <= purgesidsync_st; -- On va purger le SID de la trame de synhcro
|
844 |
|
|
ELSIF (typ_field = typ_atttid) THEN
|
845 |
|
|
-- Si c'est une commande type attribution de TID
|
846 |
|
|
cpt_byt <= x"08"; -- On se prépare à recevoir l'@ IID (8 octets)
|
847 |
|
|
fsm_comexec <= attribtid_st;
|
848 |
|
|
ELSIF (typ_field = typ_reqnoseq) THEN
|
849 |
|
|
-- Si c'est une commande non sécu
|
850 |
|
|
fsm_comexec <= getcom_st;
|
851 |
|
|
ELSE
|
852 |
|
|
-- Si c'est une trame qu'on ne sait pas traiter, on va la purger
|
853 |
|
|
rd_com <= '0';
|
854 |
|
|
fsm_comexec <= purgecom_st;
|
855 |
|
|
END IF;
|
856 |
|
|
|
857 |
|
|
WHEN purgesidsync_st =>
|
858 |
|
|
-- Etat d'attente de récupération du SID de la trame de synhcro (on n'en fait rien)
|
859 |
|
|
cpt_byt <= cpt_byt - 1;
|
860 |
|
|
IF (cpt_byt = "00") THEN
|
861 |
|
|
fsm_comexec <= getseq_st;
|
862 |
|
|
END IF;
|
863 |
|
|
|
864 |
|
|
WHEN getseq_st =>
|
865 |
|
|
-- Etat de réception du compteur de séquence de la trame de SYNC
|
866 |
|
|
seq_field <= datin;
|
867 |
|
|
IF (synchro_valide = '1') THEN
|
868 |
|
|
-- Si le champ SEQ est valable
|
869 |
|
|
rd_com <= '1'; -- On continu de lire pour supprimer le CRC
|
870 |
|
|
synchro <= '1'; -- On signale une synchro valide
|
871 |
|
|
IF (reg_config(3) = '1') THEN
|
872 |
|
|
-- Si on est autorisé à émettre la trame de réponse réflexe
|
873 |
|
|
-- On va d'abord purger les 2 CRC de la commande
|
874 |
|
|
fsm_comexec <= purgecrcsync_st;
|
875 |
|
|
cpt_byt <= x"01";
|
876 |
|
|
ELSE
|
877 |
|
|
-- Si on n'est pas autorisé à émettre la trame réflexe
|
878 |
|
|
fsm_comexec <= purgecom_st; -- On va purger la commande
|
879 |
|
|
END IF;
|
880 |
|
|
ELSE
|
881 |
|
|
IF (win_syncbefore = '0' AND win_syncafter = '0') THEN
|
882 |
|
|
-- Si on a reçu une trame de synchro en dehors des fenêtres de validité
|
883 |
|
|
synchro_outwin <= '1';
|
884 |
|
|
END IF;
|
885 |
|
|
fsm_comexec <= purgecom_st;
|
886 |
|
|
rd_com <= '0';
|
887 |
|
|
END IF;
|
888 |
|
|
|
889 |
|
|
WHEN purgecrcsync_st =>
|
890 |
|
|
-- Etat de purge des 2 octets de CRC de la trmae de synchro
|
891 |
|
|
synchro <= '0';
|
892 |
|
|
cpt_byt <= cpt_byt - 1;
|
893 |
|
|
IF (cpt_byt = "00") THEN
|
894 |
|
|
-- Si on a fini de purger le CRC de la trame de synchro
|
895 |
|
|
fsm_comexec <= startframe_st; -- On va émettre une trame
|
896 |
|
|
sof <= '1';
|
897 |
|
|
datsent <= x"F0"; -- Le 1er octet à envoyer est l'adresse de destination (i.e multicast concentrateur)
|
898 |
|
|
valsent <= '1'; -- On valide l'octet sorti
|
899 |
|
|
ad_buf <= reg_adref; -- l'@ des données à émettre est donnée par ce registre
|
900 |
|
|
cpt_byt <= reg_szref; -- le nombre d'octets à émettre est donné par ce registre
|
901 |
|
|
rd_com <= '0';
|
902 |
|
|
END IF;
|
903 |
|
|
|
904 |
|
|
WHEN attribtid_st =>
|
905 |
|
|
-- Etat d'exécution d'une trame d'attribution de TID
|
906 |
|
|
iid_temp <= datin & iid_temp(63 DOWNTO 8); -- On récupère l'@ IID octet par octet
|
907 |
|
|
cpt_byt <= cpt_byt - 1;
|
908 |
|
|
IF (cpt_byt = x"00") THEN
|
909 |
|
|
-- Si on reçu les 8 octets
|
910 |
|
|
IF (iid_temp = iid) THEN
|
911 |
|
|
-- Si l@ IID reçue correspond à l'@ IID du module
|
912 |
|
|
reg_tid <= datin; -- On mémorise le nouveau TID
|
913 |
|
|
END IF;
|
914 |
|
|
fsm_comexec <= idle_st;
|
915 |
|
|
rd_com <= '0';
|
916 |
|
|
END IF;
|
917 |
|
|
|
918 |
|
|
WHEN getcom_st =>
|
919 |
|
|
-- Etat de récupération de l'octet de commande de la trame de requête non sécu
|
920 |
|
|
com_field <= datin;
|
921 |
|
|
rd_com <= '1';
|
922 |
|
|
fsm_comexec <= getnr_st;
|
923 |
|
|
|
924 |
|
|
WHEN getnr_st =>
|
925 |
|
|
-- Etat de récupération du nombre d'octets à traiter dans la requête, que ce soit une écriture ou une lecture
|
926 |
|
|
cpt_byt <= datin;
|
927 |
|
|
rd_com <= '1';
|
928 |
|
|
fsm_comexec <= getadbuf_st;
|
929 |
|
|
|
930 |
|
|
WHEN getadbuf_st =>
|
931 |
|
|
-- Etat de récupération de l'adresse où lire ou écrire
|
932 |
|
|
ad_buf <= datin;
|
933 |
|
|
IF (com_field = com_write) THEN
|
934 |
|
|
-- Si c'est une commande d'écriture
|
935 |
|
|
fsm_comexec <= writebyt_st;
|
936 |
|
|
rd_com <= '1';
|
937 |
|
|
ELSIF (com_field = com_read) THEN
|
938 |
|
|
-- Si c'est une commande de lecture
|
939 |
|
|
fsm_comexec <= startframe_st; -- On va émettre une trame
|
940 |
|
|
sof <= '1'; -- On signale au module layer2_Tx qu'on veut émettre une trame
|
941 |
|
|
datsent <= x"F0"; -- Le 1er octet à envoyer est l'adresse de destination (i.e multicast concentrateur)
|
942 |
|
|
valsent <= '1'; -- On valide l'octet sorti
|
943 |
|
|
rd_com <= '0'; -- On ne lit plus rien de la commande pour l'instant
|
944 |
|
|
ELSE -- Si c'est autre chose, il y'a eu un problème de desynchronisation -> on va purger la mémoire de commande
|
945 |
|
|
fsm_comexec <= purgecom_st;
|
946 |
|
|
rd_com <= '0';
|
947 |
|
|
END IF;
|
948 |
|
|
|
949 |
|
|
WHEN writebyt_st =>
|
950 |
|
|
-- Etat d'écriture d'une séquence d'octets
|
951 |
|
|
datawrite <= datin;
|
952 |
|
|
wr <= '1';
|
953 |
|
|
cpt_byt <= cpt_byt - 1 ;
|
954 |
|
|
IF (wr = '1' AND (ad_buf /= ('0' & adreg_spidat)) AND ad_buf /= x"FF") THEN
|
955 |
|
|
-- on n'incrémente l'adresse que si le WR a été effectué
|
956 |
|
|
-- Si on accède à la FIFO SPI, le registre d'addresse reste bloqué à cette valeur
|
957 |
|
|
ad_buf <= ad_buf + 1;
|
958 |
|
|
END IF;
|
959 |
|
|
IF (cpt_byt = x"01") THEN
|
960 |
|
|
-- Si on a traité tous les octets
|
961 |
|
|
rd_com <= '0'; -- On arrête de lire dans la commande
|
962 |
|
|
fsm_comexec <= idle_st; -- Mais le signal de wr reste actif un cycle de plus (remis à 0 dans idle)
|
963 |
|
|
END IF;
|
964 |
|
|
|
965 |
|
|
WHEN startframe_st =>
|
966 |
|
|
-- Prépare l'envoie d'une trame
|
967 |
|
|
synchro <= '0'; -- Le signal de synhcro ne doit durer qu'1 pulse
|
968 |
|
|
IF (datsent_free = '1') THEN
|
969 |
|
|
-- Si le 1er octet est en cours de traitement, l'octet suivant est le TYPE
|
970 |
|
|
sof <= '0'; -- Le sof a été pris en compte
|
971 |
|
|
datsent <= x"80"; -- Type de réponse non sécu
|
972 |
|
|
valsent <= '1';
|
973 |
|
|
fsm_comexec <= sendsrce_st;
|
974 |
|
|
END IF;
|
975 |
|
|
|
976 |
|
|
WHEN sendsrce_st =>
|
977 |
|
|
-- Envoie l'@ source (i.e l'@ du MIO) de la trame à émettre
|
978 |
|
|
IF (datsent_free = '1') THEN
|
979 |
|
|
datsent <= reg_tid;
|
980 |
|
|
valsent <= '1';
|
981 |
|
|
fsm_comexec <= sendcom_st;
|
982 |
|
|
END IF;
|
983 |
|
|
|
984 |
|
|
WHEN sendcom_st =>
|
985 |
|
|
-- Envoie du numéro de séquence courante
|
986 |
|
|
IF (datsent_free = '1') THEN
|
987 |
|
|
IF (typ_field = typ_sync) THEN
|
988 |
|
|
-- Si on répond à une trame de synchro
|
989 |
|
|
datsent <= x"01";
|
990 |
|
|
ELSE
|
991 |
|
|
-- Si on répond à une trame de requête
|
992 |
|
|
datsent <= x"02";
|
993 |
|
|
END IF;
|
994 |
|
|
valsent <= '1';
|
995 |
|
|
fsm_comexec <= sendnr_st;
|
996 |
|
|
END IF;
|
997 |
|
|
|
998 |
|
|
WHEN sendnr_st =>
|
999 |
|
|
-- Envoie du nombre d 'octets lus
|
1000 |
|
|
IF (datsent_free = '1') THEN
|
1001 |
|
|
datsent <= cpt_byt;
|
1002 |
|
|
valsent <= '1';
|
1003 |
|
|
fsm_comexec <= sendadr_st;
|
1004 |
|
|
END IF;
|
1005 |
|
|
|
1006 |
|
|
WHEN sendadr_st =>
|
1007 |
|
|
-- Envoie de l'adresse ou on a lu les octets
|
1008 |
|
|
IF (datsent_free = '1') THEN
|
1009 |
|
|
datsent <= ad_buf;
|
1010 |
|
|
rd <= '1';
|
1011 |
|
|
rd_r <= '0';
|
1012 |
|
|
valsent <= '1';
|
1013 |
|
|
fsm_comexec <= senddata_st;
|
1014 |
|
|
END IF;
|
1015 |
|
|
|
1016 |
|
|
WHEN senddata_st =>
|
1017 |
|
|
-- Envoie les octets lus. rd_r est utilisé pour signaler que la donnée en lecture est disponible.
|
1018 |
|
|
-- Il est décalé de 1 cycle par rappott à rd
|
1019 |
|
|
IF (rd = '1' AND datsent_free = '1') THEN
|
1020 |
|
|
rd_r <= '1';
|
1021 |
|
|
IF ((ad_buf /= ('0' & adreg_spidat)) AND ad_buf /= x"FF") THEN
|
1022 |
|
|
-- Si on accède à la FIFO rx du SPI, on reste calé sur cette adresse
|
1023 |
|
|
ad_buf <= ad_buf + 1;
|
1024 |
|
|
END IF;
|
1025 |
|
|
cpt_byt <= cpt_byt - 1;
|
1026 |
|
|
END IF;
|
1027 |
|
|
IF (datsent_free = '1') THEN
|
1028 |
|
|
-- Si le module layer2_tx est dispo pour prendre la donnée
|
1029 |
|
|
IF (cpt_byt = x"01") THEN
|
1030 |
|
|
rd <= '0'; -- Il ne faut plus lire en mémoire
|
1031 |
|
|
END IF;
|
1032 |
|
|
IF (rd_r = '1') THEN
|
1033 |
|
|
-- Si le module layer2_tx est dispo et qu'une donnée est dispo
|
1034 |
|
|
datsent <= dataread; -- On l'envoie
|
1035 |
|
|
valsent <= '1';
|
1036 |
|
|
IF (cpt_byt = x"00") THEN
|
1037 |
|
|
-- Si c'est la dernière donnée
|
1038 |
|
|
IF (typ_field = typ_sync) THEN
|
1039 |
|
|
-- Si on répond à une trame de synchro
|
1040 |
|
|
fsm_comexec <= sendstatus_st; -- Il faut envoyer l'octet de status
|
1041 |
|
|
ELSE
|
1042 |
|
|
-- Si c'est une requête normale
|
1043 |
|
|
fsm_comexec <= endframe_st; -- On a fini
|
1044 |
|
|
eof <= '1';
|
1045 |
|
|
END IF;
|
1046 |
|
|
END IF;
|
1047 |
|
|
ELSE
|
1048 |
|
|
-- S'il n'y a pas dedonnée prête (cas se présente quand on rentre dans cet état et qu'on a pas encore lu)
|
1049 |
|
|
valsent <= '0'; -- On indique au module layer2_tx qu'il n'y a pas de nouvelle donnée
|
1050 |
|
|
END IF;
|
1051 |
|
|
END IF;
|
1052 |
|
|
|
1053 |
|
|
WHEN sendstatus_st =>
|
1054 |
|
|
-- Envoie du registre de status
|
1055 |
|
|
IF (datsent_free = '1') THEN
|
1056 |
|
|
datsent <= reg_status;
|
1057 |
|
|
valsent <= '1';
|
1058 |
|
|
eof <= '1';
|
1059 |
|
|
fsm_comexec <= endframe_st;
|
1060 |
|
|
END IF;
|
1061 |
|
|
|
1062 |
|
|
WHEN endframe_st =>
|
1063 |
|
|
-- Gestion de la fin d'envoie d'une trame
|
1064 |
|
|
IF (datsent_free = '1') THEN
|
1065 |
|
|
eof <= '0';
|
1066 |
|
|
valsent <= '0';
|
1067 |
|
|
fsm_comexec <= idle_st;
|
1068 |
|
|
END IF;
|
1069 |
|
|
|
1070 |
|
|
WHEN purgecom_st =>
|
1071 |
|
|
-- Purge la mémoire de commande pour se recaler au début de la commande suivante
|
1072 |
|
|
-- en cas de problème ou en cas de commande déjà reçue
|
1073 |
|
|
store_com <= '0';
|
1074 |
|
|
delete_com <= '0';
|
1075 |
|
|
synchro_outwin <= '0';
|
1076 |
|
|
IF (sel_voie = '0') THEN
|
1077 |
|
|
IF (com_dispo1 = '1' AND socin1 = '0') THEN
|
1078 |
|
|
-- On lit jusqu'à ce qu'il n'y ait plus de commande ou qu'on ait atteind le début de la commande suivante
|
1079 |
|
|
rd_com <= '1';
|
1080 |
|
|
ELSE
|
1081 |
|
|
rd_com <= '0';
|
1082 |
|
|
fsm_comexec <= idle_st;
|
1083 |
|
|
END IF;
|
1084 |
|
|
ELSE
|
1085 |
|
|
IF (com_dispo2 = '1' AND socin2 = '0') THEN
|
1086 |
|
|
rd_com <= '1';
|
1087 |
|
|
ELSE
|
1088 |
|
|
rd_com <= '0';
|
1089 |
|
|
fsm_comexec <= idle_st;
|
1090 |
|
|
END IF;
|
1091 |
|
|
END IF;
|
1092 |
|
|
|
1093 |
|
|
WHEN OTHERS =>
|
1094 |
|
|
fsm_comexec <= idle_st;
|
1095 |
|
|
END CASE;
|
1096 |
|
|
END IF;
|
1097 |
|
|
END PROCESS;
|
1098 |
|
|
|
1099 |
|
|
end rtl;
|
1100 |
|
|
|