Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- -- This VHD-File contains the UART_RECEIVER architecutre.
- -- Basic UART-Protocol is needed to understand this file.
- -- This architecture's job is to detect communication and read in a byte coming from the serial-communication cable.
- -- The received byte is outputted to the BYTE_COLLECTOR_TIMEOUT_CONTROLLER ARCHITECTURE.
- library ieee;
- use ieee.std_logic_1164.ALL;
- use ieee.numeric_std.all;
- entity UART_RECEIVER is
- generic (
- g_CLKS_PER_BIT : integer -- fpga clock freq / baudrate = 12E6/115200 ~= 104
- );
- port (
- rst : in std_logic;
- clk : in std_logic; -- fpga clock
- rx_serial : in std_logic; -- RX signal coming from the serial-communication cable
- rx_dv : out std_logic; -- data valid signal
- rx_byte : out std_logic_vector(7 downto 0) -- 8 bit data
- );
- end UART_RECEIVER;
- architecture rtl of UART_RECEIVER is
- type t_SM_Main is (s_Idle, s_RX_Start_Bit, s_RX_Data_Bits,
- s_RX_Stop_Bit, s_Cleanup); -- different states of the state machine
- signal r_SM_Main : t_SM_Main := s_Idle; -- starting state of state machine = idle
- signal r_RX_Data_R : std_logic := '0'; -- flipflop used to stabilize incoming RX signal
- signal r_RX_Data : std_logic := '0'; -- stable RX signal
- signal r_Clk_Count : integer range 0 to g_CLKS_PER_BIT-1 := 0; -- clock counter to time valid pin read
- signal r_Bit_Index : integer range 0 to 7 := 0; -- bit index to keep track of current bit
- signal r_RX_Byte : std_logic_vector(7 downto 0) := (others => '0'); -- data register
- signal r_RX_DV : std_logic := '0'; -- data valid register
- begin
- -- sampling incoming RX signal(removes problems caused by metastabiliy)
- p_SAMPLE : process (rst, clk)
- begin
- if rst = '1' then
- r_RX_Data_R <= '1';
- r_RX_Data <= '1';
- elsif rising_edge(clk) then
- r_RX_Data_R <= rx_serial;
- r_RX_Data <= r_RX_Data_R;
- end if;
- end process p_SAMPLE;
- -- state machine to read in byte
- p_UART_RX : process (clk)
- begin
- if rising_edge(clk) then
- case r_SM_Main is
- when s_Idle => -- idle state aka waiting for start bit
- r_RX_DV <= '0'; -- data valid = 0
- r_Clk_Count <= 0; -- counter = 0
- r_Bit_Index <= 0; -- bit index = 0
- if r_RX_Data = '0' then -- Start bit detected
- r_SM_Main <= s_RX_Start_Bit; -- switch to next state
- else
- r_SM_Main <= s_Idle; -- if start bit not detected stay in idle state
- end if;
- 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
- if r_Clk_Count = (g_CLKS_PER_BIT-1)/2 then
- if r_RX_Data = '0' then
- r_Clk_Count <= 0; -- reset counter since we found the middle
- r_SM_Main <= s_RX_Data_Bits; -- go to next state
- else
- r_SM_Main <= s_Idle; -- go back to idle state
- end if;
- else
- r_Clk_Count <= r_Clk_Count + 1; -- increment clock count
- r_SM_Main <= s_RX_Start_Bit; -- stay in state
- end if;
- when s_RX_Data_Bits =>
- if r_Clk_Count < g_CLKS_PER_BIT-1 then -- wait for period of one bit, aka middle of data bit
- r_Clk_Count <= r_Clk_Count + 1; -- increment clock count
- r_SM_Main <= s_RX_Data_Bits; -- stay in state
- else --
- r_Clk_Count <= 0; -- reset counter for next bit
- r_RX_Byte(r_Bit_Index) <= r_RX_Data; -- read in data bit to current byte index
- if r_Bit_Index < 7 then -- Check if we have received all bits
- r_Bit_Index <= r_Bit_Index + 1; -- increment bit index
- r_SM_Main <= s_RX_Data_Bits; -- stay in state
- else -- if all 8 bits have been read in, go to the next state
- r_Bit_Index <= 0; -- reset for next byte to be read in
- r_SM_Main <= s_RX_Stop_Bit; -- go to next state
- end if;
- end if;
- when s_RX_Stop_Bit => -- wait for one more bit, aka wait for stop bit
- if r_Clk_Count < g_CLKS_PER_BIT-1 then
- r_Clk_Count <= r_Clk_Count + 1; --increment clock counter
- r_SM_Main <= s_RX_Stop_Bit; -- stay in state
- else
- r_RX_DV <= '1'; -- data valid high
- r_Clk_Count <= 0; --reset counter
- r_SM_Main <= s_Cleanup; -- go to clean up state
- end if;
- -- Stay here 1 clock
- when s_Cleanup =>
- r_SM_Main <= s_Idle;
- r_RX_DV <= '0'; -- set data valid low (its going to be high for one clock cycle)
- when others => -- necessary to make the software happy
- r_SM_Main <= s_Idle;
- end case;
- end if;
- end process p_UART_RX;
- rx_dv <= r_RX_DV; -- bind data valid register to output
- rx_byte <= r_RX_Byte; -- bind byte data register to output
- end rtl;
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement