1 |
2 |
DavidRAMBA |
--=============================================================================
|
2 |
|
|
-- TITRE : serial_rx2
|
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 les tc_divclk+1 échantillons de chaque bit
|
9 |
|
|
-- Si la somme est > tc_divclk/2, c'est un '1', sinon, c'est un '0'
|
10 |
|
|
-- FICHIER : serial_rx2.vhd
|
11 |
|
|
--=============================================================================
|
12 |
|
|
-- CREATION
|
13 |
|
|
-- DATE AUTEUR PROJET REVISION
|
14 |
|
|
-- 10/04/2014 DRA SATURN V1.0
|
15 |
|
|
--=============================================================================
|
16 |
|
|
-- HISTORIQUE DES MODIFICATIONS :
|
17 |
|
|
-- DATE AUTEUR PROJET REVISION
|
18 |
|
|
--=============================================================================
|
19 |
|
|
|
20 |
|
|
LIBRARY IEEE;
|
21 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
22 |
|
|
USE IEEE.STD_LOGIC_ARITH.ALL;
|
23 |
|
|
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
|
24 |
|
|
|
25 |
|
|
ENTITY serial_rx2 IS
|
26 |
|
|
GENERIC (
|
27 |
|
|
nbbit_div : INTEGER := 10); -- Nombre de bits pour coder le diviseur d'horloge
|
28 |
|
|
PORT (
|
29 |
|
|
-- Ports système
|
30 |
|
|
clk_sys : IN STD_LOGIC; -- Clock système
|
31 |
|
|
rst_n : IN STD_LOGIC; -- Reset général système
|
32 |
|
|
baud_lock: IN STD_LOGIC; -- Indique que le baudrate est calé
|
33 |
|
|
|
34 |
|
|
-- Interface série
|
35 |
|
|
tc_divclk: IN STD_LOGIC_VECTOR (nbbit_div-1 DOWNTO 0); -- Diviseur de l'horloge système pour le baudrate
|
36 |
|
|
tx : OUT STD_LOGIC; -- Re transmission série
|
37 |
|
|
rx : IN STD_LOGIC; -- Port de réception série
|
38 |
|
|
|
39 |
|
|
-- Interface parallèle
|
40 |
|
|
busy : OUT STD_LOGIC; -- Indique qu'une réception est en cours
|
41 |
|
|
val : OUT STD_LOGIC; -- Indique que rx_dat contient la dernière donnée reçu
|
42 |
|
|
rx_dat : OUT STD_LOGIC_VECTOR (7 DOWNTO 0) -- Donnée reçue (synchrone de val)
|
43 |
|
|
);
|
44 |
|
|
END serial_rx2;
|
45 |
|
|
|
46 |
|
|
ARCHITECTURE rtl of serial_rx2 is
|
47 |
|
|
SIGNAL rx_r : STD_LOGIC; -- Délai pour détecter le front descendant
|
48 |
|
|
SIGNAL sumrx : STD_LOGIC_VECTOR(nbbit_div-1 DOWNTO 0); -- Pour additionner N échantillons consécutifs
|
49 |
|
|
|
50 |
|
|
SIGNAL cptbit_rx : STD_LOGIC_VECTOR(3 downto 0); -- Compteur de bits dans un caractère en réception
|
51 |
|
|
SIGNAL divclk_rx : STD_LOGIC_VECTOR(nbbit_div-1 downto 0); -- Diviseur d'horloge pour mesurer un bit en réception
|
52 |
|
|
SIGNAL rx_encours : STD_LOGIC; -- Indique qu'un caractère est en cours de réception
|
53 |
|
|
SIGNAL shifter_rx : STD_LOGIC_VECTOR(7 downto 0); -- Registre à décalage de désrialisation
|
54 |
|
|
SIGNAL consol_bit : STD_LOGIC; -- Bit consolidé après sur-échantillonnage
|
55 |
|
|
|
56 |
|
|
BEGIN
|
57 |
|
|
--------------------------------------------
|
58 |
|
|
-- Détection du front descendant sur rx
|
59 |
|
|
--------------------------------------------
|
60 |
|
|
front_rx : PROCESS(clk_sys, rst_n)
|
61 |
|
|
BEGIN
|
62 |
|
|
IF (rst_n = '0') THEN
|
63 |
|
|
rx_r <= '1';
|
64 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
65 |
|
|
rx_r <= rx;
|
66 |
|
|
END IF;
|
67 |
|
|
END PROCESS;
|
68 |
|
|
|
69 |
|
|
-- Si on a compté des '1' plus de la moitié du temps, on considère un '1' sinon un '0'
|
70 |
|
|
consol_bit <= '1' WHEN (('0' & sumrx) + rx) > ("00" & tc_divclk(nbbit_div-1 DOWNTO 1)) ELSE '0';
|
71 |
|
|
|
72 |
|
|
--------------------------------------------
|
73 |
|
|
-- Déserialisateur des données reçues sur rx
|
74 |
|
|
-- et remise en forme (retaillage des durée de bit) pour la recopie
|
75 |
|
|
--------------------------------------------
|
76 |
|
|
deser_shaper : PROCESS(clk_sys, rst_n)
|
77 |
|
|
BEGIN
|
78 |
|
|
IF (rst_n = '0') THEN
|
79 |
|
|
cptbit_rx <= (OTHERS => '0');
|
80 |
|
|
divclk_rx <= (OTHERS => '0');
|
81 |
|
|
rx_encours <= '0';
|
82 |
|
|
tx <= '1';
|
83 |
|
|
val <= '0';
|
84 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
85 |
|
|
IF (rx_encours = '0') THEN
|
86 |
|
|
-- Si on est pas déjà en train de sérialiser un car
|
87 |
|
|
val <= '0'; -- On s'assure que l'écriture dans la FIFO de réception ne dure qu'un pulse
|
88 |
|
|
IF (rx = '0' and rx_r = '1') THEN
|
89 |
|
|
-- Sur détection du front descendant (le Start bit)
|
90 |
|
|
cptbit_rx <= (OTHERS => '0'); -- On initialise le compteur de bits
|
91 |
|
|
-- on initialise le diviseur d'horloge à la fin du tc
|
92 |
|
|
-- on rajoute 1 pour compenser le retard de détection du front descendant
|
93 |
|
|
-- Donc on initialise à 0
|
94 |
|
|
divclk_rx <= (others => '0');
|
95 |
|
|
sumrx <= (others => '0'); -- On init la somme des sur-echantillonnages
|
96 |
|
|
rx_encours <= '1'; -- On indique qu'on est en réception
|
97 |
|
|
END IF;
|
98 |
|
|
tx <= '1'; -- Idle de la ligne Tx
|
99 |
|
|
ELSE
|
100 |
|
|
-- Si on est en train de recevoir un car
|
101 |
|
|
IF (divclk_rx = tc_divclk) THEN
|
102 |
|
|
-- Si on atteind le terminal count (TC) du diviseur d'horloge
|
103 |
|
|
-- On va traiter un bit de plus
|
104 |
|
|
divclk_rx <= (OTHERS => '0'); -- re init du diviseur d'horloge
|
105 |
|
|
sumrx <= (others => '0'); -- re init de la somme
|
106 |
|
|
cptbit_rx <= cptbit_rx + 1; -- Un bit de plus reçu
|
107 |
|
|
shifter_rx <= consol_bit & shifter_rx(7 downto 1); -- On considère un nouveau bit LSB first
|
108 |
|
|
IF (baud_lock = '0') THEN
|
109 |
|
|
-- Tant que l'algo d'Autobaudrate n'a pas convergé
|
110 |
|
|
tx <= '1'; -- On ne recopie rien
|
111 |
|
|
ELSE
|
112 |
|
|
tx <= consol_bit; -- On recopie le bit consolidé
|
113 |
|
|
END IF;
|
114 |
|
|
IF (cptbit_rx = "1000") then -- On est en train de recevoir le 9ème bit (Start + 8 data)
|
115 |
|
|
val <= '1'; -- On valide la donnée
|
116 |
|
|
rx_encours <= '0'; -- On arrête la réception et on va attendre le prochain start
|
117 |
|
|
ELSIF (cptbit_rx = "0000") AND (consol_bit = '1') THEN
|
118 |
|
|
-- Si on est au premier bit et que c'est pas un '0' (bit de START)
|
119 |
|
|
rx_encours <= '0'; -- On arrête la réception
|
120 |
|
|
END IF;
|
121 |
|
|
ELSE
|
122 |
|
|
divclk_rx <= divclk_rx + 1; -- En cours de réception on mesure la durée d'un bit
|
123 |
|
|
sumrx <= sumrx + rx; -- On somme les sur-échantillonnages
|
124 |
|
|
val <= '0'; -- On s'assure que le signal dure 1 pulse
|
125 |
|
|
END IF;
|
126 |
|
|
END IF;
|
127 |
|
|
END IF;
|
128 |
|
|
END PROCESS;
|
129 |
|
|
rx_dat <= shifter_rx; -- La data reçue correspond au registre à décalage lorsque val = '1'
|
130 |
|
|
busy <= rx_encours;
|
131 |
|
|
END rtl;
|
132 |
|
|
|