| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118 |
- library ieee;
- use ieee.std_logic_1164.all;
- use ieee.numeric_std.all;
- entity async_8n1_rx is
- port
- (
- clk : in std_logic;
- rst : in std_logic;
- en : in std_logic;
- read : in std_logic;
- data_in : in std_logic;
- data_available : out std_logic;
- frame_error : out std_logic;
- overflow_error : out std_logic;
- data_out : out unsigned (7 downto 0)
- );
- end entity;
- architecture beh of async_8n1_rx is
- -- RX shift register related
- signal i_reg_rx_data : unsigned(8 downto 0) := (others => '1');
- signal i_sig_data : unsigned(7 downto 0);
- signal i_sig_finished : std_logic;
- signal i_sig_clear_rx_data : std_logic;
- signal i_sig_frame_error : std_logic;
- -- Received data related
- signal i_reg_stored_data : unsigned(7 downto 0) := (others => '0');
- signal i_reg_available : std_logic := '0';
- signal i_reg_overflow : std_logic := '0';
- signal i_reg_frame_error : std_logic := '0';
- signal i_sig_storage_full : std_logic;
- signal i_sig_load_data : std_logic;
- signal i_sig_overflow_next : std_logic;
- signal i_sig_available_next : std_logic;
- begin
- -- Outputs
- data_available <= i_reg_available;
- frame_error <= i_reg_frame_error;
- overflow_error <= i_reg_overflow;
- data_out <= i_reg_stored_data;
- -- Concurrent statements
- -- RX shift register concurrent statements
- -- This is the data when a complete frame is received
- i_sig_data <= i_reg_rx_data(8 downto 1);
- -- When the start bit has propagated to bit 0 in shift register, frame is finished
- i_sig_finished <= not i_reg_rx_data(0);
- -- When frame is finished, reset shift register to only '1's
- i_sig_clear_rx_data <= i_sig_finished;
- -- If incoming stop bit is '0', we have a framing error
- i_sig_frame_error <= i_sig_finished and not data_in;
- -- Storage register concurrent statements
- -- The storage is considered full (next cycle) when data is available and no read is performed
- i_sig_storage_full <= i_reg_available and not read;
- -- Only load received byte if storage is not full
- i_sig_load_data <= i_sig_finished and not i_sig_storage_full;
- -- If there is a received byte, and the storage is full, and no read is performed, next cycle will
- -- cause an overflow and the latest received byte is discarded
- i_sig_overflow_next <= not read and (i_reg_overflow or (i_reg_available and i_sig_finished));
- -- If a byte just has been received, or the storage is full, then there will be data available next cycle
- i_sig_available_next <= i_sig_finished or i_sig_storage_full;
- -- Register
- process(clk) is
- begin
- if rising_edge(clk) then
- if en = '1' then
- -- i_reg_rx_data
- if i_sig_clear_rx_data = '0' then
- -- Take a step
- i_reg_rx_data <= data_in & i_sig_data;
- else
- -- Synchronously set to '1'
- i_reg_rx_data <= (others => '1');
- end if;
- -- i_reg_stored_data and i_reg_frame_error
- -- Update data store with received byte and frame status
- if i_sig_load_data = '1' then
- i_reg_stored_data <= i_sig_data;
- i_reg_frame_error <= i_sig_frame_error;
- else
- i_reg_stored_data <= i_reg_stored_data;
- i_reg_frame_error <= i_reg_frame_error;
- end if;
- -- i_reg_available
- -- Assume next evaluated value
- i_reg_available <= i_sig_available_next;
- -- i_reg_overflow
- -- Assume next evaluated value
- i_reg_overflow <= i_sig_overflow_next;
- else
- -- don't load registers (explicitly)
- i_reg_rx_data <= i_reg_rx_data;
- i_reg_stored_data <= i_reg_stored_data;
- i_reg_frame_error <= i_reg_frame_error;
- i_reg_available <= i_reg_available;
- i_reg_overflow <= i_reg_overflow;
- end if;
- end if;
-
- if rst = '1' then
- -- Async reset
- -- Only registers whose initial value matters
- i_reg_rx_data <= (others => '1');
- i_reg_available <= '0';
- i_reg_overflow <= '0';
- end if;
- end process;
- end architecture;
|