1 |
2 |
DavidRAMBA |
--=============================================================================
|
2 |
|
|
-- TITRE : serial_tx
|
3 |
|
|
-- DESCRIPTION :
|
4 |
|
|
-- Sérialise un mot 8 bits sur 10 bits. La durée d'un bit est
|
5 |
|
|
-- égale à tc_divclk+1 pulse de clk_sys
|
6 |
|
|
|
7 |
|
|
-- FICHIER : serial_tx.vhd
|
8 |
|
|
--=============================================================================
|
9 |
|
|
-- CREATION
|
10 |
|
|
-- DATE AUTEUR PROJET REVISION
|
11 |
|
|
-- 10/04/2014 DRA SATURN V1.0
|
12 |
|
|
--=============================================================================
|
13 |
|
|
-- HISTORIQUE DES MODIFICATIONS :
|
14 |
|
|
-- DATE AUTEUR PROJET REVISION
|
15 |
|
|
--=============================================================================
|
16 |
|
|
|
17 |
|
|
LIBRARY IEEE;
|
18 |
|
|
USE IEEE.STD_LOGIC_1164.ALL;
|
19 |
|
|
USE IEEE.STD_LOGIC_ARITH.ALL;
|
20 |
|
|
USE IEEE.STD_LOGIC_UNSIGNED.ALL;
|
21 |
|
|
|
22 |
|
|
ENTITY serial_tx IS
|
23 |
|
|
GENERIC (
|
24 |
|
|
nbbit_div : INTEGER := 10); -- Nombre de bits pour coder le diviseur d'horloge
|
25 |
|
|
PORT (
|
26 |
|
|
-- Ports système
|
27 |
|
|
clk_sys : IN STD_LOGIC; -- Clock système
|
28 |
|
|
rst_n : IN STD_LOGIC; -- Reset général système
|
29 |
|
|
|
30 |
|
|
-- Interface série
|
31 |
|
|
tc_divclk: IN STD_LOGIC_VECTOR (nbbit_div-1 DOWNTO 0); -- Diviseur de l'horloge système pour le baudrate
|
32 |
|
|
tx : OUT STD_LOGIC; -- Transmission série
|
33 |
|
|
|
34 |
|
|
-- Interface parallèle
|
35 |
|
|
ser_rdy : OUT STD_LOGIC; -- Le sérialisateur est prêt à traiter un nouveau car
|
36 |
|
|
start_ser: IN STD_LOGIC; -- Déclenche la sérialisation du mot présent sur tx_dat
|
37 |
|
|
tx_dat : IN STD_LOGIC_VECTOR (7 DOWNTO 0) -- Prochaine donnée à sérialiser
|
38 |
|
|
);
|
39 |
|
|
END serial_tx;
|
40 |
|
|
|
41 |
|
|
ARCHITECTURE rtl of serial_tx is
|
42 |
|
|
SIGNAL cptbit_tx : STD_LOGIC_VECTOR(3 downto 0); -- Compteur de bits dans un caractère en émission
|
43 |
|
|
SIGNAL divclk_tx : STD_LOGIC_VECTOR(nbbit_div-1 downto 0); -- Diviseur d'horloge pour mesurer un bit en émission
|
44 |
|
|
SIGNAL ser_rdy_buf : STD_LOGIC; -- Le sérialisateur est prêt à traiter un nouveau car
|
45 |
|
|
SIGNAL shifter_tx : STD_LOGIC_VECTOR(9 downto 0); -- Registre à décalage pour la transmission
|
46 |
|
|
|
47 |
|
|
BEGIN
|
48 |
|
|
|
49 |
|
|
--------------------------------------------
|
50 |
|
|
-- Sérialise sur 10 bits une donnée 8 bits en entrée
|
51 |
|
|
--------------------------------------------
|
52 |
|
|
ser : PROCESS(clk_sys, rst_n)
|
53 |
|
|
BEGIN
|
54 |
|
|
IF (rst_n = '0') THEN
|
55 |
|
|
cptbit_tx <= (OTHERS => '0');
|
56 |
|
|
divclk_tx <= (OTHERS => '0');
|
57 |
|
|
ser_rdy_buf <= '1';
|
58 |
|
|
shifter_tx <= (OTHERS => '1');
|
59 |
|
|
ELSIF (clk_sys'EVENT and clk_sys = '1') THEN
|
60 |
|
|
IF (ser_rdy_buf = '1') THEN
|
61 |
|
|
-- Si le sérialisateur est libre (i.e. il n'est pas déjà en train de sérialiser)
|
62 |
|
|
IF (start_ser = '1') THEN
|
63 |
|
|
-- Sur réception d'un ordre de sérialisation
|
64 |
|
|
ser_rdy_buf <= '0'; -- On indique que le sérialsiateur est occupé
|
65 |
|
|
shifter_tx <= '1' & tx_dat & '0'; -- On charge le registre à décalage avec le start, les 8 bits de data et le stop
|
66 |
|
|
cptbit_tx <= (OTHERS => '0'); -- On init le compteur de bit
|
67 |
|
|
divclk_tx <= (OTHERS => '0'); -- On init le diviseur d'horloge
|
68 |
|
|
END IF;
|
69 |
|
|
ELSE
|
70 |
|
|
-- Si on est en cours de sérialsiation
|
71 |
|
|
IF (divclk_tx = tc_divclk) THEN
|
72 |
|
|
-- Pour chaque durée de 1 bit
|
73 |
|
|
shifter_tx <= '1' & shifter_tx(9 downto 1); -- On décale LSB first en insérant des 1 (ligne IDLE)
|
74 |
|
|
cptbit_tx <= cptbit_tx + 1; -- un bit de plus traité
|
75 |
|
|
IF (cptbit_tx = "1001") THEN
|
76 |
|
|
-- Lorsqu'on a transmis les 10 bits
|
77 |
|
|
ser_rdy_buf <= '1'; -- On revient en disponible
|
78 |
|
|
ELSIF (cptbit_tx = "1000") THEN
|
79 |
|
|
-- A la fin d'émission du 9 ème bit
|
80 |
|
|
divclk_tx <= CONV_STD_LOGIC_VECTOR(1, divclk_tx'length); -- On initiaslie le compteur à 1 pour que le signal
|
81 |
|
|
-- ser_rdy soit synhcrone du dernier clk_sys du dernier bit
|
82 |
|
|
ELSE
|
83 |
|
|
-- Pour tous les autres bits, on compte le nombre de cycles exact pour la durée de 1 bit
|
84 |
|
|
divclk_tx <= (OTHERS => '0');
|
85 |
|
|
END IF;
|
86 |
|
|
ELSE
|
87 |
|
|
divclk_tx <= divclk_tx + 1;
|
88 |
|
|
END IF;
|
89 |
|
|
END IF;
|
90 |
|
|
END IF;
|
91 |
|
|
END PROCESS;
|
92 |
|
|
ser_rdy <= ser_rdy_buf;
|
93 |
|
|
tx <= shifter_tx(0);
|
94 |
|
|
|
95 |
|
|
END rtl;
|
96 |
|
|
|