library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity ff_d is port ( d : in std_logic; q : out std_logic; clk : in std_logic; res : in std_logic; en : in std_logic ); end ff_d; architecture C of ff_d is begin -- behavior process(clk) begin if clk'event and clk = '1' then if res = '1' then q <= '0'; elsif en = '1' then q <= d; end if; end if; end process; end C; ------------------------------------------------------------------------------- library IEEE; use IEEE.std_logic_1164.all; use IEEE.std_logic_arith.all; use IEEE.std_logic_unsigned.all; entity serialport is port ( cs : in std_logic; datain : in std_logic_vector(7 downto 0); set_bps : in std_logic; clk : in std_logic; reset : in std_logic; TXD : out std_logic ); end serialport; architecture A of serialport is component ff_d port ( d : in std_logic; q : out std_logic; clk : in std_logic; res : in std_logic; en : in std_logic ); end component; signal internal_data : std_logic_vector(7 downto 0); signal ff_output : std_logic_vector(7 downto 0); signal write_character : std_logic; signal enable_transmission : std_logic; signal shift_register : std_logic; signal load_register : std_logic; signal reset_counter : std_logic; signal last_bit : std_logic; signal bit_time : std_logic; signal do_not_count : std_logic; signal parity_bit : std_logic; signal parity_bit_temp : std_logic; signal select_bps : std_logic_vector(1 downto 0); signal bps_end_count : unsigned(15 downto 0); signal count, new_count : unsigned(15 downto 0); signal bitcount, new_bitcount : unsigned(2 downto 0); type serialport_state is (mark, space, transmit, parity,stop); signal present_state, next_state : serialport_state; begin -- A ----------------------------------------------------------------------------- -- logica di selezione della velocitą di trasmissione process(clk) begin if clk'event and clk = '1' then if reset = '1' then select_bps <= "00"; elsif set_bps = '1' then select_bps(0) <= datain(0); select_bps(1) <= datain(1); end if; end if; end process; process(select_bps) begin case select_bps is when "00" => bps_end_count <= conv_unsigned(8333,16); when "01" => bps_end_count <= conv_unsigned(4166,16); when "10" => bps_end_count <= conv_unsigned(2083,16); when others => bps_end_count <= conv_unsigned(4,16); -- "11",1041 end case; end process; ----------------------------------------------------------------------------- -- divisore di frequenza programmabile process(count) begin new_count <= count + conv_unsigned(1,14); end process; process(clk) begin if clk'event and clk = '1' then if reset_counter = '1' then count <= conv_unsigned(0,16); else count <= new_count; end if; end if; end process; bit_time <= '1' when (count = bps_end_count) else '0'; -- finche resto nello stato mark non devo dividere il clock, -- non mi serve un segnale che commuta alla frequenza di -- trasmissione reset_counter <= reset or do_not_count or bit_time; do_not_count <= '1' when present_state = mark else '0'; ----------------------------------------------------------------------------- -- la trasmissione avviene quando la periferica viene selezionata write_character <= cs; ------------------------------------------------------------------------------ -- bit di parita ff_parity : ff_d port map ( d => parity_bit_temp, q => parity_bit, clk => clk, res => reset, en => cs); process(datain) variable t : std_logic; begin t := '0'; for H in 0 to 7 loop t := t xor datain(H); end loop; parity_bit_temp <= t; end process; ----------------------------------------------------------------------------- -- implementiamo uno shift register con load. -- Lo shift reg verrą caricato col valore del bus dati quando comincia -- un'operazione di scrittura mux: for I in 0 to 6 generate internal_data(I) <= datain(I) when write_character = '1' else ff_output(I+1); end generate mux; internal_data(7) <= datain(7); ff: for J in 0 to 7 generate ff_J : ff_d port map ( d => internal_data(J), q => ff_output(J), clk => clk, res => reset, en => load_register); end generate ff; shift_register <= enable_transmission and bit_time; load_register <= shift_register or write_character; -- conto il numero di shift process(bitcount) begin new_bitcount <= bitcount + conv_unsigned(1,3); end process; process(clk) begin if clk'event and clk = '1' then if enable_transmission = '0' then bitcount <= conv_unsigned(0,3); elsif enable_transmission = '1' and bit_time = '1' then bitcount <= new_bitcount; end if; end if; end process; last_bit <= '1' when bitcount = 7 else '0'; -- ----------------------------------------------------------------------------- ----------------------------------------------------------------------------- -- macchina a stati che gestisce la trasmissione -- parte sequenziale della macchina a stati, commutazione -- dallo stato presente al nuovo stato process(clk) begin if clk'event and clk='1' then if reset = '1' then present_state <= mark; else present_state <= next_state; end if; end if; end process; -- parte sequenziale della macchina a stati, -- calcolo delle uscite e dello stato futuro process(present_state) begin case present_state is when mark => TXD <= '1'; enable_transmission <= '0'; if write_character = '1' then next_state <= space; else next_state <= mark; end if; when space => TXD <= '0'; enable_transmission <= '0'; if bit_time = '1' then next_state <= transmit; else next_state <= space; end if; when transmit => TXD <= ff_output(0); enable_transmission <= '1'; if last_bit = '1' and bit_time = '1' then next_state <= parity; else next_state <= transmit; end if; when parity => TXD <= parity_bit; enable_transmission <= '0'; if bit_time = '1' then next_state <= stop; else next_state <= parity; end if; when stop => TXD <= '1'; enable_transmission <= '0'; if bit_time = '1' then next_state <= mark; else next_state <= stop; end if; when others => TXD <= '1'; next_state <= mark; end case; end process; end A;