forth-cpu

Форк
0
/
uart.vhd 
937 строк · 27.3 Кб
1
-- FILE:      uart.vhd
2
-- BRIEF:     UART TX/RX module
3
-- LICENSE:   MIT
4
-- COPYRIGHT: Richard James Howe (2019)
5
--
6
-- The UART (Universal Asynchronous Receiver/Transmitter) is one of the simplest
7
-- serial communication methods available. It is often used for debugging, for
8
-- issuing commands to embedded devices and sometimes even for uploading firmware
9
-- to devices. The data format and speed are configurable but there is no method
10
-- for automatically configuring a UART, both sides must have agreed on the
11
-- settings before hand. Configurable options include; baud, use of an
12
-- even of odd parity bit, number of data bits and number of stop bits.
13
--
14
-- The clock is not transmitted as part of the signal (which is why baud
15
-- must be agreed upon before hand), a single packet starts with a 'start bit',
16
-- where the line goes low. The receiver must synchronize to this start bit (it
17
-- resets the clock that generates pulse at the sample rate and baud when it
18
-- encounters a start bit).
19
--
20
-- A transmission with 8 data bits, 1 parity bit and 1 stop bit looks like
21
-- this:
22
-- ____   ______________________________   ________________
23
--     \_/|0|1|2|3|4|5|6|7|P|S|         \_/
24
--     Start   Data     Parity Stop    |--- More data --->
25
--
26
-- Start bits are always low, stop bits high. The most common format is
27
-- 8 data bits, no parity bit, and 1 stop bit at either 9600 or 115200 baud.
28
--
29
-- For the receiver a clock that is a multiple of the baud is used so the
30
-- bits can be sampled with a higher frequency than the bit rate.
31
--
32
-- Some notes:
33
-- * We can transmit from an 8-bit UART to a less than 8-bit UART fine, so
34
-- long as parity is not used, as
35
-- * Certain UARTs have the ability to transmit a BREAK signal by holding
36
-- the line low for a period greater than the packet length. We can transmit
37
-- that by lowering the baud rate and transmitting all zeroes. Receiving a
38
-- break (correctly) would require changing the receiver.
39
--
40
--
41
-- See:
42
-- * <https://en.wikipedia.org/wiki/Universal_asynchronous_receiver-transmitter>
43
--
44
-- NOTE: We could replace this entire package with an entirely software driven
45
-- solution. The only hardware we would need two timers driven at the sample
46
-- rate (one for RX, one for TX) and a deglitched RX signal. An interrupt
47
-- would be generated on the timers expiry.
48
library ieee, work;
49
use ieee.std_logic_1164.all;
50
use ieee.numeric_std.all;
51
use work.util.common_generics;
52

53
package uart_pkg is
54
	constant uart_8N1: std_ulogic_vector(7 downto 0) := "10000100";
55

56
	component uart_tx is
