Skip to content

Commit a2843c2

Browse files
committed
Add file uart.vhd with complete RX UART side
1 parent c819e41 commit a2843c2

File tree

1 file changed

+191
-0
lines changed

1 file changed

+191
-0
lines changed

source/uart.vhd

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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

Comments
 (0)