-------------------------------------------------------------------------------- -- 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 -- internal signal for txd -- (for port txd is an output signal, its value can not be read) signal txd_out : std_logic := '0'; -- dividing factor to get a frequency that is 16 times of the baude rate -- Formular: 50 MHz / (baud_rate * 16) = 2 * cTeiler constant cTeiler : integer := 162; -- clock signal 16 x baude rate signal clk_16x_baud : std_logic := '0'; -- 2 bit shift register for received data signal rxd_del : std_logic_vector(1 downto 0) := (others => '0'); -- state vector for the receive automaton signal r_state : integer range 0 to 15 := 0; -- receive buffer signal Q : std_logic_vector(7 downto 0) := (others => '0'); begin -- still no transmitter => echo function -- comment out the following line when send automaton is added txd_out <= rxd; -- Instance of the send automaton -- sender_inst : entity work.a3_rs232_sender -- port map( -- clk_16x_baud => clk_16x_baud, -- txd => txd_out, -- data => sw, -- req => ..., -- grant => ... -- ); -- clock divider to produce the 16 times greater baud rate 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; -- receive automaton 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 -- fill a 2 bit shift register with received data -- to detect transitions from 1 to 0. rxd_del <= rxd_del(0) & rxd; -- detect falling edge if rxd_del = "10" and not busy then busy := true; sample_counter := 7; elsif busy then -- counter to find the best samling time -- (approx. mid bit time intervalls) 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; -- state transitions case r_state is -- start bit when 0 => -- start bit reveived -- 8 data bits when 1 to 8 => Q <= rxd & Q(7 downto 1); -- parity bit when 9 => -- calculate correct parity and display parity errors on a LED -- fehler <= .. -- stop bit when others => r_state <= 0; busy := false; end case; end if; end if; end process; -- output of the schift register data led(7 downto 0) <= Q; -- output of rxd and txd to a LA pin. la <= rxd & txd_out; -- internal txd signal bevor assigning to the ports txd <= txd_out; end architecture;