1+ -- ClariFi
2+ -- Part: XC7A35TICSG324-1L
3+ -- UART_RX_CTRL - Utilizes the Arty A7's USB-UART Bridge (Serial Port)
4+ -- Serialization information:
5+ -- TXD -> Pin A9
6+ -- RXD -> Pin D10
7+ -- 115200 Baud Rate
8+ -- 8 Data Bits, LSB First
9+ -- 1 Stop Bit
10+ -- No parity
11+ -- Data needs to be sampled at a rate of at least 115200*8 = 921.600 KHz
12+ -- A 100 MHz clock is expected. We sample in the middle of a bit data.
13+
14+ library ieee;
15+ use ieee.std_logic_1164.ALL ;
16+ use ieee.numeric_std.all ;
17+
18+ entity UART_RX_CTRL is
19+ generic (
20+ CLKS_PER_BIT : integer := 868 -- 868 = round(100MHz / 115200)
21+ );
22+ port (
23+ CLK : in std_logic ;
24+ RST : in std_logic ;
25+ UART_RX : in std_logic ;
26+ RX_DONE : out std_logic ;
27+ DATA : out std_logic_vector (7 downto 0 )
28+ );
29+ end UART_RX_CTRL;
30+
31+ architecture BHV of UART_RX_CTRL is
32+
33+ type state_type is (S_START, S_START_BIT, S_DATA_BITS, S_STOP_BIT, S_DONE);
34+ signal state : state_type := S_START;
35+
36+ signal r_UART_RX : std_logic := '0' ;
37+ signal r_r_UART_RX : std_logic := '0' ;
38+
39+ signal r_Bit_Counter : integer range 0 to CLKS_PER_BIT- 1 := 0 ;
40+ signal r_Bit_Index : integer range 0 to 7 := 0 ; -- 8 Bits Total
41+ signal r_RX_Byte : std_logic_vector (7 downto 0 ) := (others => '0' );
42+ signal r_RX_DONE : std_logic := '0' ;
43+
44+ begin
45+ process (CLK)
46+ begin
47+ if rising_edge (CLK) then
48+ -- Dual-flop synchronizer to stabilize incoming signal (data)
49+ r_UART_RX <= UART_RX;
50+ r_r_UART_RX <= r_UART_RX;
51+
52+ case state is
53+
54+ when S_START =>
55+ r_RX_DONE <= '0' ;
56+ r_Bit_Counter <= 0 ;
57+ r_Bit_Index <= 0 ;
58+
59+ if (r_r_UART_RX = '0' ) then -- falling_edge(r_r_UART_RX) then -- Start bit transitioned from '1' to '0'
60+ state <= S_START_BIT;
61+ end if ;
62+ state <= S_START;
63+
64+ -- Sample half bit later to make sure it's still low
65+ when S_START_BIT =>
66+ if r_Bit_Counter = (CLKS_PER_BIT- 1 )/ 2 then
67+ if r_r_UART_RX = '0' then
68+ r_Bit_Counter <= 0 ; -- Reset the counter
69+ state <= S_DATA_BITS; -- We are receiving data
70+ else
71+ state <= S_START; -- Start bit was not held low long enough
72+ end if ;
73+ else
74+ r_Bit_Counter <= r_Bit_Counter + 1 ;
75+ state <= S_START_BIT;
76+ end if ;
77+
78+
79+ -- Sample data after CLKS_PER_BIT-1 clock cycles
80+ when S_DATA_BITS =>
81+ if r_Bit_Counter < CLKS_PER_BIT- 1 then
82+ r_Bit_Counter <= r_Bit_Counter + 1 ;
83+ state <= S_DATA_BITS;
84+ else
85+ r_Bit_Counter <= 0 ;
86+ r_RX_Byte(r_Bit_Index) <= r_r_UART_RX;
87+
88+ -- Loop back until all 8 bits have been added to r_RX_Byte
89+ if r_Bit_Index < 7 then
90+ r_Bit_Index <= r_Bit_Index + 1 ;
91+ state <= S_DATA_BITS;
92+ else
93+ r_Bit_Index <= 0 ;
94+ state <= S_STOP_BIT;
95+ end if ;
96+ end if ;
97+
98+
99+ -- Receive last bit, 1 stop bit.
100+ when S_STOP_BIT =>
101+ -- Check stop bit after CLKS_PER_BIT-1 clock cycles
102+ if r_Bit_Counter < CLKS_PER_BIT- 1 then
103+ r_Bit_Counter <= r_Bit_Counter + 1 ;
104+ state <= S_STOP_BIT;
105+ else
106+ r_RX_DONE <= '1' ;
107+ r_Bit_Counter <= 0 ;
108+ state <= S_DONE;
109+ end if ;
110+
111+
112+ -- Wait 1 cycle before going back to S_START
113+ when S_DONE =>
114+ state <= S_START;
115+ r_RX_DONE <= '0' ;
116+
117+ -- Should never be reached
118+ when others =>
119+ state <= S_START;
120+
121+ end case ;
122+ end if ;
123+ end process ;
124+
125+ RX_DONE <= r_RX_DONE;
126+ DATA <= r_RX_Byte;
127+
128+ end BHV;
0 commit comments