57
		generic (g: common_generics; N: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
58
		port (
59
			clk:    in std_ulogic;
60
			rst:    in std_ulogic;
61
			cr:    out std_ulogic;
62
			baud:   in std_ulogic; -- Pulse at baud
63
			tx:    out std_ulogic;
64
			ok:    out std_ulogic;
65
			ctr:    in std_ulogic_vector(format'range);
66
			ctr_we: in std_ulogic;
67
			we:     in std_ulogic; -- di write enable
68
			di:     in std_ulogic_vector(N - 1 downto 0));
69
	end component;
70

71
	component uart_rx is
72
		generic (g: common_generics; N: positive; D: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
73
		port (
74
			clk:     in std_ulogic;
75
			rst:     in std_ulogic;
76
			cr:     out std_ulogic;
77
			baud, sample: in std_ulogic;
78
			failed: out std_ulogic_vector(1 downto 0);
79
			ctr:    in std_ulogic_vector(7 downto 0);
80
			ctr_we: in std_ulogic;
81
			rx:     in std_ulogic;
82
			we:    out std_ulogic;
83
			do:    out std_ulogic_vector(N - 1 downto 0));
84
	end component;
85

86
	component uart_baud is -- Generates a pulse at the sample rate and baud
87
		generic (g: common_generics; init: integer; N: positive := 16; D: positive := 3);
88
		port (
89
			clk:      in std_ulogic;
90
			rst:      in std_ulogic;
91
			we:       in std_ulogic;
92
			cnt:      in std_ulogic_vector(N - 1 downto 0);
93
			cr:       in std_ulogic := '0';
94
			sample:  out std_ulogic;
95
			baud:    out std_ulogic);
96
	end component;
97

98
	component uart_core is
99
		generic (g: common_generics; baud: positive := 115200; format: std_ulogic_vector(7 downto 0) := uart_8N1);
100
		port (
101
			clk:    in std_ulogic;
102
			rst:    in std_ulogic;
103

104
			tx:    out std_ulogic;
105
			tx_ok: out std_ulogic;
106
			tx_we:  in std_ulogic;
107
			tx_di:  in std_ulogic_vector(7 downto 0);
108
	
109
			rx:     in std_ulogic;
110
			rx_ok: out std_ulogic;
111
			rx_nd: out std_ulogic;
112
			rx_re:  in std_ulogic;
113
			rx_do: out std_ulogic_vector(7 downto 0);
114
	
115
			reg:             in std_ulogic_vector(15 downto 0);
116
			clock_reg_tx_we: in std_ulogic;
117
			clock_reg_rx_we: in std_ulogic;
118
			control_reg_we:  in std_ulogic);
119
	end component;
120

121
	component uart_top is
122
		generic (
123
			g:        common_generics;
124
			baud:     positive := 115200;
125
			format:   std_ulogic_vector(7 downto 0) := uart_8N1;
126
			use_fifo: boolean := false);
127
		port (
128
			clk:    in std_ulogic;
129
			rst:    in std_ulogic;
130

131
			tx:            out std_ulogic;
132
			tx_fifo_full:  out std_ulogic;
133
			tx_fifo_empty: out std_ulogic;
134
			tx_fifo_we:     in std_ulogic;
135
			tx_fifo_data:   in std_ulogic_vector(7 downto 0);
136

137
			rx:             in std_ulogic;
138
			rx_fifo_full:  out std_ulogic;
139
			rx_fifo_empty: out std_ulogic;
140
			rx_fifo_re:     in std_ulogic;
141
			rx_fifo_data:  out std_ulogic_vector(7 downto 0);
142
	
143
			reg:             in std_ulogic_vector(15 downto 0);
144
			clock_reg_tx_we: in std_ulogic;
145
			clock_reg_rx_we: in std_ulogic;
146
			control_reg_we:  in std_ulogic);
147
	end component;
148

149
	component uart_tb is
150
		generic(g: common_generics);
151
	end component;
152

153
	constant ctr_use_parity:  integer := 0;
154
	constant ctr_even_parity: integer := 1;
155
	function ctr_stop_bits(ctr: std_ulogic_vector(7 downto 0)) return integer;
156
	function ctr_data_bits(ctr: std_ulogic_vector(7 downto 0)) return integer;
157
end package;
158

159
package body uart_pkg is
160
	function ctr_stop_bits(ctr: std_ulogic_vector(7 downto 0)) return integer is
161
		variable ii: std_ulogic_vector(1 downto 0);
162
	begin
163
		ii := ctr(3 downto 2);
164
		return to_integer(unsigned(ii));
165
	end function;
166

167
	function ctr_data_bits(ctr: std_ulogic_vector(7 downto 0)) return integer is
168
		variable ii: std_ulogic_vector(3 downto 0);
169
	begin
170
		ii := ctr(7 downto 4);
171
		return to_integer(unsigned(ii));
172
	end function;
173
end;
174

175
library ieee, work;
176
use ieee.std_logic_1164.all;
177
use ieee.numeric_std.all;
178
use work.uart_pkg.all;
179
use work.util.common_generics;
180

181
entity uart_top is
182
	generic (
183
		g: common_generics;
184
		baud: positive := 115200;
185
		format: std_ulogic_vector(7 downto 0) := uart_8N1;
186
		use_fifo: boolean := false);
187
	port (
188
		clk:    in std_ulogic;
189
		rst:    in std_ulogic;
190

191
		tx:            out std_ulogic;
192
		tx_fifo_full:  out std_ulogic;
193
		tx_fifo_empty: out std_ulogic;
194
		tx_fifo_we:     in std_ulogic;
195
		tx_fifo_data:   in std_ulogic_vector(7 downto 0);
196

197
		rx:             in std_ulogic;
198
		rx_fifo_full:  out std_ulogic;
199
		rx_fifo_empty: out std_ulogic;
200
		rx_fifo_re:     in std_ulogic;
201
		rx_fifo_data:  out std_ulogic_vector(7 downto 0);
202

203
		reg:             in std_ulogic_vector(15 downto 0);
204
		clock_reg_tx_we: in std_ulogic;
205
		clock_reg_rx_we: in std_ulogic;
206
		control_reg_we:  in std_ulogic);
207
end entity;
208

209
architecture structural of uart_top is
210
	constant fifo_depth: positive := 8;
211
	signal rx_ok, rx_nd, rx_push, rx_re: std_ulogic;
212
	signal rx_pushed: std_ulogic_vector(rx_fifo_data'range);
213
	signal tx_pop, tx_ok: std_ulogic;
214
	signal tx_popped: std_ulogic_vector(tx_fifo_data'range);
215
	signal tx_fifo_empty_b, rx_fifo_full_b: std_ulogic;
216
begin
217
	uart_core_0: work.uart_pkg.uart_core
218
		generic map(g => g, baud => baud, format => format)
219
		port map(
220
			clk => clk,
221
			rst => rst,
222

223
			tx    => tx,
224
			tx_we => tx_pop,
225
			tx_di => tx_popped,
226
			tx_ok => tx_ok,
227

228
			rx    => rx,
229
			rx_nd => rx_nd,
230
			rx_ok => rx_ok,
231
			rx_do => rx_pushed,
232
			rx_re => rx_push,
233

234
			reg => reg,
235
			clock_reg_rx_we => clock_reg_rx_we,
236
			clock_reg_tx_we => clock_reg_tx_we,
237
			control_reg_we  => control_reg_we);
238

239
	ugen0: if not use_fifo generate
240
			tx_pop        <= tx_fifo_we;
241
			tx_popped     <= tx_fifo_data;
242
			tx_fifo_full  <= not tx_ok;
243
			tx_fifo_empty <= tx_ok;
244

245
			rx_push       <= rx_fifo_re;
246
			rx_fifo_data  <= rx_pushed;
247
			rx_fifo_full  <= rx_nd;
248
			rx_fifo_empty <= not rx_nd;
249
	end generate;
250

251
	ugen1: if use_fifo generate
252
		tx_fifo_empty <=               tx_fifo_empty_b;
253
		tx_pop        <= tx_ok and not tx_fifo_empty_b;
254
		uart_fifo_tx_0: work.util.fifo
255
			generic map(g => g,
256
				   data_width => tx_fifo_data'length,
257
				   fifo_depth => fifo_depth)
258
			port map (clk  => clk, rst => rst,
259
				  di   => tx_fifo_data,
260
				  we   => tx_fifo_we,
261
				  re   => tx_pop,
262
				  do   => tx_popped,
263
				  full => tx_fifo_full, empty => tx_fifo_empty_b);
264

265
		rx_fifo_full <=                         rx_fifo_full_b;
266
		rx_push      <= rx_nd and rx_ok and not rx_fifo_full_b;
267
		uart_fifo_rx_0: work.util.fifo
268
			generic map(g => g,
269
				   data_width => rx_fifo_data'length,
270
				   fifo_depth => fifo_depth,
271
			   	   read_first => false)
272
			port map (clk  => clk, rst => rst,
273
				  di   => rx_pushed,
274
				  we   => rx_push,
275
				  re   => rx_fifo_re,
276
				  do   => rx_fifo_data,
277
				  full => rx_fifo_full_b, empty => rx_fifo_empty);
278
	end generate;
279
end architecture;
280

281
library ieee, work;
282
use ieee.std_logic_1164.all;
283
use ieee.numeric_std.all;
284
use work.uart_pkg.all;
285
use work.util.common_generics;
286

287
entity uart_core is
288
	generic (
289
		g: common_generics;
290
		baud: positive := 115200;
291
		format: std_ulogic_vector(7 downto 0) := uart_8N1);
292
	port (
293
		clk:    in std_ulogic;
294
		rst:    in std_ulogic;
295

296
		tx:    out std_ulogic; -- physical UART TX signal
297
		tx_ok: out std_ulogic; -- not busy
298
		tx_we:  in std_ulogic; -- write data
299
		tx_di:  in std_ulogic_vector(7 downto 0);
300

301
		rx:     in std_ulogic; -- physical UART RX signal
302
		rx_ok: out std_ulogic; -- data has no errors (parity or frame)
303
		rx_re:  in std_ulogic; -- read data
304
		rx_nd: out std_ulogic; -- new data available
305
		rx_do: out std_ulogic_vector(7 downto 0);
306

307
		reg:             in std_ulogic_vector(15 downto 0);
308
		clock_reg_tx_we: in std_ulogic;
309
		clock_reg_rx_we: in std_ulogic;
310
		control_reg_we:  in std_ulogic);
311
end entity;
312

313
architecture structural of uart_core is
314
	constant tx_init: integer  := g.clock_frequency / (baud * 16); -- 54 = 115200 @ 100 MHz
315
	constant rx_init: positive := tx_init - 1; -- 50 = 115200 @ 100 MHz + Fudge Factor
316
	constant N: positive := 8;
317
	signal tx_sample, tx_baud, tx_cr: std_ulogic;
318
	signal rx_sample, rx_baud, rx_cr, rx_we: std_ulogic;
319
	signal rx_fail: std_ulogic_vector(1 downto 0);
320
	signal rx_ok_buf: std_ulogic;
321
	signal do, do_c, do_n: std_ulogic_vector(rx_do'range);
322
	signal fail_c, fail_n: std_ulogic_vector(1 downto 0);
323
	signal nd_c, nd_n: std_ulogic; -- new data
324
begin
325
	rx_ok_buf <= not (fail_c(0) or fail_c(1)) after g.delay;
326
	rx_ok <= rx_ok_buf;
327
	rx_do <= do after g.delay;
328
	rx_nd <= nd_c and rx_ok_buf after g.delay; -- no new data if there are errors
329

330
	process (clk, rst)
331
	begin
332
		if rst = '1' and g.asynchronous_reset then
333
			do_c   <= (others => '0') after g.delay;
334
			fail_c <= (others => '0') after g.delay;
335
			nd_c   <= '0' after g.delay;
336
		elsif rising_edge(clk) then
337
			if rst = '1' and not g.asynchronous_reset then
338
				do_c   <= (others => '0') after g.delay;
339
				fail_c <= (others => '0') after g.delay;
340
				nd_c   <= '0' after g.delay;
341
			else
342
				do_c <= do_n     after g.delay;
343
				nd_c <= nd_n     after g.delay;
344
				fail_c <= fail_n after g.delay;
345
			end if;
346
		end if;
347
	end process;
348

349
	process (do_c, do, nd_c, rx_we, rx_re, fail_c, rx_fail)
350
	begin
351
		do_n   <= do_c   after g.delay;
352
		nd_n   <= nd_c   after g.delay;
353
		fail_n <= fail_c after g.delay;
354
		if rx_we = '1' then
355
			nd_n   <= '1'     after g.delay;
356
			do_n   <= do      after g.delay;
357
			fail_n <= rx_fail after g.delay;
358
		elsif rx_re = '1' then
359
			nd_n   <= '0' after g.delay;
360
		end if;
361
	end process;
362

363
	baud_tx: work.uart_pkg.uart_baud
364
		generic map(g => g, init => tx_init, N => reg'length, D => 3)
365
		port map(
366
			clk    => clk,
367
			rst    => rst,
368
			we     => clock_reg_tx_we,
369
			cnt    => reg,  -- 0x32/50 is 152000 @ 100MHz clk
370
			cr     => tx_cr,
371
			sample => tx_sample,
372
			baud   => tx_baud);
373

374
	baud_rx: work.uart_pkg.uart_baud
375
		generic map(g => g, init => rx_init, N => reg'length, D => 3)
376
		port map(
377
			clk    => clk,
378
			rst    => rst,
379
			we     => clock_reg_rx_we,
380
			cnt    => reg,
381
			cr     => rx_cr,
382
			sample => rx_sample,
383
			baud   => rx_baud);
384

385
	tx_0: work.uart_pkg.uart_tx
386
		generic map(g => g, N => N, format => format)
387
		port map(
388
			clk     => clk,
389
			rst     => rst,
390

391
			cr      => tx_cr,
392
			baud    => tx_baud,
393
			ok      => tx_ok,
394
			we      => tx_we,
395
			ctr     => reg(reg'high downto reg'high - 7),
396
			ctr_we  => control_reg_we,
397
			di      => tx_di,
398
			tx      => tx);
399

400
	rx_0: work.uart_pkg.uart_rx
401
		generic map(g => g, N => N, D => 3, format => format)
402
		port map(
403
			clk     => clk,
404
			rst     => rst,
405

406
			baud    => rx_baud,
407
			sample  => rx_sample,
408
			cr      => rx_cr,
409
			failed  => rx_fail,
410
			ctr     => reg(reg'low + 7 downto reg'low),
411
			ctr_we  => control_reg_we,
412
			we      => rx_we,
413
			do      => do,
414
			rx      => rx);
415
end architecture;
416

417
-- This module generates a sample pulse and a baud pulse. The sample rate
418
-- can be controlled by setting 'cnt'. This sample rate is then divided by
419
-- 2^(D+1) to get the baud.
420
library ieee, work;
421
use ieee.std_logic_1164.all;
422
use ieee.numeric_std.all;
423
use work.uart_pkg.all;
424
use work.util.common_generics;
425

426
entity uart_baud is
427
	generic (g: common_generics; init: integer; N: positive := 16; D: positive := 3);
428
	port (
429
		clk:     in std_ulogic;
430
		rst:     in std_ulogic;
431
	
432
		we:      in std_ulogic;
433
		cnt:     in std_ulogic_vector(N - 1 downto 0);
434
		cr:      in std_ulogic := '0';
435

436
		sample: out std_ulogic;  -- sample pulse
437
		baud:   out std_ulogic); -- baud (sample rate / 2^(D+1))
438
end entity;
439

440
architecture behaviour of uart_baud is
441
	constant cmp_init: std_ulogic_vector := std_ulogic_vector(to_unsigned(init, cnt'length));
442
	signal cmp_c, cmp_n: std_ulogic_vector(cnt'range)  :=  cmp_init;
443
	signal cnt_c, cnt_n: std_ulogic_vector(cnt'range)  := (others => '0');
444
	signal div_c, div_n: std_ulogic_vector(D downto 0) := (others => '0');
445
	signal pul_c, pul_n: std_ulogic := '0';
446
	signal pulse: std_ulogic := '0';
447
begin
448
	pulse  <= (not cr) and pul_n and (pul_c xor pul_n) after g.delay; -- rising edge detector
449
	baud   <= (not cr) and div_n(div_n'high) and (div_c(div_c'high) xor div_n(div_n'high)) after g.delay;
450
	sample <= pulse;
451

452
	process (clk, rst)
453
	begin
454
		if rst = '1' and g.asynchronous_reset then
455
			cmp_c <= cmp_init after g.delay;
456
			cnt_c <= (others => '0') after g.delay;
457
			div_c <= (others => '0') after g.delay;
458
			pul_c <= '0' after g.delay;
459
		elsif rising_edge(clk) then
460
			if rst = '1' and not g.asynchronous_reset then
461
				cmp_c <= cmp_init after g.delay;
462
				cnt_c <= (others => '0') after g.delay;
463
				div_c <= (others => '0') after g.delay;
464
				pul_c <= '0' after g.delay;
465
			else
466
				cmp_c <= cmp_n after g.delay;
467
				cnt_c <= cnt_n after g.delay;
468
				div_c <= div_n after g.delay;
469
				pul_c <= pul_n after g.delay;
470
			end if;
471
		end if;
472
	end process;
473

474
	process (pulse, div_c, cr, we)
475
	begin
476
		div_n <= div_c after g.delay;
477
		if cr = '1' or we = '1' then
478
			div_n <= (others => '0') after g.delay;
479
			div_n(div_n'high) <= '1' after g.delay;
480
		elsif pulse = '1' then
481
			div_n <= std_ulogic_vector(unsigned(div_c) + 1) after g.delay;
482
		end if;
483
	end process;
484

485
	process (cmp_c, cnt_c, we, cnt, cr)
486
	begin
487
		cmp_n <= cmp_c after g.delay;
488
		cnt_n <= cnt_c after g.delay;
489

490
		if we = '1' then
491
			cmp_n <= cnt after g.delay;
492
			cnt_n <= (others => '0') after g.delay;
493
			pul_n <= '0' after g.delay;
494
		elsif cr = '1' then
495
			cnt_n <= (others => '0') after g.delay;
496
			pul_n <= '0' after g.delay;
497
		elsif cnt_c = cmp_c then
498
			cnt_n <= (others => '0') after g.delay;
499
			pul_n <= '1' after g.delay;
500
		else
501
			cnt_n <= std_ulogic_vector(unsigned(cnt_c) + 1) after g.delay;
502
			pul_n <= '0' after g.delay;
503
		end if;
504
	end process;
505
end architecture;
506

507
library ieee, work;
508
use ieee.std_logic_1164.all;
509
use work.uart_pkg.all;
510
use work.util.common_generics;
511
use work.util.parity;
512

513
entity uart_rx is
514
	generic (
515
		g: common_generics;
516
		N: positive;
517
		D: positive;
518
		format: std_ulogic_vector(7 downto 0) := uart_8N1);
519
	port (
520
		clk:    in std_ulogic;
521
		rst:    in std_ulogic;
522
		cr:    out std_ulogic;        -- reset sample/baud clock when start bit detected
523
		baud, sample: in std_ulogic; -- pulses at baud and sample rate
524
		failed: out std_ulogic_vector(1 downto 0);
525
		ctr:    in std_ulogic_vector(7 downto 0);
526
		ctr_we: in std_ulogic;
527
		rx:     in std_ulogic;        -- physical RX signal
528
		we:    out std_ulogic;        -- write 'do' to output register
529
		do:    out std_ulogic_vector(N - 1 downto 0));
530
end entity;
531

532
architecture behaviour of uart_rx is
533
	type state is (reset, idle, start, data, parity, stop, done);
534
	signal state_c, state_n: state;
535
	signal ctr_c, ctr_n: std_ulogic_vector(ctr'range);
536
	signal rx_c, rx_n: std_ulogic_vector(do'range);
537
	signal sr_c, sr_n: std_ulogic_vector(D - 1 downto 0);
538
	signal rx_sync: std_ulogic;
539
	signal count_c, count_n: integer range 0 to N - 1;
540
	signal majority: std_ulogic;
541
	signal fail_c, fail_n: std_ulogic_vector(1 downto 0);
542
begin
543
	do     <= rx_c after g.delay;
544
	failed <= fail_c after g.delay;
545

546
	assert D < 4 severity failure;
547

548
	majority_1: if D = 1 generate
549
		majority <= sr_c(0) after g.delay;
550
	end generate;
551

552
	majority_2: if D = 2 generate
553
		majority <= sr_c(0) and sr_c(1) after g.delay; -- even wins is 'sr_c(0) or sr_c(1)'
554
	end generate;
555

556
	majority_3: if D = 3 generate
557
		majority <= (sr_c(0) and sr_c(1)) or (sr_c(1) and sr_c(2)) or (sr_c(0) and sr_c(2)) after g.delay;
558
	end generate;
559

560
	process (clk, rst)
561
		procedure reset is
562
		begin
563
			rx_c     <= (others => '0') after g.delay;
564
			sr_c     <= (others => '0') after g.delay;
565
			fail_c   <= (others => '0') after g.delay;
566
			ctr_c    <= (others => '0') after g.delay;
567
			state_c  <= reset after g.delay;
568
			count_c  <= 0 after g.delay;
569
			rx_sync  <= '0' after g.delay;
570
		end procedure;
571
	begin
572
		if rst = '1' and g.asynchronous_reset then
573
			reset;
574
		elsif rising_edge(clk) then
575
			if rst = '1' and not g.asynchronous_reset then
576
				reset;
577
			else
578
				rx_c     <= rx_n after g.delay;
579
				sr_c     <= sr_n after g.delay;
580
				state_c  <= state_n after g.delay;
581
				count_c  <= count_n after g.delay;
582
				fail_c   <= fail_n after g.delay;
583
				ctr_c    <= ctr_n after g.delay;
584
				rx_sync  <= rx after g.delay;
585
			end if;
586
		end if;
587
	end process;
588

589
	process (rx_c, sr_c, ctr_c, ctr_we, ctr, state_c, rx_sync, baud, sample, count_c, fail_c, majority)
590
	begin
591
		fail_n  <= fail_c after g.delay;
592
		rx_n    <= rx_c after g.delay;
593
		sr_n    <= sr_c after g.delay;
594
		ctr_n   <= ctr_c after g.delay;
595
		state_n <= state_c after g.delay;
596
		we      <= '0' after g.delay;
597
		cr      <= '0' after g.delay;
598
		count_n <= count_c after g.delay;
599

600
		if sample = '1' then
601
			sr_n <= sr_c(sr_c'high - 1 downto sr_c'low) & rx_sync after g.delay;
602
		end if;
603

604
		case state_c is
605
		when reset =>
606
			rx_n     <= (others => '0') after g.delay;
607
			sr_n     <= (others => '0') after g.delay;
608
			fail_n   <= (others => '0') after g.delay;
609
			ctr_n    <= format after g.delay; -- 8 bits, 1 stop bit, parity off
610
			state_n  <= idle after g.delay;
611
		when idle =>
612
			count_n <= 0 after g.delay;
613
			if rx_sync = '0' then -- and majority = '1' then
614
				state_n <= start after g.delay;
615
				cr      <= '1' after g.delay;
616
				sr_n    <= (others => '0') after g.delay;
617
				fail_n  <= (others => '0') after g.delay;
618
			end if;
619
		when start =>
620
			if baud = '1' then
621
				if majority /= '0' then
622
					state_n   <= done after g.delay; -- frame error
623
					fail_n(0) <= '1' after g.delay;
624
				else
625
					state_n <= data after g.delay;
626
				end if;
627
				sr_n <= (others => '0') after g.delay;
628
			end if;
629
		when data =>
630
			rx_n(count_c) <= majority after g.delay;
631
			if baud = '1' then
632
				if count_c = (ctr_data_bits(ctr_c) - 1) then
633
					count_n <= 0 after g.delay;
634
					if ctr_c(ctr_use_parity) = '1' then
635
						state_n <= parity after g.delay;
636
					else
637
						state_n <= stop after g.delay;
638
					end if;
639
				else
640
					count_n <= count_c + 1 after g.delay;
641
				end if;
642
				sr_n <= (others => '0') after g.delay;
643
			end if;
644
		when parity =>
645
			if baud = '1' then
646
				if (ctr_c(ctr_use_parity) = '1') and (majority /= parity(rx_c, ctr_c(ctr_even_parity))) then
647
					fail_n(1) <= '1' after g.delay; -- parity error, still process stop bits
648
				end if;
649
				state_n <= stop after g.delay;
650
				sr_n <= (others => '0') after g.delay;
651
			end if;
652
		when stop =>
653
			if baud = '1' then
654
				if majority /= '1' then
655
					state_n   <= done after g.delay; -- frame error
656
					fail_n(0) <= '1' after g.delay;
657
				elsif count_c = ctr_stop_bits(ctr_c) then
658
					state_n <= done after g.delay;
659
				else
660
					count_n <= count_c + 1 after g.delay;
661
				end if;
662
			end if;
663
		when done => -- The consuming module needs to store rx_c/fail_c immediately
664
			we      <= '1' after g.delay;
665
			state_n <= idle after g.delay;
666
			--rx_n    <= (others => '0') after g.delay;
667
			--sr_n    <= (others => '0') after g.delay;
668
			--fail_n  <= (others => '0') after g.delay;
669
		end case;
670

671
		if ctr_we = '1' then
672
			if not (state_c = idle or state_c = done or state_c = reset) then
673
				rx_n      <= (others => '0') after g.delay;
674
				state_n   <= idle after g.delay;
675
				we        <= '1' after g.delay;
676
				fail_n(0) <= '1' after g.delay; -- frame error!
677
			end if;
678
			ctr_n <= ctr after g.delay;
679
		end if;
680
	end process;
681
end architecture;
682

683
library ieee, work;
684
use ieee.std_logic_1164.all;
685
use work.uart_pkg.all;
686
use work.util.common_generics;
687
use work.util.parity;
688

689
entity uart_tx is
690
	generic (g: common_generics; N: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
691
	port (
692
		clk:    in std_ulogic;
693
		rst:    in std_ulogic;
694
		cr:    out std_ulogic;
695
		baud:   in std_ulogic; -- Pulse at baud
696
		tx:    out std_ulogic;
697
		ok:    out std_ulogic;
698
		ctr:    in std_ulogic_vector(format'range);
699
		ctr_we: in std_ulogic;
700
		we:     in std_ulogic; -- di write enable
701
		di:     in std_ulogic_vector(N - 1 downto 0));
702
end entity;
703

704
architecture behaviour of uart_tx is
705
	type state is (reset, idle, start, data, parity, stop);
706
	signal state_c, state_n: state;
707
	signal di_c, di_n: std_ulogic_vector(di'range);
708
	signal ctr_c, ctr_n: std_ulogic_vector(ctr'range);
709
	signal busy: std_ulogic;
710
	signal parity_c, parity_n: std_ulogic;
711
	signal count_c, count_n: integer range 0 to 15;
712
begin
713
	busy <= '0' when state_c = idle else '1' after g.delay;
714
	ok <= not busy after g.delay;
715

716
	process (clk, rst)
717
		procedure reset is
718
		begin
719
			di_c     <= (others => '0') after g.delay;
720
			ctr_c    <= (others => '0') after g.delay;
721
			state_c  <= reset after g.delay;
722
			parity_c <= '0' after g.delay;
723
			count_c  <= 0 after g.delay;
724
		end procedure;
725
	begin
726
		if rst = '1' and g.asynchronous_reset then
727
			reset;
728
		elsif rising_edge(clk) then
729
			if rst = '1' and not g.asynchronous_reset then
730
				reset;
731
			else
732
				di_c     <= di_n after g.delay;
733
				ctr_c    <= ctr_n after g.delay;
734
				state_c  <= state_n after g.delay;
735
				parity_c <= parity_n after g.delay;
736
				count_c  <= count_n after g.delay;
737
			end if;
738
		end if;
739
	end process;
740

741
	process (di_c, di, ctr_c, ctr_we, ctr, state_c, we, baud, parity_c, count_c)
742
	begin
743
		count_n <= count_c after g.delay;
744
		state_n <= state_c after g.delay;
745
		di_n    <= di_c after g.delay;
746
		ctr_n   <= ctr_c after g.delay;
747
		tx <= '1' after g.delay;
748
		cr <= '0';
749

750
		if ctr_c(ctr_use_parity) = '1' then
751
			parity_n <= parity(di_c, ctr_c(ctr_even_parity)) after g.delay;
752
		else
753
			parity_n <= '0' after g.delay;
754
		end if;
755

756
		case state_c is
757
		when reset  =>
758
			state_n  <= idle after g.delay;
759
			ctr_n    <= format after g.delay; -- 8 bits, 1 stop bit, parity off
760
			count_n  <= 0 after g.delay;
761
			parity_n <= '0' after g.delay;
762
			di_n     <= (others => '0') after g.delay;
763
		when idle   =>
764
			count_n  <= 0 after g.delay;
765
			if ctr_we = '1' then -- NB. We can either lose data, or control writes
766
				ctr_n <= ctr after g.delay;
767
			elsif we = '1' then
768
				di_n    <= di after g.delay;
769
				cr      <= '1';
770
				state_n <= start after g.delay;
771
			end if;
772
		when start  =>
773
			tx <= '0' after g.delay;
774
			if baud = '1' then
775
				state_n <= data after g.delay;
776
			end if;
777
		when data   =>
778
			tx <= di_c(count_c) after g.delay;
779
			if baud = '1' then
780
				if count_c = (ctr_data_bits(ctr_c) - 1) then
781
					count_n <= 0 after g.delay;
782
					if ctr_c(ctr_use_parity) = '1' then
783
						state_n <= parity after g.delay;
784
					else
785
						state_n <= stop after g.delay;
786
					end if;
787
				else
788
					count_n <= count_c + 1 after g.delay;
789
				end if;
790
			end if;
791
		when parity =>
792
			tx <= parity_c after g.delay;
793
			if baud = '1' then
794
				state_n <= stop after g.delay;
795
			end if;
796
		when stop   =>
797
			tx <= '1' after g.delay;
798
			if baud = '1' then
799
				if count_c = ctr_stop_bits(ctr_c) then
800
					count_n <= 0 after g.delay;
801
					state_n <= idle after g.delay;
802
				else
803
					count_n <= count_c + 1 after g.delay;
804
				end if;
805
			end if;
806
		end case;
807
	end process;
808
end architecture;
809

810
library ieee, work;
811
use ieee.std_logic_1164.all;
812
use ieee.numeric_std.all;
813
use work.uart_pkg.all;
814
use work.util.common_generics;
815

816
entity uart_tb is
817
	generic(g: common_generics);
818
end entity;
819

820
architecture testing of uart_tb is
821
	constant clock_period: time     := 1000 ms / g.clock_frequency;
822
	constant use_fifo:     boolean  := true;
823
	signal rst, clk:     std_ulogic := '1';
824
	signal stop:         boolean    := false;
825
	signal loopback:     boolean    := true;
826
	signal tx, rx:       std_ulogic;
827
	signal di, do:       std_ulogic_vector(7 downto 0);
828
	signal reg:          std_ulogic_vector(15 downto 0);
829
	signal clock_reg_tx_we: std_ulogic;
830
	signal clock_reg_rx_we: std_ulogic;
831
	signal control_reg_we:  std_ulogic;
832

833
	signal tx_fifo_full:  std_ulogic;
834
	signal tx_fifo_empty: std_ulogic;
835
	signal tx_fifo_we:    std_ulogic := '0';
836
	signal rx_fifo_full:  std_ulogic;
837
	signal rx_fifo_empty: std_ulogic;
838
	signal rx_fifo_re:    std_ulogic := '0';
839
begin
840
	-- duration: process begin wait for 20000 us; stop <= true; wait; end process;
841
	clk_process: process
842
	begin
843
		rst <= '1';
844
		wait for clock_period * 5;
845
		rst <= '0';
846
		while not stop loop
847
			clk <= '1';
848
			wait for clock_period / 2;
849
			clk <= '0';
850
			wait for clock_period / 2;
851
		end loop;
852
		wait;
853
	end process;
854

855
	stimulus: process
856
		procedure write(data: std_ulogic_vector(di'range)) is
857
		begin
858
			wait for clock_period * 1;
859
			while tx_fifo_full = '1' loop
860
				wait for clock_period;
861
			end loop;
862
			di <= data;
863
			tx_fifo_we <= '1';
864
			wait for clock_period;
865
			tx_fifo_we <= '0';
866
		end procedure;
867
	begin
868
		di <= x"00";
869
		wait until rst = '0';
870
		wait for clock_period;
871
		reg             <=  x"8080";
872
		control_reg_we  <=  '1';
873
		wait for clock_period;
874
		control_reg_we  <=  '0';
875
		reg             <=  x"0036";
876
		clock_reg_tx_we <=  '1';
877
		wait for clock_period;
878
		clock_reg_tx_we <=  '0';
879
		clock_reg_rx_we <=  '1';
880
		reg             <=  x"0035";
881
		wait for clock_period;
882
		clock_reg_rx_we <=  '0';
883
		wait for clock_period;
884

885
		write(x"AA");
886
		write(x"BB");
887
		write(x"CC");
888
		write(x"DD");
889
		write(x"EE");
890
		write(x"FF");
891
		wait for clock_period;
892
		while tx_fifo_empty = '0' loop
893
			wait for clock_period;
894
		end loop;
895
		loopback <= false;
896
		wait for clock_period * 50000;
897
		stop <= true;
898
		wait;
899
	end process;
900

901
	ack: process
902
	begin
903
		while not stop loop
904
			if rx_fifo_empty = '0' then
905
				rx_fifo_re <= '1';
906
			else
907
				rx_fifo_re <= '0';
908
			end if;
909
			wait for clock_period;
910
		end loop;
911
		wait;
912
	end process;
913
	rx <= tx when loopback else '0'; -- loop back test
914
	uut: work.uart_pkg.uart_top
915
		generic map (g => g, baud => 115200, format => uart_8N1, use_fifo => use_fifo)
916
		port map (
917
			clk => clk,
918
			rst => rst,
919

920
			tx             =>  tx,
921
			tx_fifo_full   =>  tx_fifo_full,
922
			tx_fifo_empty  =>  tx_fifo_empty,
923
			tx_fifo_we     =>  tx_fifo_we,
924
			tx_fifo_data   =>  di,
925

926
			rx             =>  rx,
927
			rx_fifo_full   =>  rx_fifo_full,
928
			rx_fifo_empty  =>  rx_fifo_empty,
929
			rx_fifo_re     =>  rx_fifo_re,
930
			rx_fifo_data   =>  do,
931

932
			reg             => reg,
933
			clock_reg_tx_we => clock_reg_tx_we,
934
			clock_reg_rx_we => clock_reg_rx_we,
935
			control_reg_we  => control_reg_we);
936

937
end architecture;
938

939

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.