1 |
2 |
DavidRAMBA |
--=============================================================================
|
2 |
|
|
-- TITRE : serial_rx
|
3 |
|
|
-- DESCRIPTION :
|
4 |
|
|
-- Déserialisateur des données reçues sur rx et remet en forme
|
5 |
|
|
-- le signal (retaillage des durée de bit) pour la recopie
|
6 |
|
|
-- La durée d'un bit est égale à tc_divclk+1 pulse de clk_sys
|
7 |
|
|
--
|
8 |
|
|
-- On additionne 3 échantillons consécutifs de part et d'autre
|
9 |
|
|
-- du milieu du bit à échantilloner. Si la somme est >=2 => bit à 1
|
10 |
|
|
-- sinon bit à 0
|
11 |
|
|
-- FICHIER : serial_rx.vhd
|
12 |
|
|
--=============================================================================
|
13 |
|
|
-- CREATION
|
14 |
|
|
-- DATE AUTEUR PROJET REVISION
|
15 |
|
|
-- 29/02/2012 DRA CONCERTO V1.0
|
16 |
|
|
-- 14/01/2013 DRA Modificiation pour échantillonner 3 fois et rendre plus robuste
|
17 |
|
|
-- en environnement bruité
|
18 |
|
|
--=============================================================================
|
19 |
|
|
-- HISTORIQUE DES MODIFICATIONS :
|
20 |
|
|
-- DATE AUTEUR PROJET REVISION
|
21 |
|
|
--=============================================================================
|
22 |
|
|
|
23 |
|
|
LIBRARY IEEE;
|
24 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
25 |
|
|
USE IEEE.STD_LOGIC_ARITH.ALL;
|
26 |
|
|
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
|
27 |
|
|
|
28 |
|
|
|
29 |
|
|
|
30 |
|
|
-- Uncomment the following library declaration if instantiating
|
31 |
|
|
-- any Xilinx primitives in this code.
|
32 |
|
|
--library UNISIM;
|
33 |
|
|
--use UNISIM.VComponents.all;
|
34 |
|
|
|
35 |
|
|
ENTITY serial_rx IS
|
36 |
|
|
GENERIC (
|
37 |
|
|
nbbit_div : INTEGER := 10); -- Nombre de bits pour coder le diviseur d'horloge
|
38 |
|
|
PORT (
|
39 |
|
|
-- Ports système
|
40 |
|
|
clk_sys : IN STD_LOGIC; -- Clock système
|
41 |
|
|
rst_n : IN STD_LOGIC; -- Reset génrél système
|
42 |
|
|
baud_lock: IN STD_LOGIC; -- Indique que le baudrate est calé
|
43 |
|
|
|
44 |
|
|
-- Interface série
|
45 |
|
|
tc_divclk: IN STD_LOGIC_VECTOR (nbbit_div-1 DOWNTO 0); -- Diviseur de l'horloge système pour le baudrate
|
46 |
|
|
tx : OUT STD_LOGIC; -- Re transmission série
|
47 |
|
|
rx : IN STD_LOGIC; -- Port de réception série
|
48 |
|
|
|
49 |
|
|
-- Interface parallèle
|
50 |
|
|
busy : OUT STD_LOGIC; -- Indique qu'une réception est en cours
|
51 |
|
|
val : OUT STD_LOGIC; -- rx_dat contient la dernière donnée reçu
|
52 |
|
|
rx_dat : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) -- Donnée reçue (synchrone de val)
|
53 |
|
|
);
|
54 |
|
|
END serial_rx;
|
55 |
|
|
|
56 |
|
|
ARCHITECTURE rtl of serial_rx is
|
57 |
|
|
SIGNAL rx_r : STD_LOGIC_VECTOR(1 DOWNTO 0); -- Délai pour détecter le front descendant
|
58 |
|
|
SIGNAL sumrx : STD_LOGIC_VECTOR(1 DOWNTO 0); -- Pour additionner 3 échantillons consécutifs
|
59 |
|
|
SIGNAL front_des_rx_c : STD_LOGIC; -- Un pulse de clk_sys sur front descendant de rx
|
60 |
|
|
|
61 |
|
|
SIGNAL cptbit_rx : STD_LOGIC_VECTOR(3 downto 0); -- Compteur de bits dans un caractère en réception
|
62 |
|
|
SIGNAL divclk_rx : STD_LOGIC_VECTOR(nbbit_div-1 downto 0); -- Diviseur d'horloge pour mesurer un bit en réception
|
63 |
|
|
SIGNAL rx_encours : STD_LOGIC; -- Indique qu'un caractère est en cours de réception
|
64 |
|
|
SIGNAL shifter_rx : STD_LOGIC_VECTOR(7 downto 0); -- Registre à décalage de réception
|
65 |
|
|
|
66 |
|
|
BEGIN
|
67 |
|
|
--------------------------------------------
|
68 |
|
|
-- Détection du front descendant sur rx
|
69 |
|
|
--------------------------------------------
|
70 |
|
|
-- rx_r(1) & rx_r(0) & rx représente un registre à décalage du flux rx
|
71 |
|
|
front_rx : PROCESS(clk_sys, rst_n)
|
72 |
|
|
BEGIN
|
73 |
|
|
IF (rst_n = '0') THEN
|
74 |
|
|
rx_r <= (OTHERS => '1');
|
75 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
76 |
|
|
rx_r <= rx_r(0) & rx;
|
77 |
|
|
END IF;
|
78 |
|
|
END PROCESS;
|
79 |
|
|
front_des_rx_c <= NOT(rx_r(0)) AND rx_r(1); -- Détection du front descendant
|
80 |
|
|
sumrx <= CONV_STD_LOGIC_VECTOR(rx_r(0), 2) + CONV_STD_LOGIC_VECTOR(rx_r(1), 2) +
|
81 |
|
|
CONV_STD_LOGIC_VECTOR(rx, 2); -- On compte les 3 échantillons consécutif
|
82 |
|
|
|
83 |
|
|
--------------------------------------------
|
84 |
|
|
-- Déserialisateur des données reçues sur rx
|
85 |
|
|
-- et remise en forme (retaillage des durée de bit) pour la recopie
|
86 |
|
|
--------------------------------------------
|
87 |
|
|
deser_shaper : PROCESS(clk_sys, rst_n)
|
88 |
|
|
BEGIN
|
89 |
|
|
IF (rst_n = '0') THEN
|
90 |
|
|
cptbit_rx <= (OTHERS => '0');
|
91 |
|
|
divclk_rx <= (OTHERS => '0');
|
92 |
|
|
rx_encours <= '0';
|
93 |
|
|
tx <= '1';
|
94 |
|
|
val <= '0';
|
95 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
96 |
|
|
IF (rx_encours = '0') THEN
|
97 |
|
|
-- Si on est pas déjà en train de sérialiser un car
|
98 |
|
|
val <= '0'; -- On s'assure que l'écriture dans la FIFO de réception ne dure qu'un pulse
|
99 |
|
|
IF (front_des_rx_c = '1') THEN
|
100 |
|
|
-- Sur détection du front descendant (le Start bit)
|
101 |
|
|
cptbit_rx <= (OTHERS => '0');
|
102 |
|
|
-- on initialise le diviseur d'horloge à la motié de tc pour échantilloner au milieu du bit
|
103 |
|
|
-- on rajoute 2 pour compenser le retard de détection du front descendant
|
104 |
|
|
divclk_rx <= ('0' & tc_divclk(tc_divclk'LEFT downto 1))+2;
|
105 |
|
|
rx_encours <= '1';
|
106 |
|
|
END IF;
|
107 |
|
|
tx <= '1';
|
108 |
|
|
ELSE
|
109 |
|
|
-- Si on est en train de recevoir un car
|
110 |
|
|
IF (divclk_rx = tc_divclk) THEN
|
111 |
|
|
-- Si on atteind le terminal count (TC) du diviseur d'horloge
|
112 |
|
|
divclk_rx <= (OTHERS => '0');
|
113 |
|
|
cptbit_rx <= cptbit_rx + 1; -- Un bit de plus reçu
|
114 |
|
|
-- Si la somme des 3 echantillons est >= 2 (i.e. le MSB est à 1) -> le bit est à 1
|
115 |
|
|
shifter_rx <= sumrx(1) & shifter_rx(7 downto 1); -- On garde le bit LSB first
|
116 |
|
|
IF (baud_lock = '0') THEN
|
117 |
|
|
-- Tant que l'algo d'Autobaudrate n'a pas convergé
|
118 |
|
|
tx <= '1'; -- On ne recopie rien
|
119 |
|
|
ELSE
|
120 |
|
|
tx <= sumrx(1); -- On échantillonne rx pour la recopie
|
121 |
|
|
END IF;
|
122 |
|
|
IF (cptbit_rx = "1000") then -- On est en train de recevoir le 9ème bit (Start + 8 data)
|
123 |
|
|
val <= '1'; -- On valide la donnée
|
124 |
|
|
ELSIF (cptbit_rx = "1001") then -- Au 10 ème bit reçu
|
125 |
|
|
-- Il faut attendre le 10ème bit pour garantir qu'en recopie, le 8ème bit utile (i.e. le 9ème) dure le bon temps
|
126 |
|
|
rx_encours <= '0'; -- On arrête la réception
|
127 |
|
|
val <= '0'; -- On s'assure que le signal dure 1 pulse
|
128 |
|
|
END IF;
|
129 |
|
|
ELSE
|
130 |
|
|
divclk_rx <= divclk_rx + 1; -- En cours de réception on mesure la durée d'un bit
|
131 |
|
|
val <= '0'; -- On s'assure que le signal dure 1 pulse
|
132 |
|
|
END IF;
|
133 |
|
|
END IF;
|
134 |
|
|
END IF;
|
135 |
|
|
END PROCESS;
|
136 |
|
|
rx_dat <= shifter_rx; -- La data reçue correspond au registre à décalage lorsque val = '1'
|
137 |
|
|
busy <= rx_encours;
|
138 |
|
|
END rtl;
|
139 |
|
|
|