📄 rx_async.vhd
字号:
-- File................: RX_ASYNC.VHD
-- Function............: Perform the asynchronous receive function for the SCC
-- Component of........: SCC.VHD
-- Components Required.: NONE
-- Compilation Notes...:
--
-- Functional Description:
--
LIBRARY IEEE;
USE IEEE.std_logic_1164.all;
USE IEEE.std_logic_arith.all;
USE IEEE.std_logic_unsigned.all;
entity Rx_async is port (
clk : in std_logic; -- system clock
baud_clock : in std_logic; -- 8x baud clock pulse
reset_n : in std_logic; -- active low async reset
bit8 : in std_logic; -- if set to one 8 data bits otherwise 7 data bits
parity_en : in std_logic; -- if set to one parity is enabled otherwise disabled
odd_n_even : in std_logic; -- if set to one odd parity otherwise even parity
read_rx_byte : in std_logic; -- read rx byte register
SCCrx : in std_logic;
overflow : out std_logic; -- receiver overflow
parity_err : out std_logic; -- parity error indicator on recieved data
receive_full : out std_logic; -- receiver has a byte ready
rx_byte : out std_logic_vector(7 downto 0) -- receive byte register
);
end Rx_async;
architecture rtl of Rx_async is
type receive_states is (rx_idle, rx_data_bits, rx_stop_bit);
signal rx_state : receive_states; -- receive state machine
signal receive_count : std_logic_vector(3 downto 0); -- counts bits received
signal rx_filtered : std_logic; -- filtered rx data
signal rx_shift : std_logic_vector(8 downto 0); -- receive shift register
signal rx_parity_calc,clearParity : std_logic; -- received parity, calculated
signal rx_bit_cnt : std_logic_vector(3 downto 0); -- count of received bits
signal receive_full_int : std_logic; -- receiver has a byte ready
signal samples : std_logic_vector(2 downto 0);
signal overflow_int : std_logic;
signal shift_choice : std_logic_vector(1 downto 0);
signal parity_choice : std_logic_vector(1 downto 0);
signal last_bit : std_logic_vector(3 downto 0);
begin
------------------------------------------------------------------------------
majority : -- filter the receive data
------------------------------------------------------------------------------
-- The receive data filter is a simple majority voter that accepts three
-- samples of the "raw" data and reports the most populus result. This
-- provides a simple single-cycle glitch filter.
-- This input needs to go to both the state machine start bit detector as
-- well as the data shift register as this filter introduces a three-clock
-- delay and we need to keep the phases lined up.
--
process(clk,reset_n)
begin
if (reset_n = '0') then
samples <= "000";
elsif (clk'event and clk = '1') then
if(baud_clock = '1') then
samples(1 downto 0) <= samples(2 downto 1);
samples(2) <= SCCrx;
end if;
end if;
end process;
process(samples)
begin
-- our voter
case samples is
when "000" => rx_filtered <= '0';
when "001" => rx_filtered <= '0';
when "010" => rx_filtered <= '0';
when "011" => rx_filtered <= '1';
when "100" => rx_filtered <= '0';
when "101" => rx_filtered <= '1';
when "110" => rx_filtered <= '1';
when others => rx_filtered <= '1';
end case;
end process;
------------------------------------------------------------------------------
rcv_cnt : -- receive bit counter
------------------------------------------------------------------------------
process (clk, reset_n)
begin
if (reset_n = '0') then
receive_count <= "0000";
elsif (clk'event and clk = '1') then
if(baud_clock = '1') then
-- no start bit yet or begin sample period for data
if (rx_state = rx_idle) and (rx_filtered = '1' or receive_count = "1000") then
receive_count <= "0000";
else
receive_count <= receive_count + '1';
end if;
end if;
end if;
end process;
------------------------------------------------------------------------------
make_overflow : -- registering of the overflow signal
------------------------------------------------------------------------------
process(clk, reset_n)
begin
if(reset_n = '0') then
overflow <= '0';
elsif(clk'event and clk='1') then
if(baud_clock = '1') then
if(overflow_int = '1') then
overflow <= '1';
end if;
end if;
if(read_rx_byte = '1') then
overflow <= '0';
end if;
end if;
end process;
last_bit <= "0111" when BIT8='0' and PARITY_EN='0' else
"1000" when BIT8='0' and PARITY_EN='1' else
"1000" when BIT8='1' and PARITY_EN='0' else
"1001";
------------------------------------------------------------------------------
rcv_sm : -- receive state machine & byte register
------------------------------------------------------------------------------
process (clk, reset_n)
begin
if (reset_n = '0') then
rx_state <= rx_idle;
rx_byte <= "00000000";
overflow_int <= '0';
elsif (clk'event and clk = '1') then
if(baud_clock = '1') then
overflow_int <= '0';
case rx_state is
when rx_idle =>
if (receive_count = "1000") then
rx_state <= rx_data_bits;
else
rx_state <= rx_idle;
end if;
when rx_data_bits =>
if (rx_bit_cnt = last_bit) then -- last bit has been received
rx_state <= rx_stop_bit;
-- if receive_full is still active at this point, then overflow
overflow_int <= receive_full_int;
if (receive_full_int = '0') then
rx_byte <= (BIT8 and rx_shift(7)) & rx_shift(6 downto 0);
end if;
else
rx_state <= rx_data_bits; -- still clocking in bits
end if;
when rx_stop_bit =>
if (receive_count = "1111") then
rx_state <= rx_idle;
else
rx_state <= rx_stop_bit;
end if;
when others => rx_state <= rx_idle;
end case;
end if;
end if;
end process;
shift_choice <= BIT8 & parity_en;
------------------------------------------------------------------------------
receive_shift : -- receive shift register and parity calculation
------------------------------------------------------------------------------
process (clk, reset_n)
begin
if (reset_n = '0') then
rx_shift(8 downto 0) <= "000000000";
rx_bit_cnt <= "0000";
elsif (clk'event and clk = '1') then
if(baud_clock = '1') then
if (rx_state = rx_idle) then
rx_shift(8 downto 0) <= "000000000";
rx_bit_cnt <= "0000";
elsif (receive_count = "1111") then
rx_bit_cnt <= rx_bit_cnt + '1';
-- sample new data bit
case shift_choice is
when "00" =>
rx_shift(5 downto 0) <= rx_shift(6 downto 1);
rx_shift(6) <= rx_filtered;
when "11" =>
rx_shift(7 downto 0) <= rx_shift(8 downto 1);
rx_shift(8) <= rx_filtered;
when others =>
rx_shift(6 downto 0) <= rx_shift(7 downto 1);
rx_shift(7) <= rx_filtered;
end case;
end if;
end if;
end if;
end process;
------------------------------------------------------------------------------
rx_par_calc : -- receiver parity calculation
------------------------------------------------------------------------------
process(clk, reset_n)
begin
if(reset_n = '0') then
rx_parity_calc <= '0';
elsif(clk'event and clk = '1') then
if(baud_clock = '1') then
if(receive_count = "1111" and PARITY_EN = '1') then
rx_parity_calc <= rx_parity_calc xor rx_filtered;
end if;
if(rx_state = rx_stop_bit) then
rx_parity_calc <= '0';
end if;
end if;
end if;
end process;
parity_choice <= BIT8 & ODD_N_EVEN;
------------------------------------------------------------------------------
make_parity_err : -- latch parity error for even or odd parity
------------------------------------------------------------------------------
process(clk, reset_n)
begin
if(reset_n = '0') then
parity_err <= '0';
clearParity<='0';
elsif(clk'event and clk = '1') then
if(baud_clock = '1' and PARITY_EN = '1' and receive_count = "1111") then
case parity_choice is
when "00" =>
if(rx_bit_cnt = "0111") then
parity_err <= rx_parity_calc xor rx_filtered;
end if;
when "01" =>
if(rx_bit_cnt = "0111") then
parity_err <= not (rx_parity_calc xor rx_filtered);
end if;
when "10" =>
if(rx_bit_cnt = "1000") then
parity_err <= rx_parity_calc xor rx_filtered;
end if;
when others =>
if(rx_bit_cnt = "1000") then
parity_err <= not (rx_parity_calc xor rx_filtered);
end if;
end case;
end if;
clearParity<= read_rx_byte;
if(clearParity = '1') then
parity_err <= '0';
end if;
end if;
end process;
------------------------------------------------------------------------------
receive_full_indicator : -- receive full indicator process
------------------------------------------------------------------------------
process (clk, reset_n)
begin
if (reset_n = '0') then
receive_full_int <= '0';
elsif (clk'event and clk = '1') then
if(baud_clock = '1') then
-- last bit has been received
if(BIT8='1') then
if(PARITY_EN = '1') then
if (rx_bit_cnt = "1001" and rx_state = rx_data_bits) then
receive_full_int <= '1';
end if;
else
if (rx_bit_cnt = "1000" and rx_state = rx_data_bits) then
receive_full_int <= '1';
end if;
end if;
else
if(PARITY_EN = '1') then
if (rx_bit_cnt = "1000" and rx_state = rx_data_bits) then
receive_full_int <= '1';
end if;
else
if (rx_bit_cnt = "0111" and rx_state = rx_data_bits) then
receive_full_int <= '1';
end if;
end if;
end if;
end if;
if(read_rx_byte = '1') then
receive_full_int <= '0';
end if;
end if;
end process;
receive_full <= receive_full_int;
end rtl;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -