-------------------------------------------------------------------------------- -- a3_rs232.vhd -------------------------------------------------------------------------------- library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.NUMERIC_STD.ALL; entity rs232_top is port( clk : in std_logic; rxd : in std_logic; txd : out std_logic; led : out std_logic_vector(7 downto 0); la : out std_logic_vector(1 downto 0); fehler : out std_logic ); end entity; architecture synth of rs232_top is -- Internes txd Signal -- (da der Port txd ein Ausgabeport ist, kann er nicht gelesen werden) signal txd_out : std_logic := '0'; -- Teilerkostante zur Erzeugung der 16-fachen Baudrate -- Formel: 50 MHz / (Baudrate * 16) = 2 * cTeiler constant cTeiler : integer := 162; -- Taktsignal für 16-fache Baudrate signal clk_16x_baud : std_logic := '0'; -- 2 Bit Schieberegister für Empfangsdaten signal rxd_del : std_logic_vector(1 downto 0) := (others => '0'); -- Zustand des Empfangsautomaten signal r_state : integer range 0 to 15 := 0; -- Empfangspuffer signal Q : std_logic_vector(7 downto 0) := (others => '0'); begin -- Noch kein Sender => Echofunktion -- Zeile auskommentieren oder löschen wenn der Sendeautomat eingebaut wird txd_out <= rxd; -- Instanz des Sendeautomaten erzeugen -- sender_inst : entity work.a3_rs232_sender -- port map( -- clk_16x_baud => clk_16x_baud, -- txd => txd_out, -- data => sw, -- req => ..., -- grant => ... -- ); -- Taktteiler zur Erzeugung der 16-fachen Baudrate process(clk) variable counter : integer range 0 to cTeiler - 1 := cTeiler - 1; begin if rising_edge(clk) then if counter = 0 then clk_16x_baud <= not clk_16x_baud; counter := cTeiler - 1; else counter := counter - 1; end if; end if; end process; -- Empfangsautomat process(clk_16x_baud) variable sample_counter : integer range 0 to 15 := 7; variable busy : boolean := false; begin if rising_edge(clk_16x_baud) then -- 2 Bit Schieberegister mit den empfangenen Daten füllen, -- um Pegelwechsel von 1 auf 0 erkennen zu können rxd_del <= rxd_del(0) & rxd; -- Fallende Flanke detektiert if rxd_del = "10" and not busy then busy := true; sample_counter := 7; elsif busy then -- Zähler zum Finden des idealen Abtastzeitpunktes -- (dieser liegt in der Mitte des Bitintervalls) if sample_counter = 0 then sample_counter := 15; else sample_counter := sample_counter - 1; end if; end if; if busy and sample_counter = 0 then r_state <= r_state + 1; -- Zustandsübergänge case r_state is -- Startbit when 0 => -- Startbit empfangen -- 8 Datenbits when 1 to 8 => Q <= rxd & Q(7 downto 1); -- Paritätsbit when 9 => -- Parität berechnen und auf Fehler-LED ausgeben -- fehler <= .. -- Stoppbit when others => r_state <= 0; busy := false; end case; end if; end if; end process; -- Ausgabe des Schieberegisterzustandes led(7 downto 0) <= Q; -- Ausgabe von rxd und txd an die LA Pins la <= rxd & txd_out; -- Internes txd Signal an Port zuweisen txd <= txd_out; end architecture;