forth-cpu
/
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.
48library ieee, work;
49use ieee.std_logic_1164.all;
50use ieee.numeric_std.all;
51use work.util.common_generics;
52
53package uart_pkg is
54constant uart_8N1: std_ulogic_vector(7 downto 0) := "10000100";
55
56component uart_tx is
57generic (g: common_generics; N: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
58port (
59clk: in std_ulogic;
60rst: in std_ulogic;
61cr: out std_ulogic;
62baud: in std_ulogic; -- Pulse at baud
63tx: out std_ulogic;
64ok: out std_ulogic;
65ctr: in std_ulogic_vector(format'range);
66ctr_we: in std_ulogic;
67we: in std_ulogic; -- di write enable
68di: in std_ulogic_vector(N - 1 downto 0));
69end component;
70
71component uart_rx is
72generic (g: common_generics; N: positive; D: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
73port (
74clk: in std_ulogic;
75rst: in std_ulogic;
76cr: out std_ulogic;
77baud, sample: in std_ulogic;
78failed: out std_ulogic_vector(1 downto 0);
79ctr: in std_ulogic_vector(7 downto 0);
80ctr_we: in std_ulogic;
81rx: in std_ulogic;
82we: out std_ulogic;
83do: out std_ulogic_vector(N - 1 downto 0));
84end component;
85
86component uart_baud is -- Generates a pulse at the sample rate and baud
87generic (g: common_generics; init: integer; N: positive := 16; D: positive := 3);
88port (
89clk: in std_ulogic;
90rst: in std_ulogic;
91we: in std_ulogic;
92cnt: in std_ulogic_vector(N - 1 downto 0);
93cr: in std_ulogic := '0';
94sample: out std_ulogic;
95baud: out std_ulogic);
96end component;
97
98component uart_core is
99generic (g: common_generics; baud: positive := 115200; format: std_ulogic_vector(7 downto 0) := uart_8N1);
100port (
101clk: in std_ulogic;
102rst: in std_ulogic;
103
104tx: out std_ulogic;
105tx_ok: out std_ulogic;
106tx_we: in std_ulogic;
107tx_di: in std_ulogic_vector(7 downto 0);
108
109rx: in std_ulogic;
110rx_ok: out std_ulogic;
111rx_nd: out std_ulogic;
112rx_re: in std_ulogic;
113rx_do: out std_ulogic_vector(7 downto 0);
114
115reg: in std_ulogic_vector(15 downto 0);
116clock_reg_tx_we: in std_ulogic;
117clock_reg_rx_we: in std_ulogic;
118control_reg_we: in std_ulogic);
119end component;
120
121component uart_top is
122generic (
123g: common_generics;
124baud: positive := 115200;
125format: std_ulogic_vector(7 downto 0) := uart_8N1;
126use_fifo: boolean := false);
127port (
128clk: in std_ulogic;
129rst: in std_ulogic;
130
131tx: out std_ulogic;
132tx_fifo_full: out std_ulogic;
133tx_fifo_empty: out std_ulogic;
134tx_fifo_we: in std_ulogic;
135tx_fifo_data: in std_ulogic_vector(7 downto 0);
136
137rx: in std_ulogic;
138rx_fifo_full: out std_ulogic;
139rx_fifo_empty: out std_ulogic;
140rx_fifo_re: in std_ulogic;
141rx_fifo_data: out std_ulogic_vector(7 downto 0);
142
143reg: in std_ulogic_vector(15 downto 0);
144clock_reg_tx_we: in std_ulogic;
145clock_reg_rx_we: in std_ulogic;
146control_reg_we: in std_ulogic);
147end component;
148
149component uart_tb is
150generic(g: common_generics);
151end component;
152
153constant ctr_use_parity: integer := 0;
154constant ctr_even_parity: integer := 1;
155function ctr_stop_bits(ctr: std_ulogic_vector(7 downto 0)) return integer;
156function ctr_data_bits(ctr: std_ulogic_vector(7 downto 0)) return integer;
157end package;
158
159package body uart_pkg is
160function ctr_stop_bits(ctr: std_ulogic_vector(7 downto 0)) return integer is
161variable ii: std_ulogic_vector(1 downto 0);
162begin
163ii := ctr(3 downto 2);
164return to_integer(unsigned(ii));
165end function;
166
167function ctr_data_bits(ctr: std_ulogic_vector(7 downto 0)) return integer is
168variable ii: std_ulogic_vector(3 downto 0);
169begin
170ii := ctr(7 downto 4);
171return to_integer(unsigned(ii));
172end function;
173end;
174
175library ieee, work;
176use ieee.std_logic_1164.all;
177use ieee.numeric_std.all;
178use work.uart_pkg.all;
179use work.util.common_generics;
180
181entity uart_top is
182generic (
183g: common_generics;
184baud: positive := 115200;
185format: std_ulogic_vector(7 downto 0) := uart_8N1;
186use_fifo: boolean := false);
187port (
188clk: in std_ulogic;
189rst: in std_ulogic;
190
191tx: out std_ulogic;
192tx_fifo_full: out std_ulogic;
193tx_fifo_empty: out std_ulogic;
194tx_fifo_we: in std_ulogic;
195tx_fifo_data: in std_ulogic_vector(7 downto 0);
196
197rx: in std_ulogic;
198rx_fifo_full: out std_ulogic;
199rx_fifo_empty: out std_ulogic;
200rx_fifo_re: in std_ulogic;
201rx_fifo_data: out std_ulogic_vector(7 downto 0);
202
203reg: in std_ulogic_vector(15 downto 0);
204clock_reg_tx_we: in std_ulogic;
205clock_reg_rx_we: in std_ulogic;
206control_reg_we: in std_ulogic);
207end entity;
208
209architecture structural of uart_top is
210constant fifo_depth: positive := 8;
211signal rx_ok, rx_nd, rx_push, rx_re: std_ulogic;
212signal rx_pushed: std_ulogic_vector(rx_fifo_data'range);
213signal tx_pop, tx_ok: std_ulogic;
214signal tx_popped: std_ulogic_vector(tx_fifo_data'range);
215signal tx_fifo_empty_b, rx_fifo_full_b: std_ulogic;
216begin
217uart_core_0: work.uart_pkg.uart_core
218generic map(g => g, baud => baud, format => format)
219port map(
220clk => clk,
221rst => rst,
222
223tx => tx,
224tx_we => tx_pop,
225tx_di => tx_popped,
226tx_ok => tx_ok,
227
228rx => rx,
229rx_nd => rx_nd,
230rx_ok => rx_ok,
231rx_do => rx_pushed,
232rx_re => rx_push,
233
234reg => reg,
235clock_reg_rx_we => clock_reg_rx_we,
236clock_reg_tx_we => clock_reg_tx_we,
237control_reg_we => control_reg_we);
238
239ugen0: if not use_fifo generate
240tx_pop <= tx_fifo_we;
241tx_popped <= tx_fifo_data;
242tx_fifo_full <= not tx_ok;
243tx_fifo_empty <= tx_ok;
244
245rx_push <= rx_fifo_re;
246rx_fifo_data <= rx_pushed;
247rx_fifo_full <= rx_nd;
248rx_fifo_empty <= not rx_nd;
249end generate;
250
251ugen1: if use_fifo generate
252tx_fifo_empty <= tx_fifo_empty_b;
253tx_pop <= tx_ok and not tx_fifo_empty_b;
254uart_fifo_tx_0: work.util.fifo
255generic map(g => g,
256data_width => tx_fifo_data'length,
257fifo_depth => fifo_depth)
258port map (clk => clk, rst => rst,
259di => tx_fifo_data,
260we => tx_fifo_we,
261re => tx_pop,
262do => tx_popped,
263full => tx_fifo_full, empty => tx_fifo_empty_b);
264
265rx_fifo_full <= rx_fifo_full_b;
266rx_push <= rx_nd and rx_ok and not rx_fifo_full_b;
267uart_fifo_rx_0: work.util.fifo
268generic map(g => g,
269data_width => rx_fifo_data'length,
270fifo_depth => fifo_depth,
271read_first => false)
272port map (clk => clk, rst => rst,
273di => rx_pushed,
274we => rx_push,
275re => rx_fifo_re,
276do => rx_fifo_data,
277full => rx_fifo_full_b, empty => rx_fifo_empty);
278end generate;
279end architecture;
280
281library ieee, work;
282use ieee.std_logic_1164.all;
283use ieee.numeric_std.all;
284use work.uart_pkg.all;
285use work.util.common_generics;
286
287entity uart_core is
288generic (
289g: common_generics;
290baud: positive := 115200;
291format: std_ulogic_vector(7 downto 0) := uart_8N1);
292port (
293clk: in std_ulogic;
294rst: in std_ulogic;
295
296tx: out std_ulogic; -- physical UART TX signal
297tx_ok: out std_ulogic; -- not busy
298tx_we: in std_ulogic; -- write data
299tx_di: in std_ulogic_vector(7 downto 0);
300
301rx: in std_ulogic; -- physical UART RX signal
302rx_ok: out std_ulogic; -- data has no errors (parity or frame)
303rx_re: in std_ulogic; -- read data
304rx_nd: out std_ulogic; -- new data available
305rx_do: out std_ulogic_vector(7 downto 0);
306
307reg: in std_ulogic_vector(15 downto 0);
308clock_reg_tx_we: in std_ulogic;
309clock_reg_rx_we: in std_ulogic;
310control_reg_we: in std_ulogic);
311end entity;
312
313architecture structural of uart_core is
314constant tx_init: integer := g.clock_frequency / (baud * 16); -- 54 = 115200 @ 100 MHz
315constant rx_init: positive := tx_init - 1; -- 50 = 115200 @ 100 MHz + Fudge Factor
316constant N: positive := 8;
317signal tx_sample, tx_baud, tx_cr: std_ulogic;
318signal rx_sample, rx_baud, rx_cr, rx_we: std_ulogic;
319signal rx_fail: std_ulogic_vector(1 downto 0);
320signal rx_ok_buf: std_ulogic;
321signal do, do_c, do_n: std_ulogic_vector(rx_do'range);
322signal fail_c, fail_n: std_ulogic_vector(1 downto 0);
323signal nd_c, nd_n: std_ulogic; -- new data
324begin
325rx_ok_buf <= not (fail_c(0) or fail_c(1)) after g.delay;
326rx_ok <= rx_ok_buf;
327rx_do <= do after g.delay;
328rx_nd <= nd_c and rx_ok_buf after g.delay; -- no new data if there are errors
329
330process (clk, rst)
331begin
332if rst = '1' and g.asynchronous_reset then
333do_c <= (others => '0') after g.delay;
334fail_c <= (others => '0') after g.delay;
335nd_c <= '0' after g.delay;
336elsif rising_edge(clk) then
337if rst = '1' and not g.asynchronous_reset then
338do_c <= (others => '0') after g.delay;
339fail_c <= (others => '0') after g.delay;
340nd_c <= '0' after g.delay;
341else
342do_c <= do_n after g.delay;
343nd_c <= nd_n after g.delay;
344fail_c <= fail_n after g.delay;
345end if;
346end if;
347end process;
348
349process (do_c, do, nd_c, rx_we, rx_re, fail_c, rx_fail)
350begin
351do_n <= do_c after g.delay;
352nd_n <= nd_c after g.delay;
353fail_n <= fail_c after g.delay;
354if rx_we = '1' then
355nd_n <= '1' after g.delay;
356do_n <= do after g.delay;
357fail_n <= rx_fail after g.delay;
358elsif rx_re = '1' then
359nd_n <= '0' after g.delay;
360end if;
361end process;
362
363baud_tx: work.uart_pkg.uart_baud
364generic map(g => g, init => tx_init, N => reg'length, D => 3)
365port map(
366clk => clk,
367rst => rst,
368we => clock_reg_tx_we,
369cnt => reg, -- 0x32/50 is 152000 @ 100MHz clk
370cr => tx_cr,
371sample => tx_sample,
372baud => tx_baud);
373
374baud_rx: work.uart_pkg.uart_baud
375generic map(g => g, init => rx_init, N => reg'length, D => 3)
376port map(
377clk => clk,
378rst => rst,
379we => clock_reg_rx_we,
380cnt => reg,
381cr => rx_cr,
382sample => rx_sample,
383baud => rx_baud);
384
385tx_0: work.uart_pkg.uart_tx
386generic map(g => g, N => N, format => format)
387port map(
388clk => clk,
389rst => rst,
390
391cr => tx_cr,
392baud => tx_baud,
393ok => tx_ok,
394we => tx_we,
395ctr => reg(reg'high downto reg'high - 7),
396ctr_we => control_reg_we,
397di => tx_di,
398tx => tx);
399
400rx_0: work.uart_pkg.uart_rx
401generic map(g => g, N => N, D => 3, format => format)
402port map(
403clk => clk,
404rst => rst,
405
406baud => rx_baud,
407sample => rx_sample,
408cr => rx_cr,
409failed => rx_fail,
410ctr => reg(reg'low + 7 downto reg'low),
411ctr_we => control_reg_we,
412we => rx_we,
413do => do,
414rx => rx);
415end 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.
420library ieee, work;
421use ieee.std_logic_1164.all;
422use ieee.numeric_std.all;
423use work.uart_pkg.all;
424use work.util.common_generics;
425
426entity uart_baud is
427generic (g: common_generics; init: integer; N: positive := 16; D: positive := 3);
428port (
429clk: in std_ulogic;
430rst: in std_ulogic;
431
432we: in std_ulogic;
433cnt: in std_ulogic_vector(N - 1 downto 0);
434cr: in std_ulogic := '0';
435
436sample: out std_ulogic; -- sample pulse
437baud: out std_ulogic); -- baud (sample rate / 2^(D+1))
438end entity;
439
440architecture behaviour of uart_baud is
441constant cmp_init: std_ulogic_vector := std_ulogic_vector(to_unsigned(init, cnt'length));
442signal cmp_c, cmp_n: std_ulogic_vector(cnt'range) := cmp_init;
443signal cnt_c, cnt_n: std_ulogic_vector(cnt'range) := (others => '0');
444signal div_c, div_n: std_ulogic_vector(D downto 0) := (others => '0');
445signal pul_c, pul_n: std_ulogic := '0';
446signal pulse: std_ulogic := '0';
447begin
448pulse <= (not cr) and pul_n and (pul_c xor pul_n) after g.delay; -- rising edge detector
449baud <= (not cr) and div_n(div_n'high) and (div_c(div_c'high) xor div_n(div_n'high)) after g.delay;
450sample <= pulse;
451
452process (clk, rst)
453begin
454if rst = '1' and g.asynchronous_reset then
455cmp_c <= cmp_init after g.delay;
456cnt_c <= (others => '0') after g.delay;
457div_c <= (others => '0') after g.delay;
458pul_c <= '0' after g.delay;
459elsif rising_edge(clk) then
460if rst = '1' and not g.asynchronous_reset then
461cmp_c <= cmp_init after g.delay;
462cnt_c <= (others => '0') after g.delay;
463div_c <= (others => '0') after g.delay;
464pul_c <= '0' after g.delay;
465else
466cmp_c <= cmp_n after g.delay;
467cnt_c <= cnt_n after g.delay;
468div_c <= div_n after g.delay;
469pul_c <= pul_n after g.delay;
470end if;
471end if;
472end process;
473
474process (pulse, div_c, cr, we)
475begin
476div_n <= div_c after g.delay;
477if cr = '1' or we = '1' then
478div_n <= (others => '0') after g.delay;
479div_n(div_n'high) <= '1' after g.delay;
480elsif pulse = '1' then
481div_n <= std_ulogic_vector(unsigned(div_c) + 1) after g.delay;
482end if;
483end process;
484
485process (cmp_c, cnt_c, we, cnt, cr)
486begin
487cmp_n <= cmp_c after g.delay;
488cnt_n <= cnt_c after g.delay;
489
490if we = '1' then
491cmp_n <= cnt after g.delay;
492cnt_n <= (others => '0') after g.delay;
493pul_n <= '0' after g.delay;
494elsif cr = '1' then
495cnt_n <= (others => '0') after g.delay;
496pul_n <= '0' after g.delay;
497elsif cnt_c = cmp_c then
498cnt_n <= (others => '0') after g.delay;
499pul_n <= '1' after g.delay;
500else
501cnt_n <= std_ulogic_vector(unsigned(cnt_c) + 1) after g.delay;
502pul_n <= '0' after g.delay;
503end if;
504end process;
505end architecture;
506
507library ieee, work;
508use ieee.std_logic_1164.all;
509use work.uart_pkg.all;
510use work.util.common_generics;
511use work.util.parity;
512
513entity uart_rx is
514generic (
515g: common_generics;
516N: positive;
517D: positive;
518format: std_ulogic_vector(7 downto 0) := uart_8N1);
519port (
520clk: in std_ulogic;
521rst: in std_ulogic;
522cr: out std_ulogic; -- reset sample/baud clock when start bit detected
523baud, sample: in std_ulogic; -- pulses at baud and sample rate
524failed: out std_ulogic_vector(1 downto 0);
525ctr: in std_ulogic_vector(7 downto 0);
526ctr_we: in std_ulogic;
527rx: in std_ulogic; -- physical RX signal
528we: out std_ulogic; -- write 'do' to output register
529do: out std_ulogic_vector(N - 1 downto 0));
530end entity;
531
532architecture behaviour of uart_rx is
533type state is (reset, idle, start, data, parity, stop, done);
534signal state_c, state_n: state;
535signal ctr_c, ctr_n: std_ulogic_vector(ctr'range);
536signal rx_c, rx_n: std_ulogic_vector(do'range);
537signal sr_c, sr_n: std_ulogic_vector(D - 1 downto 0);
538signal rx_sync: std_ulogic;
539signal count_c, count_n: integer range 0 to N - 1;
540signal majority: std_ulogic;
541signal fail_c, fail_n: std_ulogic_vector(1 downto 0);
542begin
543do <= rx_c after g.delay;
544failed <= fail_c after g.delay;
545
546assert D < 4 severity failure;
547
548majority_1: if D = 1 generate
549majority <= sr_c(0) after g.delay;
550end generate;
551
552majority_2: if D = 2 generate
553majority <= sr_c(0) and sr_c(1) after g.delay; -- even wins is 'sr_c(0) or sr_c(1)'
554end generate;
555
556majority_3: if D = 3 generate
557majority <= (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;
558end generate;
559
560process (clk, rst)
561procedure reset is
562begin
563rx_c <= (others => '0') after g.delay;
564sr_c <= (others => '0') after g.delay;
565fail_c <= (others => '0') after g.delay;
566ctr_c <= (others => '0') after g.delay;
567state_c <= reset after g.delay;
568count_c <= 0 after g.delay;
569rx_sync <= '0' after g.delay;
570end procedure;
571begin
572if rst = '1' and g.asynchronous_reset then
573reset;
574elsif rising_edge(clk) then
575if rst = '1' and not g.asynchronous_reset then
576reset;
577else
578rx_c <= rx_n after g.delay;
579sr_c <= sr_n after g.delay;
580state_c <= state_n after g.delay;
581count_c <= count_n after g.delay;
582fail_c <= fail_n after g.delay;
583ctr_c <= ctr_n after g.delay;
584rx_sync <= rx after g.delay;
585end if;
586end if;
587end process;
588
589process (rx_c, sr_c, ctr_c, ctr_we, ctr, state_c, rx_sync, baud, sample, count_c, fail_c, majority)
590begin
591fail_n <= fail_c after g.delay;
592rx_n <= rx_c after g.delay;
593sr_n <= sr_c after g.delay;
594ctr_n <= ctr_c after g.delay;
595state_n <= state_c after g.delay;
596we <= '0' after g.delay;
597cr <= '0' after g.delay;
598count_n <= count_c after g.delay;
599
600if sample = '1' then
601sr_n <= sr_c(sr_c'high - 1 downto sr_c'low) & rx_sync after g.delay;
602end if;
603
604case state_c is
605when reset =>
606rx_n <= (others => '0') after g.delay;
607sr_n <= (others => '0') after g.delay;
608fail_n <= (others => '0') after g.delay;
609ctr_n <= format after g.delay; -- 8 bits, 1 stop bit, parity off
610state_n <= idle after g.delay;
611when idle =>
612count_n <= 0 after g.delay;
613if rx_sync = '0' then -- and majority = '1' then
614state_n <= start after g.delay;
615cr <= '1' after g.delay;
616sr_n <= (others => '0') after g.delay;
617fail_n <= (others => '0') after g.delay;
618end if;
619when start =>
620if baud = '1' then
621if majority /= '0' then
622state_n <= done after g.delay; -- frame error
623fail_n(0) <= '1' after g.delay;
624else
625state_n <= data after g.delay;
626end if;
627sr_n <= (others => '0') after g.delay;
628end if;
629when data =>
630rx_n(count_c) <= majority after g.delay;
631if baud = '1' then
632if count_c = (ctr_data_bits(ctr_c) - 1) then
633count_n <= 0 after g.delay;
634if ctr_c(ctr_use_parity) = '1' then
635state_n <= parity after g.delay;
636else
637state_n <= stop after g.delay;
638end if;
639else
640count_n <= count_c + 1 after g.delay;
641end if;
642sr_n <= (others => '0') after g.delay;
643end if;
644when parity =>
645if baud = '1' then
646if (ctr_c(ctr_use_parity) = '1') and (majority /= parity(rx_c, ctr_c(ctr_even_parity))) then
647fail_n(1) <= '1' after g.delay; -- parity error, still process stop bits
648end if;
649state_n <= stop after g.delay;
650sr_n <= (others => '0') after g.delay;
651end if;
652when stop =>
653if baud = '1' then
654if majority /= '1' then
655state_n <= done after g.delay; -- frame error
656fail_n(0) <= '1' after g.delay;
657elsif count_c = ctr_stop_bits(ctr_c) then
658state_n <= done after g.delay;
659else
660count_n <= count_c + 1 after g.delay;
661end if;
662end if;
663when done => -- The consuming module needs to store rx_c/fail_c immediately
664we <= '1' after g.delay;
665state_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;
669end case;
670
671if ctr_we = '1' then
672if not (state_c = idle or state_c = done or state_c = reset) then
673rx_n <= (others => '0') after g.delay;
674state_n <= idle after g.delay;
675we <= '1' after g.delay;
676fail_n(0) <= '1' after g.delay; -- frame error!
677end if;
678ctr_n <= ctr after g.delay;
679end if;
680end process;
681end architecture;
682
683library ieee, work;
684use ieee.std_logic_1164.all;
685use work.uart_pkg.all;
686use work.util.common_generics;
687use work.util.parity;
688
689entity uart_tx is
690generic (g: common_generics; N: positive; format: std_ulogic_vector(7 downto 0) := uart_8N1);
691port (
692clk: in std_ulogic;
693rst: in std_ulogic;
694cr: out std_ulogic;
695baud: in std_ulogic; -- Pulse at baud
696tx: out std_ulogic;
697ok: out std_ulogic;
698ctr: in std_ulogic_vector(format'range);
699ctr_we: in std_ulogic;
700we: in std_ulogic; -- di write enable
701di: in std_ulogic_vector(N - 1 downto 0));
702end entity;
703
704architecture behaviour of uart_tx is
705type state is (reset, idle, start, data, parity, stop);
706signal state_c, state_n: state;
707signal di_c, di_n: std_ulogic_vector(di'range);
708signal ctr_c, ctr_n: std_ulogic_vector(ctr'range);
709signal busy: std_ulogic;
710signal parity_c, parity_n: std_ulogic;
711signal count_c, count_n: integer range 0 to 15;
712begin
713busy <= '0' when state_c = idle else '1' after g.delay;
714ok <= not busy after g.delay;
715
716process (clk, rst)
717procedure reset is
718begin
719di_c <= (others => '0') after g.delay;
720ctr_c <= (others => '0') after g.delay;
721state_c <= reset after g.delay;
722parity_c <= '0' after g.delay;
723count_c <= 0 after g.delay;
724end procedure;
725begin
726if rst = '1' and g.asynchronous_reset then
727reset;
728elsif rising_edge(clk) then
729if rst = '1' and not g.asynchronous_reset then
730reset;
731else
732di_c <= di_n after g.delay;
733ctr_c <= ctr_n after g.delay;
734state_c <= state_n after g.delay;
735parity_c <= parity_n after g.delay;
736count_c <= count_n after g.delay;
737end if;
738end if;
739end process;
740
741process (di_c, di, ctr_c, ctr_we, ctr, state_c, we, baud, parity_c, count_c)
742begin
743count_n <= count_c after g.delay;
744state_n <= state_c after g.delay;
745di_n <= di_c after g.delay;
746ctr_n <= ctr_c after g.delay;
747tx <= '1' after g.delay;
748cr <= '0';
749
750if ctr_c(ctr_use_parity) = '1' then
751parity_n <= parity(di_c, ctr_c(ctr_even_parity)) after g.delay;
752else
753parity_n <= '0' after g.delay;
754end if;
755
756case state_c is
757when reset =>
758state_n <= idle after g.delay;
759ctr_n <= format after g.delay; -- 8 bits, 1 stop bit, parity off
760count_n <= 0 after g.delay;
761parity_n <= '0' after g.delay;
762di_n <= (others => '0') after g.delay;
763when idle =>
764count_n <= 0 after g.delay;
765if ctr_we = '1' then -- NB. We can either lose data, or control writes
766ctr_n <= ctr after g.delay;
767elsif we = '1' then
768di_n <= di after g.delay;
769cr <= '1';
770state_n <= start after g.delay;
771end if;
772when start =>
773tx <= '0' after g.delay;
774if baud = '1' then
775state_n <= data after g.delay;
776end if;
777when data =>
778tx <= di_c(count_c) after g.delay;
779if baud = '1' then
780if count_c = (ctr_data_bits(ctr_c) - 1) then
781count_n <= 0 after g.delay;
782if ctr_c(ctr_use_parity) = '1' then
783state_n <= parity after g.delay;
784else
785state_n <= stop after g.delay;
786end if;
787else
788count_n <= count_c + 1 after g.delay;
789end if;
790end if;
791when parity =>
792tx <= parity_c after g.delay;
793if baud = '1' then
794state_n <= stop after g.delay;
795end if;
796when stop =>
797tx <= '1' after g.delay;
798if baud = '1' then
799if count_c = ctr_stop_bits(ctr_c) then
800count_n <= 0 after g.delay;
801state_n <= idle after g.delay;
802else
803count_n <= count_c + 1 after g.delay;
804end if;
805end if;
806end case;
807end process;
808end architecture;
809
810library ieee, work;
811use ieee.std_logic_1164.all;
812use ieee.numeric_std.all;
813use work.uart_pkg.all;
814use work.util.common_generics;
815
816entity uart_tb is
817generic(g: common_generics);
818end entity;
819
820architecture testing of uart_tb is
821constant clock_period: time := 1000 ms / g.clock_frequency;
822constant use_fifo: boolean := true;
823signal rst, clk: std_ulogic := '1';
824signal stop: boolean := false;
825signal loopback: boolean := true;
826signal tx, rx: std_ulogic;
827signal di, do: std_ulogic_vector(7 downto 0);
828signal reg: std_ulogic_vector(15 downto 0);
829signal clock_reg_tx_we: std_ulogic;
830signal clock_reg_rx_we: std_ulogic;
831signal control_reg_we: std_ulogic;
832
833signal tx_fifo_full: std_ulogic;
834signal tx_fifo_empty: std_ulogic;
835signal tx_fifo_we: std_ulogic := '0';
836signal rx_fifo_full: std_ulogic;
837signal rx_fifo_empty: std_ulogic;
838signal rx_fifo_re: std_ulogic := '0';
839begin
840-- duration: process begin wait for 20000 us; stop <= true; wait; end process;
841clk_process: process
842begin
843rst <= '1';
844wait for clock_period * 5;
845rst <= '0';
846while not stop loop
847clk <= '1';
848wait for clock_period / 2;
849clk <= '0';
850wait for clock_period / 2;
851end loop;
852wait;
853end process;
854
855stimulus: process
856procedure write(data: std_ulogic_vector(di'range)) is
857begin
858wait for clock_period * 1;
859while tx_fifo_full = '1' loop
860wait for clock_period;
861end loop;
862di <= data;
863tx_fifo_we <= '1';
864wait for clock_period;
865tx_fifo_we <= '0';
866end procedure;
867begin
868di <= x"00";
869wait until rst = '0';
870wait for clock_period;
871reg <= x"8080";
872control_reg_we <= '1';
873wait for clock_period;
874control_reg_we <= '0';
875reg <= x"0036";
876clock_reg_tx_we <= '1';
877wait for clock_period;
878clock_reg_tx_we <= '0';
879clock_reg_rx_we <= '1';
880reg <= x"0035";
881wait for clock_period;
882clock_reg_rx_we <= '0';
883wait for clock_period;
884
885write(x"AA");
886write(x"BB");
887write(x"CC");
888write(x"DD");
889write(x"EE");
890write(x"FF");
891wait for clock_period;
892while tx_fifo_empty = '0' loop
893wait for clock_period;
894end loop;
895loopback <= false;
896wait for clock_period * 50000;
897stop <= true;
898wait;
899end process;
900
901ack: process
902begin
903while not stop loop
904if rx_fifo_empty = '0' then
905rx_fifo_re <= '1';
906else
907rx_fifo_re <= '0';
908end if;
909wait for clock_period;
910end loop;
911wait;
912end process;
913rx <= tx when loopback else '0'; -- loop back test
914uut: work.uart_pkg.uart_top
915generic map (g => g, baud => 115200, format => uart_8N1, use_fifo => use_fifo)
916port map (
917clk => clk,
918rst => rst,
919
920tx => tx,
921tx_fifo_full => tx_fifo_full,
922tx_fifo_empty => tx_fifo_empty,
923tx_fifo_we => tx_fifo_we,
924tx_fifo_data => di,
925
926rx => rx,
927rx_fifo_full => rx_fifo_full,
928rx_fifo_empty => rx_fifo_empty,
929rx_fifo_re => rx_fifo_re,
930rx_fifo_data => do,
931
932reg => reg,
933clock_reg_tx_we => clock_reg_tx_we,
934clock_reg_rx_we => clock_reg_rx_we,
935control_reg_we => control_reg_we);
936
937end architecture;
938
939