OpenCores
URL https://opencores.org/ocsvn/forth-cpu/forth-cpu/trunk

Subversion Repositories forth-cpu

[/] [forth-cpu/] [trunk/] [uart.vhd] - Blame information for rev 5

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 5 howe.r.j.8
-- 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 3 howe.r.j.8
use ieee.std_logic_1164.all;
50 5 howe.r.j.8
use ieee.numeric_std.all;
51
use work.util.common_generics;
52 3 howe.r.j.8
 
53
package uart_pkg is
54 5 howe.r.j.8
        constant uart_8N1: std_ulogic_vector(7 downto 0) := "10000100";
55 3 howe.r.j.8
 
56 5 howe.r.j.8
        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 3 howe.r.j.8
 
71 5 howe.r.j.8
        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 3 howe.r.j.8
 
86 5 howe.r.j.8
        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 3 howe.r.j.8
 
98 5 howe.r.j.8
        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 3 howe.r.j.8
 
104 5 howe.r.j.8
                        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 3 howe.r.j.8
        end component;
120
 
121 5 howe.r.j.8
        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 3 howe.r.j.8
                port (
128 5 howe.r.j.8
                        clk:    in std_ulogic;
129
                        rst:    in std_ulogic;
130 3 howe.r.j.8
 
131 5 howe.r.j.8
                        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 3 howe.r.j.8
 
137 5 howe.r.j.8
                        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 3 howe.r.j.8
        end component;
148
 
149 5 howe.r.j.8
        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 3 howe.r.j.8
end package;
158
 
159 5 howe.r.j.8
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 3 howe.r.j.8
 
167 5 howe.r.j.8
        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 3 howe.r.j.8
 
175 5 howe.r.j.8
library ieee, work;
176 3 howe.r.j.8
use ieee.std_logic_1164.all;
177
use ieee.numeric_std.all;
178 5 howe.r.j.8
use work.uart_pkg.all;
179
use work.util.common_generics;
180 3 howe.r.j.8
 
181
entity uart_top is
182 5 howe.r.j.8
        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 3 howe.r.j.8
        port (
188 5 howe.r.j.8
                clk:    in std_ulogic;
189
                rst:    in std_ulogic;
190 3 howe.r.j.8
 
191 5 howe.r.j.8
                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 3 howe.r.j.8
 
197 5 howe.r.j.8
                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 3 howe.r.j.8
 
203 5 howe.r.j.8
                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 3 howe.r.j.8
end entity;
208
 
209 5 howe.r.j.8
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 3 howe.r.j.8
 
223 5 howe.r.j.8
                        tx    => tx,
224
                        tx_we => tx_pop,
225
                        tx_di => tx_popped,
226
                        tx_ok => tx_ok,
227 3 howe.r.j.8
 
228 5 howe.r.j.8
                        rx    => rx,
229
                        rx_nd => rx_nd,
230
                        rx_ok => rx_ok,
231
                        rx_do => rx_pushed,
232
                        rx_re => rx_push,
233 3 howe.r.j.8
 
234 5 howe.r.j.8
                        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 3 howe.r.j.8
 
239 5 howe.r.j.8
        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 3 howe.r.j.8
 
245 5 howe.r.j.8
                        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 3 howe.r.j.8
begin
325 5 howe.r.j.8
        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 3 howe.r.j.8
        begin
332 5 howe.r.j.8
                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 3 howe.r.j.8
                elsif rising_edge(clk) then
337 5 howe.r.j.8
                        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 3 howe.r.j.8
                end if;
347
        end process;
348
 
349 5 howe.r.j.8
        process (do_c, do, nd_c, rx_we, rx_re, fail_c, rx_fail)
350 3 howe.r.j.8
        begin
351 5 howe.r.j.8
                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 3 howe.r.j.8
        end process;
362
 
363 5 howe.r.j.8
        baud_tx: work.uart_pkg.uart_baud
364
                generic map(g => g, init => tx_init, N => reg'length, D => 3)
365 3 howe.r.j.8
                port map(
366 5 howe.r.j.8
                        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 3 howe.r.j.8
 
374 5 howe.r.j.8
        baud_rx: work.uart_pkg.uart_baud
375
                generic map(g => g, init => rx_init, N => reg'length, D => 3)
376 3 howe.r.j.8
                port map(
377 5 howe.r.j.8
                        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 3 howe.r.j.8
 
385 5 howe.r.j.8
        tx_0: work.uart_pkg.uart_tx
386
                generic map(g => g, N => N, format => format)
387 3 howe.r.j.8
                port map(
388 5 howe.r.j.8
                        clk     => clk,
389
                        rst     => rst,
390 3 howe.r.j.8
 
391 5 howe.r.j.8
                        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 3 howe.r.j.8
 
400 5 howe.r.j.8
        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 3 howe.r.j.8
 
406 5 howe.r.j.8
                        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 3 howe.r.j.8
 
417 5 howe.r.j.8
-- 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 3 howe.r.j.8
use ieee.std_logic_1164.all;
422
use ieee.numeric_std.all;
423 5 howe.r.j.8
use work.uart_pkg.all;
424
use work.util.common_generics;
425 3 howe.r.j.8
 
426 5 howe.r.j.8
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 3 howe.r.j.8
 
436 5 howe.r.j.8
                sample: out std_ulogic;  -- sample pulse
437
                baud:   out std_ulogic); -- baud (sample rate / 2^(D+1))
438 3 howe.r.j.8
end entity;
439
 
440 5 howe.r.j.8
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 3 howe.r.j.8
 
452 5 howe.r.j.8
        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 3 howe.r.j.8
 
474 5 howe.r.j.8
        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 3 howe.r.j.8
 
485 5 howe.r.j.8
        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 3 howe.r.j.8
 
490 5 howe.r.j.8
                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 3 howe.r.j.8
 
507 5 howe.r.j.8
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 3 howe.r.j.8
 
513 5 howe.r.j.8
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 3 howe.r.j.8
begin
543 5 howe.r.j.8
        do     <= rx_c after g.delay;
544
        failed <= fail_c after g.delay;
545 3 howe.r.j.8
 
546 5 howe.r.j.8
        assert D < 4 severity failure;
547 3 howe.r.j.8
 
548 5 howe.r.j.8
        majority_1: if D = 1 generate
549
                majority <= sr_c(0) after g.delay;
550
        end generate;
551 3 howe.r.j.8
 
552 5 howe.r.j.8
        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 3 howe.r.j.8
        begin
572 5 howe.r.j.8
                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 3 howe.r.j.8
                        else
578 5 howe.r.j.8
                                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 3 howe.r.j.8
                        end if;
586
                end if;
587
        end process;
588
 
589 5 howe.r.j.8
        process (rx_c, sr_c, ctr_c, ctr_we, ctr, state_c, rx_sync, baud, sample, count_c, fail_c, majority)
590 3 howe.r.j.8
        begin
591 5 howe.r.j.8
                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 3 howe.r.j.8
                                end if;
627 5 howe.r.j.8
                                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 3 howe.r.j.8
                                        else
637 5 howe.r.j.8
                                                state_n <= stop after g.delay;
638 3 howe.r.j.8
                                        end if;
639 5 howe.r.j.8
                                else
640
                                        count_n <= count_c + 1 after g.delay;
641 3 howe.r.j.8
                                end if;
642 5 howe.r.j.8
                                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 3 howe.r.j.8
                                end if;
649 5 howe.r.j.8
                                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 3 howe.r.j.8
 
671 5 howe.r.j.8
                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 3 howe.r.j.8
                        end if;
678 5 howe.r.j.8
                        ctr_n <= ctr after g.delay;
679 3 howe.r.j.8
                end if;
680
        end process;
681 5 howe.r.j.8
end architecture;
682 3 howe.r.j.8
 
683 5 howe.r.j.8
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 3 howe.r.j.8
        begin
726 5 howe.r.j.8
                if rst = '1' and g.asynchronous_reset then
727
                        reset;
728 3 howe.r.j.8
                elsif rising_edge(clk) then
729 5 howe.r.j.8
                        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 3 howe.r.j.8
                        end if;
738
                end if;
739
        end process;
740
 
741 5 howe.r.j.8
        process (di_c, di, ctr_c, ctr_we, ctr, state_c, we, baud, parity_c, count_c)
742 3 howe.r.j.8
        begin
743 5 howe.r.j.8
                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 3 howe.r.j.8
                end if;
755
 
756 5 howe.r.j.8
                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 3 howe.r.j.8
                                else
788 5 howe.r.j.8
                                        count_n <= count_c + 1 after g.delay;
789 3 howe.r.j.8
                                end if;
790 5 howe.r.j.8
                        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 3 howe.r.j.8
                                end if;
805
                        end if;
806 5 howe.r.j.8
                end case;
807 3 howe.r.j.8
        end process;
808 5 howe.r.j.8
end architecture;
809 3 howe.r.j.8
 
810 5 howe.r.j.8
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 3 howe.r.j.8
        begin
843 5 howe.r.j.8
                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 3 howe.r.j.8
        end process;
854
 
855 5 howe.r.j.8
        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
 

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.