-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathuart.vhd
executable file
·133 lines (122 loc) · 3.35 KB
/
uart.vhd
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
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity uart is
port ( clock : in STD_LOGIC; -- Master clock
reset : in STD_LOGIC; -- Master reset
trigger : in STD_LOGIC; -- There's a byte to send
write_data : in STD_LOGIC_VECTOR (7 downto 0); -- Data to write
read_data : out STD_LOGIC_VECTOR (7 downto 0); -- Data we have read
framing_error_set : out STD_LOGIC; -- Start or stop error
tx_ready : out STD_LOGIC; -- Transmitter is ready = 1
rx_ready_set : out STD_LOGIC; -- Got a full byte
tx : out STD_LOGIC;
rx : in STD_LOGIC
);
end entity;
architecture behavioral of uart is
type T_STATE is (IDLE, START, DATA, STOP);
begin
process (reset, clock)
-- 115200 with 20MHz input clock, actual baud rate c. 114942, an error of 0.3%
variable baud_counter : INTEGER range 0 to 174 := 0;
variable sending : STD_LOGIC := '0';
variable bit_counter : INTEGER range 0 to 7 := 0;
variable state : T_STATE := IDLE;
begin
if (reset = '1') then
state := IDLE;
elsif (clock'Event and clock = '1') then
tx_ready <= not sending;
if (sending = '1') then
if (baud_counter = 0) then
baud_counter := 174;
end if;
baud_counter := baud_counter - 1;
end if;
case state is
when IDLE =>
tx <= '1';
sending := '0';
baud_counter := 174;
if (trigger = '1') then
sending := '1';
state := START;
end if;
when START =>
tx <= '0';
if (baud_counter = 0) then
state := DATA;
bit_counter := 0;
end if;
when DATA =>
tx <= write_data (bit_counter);
if (baud_counter = 0) then
if (bit_counter = 7) then
state := STOP;
else
bit_counter := bit_counter + 1;
end if;
end if;
when STOP =>
tx <= '1';
if (baud_counter = 0) then
state := IDLE;
end if;
end case;
end if;
end process;
process (reset, clock)
variable baud_counter : INTEGER range 0 to 174 := 0;
variable receiving : STD_LOGIC := '0';
variable bit_counter : INTEGER range 0 to 7 := 0;
variable state : T_STATE := IDLE;
begin
if (reset = '1') then
state := IDLE;
elsif (clock'Event and clock = '1') then
rx_ready_set <= '0';
if (receiving = '1') then
if (baud_counter = 0) then
baud_counter := 174;
end if;
baud_counter := baud_counter - 1;
end if;
case state is
when IDLE =>
framing_error_set <= '0';
receiving := '0';
-- Center over the incoming bit
baud_counter := 174 / 2;
if (rx = '0') then
receiving := '1';
state := START;
end if;
when START =>
if (baud_counter = 0) then
if (rx = '1') then
framing_error_set <= '1';
end if;
bit_counter := 0;
state := DATA;
end if;
when DATA =>
read_data (bit_counter) <= rx;
if (baud_counter = 0) then
if (bit_counter = 7) then
state := STOP;
else
bit_counter := bit_counter + 1;
end if;
end if;
when STOP =>
if (baud_counter = 0) then
if (rx = '0') then
framing_error_set <= '1';
end if;
rx_ready_set <= '1';
state := IDLE;
end if;
end case;
end if;
end process;
end architecture;