uart_rx: rewrite inkl. testbench
[hwmod.git] / src / uart_rx.vhd
1 library ieee;
2 use ieee.std_logic_1164.all;
3 use ieee.numeric_std.all;
4 use work.gen_pkg.all;
5
6 entity uart_rx is
7         generic (
8                 CLK_FREQ : integer := 33000000;
9                 BAUDRATE : integer := 115200
10         );
11         port(
12                 sys_clk : in std_logic;
13                 sys_res_n : in std_logic;
14                 rxd : in std_logic;
15                 rx_data : out std_logic_vector(7 downto 0);
16                 rx_new : out std_logic
17         );
18 end entity uart_rx;
19
20 architecture beh of uart_rx is
21         constant BAUD : integer := CLK_FREQ/BAUDRATE;
22
23         type STATE_UART_RX is (IDLE, STARTBIT, DBITS, STOPBIT);
24         signal state_int, state_next : STATE_UART_RX;
25
26         signal rx_data_next, rx_data_int : std_logic_vector(7 downto 0);
27         signal rx_new_next, rx_new_int : std_logic;
28         signal startbitdetection : std_logic_vector(1 downto 0);
29         signal bitcnt_int, bitcnt_next : integer range 0 to 7;
30         signal baudcnt_int, baudcnt_next : integer range 0 to BAUD;
31 begin
32         rx_new <= rx_new_int;
33         rx_data <= rx_data_int;
34
35         process(sys_clk, sys_res_n)
36         begin
37                 if (sys_res_n = '0') then
38                         state_int <= IDLE;
39                         rx_data_int <= (others => '0');
40                         rx_new_int <= '0';
41                         bitcnt_int <= 0;
42                         baudcnt_int <= 0;
43                         startbitdetection <= b"11";
44                 elsif rising_edge(sys_clk) then
45                         state_int <= state_next;
46                         rx_data_int <= rx_data_next;
47                         rx_new_int <= rx_new_next;
48                         bitcnt_int <= bitcnt_next;
49                         baudcnt_int <= baudcnt_next;
50                         startbitdetection(0) <= rxd;
51                         startbitdetection(1) <= startbitdetection(0);
52                 end if;
53         end process;
54
55         process(state_int, rx_data_int, rxd, bitcnt_int, baudcnt_int,
56                 startbitdetection)
57         begin
58                 state_next <= state_int;
59                 rx_data_next <= rx_data_int;
60                 rx_new_next <= '0';
61                 bitcnt_next <= bitcnt_int;
62                 baudcnt_next <= baudcnt_int;
63
64                 case state_int is
65                         when IDLE =>
66                                 -- bei fallender flanke koennte starbit folgen
67                                 if startbitdetection = b"10" then
68                                         state_next <= STARTBIT;
69                                         baudcnt_next <= 0;
70                                 end if;
71                         when STARTBIT =>
72                                 rx_data_next <= (others => '0');
73
74                                 -- halbe BAUDTIME warten, um immer in der mitte abzutasten
75                                 -- vgl. http://upload.wikimedia.org/wikipedia/de/d/de/RS-232_timing.png
76                                 if baudcnt_int < BAUD/2 then
77                                         baudcnt_next <= baudcnt_int + 1;
78                                 else
79                                         baudcnt_next <= 0;
80                                         if rxd = '0' then
81                                                 -- starbit (= '0')? dann kommen daten
82                                                 state_next <= DBITS;
83                                                 bitcnt_next <= 0;
84                                         else
85                                                 -- sonst war das nix...
86                                                 state_next <= IDLE;
87                                         end if;
88                                 end if;
89                         when DBITS =>
90                                 if baudcnt_int < BAUD then
91                                         baudcnt_next <= baudcnt_int + 1;
92                                 else
93                                         baudcnt_next <= 0;
94                                         rx_data_next <= rx_data_int(6 downto 0) & rxd;
95
96                                         if bitcnt_int = 7 then
97                                                 state_next <= STOPBIT;
98                                         else
99                                                 bitcnt_next <= bitcnt_int + 1;  
100                                         end if;
101                                 end if;
102                         when STOPBIT =>
103                                 if baudcnt_int < BAUD then
104                                         baudcnt_next <= baudcnt_int + 1;
105                                 else
106                                         state_next <= IDLE;
107                                         if rxd = '1' then
108                                                 rx_new_next <= '1';
109                                         end if;
110                                 end if;
111                 end case;
112         end process;
113 end architecture beh;