-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathuart_rx.vhd
More file actions
145 lines (137 loc) · 4.63 KB
/
uart_rx.vhd
File metadata and controls
145 lines (137 loc) · 4.63 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
entity uart_rx is
port (
clock_in : in std_logic;
reset_in : in std_logic;
uart_data_rx : in std_logic;
uart_rate_rx_sel: in std_logic_vector(1 downto 0);
data_p_out : out std_logic_vector(7 downto 0);
data_p_en_out : out std_logic
);
end uart_rx;
architecture rtl of uart_rx is
-- Estados da máquina de estados
type states is (IDLE, START, RECEIVE, STOP, DONE);
signal state : states := IDLE;
signal bit_index : integer range 0 to 7 := 0;
signal shift_reg : std_logic_vector(0 to 7) := (others => '0');
signal counter : integer range 0 to 10416 := 0; -- 14 bits cobrem até 16383
signal counter_half : integer range 0 to 10416 := 0; -- 14 bits cobrem até 16383
signal baud_divisor : integer range 0 to 10416 := 0;
signal tick : std_logic:= '0';
signal tick_half : std_logic:= '0';
signal tick_half2 : std_logic:= '0';
begin
--------------------------------------------------------------------------------------------
----------------------------- Instância do gerador de baud rate-----------------------------
--------------------------------------------------------------------------------------------
baud_divisor <= 1040 when uart_rate_rx_sel = "00"else -- (int)10416/(int)10(ns) = 1041
520 when uart_rate_rx_sel = "01" else -- (int)5208/(int)10(ns) = 520
346 when uart_rate_rx_sel = "10" else -- (int)3472/(int)10(ns) = 347
172 when uart_rate_rx_sel = "11" else -- (int)1736/(int)10(ns) = 173
1040;-- (int)10416/(int)10(ns) = 1041 + 1 = 1042
--------------------------------------------------------------------------------------------
------------------------------ FSM principal da recepção UART ------------------------------
--------------------------------------------------------------------------------------------
process(clock_in)
begin
if rising_edge(clock_in) then
if reset_in = '1' then
state <= IDLE;
bit_index <= 0;
shift_reg <= (others => '0');
data_p_out <= (others => '0');
data_p_en_out <= '0';
-----------------------------
counter <= 0;
tick <= '0';
tick_half <= '0';
-----------------------------
else
data_p_en_out <= '0'; -- padrão: sem dado novo
-----------------------------
tick <= '0';
-----------------------------
------------------------------------------------------
case state is
----------<<<<<<<<<<<<< IDLE >>>>>>>>>>>>>----------
when IDLE =>
if uart_data_rx = '0' then
state <= START;
end if;
----------<<<<<<<<<<<<< START >>>>>>>>>>>>>----------
when START =>
-----------------------------
if counter_half = (baud_divisor/2) then
tick_half <= '1';
counter_half <= 0;
else
counter_half <= counter_half + 1;
if tick_half = '1' then
counter <= counter + 1;
end if;
end if;
if counter = (baud_divisor/2) then
tick_half2 <= '1';
end if;
-----------------------------
if tick_half2 = '1' then
if uart_data_rx = '0' then
state <= RECEIVE;
bit_index <= 0;
tick_half <= '0';
tick_half2 <= '0';
else
state <= IDLE; -- ruído
end if;
end if;
-----------------------------
----------<<<<<<<<<<<<< RECEIVE >>>>>>>>>>>>>----------
when RECEIVE =>
if counter = baud_divisor then
tick <= '1';
counter <= 0;
else
counter <= counter + 1;
end if;
-----------------------------
if tick = '1' then
shift_reg(bit_index) <= uart_data_rx;
if bit_index = 7 then
state <= STOP;
else
bit_index <= bit_index + 1;
end if;
end if;
-----------<<<<<<<<<<<<< STOP >>>>>>>>>>>>>-----------
when STOP =>
if counter = baud_divisor then
tick <= '1';
counter <= 0;
else
counter <= counter + 1;
end if;
-----------------------------
if tick = '1' then
if uart_data_rx = '1' then
state <= DONE;
else
state <= IDLE; -- erro de stop bit
end if;
end if;
-----------<<<<<<<<<<<<< DONE >>>>>>>>>>>>>-----------
when DONE =>
data_p_out <= shift_reg;
data_p_en_out <= '1';
state <= IDLE;
-----------------------------
counter <= 0;
counter_half <= 0;
end case;
-----------------------------------------------------------
end if;
end if;
end process;
end rtl;