Skip to content

Commit 3d8cca4

Browse files
committed
Added more precisely clock dividers, dividing with rounding.
1 parent 2e4d214 commit 3d8cca4

File tree

3 files changed

+42
-24
lines changed

3 files changed

+42
-24
lines changed

rtl/comp/uart_rx.vhd

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
library IEEE;
1111
use IEEE.STD_LOGIC_1164.ALL;
1212
use IEEE.NUMERIC_STD.ALL;
13+
use IEEE.MATH_REAL.ALL;
1314

1415
entity UART_RX is
1516
Generic (
16-
PARITY_BIT : string := "none" -- type of parity: "none", "even", "odd", "mark", "space"
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"
1720
);
1821
Port (
1922
CLK : in std_logic; -- system clock
@@ -31,8 +34,12 @@ end entity;
3134

3235
architecture RTL of UART_RX is
3336

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+
3441
signal rx_clk_en : std_logic;
35-
signal rx_ticks : unsigned(3 downto 0);
42+
signal rx_ticks : unsigned(UART_CLK_DIV_WIDTH-1 downto 0);
3643
signal rx_data : std_logic_vector(7 downto 0);
3744
signal rx_bit_count : unsigned(2 downto 0);
3845
signal rx_parity_bit : std_logic;
@@ -58,7 +65,7 @@ begin
5865
if (rising_edge(CLK)) then
5966
if (fsm_receiving = '1') then
6067
if (UART_CLK_EN = '1') then
61-
if (rx_ticks = "1111") then
68+
if (rx_ticks = UART_CLK_DIV_VAL-1) then
6269
rx_ticks <= (others => '0');
6370
else
6471
rx_ticks <= rx_ticks + 1;
@@ -77,7 +84,7 @@ begin
7784
if (rising_edge(CLK)) then
7885
if (RST = '1') then
7986
rx_clk_en <= '0';
80-
elsif (UART_CLK_EN = '1' AND rx_ticks = "0111") then
87+
elsif (UART_CLK_EN = '1' AND rx_ticks = 3) then
8188
rx_clk_en <= '1';
8289
else
8390
rx_clk_en <= '0';

rtl/comp/uart_tx.vhd

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@
1010
library IEEE;
1111
use IEEE.STD_LOGIC_1164.ALL;
1212
use IEEE.NUMERIC_STD.ALL;
13+
use IEEE.MATH_REAL.ALL;
1314

1415
entity UART_TX is
1516
Generic (
16-
PARITY_BIT : string := "none" -- type of parity: "none", "even", "odd", "mark", "space"
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"
1720
);
1821
Port (
1922
CLK : in std_logic; -- system clock
@@ -30,9 +33,13 @@ end UART_TX;
3033

3134
architecture FULL of UART_TX is
3235

36+
constant OS_CLK_DIV_VAL : integer := integer(real(CLK_FREQ)/real(16*BAUD_RATE));
37+
constant UART_CLK_DIV_VAL : integer := integer(real(CLK_FREQ)/real(OS_CLK_DIV_VAL*BAUD_RATE));
38+
constant UART_CLK_DIV_WIDTH : integer := integer(ceil(log2(real(UART_CLK_DIV_VAL))));
39+
3340
signal tx_clk_en : std_logic;
3441
signal tx_clk_divider_en : std_logic;
35-
signal tx_ticks : unsigned(3 downto 0);
42+
signal tx_ticks : unsigned(UART_CLK_DIV_WIDTH-1 downto 0);
3643
signal tx_data : std_logic_vector(7 downto 0);
3744
signal tx_bit_count : unsigned(2 downto 0);
3845
signal tx_bit_count_en : std_logic;
@@ -57,7 +64,7 @@ begin
5764
if (rising_edge(CLK)) then
5865
if (tx_clk_divider_en = '1') then
5966
if (uart_clk_en = '1') then
60-
if (tx_ticks = "1111") then
67+
if (tx_ticks = UART_CLK_DIV_VAL-1) then
6168
tx_ticks <= (others => '0');
6269
else
6370
tx_ticks <= tx_ticks + 1;
@@ -76,7 +83,7 @@ begin
7683
if (rising_edge(CLK)) then
7784
if (RST = '1') then
7885
tx_clk_en <= '0';
79-
elsif (uart_clk_en = '1' AND tx_ticks = "0001") then
86+
elsif (uart_clk_en = '1' AND tx_ticks = 1) then
8087
tx_clk_en <= '1';
8188
else
8289
tx_clk_en <= '0';

rtl/uart.vhd

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ use IEEE.MATH_REAL.ALL;
3030
-- Version 1.2 -
3131
-- Added double FF for safe CDC.
3232
-- Fixed fake received transaction after FPGA boot without reset.
33+
-- Added more precisely clock dividers, dividing with rounding.
3334

3435
entity UART is
3536
Generic (
@@ -58,12 +59,11 @@ end entity;
5859

5960
architecture RTL of UART is
6061

61-
constant DIVIDER_VALUE : integer := CLK_FREQ/(16*BAUD_RATE);
62-
constant CLK_CNT_WIDTH : integer := integer(ceil(log2(real(DIVIDER_VALUE))));
63-
constant CLK_CNT_MAX : unsigned := to_unsigned(DIVIDER_VALUE-1, CLK_CNT_WIDTH);
62+
constant OS_CLK_DIV_VAL : integer := integer(real(CLK_FREQ)/real(16*BAUD_RATE));
63+
constant OS_CLK_DIV_WIDTH : integer := integer(ceil(log2(real(OS_CLK_DIV_VAL))));
6464

65-
signal oversampling_clk_cnt : unsigned(CLK_CNT_WIDTH-1 downto 0);
66-
signal oversampling_clk_en : std_logic;
65+
signal os_clk_div_cnt : unsigned(OS_CLK_DIV_WIDTH-1 downto 0);
66+
signal os_clk_div_cnt_max : std_logic;
6767
signal uart_rxd_meta_n : std_logic;
6868
signal uart_rxd_synced_n : std_logic;
6969
signal uart_rxd_debounced_n : std_logic;
@@ -72,25 +72,25 @@ architecture RTL of UART is
7272
begin
7373

7474
-- -------------------------------------------------------------------------
75-
-- UART OVERSAMPLING (16X) CLOCK COUNTER AND CLOCK ENABLE FLAG
75+
-- UART OVERSAMPLING (16X) CLOCK DIVIDER AND CLOCK ENABLE FLAG
7676
-- -------------------------------------------------------------------------
7777

78-
oversampling_clk_cnt_p : process (CLK)
78+
os_clk_div_cnt_p : process (CLK)
7979
begin
8080
if (rising_edge(CLK)) then
8181
if (RST = '1') then
82-
oversampling_clk_cnt <= (others => '0');
82+
os_clk_div_cnt <= (others => '0');
8383
else
84-
if (oversampling_clk_en = '1') then
85-
oversampling_clk_cnt <= (others => '0');
84+
if (os_clk_div_cnt_max = '1') then
85+
os_clk_div_cnt <= (others => '0');
8686
else
87-
oversampling_clk_cnt <= oversampling_clk_cnt + 1;
87+
os_clk_div_cnt <= os_clk_div_cnt + 1;
8888
end if;
8989
end if;
9090
end if;
9191
end process;
9292

93-
oversampling_clk_en <= '1' when (oversampling_clk_cnt = CLK_CNT_MAX) else '0';
93+
os_clk_div_cnt_max <= '1' when (os_clk_div_cnt = OS_CLK_DIV_VAL-1) else '0';
9494

9595
-- -------------------------------------------------------------------------
9696
-- UART RXD CROSS DOMAIN CROSSING
@@ -132,13 +132,15 @@ begin
132132

133133
uart_rx_i: entity work.UART_RX
134134
generic map (
135-
PARITY_BIT => PARITY_BIT
135+
CLK_FREQ => CLK_FREQ,
136+
BAUD_RATE => BAUD_RATE,
137+
PARITY_BIT => PARITY_BIT
136138
)
137139
port map (
138140
CLK => CLK,
139141
RST => RST,
140142
-- UART INTERFACE
141-
UART_CLK_EN => oversampling_clk_en,
143+
UART_CLK_EN => os_clk_div_cnt_max,
142144
UART_RXD => uart_rxd_debounced,
143145
-- USER DATA OUTPUT INTERFACE
144146
DOUT => DOUT,
@@ -153,13 +155,15 @@ begin
153155

154156
uart_tx_i: entity work.UART_TX
155157
generic map (
156-
PARITY_BIT => PARITY_BIT
158+
CLK_FREQ => CLK_FREQ,
159+
BAUD_RATE => BAUD_RATE,
160+
PARITY_BIT => PARITY_BIT
157161
)
158162
port map (
159163
CLK => CLK,
160164
RST => RST,
161165
-- UART INTERFACE
162-
UART_CLK_EN => oversampling_clk_en,
166+
UART_CLK_EN => os_clk_div_cnt_max,
163167
UART_TXD => UART_TXD,
164168
-- USER DATA INPUT INTERFACE
165169
DIN => DIN,

0 commit comments

Comments
 (0)