1+ -- The MIT License (MIT)
2+ --
3+ -- Copyright (c) 2015 Jakub Cabal
4+ --
5+ -- Permission is hereby granted, free of charge, to any person obtaining a copy
6+ -- of this software and associated documentation files (the "Software"), to deal
7+ -- in the Software without restriction, including without limitation the rights
8+ -- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+ -- copies of the Software, and to permit persons to whom the Software is
10+ -- furnished to do so, subject to the following conditions:
11+ --
12+ -- The above copyright notice and this permission notice shall be included in
13+ -- all copies or substantial portions of the Software.
14+ --
15+ -- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+ -- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+ -- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+ -- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+ -- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+ -- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+ -- SOFTWARE.
22+ --------------------------------------------------------------------------------
23+
24+ library IEEE;
25+ use IEEE.STD_LOGIC_1164.ALL ;
26+ use IEEE.STD_LOGIC_UNSIGNED.ALL ;
27+
28+ entity UART is
29+ Generic (
30+ BAUD_RATE : integer := 9600 ; -- baud rate value, default is 9600
31+ DATA_BITS : integer := 8 ; -- legal values: 5,6,7,8
32+ --STOP_BITS : integer; -- TODO, now is default 1 stop bit
33+ --PARITY_BIT : integer; -- TODO, now is default none parity bit
34+ CLK_FREQ : integer := 50e6 -- set system clock frequency in Hz, default is 50 MHz
35+ );
36+ Port (
37+ CLK : in std_logic ; -- system clock
38+ RST : in std_logic ; -- high active synchronous reset
39+ -- UART INTERFACE
40+ TX_UART : out std_logic ;
41+ RX_UART : in std_logic ;
42+ -- USER TX INTERFACE
43+ TX_DATA : out std_logic_vector (DATA_BITS- 1 downto 0 );
44+ TX_VALID : out std_logic ; -- when TX_VALID = 1, data on TX_DATA are valid
45+ -- USER RX INTERFACE
46+ RX_DATA : in std_logic_vector (DATA_BITS- 1 downto 0 );
47+ RX_VALID : in std_logic -- when RX_VALID = 1, data on RX_DATA are valid
48+ );
49+ end UART;
50+
51+ architecture FULL of UART is
52+
53+ -- constants
54+ constant divider_value : integer := CLK_FREQ / BAUD_RATE;
55+ -- signals
56+ signal rx_data_reg : std_logic_vector (DATA_BITS- 1 downto 0 );
57+ signal rx_data_reg_next : std_logic_vector (DATA_BITS- 1 downto 0 );
58+ signal rx_data_vld : std_logic ;
59+ signal rx_data_vld_next : std_logic ;
60+ signal uart_clk_en : std_logic ;
61+
62+ signal ticks : integer range 0 to divider_value;
63+ signal rx_data_bit_count : integer range 0 to DATA_BITS- 1 ;
64+ signal rx_data_bit_count_next : integer range 0 to DATA_BITS- 1 ;
65+
66+ type state is (idle, receive_data, receive_stop_bit);
67+ signal rx_present_st : state;
68+ signal rx_next_st : state;
69+
70+ begin
71+
72+ -- -------------------------------------------------------------------------
73+ -- UART CLOCK DIVIDER
74+ -- -------------------------------------------------------------------------
75+
76+ process (CLK)
77+ begin
78+ if (rising_edge (CLK)) then
79+ if (RST = '1' ) then
80+ uart_clk_en <= '0' ;
81+ elsif (ticks = divider_value) then
82+ ticks <= 0 ;
83+ uart_clk_en <= '1' ;
84+ else
85+ ticks <= ticks + 1 ;
86+ uart_clk_en <= '0' ;
87+ end if ;
88+ end if ;
89+ end process ;
90+
91+ -- -------------------------------------------------------------------------
92+ -- INPUT REGISTER
93+ -- -------------------------------------------------------------------------
94+
95+ -- TODO
96+
97+ -- -------------------------------------------------------------------------
98+ -- OUTPUT REGISTER
99+ -- -------------------------------------------------------------------------
100+
101+ TX_VALID <= rx_data_vld;
102+
103+ process (CLK)
104+ begin
105+ if (rising_edge (CLK)) then
106+ if (RST = '1' ) then
107+ TX_DATA <= (others => '0' );
108+ elsif (rx_data_vld = '1' ) then
109+ TX_DATA <= rx_data_reg;
110+ end if ;
111+ end if ;
112+ end process ;
113+
114+ -- -------------------------------------------------------------------------
115+ -- TX UART FSM
116+ -- -------------------------------------------------------------------------
117+
118+ -- TODO
119+
120+ -- -------------------------------------------------------------------------
121+ -- RX UART FSM
122+ -- -------------------------------------------------------------------------
123+
124+ process (CLK)
125+ begin
126+ if (rising_edge (CLK)) then
127+ if (RST = '1' ) then
128+ rx_present_st <= idle;
129+ rx_data_bit_count <= 0 ;
130+ rx_data_reg <= (others => '0' );
131+ rx_data_vld <= '0' ;
132+ else
133+ rx_present_st <= rx_next_st;
134+ rx_data_bit_count <= rx_data_bit_count_next;
135+ rx_data_reg <= rx_data_reg_next;
136+ rx_data_vld <= rx_data_vld_next;
137+ end if ;
138+ end if ;
139+ end process ;
140+
141+ process (rx_present_st, uart_clk_en, RX_UART, rx_data_bit_count, rx_data_reg, rx_data_vld)
142+ begin
143+
144+ rx_data_bit_count_next <= rx_data_bit_count;
145+ rx_data_reg_next <= rx_data_reg;
146+ rx_data_vld_next <= rx_data_vld;
147+ rx_next_st <= rx_present_st;
148+
149+ case rx_present_st is
150+
151+ when idle =>
152+ if (uart_clk_en = '1' AND RX_UART = '0' ) then
153+ rx_next_st <= receive_data;
154+ else
155+ rx_next_st <= idle;
156+ end if ;
157+
158+ when receive_data =>
159+ if (uart_clk_en = '1' ) then
160+ if (rx_data_bit_count = DATA_BITS- 1 ) then
161+ rx_data_bit_count_next <= 0 ;
162+ rx_data_reg_next(DATA_BITS- 1 ) <= RX_UART;
163+ rx_data_reg_next(DATA_BITS- 2 downto 0 ) <= rx_data_reg(DATA_BITS- 1 downto 1 );
164+ rx_next_st <= receive_stop_bit;
165+ else
166+ rx_data_bit_count_next <= rx_data_bit_count + 1 ;
167+ rx_data_reg_next(DATA_BITS- 1 ) <= RX_UART;
168+ rx_data_reg_next(DATA_BITS- 2 downto 0 ) <= rx_data_reg(DATA_BITS- 1 downto 1 );
169+ rx_next_st <= receive_data;
170+ end if ;
171+ end if ;
172+
173+ when receive_stop_bit =>
174+ if (uart_clk_en = '1' AND RX_UART = '1' ) then
175+ rx_data_vld_next <= '1' ;
176+ rx_next_st <= idle;
177+ else
178+ rx_data_vld_next <= '0' ;
179+ rx_next_st <= receive_stop_bit;
180+ end if ;
181+
182+ when others =>
183+ rx_data_bit_count_next <= 0 ;
184+ rx_data_reg_next <= (others => '0' );
185+ rx_data_vld_next <= '0' ;
186+ rx_next_st <= idle;
187+
188+ end case ;
189+ end process ;
190+
191+ end FULL;
0 commit comments