Project

General

Profile

Download (14.8 KB) Statistics
| Branch: | Tag: | Revision:
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 -----------------------------------------------------------------
(13-13/21)