library IEEE; use IEEE.STD_LOGIC_1164.ALL; use IEEE.STD_LOGIC_ARITH.ALL; use IEEE.STD_LOGIC_UNSIGNED.ALL; entity LArs232 is Port ( CLK : in std_logic; sio_RxD : in std_logic; -- serieller Eingang sio_TxD : out std_logic:='1'; -- serieller Ausgang sw: in std_logic_vector(8 downto 1); led : out std_logic_vector(15 downto 0); Tout: out std_logic); end LArs232; architecture Behavioral of LArs232 is signal Baude_CLK: std_logic; -- 16-facher Baudetakt signal RxD_del: std_logic_vector(1 downto 0); -- verzögertes empf. Sig. signal State: integer range 0 to 9:=0; -- Zustand Empfangsautomat signal Q: std_logic_vector(7 downto 0); -- Empfangsschieberegister signal busy: std_logic; -- Signal zum Anschalten des 1:16 Teilers und des Empfängers signal realbaud: std_logic_vector(3 downto 0); begin --========================================================== -- Baude_CLK mit der 16fachen Frequenz der Bauderate und -- Tastverhältnis 1:1 erzeugen -- Bauderate: 9,6 kBaude; fCLK=50MHz -- Teilerfaktor: 50M/(9,6k * 16) = 2 * 162 -- (Baude_CLK wird jeweils nach 162 Takten invertiert) ------------------------------------------------------------- process(CLK) variable ClkVT: integer range 0 to 161:=0; variable ClkShifted: integer range 0 to 193:=0; begin if CLK'event and CLK='1' then ClkShifted := CONV_INTEGER(sw(8 downto 4)); led(12 downto 8) <= sw(8 downto 4); if ClkVT=161+ClkShifted then ClkVT:=0; Baude_CLK<=not Baude_CLK; else ClkVT:=ClkVT+1; end if; end if; end process; process(Baude_CLK) variable ClkDiv: std_logic_vector(3 downto 0); begin if Baude_CLK'event and Baude_CLK='1' then realbaud <= realbaud + '1'; --========================================================== -- Taktvorteiler, der im Automatenzustand 0 bei einer -- fallenden Flanke auf RxD rückgesetzt wird und beim Rücksetzen -- den Empfangsautomaten startet ------------------------------------------------------------- RxD_del<=RxD_del(0) & sio_RxD; if RxD_del="10" and busy='0' then ClkDiv:=x"0"; busy<='1'; elsif busy='1' then ClkDiv:=ClkDiv+'1'; end if; --========================================================== -- Der Empfangsautomat schaltet nach der fallenden Flanke auf RxD -- beim 1. mal nach 8 und danach 10 mal nach 16 Takten einen -- Zustand weiter. In jedem Zustand wird ein Bit von der Datenleitung -- übernommen/getestet ------------------------------------------------------------- if ClkDiv=x"8" and busy='1' then State<=State+1; case State is when 0=> -- Startbit in led(13) testen led(13)<=sio_RxD; when 1 to 8 => -- Datenbit übernehmen Q<= sio_RxD & Q(7 downto 1); when 9 => -- Paritätsbit in led(14) übernehmen led(14)<='0'; when others => -- Zustand 100: Stopbit in led(15) übernehmen -- und Übergang in den Anfangszustand led(15) <= sio_RxD; State<=0; busy<='0'; end case; end if; end if; end process; --========================================================== -- kombinatorische Ausgabe ------------------------------------------------------------- -- Ausgabe des Schieberegisterzustandes led(7 downto 0)<=Q; Tout <= realbaud(3); -- Echofunktion: Zurücksenden der empfangenen Daten zum PC -- Die Echofunktion muss beim Start von Hyperterm eingeschalten -- sein. Hyperterm führt beim Start irgendwelche Autodetect- -- aus und kommt nicht damit klar, wenn überhaupt keine Daten -- zurückkommen. -- ACHTUNG! die Funktion sendet 1 zu 1 zurück, was empfangen wurde!! -- Unabhängig vom Emfangsautomaten erkennt HyperTerm seine eigene Sendung -- natürlich richtig, deswegen kann ein Unterschied zwischen der LED-Anzeige -- und der Hypertermanzeige bestehen....immer nachprüfen! sio_TxD<= sio_RxD when sw(1)='1' else '1'; -- E end Behavioral;