copyleft: gplv3 added and set repo to public
[calu.git] / cpu / src / rs232_rx_arc.vhd
1 --   `Deep Thought', a softcore CPU implemented on a FPGA
2 --
3 --  Copyright (C) 2010 Markus Hofstaetter <markus.manrow@gmx.at>
4 --  Copyright (C) 2010 Martin Perner <e0725782@student.tuwien.ac.at>
5 --  Copyright (C) 2010 Stefan Rebernig <stefan.rebernig@gmail.com>
6 --  Copyright (C) 2010 Manfred Schwarz <e0725898@student.tuwien.ac.at>
7 --  Copyright (C) 2010 Bernhard Urban <lewurm@gmail.com>
8 --
9 --  This program is free software: you can redistribute it and/or modify
10 --  it under the terms of the GNU General Public License as published by
11 --  the Free Software Foundation, either version 3 of the License, or
12 --  (at your option) any later version.
13 --
14 --  This program is distributed in the hope that it will be useful,
15 --  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 --  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 --  GNU General Public License for more details.
18 --
19 --  You should have received a copy of the GNU General Public License
20 --  along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
22 library IEEE;
23 use IEEE.std_logic_1164.all;
24 use IEEE.numeric_std.all;
25
26 use work.extension_uart_pkg.all;
27
28 use work.common_pkg.all;
29 use work.core_pkg.all;
30
31 architecture beh of rs232_rx is
32         -- definierern der intern verwendeten Signale
33         type STATE_TYPE is (IDLE, READ_START, READ_BIT, READ_STOP);
34         signal state, state_next : STATE_TYPE;
35         signal bus_rx_last, bus_rx_int, new_rx_data_nxt : std_logic := '0';
36         signal cnt, cnt_next : integer := 0;
37         signal baud_cnt, baud_cnt_next : std_logic_vector(BAUD_RATE_WIDTH-1 downto 0);
38         signal rx_data_int, rx_data_nxt, rx_data_res_int, rx_data_res_nxt : uart_data;
39         signal sync : std_logic_vector(1 to SYNC_STAGES);
40         signal bus_rx : std_logic;
41         
42 begin
43         -- syncronisierungs Prozess
44         rs232_rx_syn : process(sys_clk, sys_res_n)
45         begin
46                 if (sys_res_n = RESET_VALUE) then
47                         -- reset Zustand
48                         state <= IDLE;
49                         cnt <= 0;
50                         rx_data_res_int <= x"00";
51                         rx_data_int <= (others => '0');
52                         baud_cnt <= (others => '0');
53                         sync <= (others => '1');
54
55                 elsif rising_edge(sys_clk) then
56                         -- sync Zustand, uebernehmen der next-Signale
57                         state <= state_next;
58                         cnt <= cnt_next;
59                         baud_cnt <= baud_cnt_next;
60                         bus_rx_int <= bus_rx_last;
61                         rx_data_int <= rx_data_nxt;
62                         rx_data_res_int <= rx_data_res_nxt;
63                         new_rx_data <= new_rx_data_nxt;
64
65                         sync(1) <= bus_rx_unsync;
66                         for i in 2 to SYNC_STAGES loop
67                                 sync(i) <= sync(i - 1);
68                         end loop;
69                         
70                 end if;
71         end process;
72
73         -- setzen des Ausgangsignals, Rxt-Daten
74         rx_data <= rx_data_res_int;
75         bus_rx <= sync(SYNC_STAGES);
76
77         -- Zustandsmaschienen Prozess
78         rs232_states : process(sys_clk,state,cnt, bus_rx, bus_rx_last, baud_cnt,bus_rx_int,bd_rate)
79         begin
80                 state_next <= state;    -- mal schauen ob des so geht
81                 bus_rx_last <= bus_rx; -- mal schauen ob des so geht
82                 case state is
83                         when IDLE =>
84                                 -- nach einem Wechsel der rxt-Leitung von 1 auf 0 wird der einlese Vorgang
85                                 -- getriggert mithilfe eines Zustandsuebergangs von IDLE auf READ_START
86                                 if (bus_rx_last = '0' and bus_rx_int = '1') then
87                                         state_next <= READ_START;
88                                 end if;
89                         when READ_START =>
90                                 -- im READ_START Zustand wird eine halbe Bitzeit gewartet. Liegt auf der rxt-Leitung
91                                 -- immer noch die 0 an so wird mit deim Lesebvorgang mit einem Zustandswechsel von
92                                 -- READ_START nach READ_BIT vorgefahren, wenn eine 1 anliegt wird abgebrochen und
93                                 -- wieder nach IDLE gewechselt
94                                 
95                                 if (bus_rx = '0' and baud_cnt(BAUD_RATE_WIDTH-2 downto 0) = bd_rate(BAUD_RATE_WIDTH-1 downto 1)) then
96                                         state_next <= READ_BIT;
97                                 elsif (bus_rx = '1' and baud_cnt(BAUD_RATE_WIDTH-2 downto 0) = bd_rate(BAUD_RATE_WIDTH-1 downto 1)) then
98                                         state_next <= IDLE;
99                                 end if;
100                         when READ_BIT =>
101                                 -- hier werden mit Hilfe eines Countersignals 8 Datenbits im Abstand der eingestellten
102                                 -- Bitzeit eingelesen und gespeichert.
103                                 -- Nach beendigung wird in den Zustand READ_STOP gewechselt.
104                                 if (cnt = 7 and  baud_cnt = bd_rate) then
105                                         state_next <= READ_STOP;
106                                 else
107                                         state_next <= READ_BIT;
108                                 end if;
109                         when READ_STOP =>
110                                 -- hier wird nur noch auf das Stopbit abgewartet und gelesen um den
111                                 -- Lesevorgang koerrekt zu beenden
112                                 if baud_cnt = bd_rate then
113                                         state_next <= IDLE;
114                                 end if;
115                 end case;
116         end process;
117
118         -- Ausgabe Logik
119         rs232_rx_baud : process(state, cnt, bus_rx, baud_cnt, rx_data_int, rx_data_res_int, bd_rate)
120         begin
121                 -- Signale halten um Latches zu vermeiden
122                 cnt_next <= cnt;
123                 new_rx_data_nxt <= '0';
124                 baud_cnt_next <= baud_cnt;
125                 rx_data_nxt <= rx_data_int;
126                 rx_data_res_nxt <= rx_data_res_int;
127                 -- Statewechesel wie obenbeschrieben
128                 case state is
129                         when IDLE =>
130                                 cnt_next <= 0;
131                                 baud_cnt_next <= (others =>'0'); --0;
132                         when READ_START =>
133                                 -- baut_cnt zyklenweise erhoehen bis es einer halben Bitzeit entspricht
134                                 -- anschliessend zuruecksetzten
135                                 baud_cnt_next <= std_logic_vector(unsigned(baud_cnt) + 1);
136                                 if baud_cnt(BAUD_RATE_WIDTH-2 downto 0) = bd_rate(BAUD_RATE_WIDTH-1 downto 1) then 
137                                         baud_cnt_next <= (others => '0');
138                                         rx_data_nxt <= x"00";
139                                 end if;
140                         when READ_BIT =>
141                                 -- baut_cnt zyklenweise erhoehen bis es einer Bitzeit entspricht
142                                 -- anschliessend zuruecksetzen
143                                 -- Zustand der rxt-Leitung im rx_data_nxt abspeichern
144                                 baud_cnt_next <= std_logic_vector(unsigned(baud_cnt) + 1);
145                                 if baud_cnt = bd_rate then 
146                                         baud_cnt_next <= (others => '0');
147                                         cnt_next <= cnt+1;
148                                         rx_data_nxt(cnt) <= bus_rx;
149                                 end if;
150                         when READ_STOP =>
151                                 -- baut_cnt zyklenweise erhoehen bis es einer Bitzeit entspricht
152                                 -- anschliessend zuruecksetzen
153                                 -- Counter reseten
154                                 -- Signal fuer neue rx-Daten setzen um die send_logic zu aktivieren
155                                 cnt_next <= 0;
156                                 baud_cnt_next <= std_logic_vector(unsigned(baud_cnt) + 1);
157                                 if baud_cnt = bd_rate then 
158                                         baud_cnt_next <= (others => '0');
159                                         new_rx_data_nxt <= bus_rx;
160                                         rx_data_res_nxt <= rx_data_int;
161                                 end if;
162                 end case;
163         end process;
164
165 end architecture beh;
166