-- `Deep Thought', a softcore CPU implemented on a FPGA -- -- Copyright (C) 2010 Markus Hofstaetter -- Copyright (C) 2010 Martin Perner -- Copyright (C) 2010 Stefan Rebernig -- Copyright (C) 2010 Manfred Schwarz -- Copyright (C) 2010 Bernhard Urban -- -- This program is free software: you can redistribute it and/or modify -- it under the terms of the GNU General Public License as published by -- the Free Software Foundation, either version 3 of the License, or -- (at your option) any later version. -- -- This program is distributed in the hope that it will be useful, -- but WITHOUT ANY WARRANTY; without even the implied warranty of -- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- GNU General Public License for more details. -- -- You should have received a copy of the GNU General Public License -- along with this program. If not, see . library IEEE; use IEEE.std_logic_1164.all; use IEEE.numeric_std.all; use work.extension_uart_pkg.all; use work.common_pkg.all; use work.core_pkg.all; architecture beh of rs232_rx is -- definierern der intern verwendeten Signale type STATE_TYPE is (IDLE, READ_START, READ_BIT, READ_STOP); signal state, state_next : STATE_TYPE; signal bus_rx_last, bus_rx_int, new_rx_data_nxt : std_logic := '0'; signal cnt, cnt_next : integer := 0; signal baud_cnt, baud_cnt_next : std_logic_vector(BAUD_RATE_WIDTH-1 downto 0); signal rx_data_int, rx_data_nxt, rx_data_res_int, rx_data_res_nxt : uart_data; signal sync : std_logic_vector(1 to SYNC_STAGES); signal bus_rx : std_logic; begin -- syncronisierungs Prozess rs232_rx_syn : process(sys_clk, sys_res_n) begin if (sys_res_n = RESET_VALUE) then -- reset Zustand state <= IDLE; cnt <= 0; rx_data_res_int <= x"00"; rx_data_int <= (others => '0'); baud_cnt <= (others => '0'); sync <= (others => '1'); elsif rising_edge(sys_clk) then -- sync Zustand, uebernehmen der next-Signale state <= state_next; cnt <= cnt_next; baud_cnt <= baud_cnt_next; bus_rx_int <= bus_rx_last; rx_data_int <= rx_data_nxt; rx_data_res_int <= rx_data_res_nxt; new_rx_data <= new_rx_data_nxt; sync(1) <= bus_rx_unsync; for i in 2 to SYNC_STAGES loop sync(i) <= sync(i - 1); end loop; end if; end process; -- setzen des Ausgangsignals, Rxt-Daten rx_data <= rx_data_res_int; bus_rx <= sync(SYNC_STAGES); -- Zustandsmaschienen Prozess rs232_states : process(sys_clk,state,cnt, bus_rx, bus_rx_last, baud_cnt,bus_rx_int,bd_rate) begin state_next <= state; -- mal schauen ob des so geht bus_rx_last <= bus_rx; -- mal schauen ob des so geht case state is when IDLE => -- nach einem Wechsel der rxt-Leitung von 1 auf 0 wird der einlese Vorgang -- getriggert mithilfe eines Zustandsuebergangs von IDLE auf READ_START if (bus_rx_last = '0' and bus_rx_int = '1') then state_next <= READ_START; end if; when READ_START => -- im READ_START Zustand wird eine halbe Bitzeit gewartet. Liegt auf der rxt-Leitung -- immer noch die 0 an so wird mit deim Lesebvorgang mit einem Zustandswechsel von -- READ_START nach READ_BIT vorgefahren, wenn eine 1 anliegt wird abgebrochen und -- wieder nach IDLE gewechselt if (bus_rx = '0' and baud_cnt(BAUD_RATE_WIDTH-2 downto 0) = bd_rate(BAUD_RATE_WIDTH-1 downto 1)) then state_next <= READ_BIT; elsif (bus_rx = '1' and baud_cnt(BAUD_RATE_WIDTH-2 downto 0) = bd_rate(BAUD_RATE_WIDTH-1 downto 1)) then state_next <= IDLE; end if; when READ_BIT => -- hier werden mit Hilfe eines Countersignals 8 Datenbits im Abstand der eingestellten -- Bitzeit eingelesen und gespeichert. -- Nach beendigung wird in den Zustand READ_STOP gewechselt. if (cnt = 7 and baud_cnt = bd_rate) then state_next <= READ_STOP; else state_next <= READ_BIT; end if; when READ_STOP => -- hier wird nur noch auf das Stopbit abgewartet und gelesen um den -- Lesevorgang koerrekt zu beenden if baud_cnt = bd_rate then state_next <= IDLE; end if; end case; end process; -- Ausgabe Logik rs232_rx_baud : process(state, cnt, bus_rx, baud_cnt, rx_data_int, rx_data_res_int, bd_rate) begin -- Signale halten um Latches zu vermeiden cnt_next <= cnt; new_rx_data_nxt <= '0'; baud_cnt_next <= baud_cnt; rx_data_nxt <= rx_data_int; rx_data_res_nxt <= rx_data_res_int; -- Statewechesel wie obenbeschrieben case state is when IDLE => cnt_next <= 0; baud_cnt_next <= (others =>'0'); --0; when READ_START => -- baut_cnt zyklenweise erhoehen bis es einer halben Bitzeit entspricht -- anschliessend zuruecksetzten baud_cnt_next <= std_logic_vector(unsigned(baud_cnt) + 1); if baud_cnt(BAUD_RATE_WIDTH-2 downto 0) = bd_rate(BAUD_RATE_WIDTH-1 downto 1) then baud_cnt_next <= (others => '0'); rx_data_nxt <= x"00"; end if; when READ_BIT => -- baut_cnt zyklenweise erhoehen bis es einer Bitzeit entspricht -- anschliessend zuruecksetzen -- Zustand der rxt-Leitung im rx_data_nxt abspeichern baud_cnt_next <= std_logic_vector(unsigned(baud_cnt) + 1); if baud_cnt = bd_rate then baud_cnt_next <= (others => '0'); cnt_next <= cnt+1; rx_data_nxt(cnt) <= bus_rx; end if; when READ_STOP => -- baut_cnt zyklenweise erhoehen bis es einer Bitzeit entspricht -- anschliessend zuruecksetzen -- Counter reseten -- Signal fuer neue rx-Daten setzen um die send_logic zu aktivieren cnt_next <= 0; baud_cnt_next <= std_logic_vector(unsigned(baud_cnt) + 1); if baud_cnt = bd_rate then baud_cnt_next <= (others => '0'); new_rx_data_nxt <= bus_rx; rx_data_res_nxt <= rx_data_int; end if; end case; end process; end architecture beh;