Guest User

uart_receiver

a guest
Sep 4th, 2020
143
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1.  
  2. -- This VHD-File contains the UART_RECEIVER architecutre.
  3. -- Basic UART-Protocol is needed to understand this file.
  4. -- This architecture's job is to detect communication and read in a byte coming from the serial-communication cable.
  5. -- The received byte is outputted to the BYTE_COLLECTOR_TIMEOUT_CONTROLLER ARCHITECTURE.
  6.  
  7. library ieee;
  8. use ieee.std_logic_1164.ALL;
  9. use ieee.numeric_std.all;
  10.  
  11.  
  12. entity UART_RECEIVER is
  13.   generic (
  14.     g_CLKS_PER_BIT : integer     -- fpga clock freq / baudrate = 12E6/115200 ~= 104
  15.     );
  16.    
  17.   port (
  18.     rst     :   in  std_logic;
  19.     clk       : in  std_logic; -- fpga clock
  20.     rx_serial : in  std_logic; -- RX signal coming from the serial-communication cable
  21.    
  22.     rx_dv     : out std_logic; -- data valid signal
  23.     rx_byte   : out std_logic_vector(7 downto 0) -- 8 bit data
  24.     );
  25. end UART_RECEIVER;
  26.  
  27.  
  28. architecture rtl of UART_RECEIVER is
  29.  
  30.   type t_SM_Main is (s_Idle, s_RX_Start_Bit, s_RX_Data_Bits,
  31.                      s_RX_Stop_Bit, s_Cleanup); -- different states of the state machine
  32.   signal r_SM_Main : t_SM_Main := s_Idle; -- starting state of state machine = idle
  33.  
  34.   signal r_RX_Data_R : std_logic := '0'; -- flipflop used to stabilize incoming RX signal
  35.   signal r_RX_Data   : std_logic := '0'; -- stable RX signal
  36.    
  37.   signal r_Clk_Count : integer range 0 to g_CLKS_PER_BIT-1 := 0; -- clock counter to time valid pin read
  38.   signal r_Bit_Index : integer range 0 to 7 := 0;  -- bit index to keep track of current bit
  39.   signal r_RX_Byte   : std_logic_vector(7 downto 0) := (others => '0'); -- data register
  40.   signal r_RX_DV     : std_logic := '0'; -- data valid register
  41.    
  42. begin
  43.  
  44.   -- sampling incoming RX signal(removes problems caused by metastabiliy)
  45.   p_SAMPLE : process (rst, clk)
  46.   begin
  47.     if rst = '1' then
  48.         r_RX_Data_R <= '1';
  49.         r_RX_Data <= '1';
  50.     elsif rising_edge(clk) then
  51.       r_RX_Data_R <= rx_serial;
  52.       r_RX_Data   <= r_RX_Data_R;
  53.     end if;
  54.   end process p_SAMPLE;
  55.    
  56.  
  57.   -- state machine to read in byte
  58.   p_UART_RX : process (clk)
  59.   begin
  60.     if rising_edge(clk) then
  61.         case r_SM_Main is
  62.        
  63.             when s_Idle => -- idle state aka waiting for start bit
  64.                 r_RX_DV     <= '0'; -- data valid = 0
  65.                 r_Clk_Count <= 0; -- counter = 0
  66.                 r_Bit_Index <= 0; -- bit index = 0
  67.                
  68.                 if r_RX_Data = '0' then       -- Start bit detected
  69.                     r_SM_Main <= s_RX_Start_Bit; -- switch to next state
  70.                
  71.                 else
  72.                 r_SM_Main <= s_Idle; -- if start bit not detected stay in idle state
  73.                
  74.                 end if;
  75.  
  76.            
  77.        
  78.             when s_RX_Start_Bit =>  -- Check half period of a bit bit to make sure start bit is still low, aka find middle of start bit
  79.                 if r_Clk_Count = (g_CLKS_PER_BIT-1)/2 then
  80.                     if r_RX_Data = '0' then
  81.                         r_Clk_Count <= 0;  -- reset counter since we found the middle
  82.                         r_SM_Main   <= s_RX_Data_Bits; -- go to next state
  83.                
  84.                     else
  85.                         r_SM_Main   <= s_Idle; -- go back to idle state
  86.            
  87.                     end if;
  88.                 else
  89.                     r_Clk_Count <= r_Clk_Count + 1; -- increment clock count
  90.                     r_SM_Main   <= s_RX_Start_Bit; -- stay in state
  91.                    
  92.                 end if;
  93.  
  94.            
  95.             when s_RX_Data_Bits =>
  96.                 if r_Clk_Count < g_CLKS_PER_BIT-1 then -- wait for period of one bit, aka middle of data bit
  97.                     r_Clk_Count <= r_Clk_Count + 1; --  increment clock count
  98.                     r_SM_Main   <= s_RX_Data_Bits; -- stay in state
  99.                
  100.                 else --
  101.                     r_Clk_Count            <= 0; -- reset counter for next bit
  102.                     r_RX_Byte(r_Bit_Index) <= r_RX_Data; -- read in data bit to current byte index
  103.              
  104.                                            
  105.                     if r_Bit_Index < 7 then -- Check if we have received all bits
  106.                         r_Bit_Index <= r_Bit_Index + 1; -- increment bit index
  107.                         r_SM_Main   <= s_RX_Data_Bits; -- stay in state
  108.            
  109.                     else -- if all 8 bits have been read in, go to the next state
  110.                         r_Bit_Index <= 0; -- reset for next byte to be read in
  111.                         r_SM_Main   <= s_RX_Stop_Bit; -- go to next state
  112.                        
  113.                     end if;
  114.                 end if;
  115.  
  116.  
  117.             when s_RX_Stop_Bit => -- wait for one more bit, aka wait for stop bit
  118.                 if r_Clk_Count < g_CLKS_PER_BIT-1 then
  119.                     r_Clk_Count <= r_Clk_Count + 1; --increment clock counter
  120.                     r_SM_Main   <= s_RX_Stop_Bit; -- stay in state
  121.                 else
  122.                     r_RX_DV     <= '1'; -- data valid high
  123.                     r_Clk_Count <= 0; --reset counter
  124.                     r_SM_Main   <= s_Cleanup; -- go to clean up state
  125.                 end if;
  126.  
  127.                    
  128.         -- Stay here 1 clock
  129.         when s_Cleanup =>
  130.           r_SM_Main <= s_Idle;
  131.           r_RX_DV   <= '0'; -- set data valid low (its going to be high for one clock cycle)
  132.  
  133.              
  134.         when others => -- necessary to make the software happy
  135.           r_SM_Main <= s_Idle;
  136.  
  137.       end case;
  138.     end if;
  139.   end process p_UART_RX;
  140.  
  141.   rx_dv   <= r_RX_DV; -- bind data valid register to output
  142.   rx_byte <= r_RX_Byte; -- bind byte data register to output
  143.    
  144. end rtl;
RAW Paste Data