⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 rx_async.vhd

📁 Usart model in vhdl code
💻 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 + -