Skip to content

Commit 98be276

Browse files
committed
Added universal clock divider.
1 parent c7cb0b9 commit 98be276

File tree

5 files changed

+155
-150
lines changed

5 files changed

+155
-150
lines changed

example/quartus/uart_loopback_cyc1000.qsf

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ set_global_assignment -name DEVICE 10CL025YU256C8G
1212
set_global_assignment -name TOP_LEVEL_ENTITY UART_LOOPBACK_CYC1000
1313

1414
# PROJECT VHDL FILES
15-
set_global_assignment -name VHDL_FILE ../../rtl/uart.vhd
16-
set_global_assignment -name VHDL_FILE ../../rtl/comp/uart_tx.vhd
17-
set_global_assignment -name VHDL_FILE ../../rtl/comp/uart_rx.vhd
15+
set_global_assignment -name VHDL_FILE ../../rtl/comp/uart_clk_div.vhd
1816
set_global_assignment -name VHDL_FILE ../../rtl/comp/uart_parity.vhd
1917
set_global_assignment -name VHDL_FILE ../../rtl/comp/uart_debouncer.vhd
18+
set_global_assignment -name VHDL_FILE ../../rtl/comp/uart_tx.vhd
19+
set_global_assignment -name VHDL_FILE ../../rtl/comp/uart_rx.vhd
20+
set_global_assignment -name VHDL_FILE ../../rtl/uart.vhd
2021
set_global_assignment -name VHDL_FILE ../rst_sync.vhd
2122
set_global_assignment -name VHDL_FILE ../uart_loopback_cyc1000.vhd
2223

rtl/comp/uart_clk_div.vhd

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
--------------------------------------------------------------------------------
2+
-- PROJECT: SIMPLE UART FOR FPGA
3+
--------------------------------------------------------------------------------
4+
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
5+
-- LICENSE: The MIT License (MIT), please read LICENSE file
6+
-- WEBSITE: https://github.com/jakubcabal/uart-for-fpga
7+
--------------------------------------------------------------------------------
8+
9+
library IEEE;
10+
use IEEE.STD_LOGIC_1164.ALL;
11+
use IEEE.NUMERIC_STD.ALL;
12+
use IEEE.MATH_REAL.ALL;
13+
14+
entity UART_CLK_DIV is
15+
Generic (
16+
DIV_MAX_VAL : integer := 16;
17+
DIV_MARK_POS : integer := 1
18+
);
19+
Port (
20+
CLK : in std_logic; -- system clock
21+
RST : in std_logic; -- high active synchronous reset
22+
-- USER INTERFACE
23+
CLEAR : in std_logic; -- clock divider counter clear
24+
ENABLE : in std_logic; -- clock divider counter enable
25+
DIV_MARK : out std_logic -- output divider mark (divided clock enable)
26+
);
27+
end entity;
28+
29+
architecture RTL of UART_CLK_DIV is
30+
31+
constant CLK_DIV_WIDTH : integer := integer(ceil(log2(real(DIV_MAX_VAL))));
32+
33+
signal clk_div_cnt : unsigned(CLK_DIV_WIDTH-1 downto 0);
34+
signal clk_div_cnt_mark : std_logic;
35+
36+
begin
37+
38+
clk_div_cnt_p : process (CLK)
39+
begin
40+
if (rising_edge(CLK)) then
41+
if (CLEAR = '1') then
42+
clk_div_cnt <= (others => '0');
43+
elsif (ENABLE = '1') then
44+
if (clk_div_cnt = DIV_MAX_VAL-1) then
45+
clk_div_cnt <= (others => '0');
46+
else
47+
clk_div_cnt <= clk_div_cnt + 1;
48+
end if;
49+
end if;
50+
end if;
51+
end process;
52+
53+
clk_div_cnt_mark <= '1' when (clk_div_cnt = DIV_MARK_POS) else '0';
54+
55+
div_mark_p : process (CLK)
56+
begin
57+
if (rising_edge(CLK)) then
58+
if (RST = '1') then
59+
DIV_MARK <= '0';
60+
else
61+
DIV_MARK <= ENABLE and clk_div_cnt_mark;
62+
end if;
63+
end if;
64+
end process;
65+
66+
end architecture;

rtl/comp/uart_rx.vhd

Lines changed: 34 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
--------------------------------------------------------------------------------
22
-- PROJECT: SIMPLE UART FOR FPGA
33
--------------------------------------------------------------------------------
4-
-- MODULE: UART RECEIVER
54
-- AUTHORS: Jakub Cabal <jakubcabal@gmail.com>
65
-- LICENSE: The MIT License (MIT), please read LICENSE file
76
-- WEBSITE: https://github.com/jakubcabal/uart-for-fpga
@@ -10,13 +9,11 @@
109
library IEEE;
1110
use IEEE.STD_LOGIC_1164.ALL;
1211
use IEEE.NUMERIC_STD.ALL;
13-
use IEEE.MATH_REAL.ALL;
1412

