1
|
--------------------------------------------------------------------------------
|
2
|
--| @file uart.vhd
|
3
|
--| @brief implements a universal asynchronous receiver transmitter with
|
4
|
--| parameterisable baud rate. tested on a spartan 6 lx9 connected to a
|
5
|
--| silicon labs cp210 usb-uart bridge.
|
6
|
--|
|
7
|
--| @author peter a bennett
|
8
|
--| @copyright (c) 2012 peter a bennett
|
9
|
--| @license Apache 2.0
|
10
|
--| @email pab850@googlemail.com
|
11
|
--| @contact www.bytebash.com
|
12
|
--|
|
13
|
--| See https://github.com/pabennett/uart
|
14
|
--|
|
15
|
--| There have been many changes to the original code, consult the git logs
|
16
|
--| for a full list of changes.
|
17
|
--|
|
18
|
--| @note Changes made to range to stop Xilinx warnings and with formatting,
|
19
|
--| the UART has also been wrapped up in a package and top level component
|
20
|
--| (called "uart_top") to make the interface easier to use and less confusing.
|
21
|
--| This has not be tested yet.
|
22
|
--|
|
23
|
--| @note Somewhere along the chain from the computer, to the Nexys3 board,
|
24
|
--| to the UART module, and finally to the H2 core, bytes are being lost in
|
25
|
--| transmission from the computer. This UART really should be buffered
|
26
|
--| as well.
|
27
|
--|
|
28
|
--| START 0 1 2 3 4 5 6 7 STOP
|
29
|
--| ----\_/-|-|-|-|-|-|-|-|-|-------
|
30
|
--|
|
31
|
--------------------------------------------------------------------------------
|
32
|
library ieee;
|
33
|
use ieee.std_logic_1164.all;
|
34
|
|
35
|
package uart_pkg is
|
36
|
|
37
|
component uart_top is
|
38
|
generic (baud_rate: positive; clock_frequency: positive; fifo_depth: positive := 8);
|
39
|
port (
|
40
|
clk: in std_ulogic;
|
41
|
rst: in std_ulogic;
|
42
|
|
43
|
rx_data: out std_ulogic_vector(7 downto 0);
|
44
|
rx_fifo_empty: out std_ulogic;
|
45
|
rx_fifo_full: out std_ulogic;
|
46
|
rx_data_re: in std_ulogic;
|
47
|
|
48
|
tx_data: in std_ulogic_vector(7 downto 0);
|
49
|
tx_fifo_full: out std_ulogic;
|
50
|
tx_fifo_empty: out std_ulogic;
|
51
|
tx_data_we: in std_ulogic;
|
52
|
|
53
|
tx: out std_ulogic;
|
54
|
rx: in std_ulogic);
|
55
|
|
56
|
end component;
|
57
|
|
58
|
component uart_core is
|
59
|
generic (baud_rate: positive; clock_frequency: positive);
|
60
|
port (
|
61
|
clk: in std_ulogic;
|
62
|
rst: in std_ulogic;
|
63
|
din: in std_ulogic_vector(7 downto 0);
|
64
|
din_stb: in std_ulogic;
|
65
|
din_ack: out std_ulogic := '0';
|
66
|
din_busy: out std_ulogic;
|
67
|
|
68
|
dout: out std_ulogic_vector(7 downto 0);
|
69
|
dout_stb: out std_ulogic;
|
70
|
dout_ack: in std_ulogic;
|
71
|
dout_busy: out std_ulogic;
|
72
|
|
73
|
tx: out std_ulogic;
|
74
|
rx: in std_ulogic);
|
75
|
end component;
|
76
|
|
77
|
end package;
|
78
|
|
79
|
---- UART Package --------------------------------------------------------------
|
80
|
|
81
|
---- UART Top ------------------------------------------------------------------
|
82
|
|
83
|
library ieee;
|
84
|
use ieee.std_logic_1164.all;
|
85
|
use ieee.numeric_std.all;
|
86
|
use work.util.fifo;
|
87
|
use work.uart_pkg.uart_core;
|
88
|
|
89
|
entity uart_top is
|
90
|
generic (baud_rate: positive; clock_frequency: positive; fifo_depth: positive := 8);
|
91
|
port (
|
92
|
clk: in std_ulogic;
|
93
|
rst: in std_ulogic;
|
94
|
|
95
|
rx_data: out std_ulogic_vector(7 downto 0);
|
96
|
rx_fifo_empty: out std_ulogic;
|
97
|
rx_fifo_full: out std_ulogic;
|
98
|
rx_data_re: in std_ulogic;
|
99
|
|
100
|
tx_data: in std_ulogic_vector(7 downto 0);
|
101
|
tx_fifo_full: out std_ulogic;
|
102
|
tx_fifo_empty: out std_ulogic;
|
103
|
tx_data_we: in std_ulogic;
|
104
|
|
105
|
tx: out std_ulogic;
|
106
|
rx: in std_ulogic);
|
107
|
end entity;
|
108
|
|
109
|
architecture behav of uart_top is
|
110
|
signal rx_sync, rx_uart, tx_uart: std_ulogic := '0';
|
111
|
|
112
|
signal din: std_ulogic_vector(7 downto 0) := (others => '0');
|
113
|
signal din_stb: std_ulogic := '0';
|
114
|
signal din_ack: std_ulogic := '0';
|
115
|
signal din_busy: std_ulogic := '0';
|
116
|
|
117
|
signal dout: std_ulogic_vector(7 downto 0) := (others => '0');
|
118
|
signal dout_stb: std_ulogic := '0';
|
119
|
signal dout_ack: std_ulogic := '0';
|
120
|
signal dout_busy: std_ulogic := '0';
|
121
|
|
122
|
signal tx_fifo_re: std_ulogic := '0';
|
123
|
signal tx_fifo_empty_internal: std_ulogic := '1';
|
124
|
signal tx_fifo_full_internal: std_ulogic := '0';
|
125
|
|
126
|
signal wrote_c, wrote_n: std_ulogic := '0';
|
127
|
|
128
|
begin
|
129
|
uart_deglitch: process (clk, rst)
|
130
|
begin
|
131
|
if rst = '1' then
|
132
|
wrote_c <= '0';
|
133
|
elsif rising_edge(clk) then
|
134
|
rx_sync <= rx;
|
135
|
rx_uart <= rx_sync;
|
136
|
tx <= tx_uart;
|
137
|
wrote_c <= wrote_n;
|
138
|
end if;
|
139
|
end process;
|
140
|
|
141
|
process(dout_stb, tx_fifo_empty_internal, tx_fifo_full_internal, din_ack, wrote_c, din_busy)
|
142
|
begin
|
143
|
dout_ack <= '0';
|
144
|
din_stb <= '0';
|
145
|
tx_fifo_re <= '0';
|
146
|
wrote_n <= wrote_c;
|
147
|
|
148
|
if dout_stb = '1' then
|
149
|
dout_ack <= '1';
|
150
|
end if;
|
151
|
|
152
|
if tx_fifo_empty_internal = '0' and tx_fifo_full_internal = '0' and din_busy = '0' then
|
153
|
tx_fifo_re <= '1';
|
154
|
wrote_n <= '1';
|
155
|
elsif din_ack = '0' and wrote_c = '1' then
|
156
|
--elsif wrote_c = '1' then
|
157
|
-- assert din_ack = '1' on the next cycle?
|
158
|
din_stb <= '1';
|
159
|
wrote_n <= '0';
|
160
|
end if;
|
161
|
end process;
|
162
|
|
163
|
rx_fifo: work.util.fifo
|
164
|
generic map (
|
165
|
data_width => 8,
|
166
|
fifo_depth => fifo_depth)
|
167
|
port map(
|
168
|
clk => clk,
|
169
|
rst => rst,
|
170
|
di => dout,
|
171
|
we => dout_stb,
|
172
|
re => rx_data_re,
|
173
|
do => rx_data,
|
174
|
full => rx_fifo_full,
|
175
|
empty => rx_fifo_empty);
|
176
|
|
177
|
tx_fifo: work.util.fifo
|
178
|
generic map (
|
179
|
data_width => 8,
|
180
|
fifo_depth => fifo_depth)
|
181
|
port map(
|
182
|
clk => clk,
|
183
|
rst => rst,
|
184
|
di => tx_data,
|
185
|
we => tx_data_we,
|
186
|
re => tx_fifo_re,
|
187
|
do => din,
|
188
|
full => tx_fifo_full_internal,
|
189
|
empty => tx_fifo_empty_internal);
|
190
|
|
191
|
tx_fifo_empty <= tx_fifo_empty_internal;
|
192
|
-- @bug This is a hack, it should be just 'tx_fifo_full_internal', but
|
193
|
-- it does not work correctly, so as a temporary hack the busy signal
|
194
|
-- is or'd in so the data source can block until the FIFO is 'not full'
|
195
|
-- and not lose any data thinking it has been transmitted.
|
196
|
tx_fifo_full <= '1' when tx_fifo_full_internal = '1' or din_busy = '1' else '0';
|
197
|
|
198
|
uart: work.uart_pkg.uart_core
|
199
|
generic map(
|
200
|
baud_rate => baud_rate,
|
201
|
clock_frequency => clock_frequency)
|
202
|
port map(
|
203
|
clk => clk,
|
204
|
rst => rst,
|
205
|
din => din,
|
206
|
din_stb => din_stb,
|
207
|
din_ack => din_ack,
|
208
|
din_busy => din_busy,
|
209
|
dout => dout,
|
210
|
dout_stb => dout_stb,
|
211
|
dout_ack => dout_ack,
|
212
|
dout_busy=> dout_busy,
|
213
|
rx => rx_uart,
|
214
|
tx => tx_uart);
|
215
|
|
216
|
end;
|
217
|
|
218
|
---- UART Top ------------------------------------------------------------------
|
219
|
|
220
|
---- UART Core -----------------------------------------------------------------
|
221
|
|
222
|
library ieee;
|
223
|
use ieee.std_logic_1164.all;
|
224
|
use ieee.numeric_std.all;
|
225
|
|
226
|
entity uart_core is
|
227
|
generic(baud_rate: positive; clock_frequency: positive);
|
228
|
port(
|
229
|
clk: in std_ulogic;
|
230
|
rst: in std_ulogic;
|
231
|
din: in std_ulogic_vector(7 downto 0);
|
232
|
din_stb: in std_ulogic;
|
233
|
din_ack: out std_ulogic := '0';
|
234
|
din_busy: out std_ulogic;
|
235
|
|
236
|
dout: out std_ulogic_vector(7 downto 0);
|
237
|
dout_stb: out std_ulogic;
|
238
|
dout_ack: in std_ulogic;
|
239
|
dout_busy: out std_ulogic;
|
240
|
|
241
|
tx: out std_ulogic;
|
242
|
rx: in std_ulogic);
|
243
|
end entity;
|
244
|
|
245
|
architecture behav of uart_core is
|
246
|
|
247
|
constant uart_tx_count_max: positive := 7;
|
248
|
constant uart_rx_count_max: positive := 7;
|
249
|
----------------------------------------------------------------------------
|
250
|
-- baud generation
|
251
|
----------------------------------------------------------------------------
|
252
|
constant c_tx_divider_val: integer := clock_frequency / baud_rate;
|
253
|
constant c_rx_divider_val: integer := clock_frequency / (baud_rate * 16);
|
254
|
|
255
|
signal baud_counter: integer range 0 to c_tx_divider_val;
|
256
|
signal baud_tick: std_ulogic := '0';
|
257
|
signal oversample_baud_counter: integer range 0 to c_rx_divider_val := 0;
|
258
|
signal oversample_baud_tick: std_ulogic := '0';
|
259
|
|
260
|
----------------------------------------------------------------------------
|
261
|
-- transmitter signals
|
262
|
----------------------------------------------------------------------------
|
263
|
type uart_tx_states is (idle,
|
264
|
wait_for_tick,
|
265
|
send_start_bit,
|
266
|
transmit_data,
|
267
|
send_stop_bit);
|
268
|
|
269
|
signal uart_tx_state: uart_tx_states := idle;
|
270
|
|
271
|
signal uart_tx_data_block: std_ulogic_vector(7 downto 0) := (others => '0');
|
272
|
signal uart_tx_data: std_ulogic := '1';
|
273
|
signal uart_tx_count: integer range 0 to uart_tx_count_max := 0;
|
274
|
signal uart_rx_data_in_ack: std_ulogic := '0';
|
275
|
----------------------------------------------------------------------------
|
276
|
-- receiver signals
|
277
|
----------------------------------------------------------------------------
|
278
|
type uart_rx_states is (rx_wait_start_synchronise,
|
279
|
rx_get_start_bit,
|
280
|
rx_get_data,
|
281
|
rx_get_stop_bit,
|
282
|
rx_send_block);
|
283
|
|
284
|
signal uart_rx_state: uart_rx_states := rx_get_start_bit;
|
285
|
signal uart_rx_bit: std_ulogic := '1'; -- @note should the be 0 or 1?
|
286
|
signal uart_rx_data_block: std_ulogic_vector(7 downto 0) := (others => '0');
|
287
|
signal uart_rx_data_vec: std_ulogic_vector(1 downto 0) := (others => '0');
|
288
|
signal uart_rx_filter: unsigned(1 downto 0) := (others => '1');
|
289
|
signal uart_rx_count: integer range 0 to uart_rx_count_max := 0;
|
290
|
signal uart_rx_data_out_stb: std_ulogic := '0';
|
291
|
signal uart_rx_bit_spacing: unsigned (3 downto 0) := (others => '0');
|
292
|
signal uart_rx_bit_tick: std_ulogic := '0';
|
293
|
begin
|
294
|
|
295
|
din_ack <= uart_rx_data_in_ack;
|
296
|
dout <= uart_rx_data_block;
|
297
|
dout_stb <= uart_rx_data_out_stb;
|
298
|
tx <= uart_tx_data;
|
299
|
|
300
|
din_busy <= '0' when uart_tx_state = idle else '1';
|
301
|
dout_busy <= '0' when uart_rx_state = rx_get_start_bit or uart_rx_state = rx_send_block else '1';
|
302
|
|
303
|
-- the input clk is 100MHz, this needs to be divided down to the
|
304
|
-- rate dictated by the baud_rate. for example, if 115200 baud is selected
|
305
|
-- (115200 baud = 115200 bps - 115.2kbps) a tick must be generated once
|
306
|
-- every 1/115200
|
307
|
tx_clk_divider: process (clk, rst)
|
308
|
begin
|
309
|
if rst = '1' then
|
310
|
baud_counter <= 0;
|
311
|
baud_tick <= '0';
|
312
|
elsif rising_edge (clk) then
|
313
|
if baud_counter = c_tx_divider_val then
|
314
|
baud_counter <= 0;
|
315
|
baud_tick <= '1';
|
316
|
else
|
317
|
baud_counter <= baud_counter + 1;
|
318
|
baud_tick <= '0';
|
319
|
end if;
|
320
|
end if;
|
321
|
end process;
|
322
|
|
323
|
-- get data from din and send it one bit at a time
|
324
|
-- upon each baud tick. lsb first.
|
325
|
-- wait 1 tick, send start bit (0), send data 0-7, send stop bit (1)
|
326
|
uart_send_data: process(clk, rst)
|
327
|
begin
|
328
|
if rst = '1' then
|
329
|
uart_tx_data <= '1';
|
330
|
uart_tx_data_block <= (others => '0');
|
331
|
uart_tx_count <= 0;
|
332
|
uart_tx_state <= idle;
|
333
|
uart_rx_data_in_ack <= '0';
|
334
|
elsif rising_edge(clk) then
|
335
|
uart_rx_data_in_ack <= '0';
|
336
|
case uart_tx_state is
|
337
|
when idle =>
|
338
|
if din_stb = '1' then
|
339
|
uart_tx_data_block <= din;
|
340
|
uart_rx_data_in_ack <= '1';
|
341
|
uart_tx_state <= wait_for_tick;
|
342
|
end if;
|
343
|
when wait_for_tick =>
|
344
|
if baud_tick = '1' then
|
345
|
uart_tx_state <= send_start_bit;
|
346
|
end if;
|
347
|
when send_start_bit =>
|
348
|
if baud_tick = '1' then
|
349
|
uart_tx_data <= '0';
|
350
|
uart_tx_state <= transmit_data;
|
351
|
uart_tx_count <= 0;
|
352
|
end if;
|
353
|
when transmit_data =>
|
354
|
if baud_tick = '1' then
|
355
|
if uart_tx_count < uart_tx_count_max then
|
356
|
uart_tx_data <= uart_tx_data_block(uart_tx_count);
|
357
|
uart_tx_count <= uart_tx_count + 1;
|
358
|
else
|
359
|
uart_tx_data <= uart_tx_data_block(7);
|
360
|
uart_tx_count <= 0;
|
361
|
uart_tx_state <= send_stop_bit;
|
362
|
end if;
|
363
|
end if;
|
364
|
when send_stop_bit =>
|
365
|
if baud_tick = '1' then
|
366
|
uart_tx_data <= '1';
|
367
|
uart_tx_state <= idle;
|
368
|
end if;
|
369
|
when others =>
|
370
|
uart_tx_data <= '1';
|
371
|
uart_tx_state <= idle;
|
372
|
end case;
|
373
|
end if;
|
374
|
end process;
|
375
|
|
376
|
-- generate an oversampled tick (baud * 16)
|
377
|
oversample_clk_divider: process (clk, rst)
|
378
|
begin
|
379
|
if rst = '1' then
|
380
|
oversample_baud_counter <= 0;
|
381
|
oversample_baud_tick <= '0';
|
382
|
elsif rising_edge (clk) then
|
383
|
if oversample_baud_counter = c_rx_divider_val then
|
384
|
oversample_baud_counter <= 0;
|
385
|
oversample_baud_tick <= '1';
|
386
|
else
|
387
|
oversample_baud_counter <= oversample_baud_counter + 1;
|
388
|
oversample_baud_tick <= '0';
|
389
|
end if;
|
390
|
end if;
|
391
|
end process;
|
392
|
|
393
|
-- synchronise rxd to the oversampled baud
|
394
|
rxd_synchronise: process(clk, rst)
|
395
|
begin
|
396
|
if rst = '1' then
|
397
|
uart_rx_data_vec <= (others => '0');
|
398
|
elsif rising_edge(clk) then
|
399
|
if oversample_baud_tick = '1' then
|
400
|
uart_rx_data_vec(0) <= rx;
|
401
|
uart_rx_data_vec(1) <= uart_rx_data_vec(0);
|
402
|
end if;
|
403
|
end if;
|
404
|
end process;
|
405
|
|
406
|
-- filter rxd with a 2 bit counter.
|
407
|
rxd_filter: process(clk, rst)
|
408
|
begin
|
409
|
if rst = '1' then
|
410
|
uart_rx_filter <= (others => '1');
|
411
|
uart_rx_bit <= '1';
|
412
|
elsif rising_edge(clk) then
|
413
|
if oversample_baud_tick = '1' then
|
414
|
-- filter rxd.
|
415
|
if uart_rx_data_vec(1) = '1' and uart_rx_filter < 3 then
|
416
|
uart_rx_filter <= uart_rx_filter + 1;
|
417
|
elsif uart_rx_data_vec(1) = '0' and uart_rx_filter > 0 then
|
418
|
uart_rx_filter <= uart_rx_filter - 1;
|
419
|
end if;
|
420
|
-- set the rx bit.
|
421
|
if uart_rx_filter = 3 then
|
422
|
uart_rx_bit <= '1';
|
423
|
elsif uart_rx_filter = 0 then
|
424
|
uart_rx_bit <= '0';
|
425
|
end if;
|
426
|
end if;
|
427
|
end if;
|
428
|
end process;
|
429
|
|
430
|
rx_bit_spacing: process (clk, rst)
|
431
|
begin
|
432
|
if rising_edge(clk) then
|
433
|
uart_rx_bit_tick <= '0';
|
434
|
if oversample_baud_tick = '1' then
|
435
|
if uart_rx_bit_spacing = 15 then
|
436
|
uart_rx_bit_tick <= '1';
|
437
|
uart_rx_bit_spacing <= (others => '0');
|
438
|
else
|
439
|
uart_rx_bit_spacing <= uart_rx_bit_spacing + 1;
|
440
|
end if;
|
441
|
if uart_rx_state = rx_get_start_bit then
|
442
|
uart_rx_bit_spacing <= (others => '0');
|
443
|
end if;
|
444
|
end if;
|
445
|
end if;
|
446
|
end process;
|
447
|
|
448
|
uart_receive_data: process(clk, rst)
|
449
|
begin
|
450
|
if rst = '1' then
|
451
|
uart_rx_state <= rx_get_start_bit;
|
452
|
uart_rx_data_block <= (others => '0');
|
453
|
uart_rx_count <= 0;
|
454
|
uart_rx_data_out_stb <= '0';
|
455
|
elsif rising_edge(clk) then
|
456
|
case uart_rx_state is
|
457
|
when rx_get_start_bit =>
|
458
|
if oversample_baud_tick = '1' and uart_rx_bit = '0' then
|
459
|
uart_rx_state <= rx_get_data;
|
460
|
end if;
|
461
|
when rx_get_data =>
|
462
|
if uart_rx_bit_tick = '1' then
|
463
|
if uart_rx_count < uart_rx_count_max then
|
464
|
uart_rx_data_block(uart_rx_count) <= uart_rx_bit;
|
465
|
uart_rx_count <= uart_rx_count + 1;
|
466
|
else
|
467
|
uart_rx_data_block(7) <= uart_rx_bit;
|
468
|
uart_rx_count <= 0;
|
469
|
uart_rx_state <= rx_get_stop_bit;
|
470
|
end if;
|
471
|
end if;
|
472
|
when rx_get_stop_bit =>
|
473
|
if uart_rx_bit_tick = '1' then
|
474
|
if uart_rx_bit = '1' then
|
475
|
uart_rx_state <= rx_send_block;
|
476
|
uart_rx_data_out_stb <= '1';
|
477
|
end if;
|
478
|
end if;
|
479
|
when rx_send_block =>
|
480
|
if dout_ack = '1' then
|
481
|
uart_rx_data_out_stb <= '0';
|
482
|
uart_rx_data_block <= (others => '0');
|
483
|
uart_rx_state <= rx_get_start_bit;
|
484
|
else
|
485
|
uart_rx_data_out_stb <= '1';
|
486
|
end if;
|
487
|
when others =>
|
488
|
uart_rx_state <= rx_get_start_bit;
|
489
|
end case;
|
490
|
end if;
|
491
|
end process;
|
492
|
end;
|
493
|
|
494
|
---- UART Core -----------------------------------------------------------------
|