1513
entity UART_RX is
1614
Generic (
17-
CLK_FREQ : integer := 50e6; -- system clock frequency in Hz
18-
BAUD_RATE : integer := 115200; -- baud rate value
19-
PARITY_BIT : string := "none" -- type of parity: "none", "even", "odd", "mark", "space"
15+
CLK_DIV_VAL : integer := 16;
16+
PARITY_BIT : string := "none" -- type of parity: "none", "even", "odd", "mark", "space"
2017
);
2118
Port (
2219
CLK : in std_logic; -- system clock
@@ -34,19 +31,14 @@ end entity;
3431

3532
architecture RTL of UART_RX is
3633

37-
constant OS_CLK_DIV_VAL : integer := integer(real(CLK_FREQ)/real(16*BAUD_RATE));
38-
constant UART_CLK_DIV_VAL : integer := integer(real(CLK_FREQ)/real(OS_CLK_DIV_VAL*BAUD_RATE));
39-
constant UART_CLK_DIV_WIDTH : integer := integer(ceil(log2(real(UART_CLK_DIV_VAL))));
40-
4134
signal rx_clk_en : std_logic;
42-
signal rx_ticks : unsigned(UART_CLK_DIV_WIDTH-1 downto 0);
4335
signal rx_data : std_logic_vector(7 downto 0);
4436
signal rx_bit_count : unsigned(2 downto 0);
4537
signal rx_parity_bit : std_logic;
4638
signal rx_parity_error : std_logic;
4739
signal rx_parity_check_en : std_logic;
4840
signal rx_done : std_logic;
49-
signal fsm_receiving : std_logic;
41+
signal fsm_idle : std_logic;
5042
signal fsm_databits : std_logic;
5143
signal fsm_stopbit : std_logic;
5244

@@ -60,37 +52,18 @@ begin
6052
-- UART RECEIVER CLOCK DIVIDER AND CLOCK ENABLE FLAG
6153
-- -------------------------------------------------------------------------
6254

63-
uart_rx_clk_divider_p : process (CLK)
64-
begin
65-
if (rising_edge(CLK)) then
66-
if (fsm_receiving = '1') then
67-
if (UART_CLK_EN = '1') then
68-
if (rx_ticks = UART_CLK_DIV_VAL-1) then
69-
rx_ticks <= (others => '0');
70-
else
71-
rx_ticks <= rx_ticks + 1;
72-
end if;
73-
else
74-
rx_ticks <= rx_ticks;
75-
end if;
76-
else
77-
rx_ticks <= (others => '0');
78-
end if;
79-
end if;
80-
end process;
81-
82-
uart_rx_clk_en_p : process (CLK)
83-
begin
84-
if (rising_edge(CLK)) then
85-
if (RST = '1') then
86-
rx_clk_en <= '0';
87-
elsif (UART_CLK_EN = '1' AND rx_ticks = 3) then
88-
rx_clk_en <= '1';
89-
else
90-
rx_clk_en <= '0';
91-
end if;
92-
end if;
93-
end process;
55+
rx_clk_divider_i : entity work.UART_CLK_DIV
56+
generic map(
57+
DIV_MAX_VAL => CLK_DIV_VAL,
58+
DIV_MARK_POS => 3
59+
)
60+
port map (
61+
CLK => CLK,
62+
RST => RST,
63+
CLEAR => fsm_idle,
64+
ENABLE => UART_CLK_EN,
65+
DIV_MARK => rx_clk_en
66+
);
9467

9568
-- -------------------------------------------------------------------------
9669
-- UART RECEIVER BIT COUNTER
@@ -198,9 +171,9 @@ begin
198171
case fsm_pstate is
199172

200173
when idle =>
201-
fsm_stopbit <= '0';
202-
fsm_databits <= '0';
203-
fsm_receiving <= '0';
174+
fsm_stopbit <= '0';
175+
fsm_databits <= '0';
176+
fsm_idle <= '1';
204177

205178
if (UART_RXD = '0') then
206179
fsm_nstate <= startbit;
@@ -209,9 +182,9 @@ begin
209182
end if;
210183

211184
when startbit =>
212-
fsm_stopbit <= '0';
213-
fsm_databits <= '0';
214-
fsm_receiving <= '1';
185+
fsm_stopbit <= '0';
186+
fsm_databits <= '0';
187+
fsm_idle <= '0';
215188

216189
if (rx_clk_en = '1') then
217190
fsm_nstate <= databits;
@@ -220,9 +193,9 @@ begin
220193
end if;
221194

222195
when databits =>
223-
fsm_stopbit <= '0';
224-
fsm_databits <= '1';
225-
fsm_receiving <= '1';
196+
fsm_stopbit <= '0';
197+
fsm_databits <= '1';
198+
fsm_idle <= '0';
226199

227200
if ((rx_clk_en = '1') AND (rx_bit_count = "111")) then
228201
if (PARITY_BIT = "none") then
@@ -235,9 +208,9 @@ begin
235208
end if;
236209

237210
when paritybit =>
238-
fsm_stopbit <= '0';
239-
fsm_databits <= '0';
240-
fsm_receiving <= '1';
211+
fsm_stopbit <= '0';
212+
fsm_databits <= '0';
213+
fsm_idle <= '0';
241214

242215
if (rx_clk_en = '1') then
243216
fsm_nstate <= stopbit;
@@ -246,9 +219,9 @@ begin
246219
end if;
247220

248221
when stopbit =>
249-
fsm_stopbit <= '1';
250-
fsm_databits <= '0';
251-
fsm_receiving <= '1';
222+
fsm_stopbit <= '1';
223+
fsm_databits <= '0';
224+
fsm_idle <= '0';
252225

253226
if (rx_clk_en = '1') then
254227
fsm_nstate <= idle;
@@ -257,10 +230,10 @@ begin
257230
end if;
258231

259232
when others =>
260-
fsm_stopbit <= '0';
261-
fsm_databits <= '0';
262-
fsm_receiving <= '0';
263-
fsm_nstate <= idle;
233+
fsm_stopbit <= '0';
234+
fsm_databits <= '0';
235+
fsm_idle <= '0';
236+
fsm_nstate <= idle;
264237

265238
end case;
266239
end process;

0 commit comments

Comments
 (0)