1 | library ieee;
|
2 | use ieee.std_logic_1164.all;
|
3 | use ieee.std_logic_unsigned.all;
|
4 |
|
5 | entity uart is
|
6 | port (
|
7 | reset :in std_logic;
|
8 | txclk :in std_logic;
|
9 | ld_tx_data :in std_logic;
|
10 | tx_data :in std_logic_vector (7 downto 0);
|
11 | tx_enable :in std_logic;
|
12 | tx_out :out std_logic;
|
13 | tx_empty :out std_logic;
|
14 | rxclk :in std_logic;
|
15 | uld_rx_data :in std_logic;
|
16 | rx_data :out std_logic_vector (7 downto 0);
|
17 | rx_enable :in std_logic;
|
18 | rx_in :in std_logic;
|
19 | rx_empty :out std_logic
|
20 | );
|
21 | end entity;
|
22 | architecture rtl of uart is
|
23 | -- Internal Variables
|
24 | signal tx_reg :std_logic_vector (7 downto 0);
|
25 | signal tx_over_run :std_logic; -- counter that check that we transmit all the data bits.
|
26 | signal tx_cnt :std_logic_vector (3 downto 0);--the counter that check that we transmit all the data bits.
|
27 | signal rx_reg :std_logic_vector (7 downto 0);
|
28 | signal rx_sample_cnt :std_logic_vector (3 downto 0);-- the counter that check that we run half of the bit transmit.
|
29 | signal rx_cnt :std_logic_vector (3 downto 0);-- the counter that check that we recive all the data bits.
|
30 | signal rx_frame_err :std_logic;
|
31 | signal rx_over_run :std_logic;--the flag that check that we recive all the data bits.
|
32 | signal rx_d1 :std_logic;
|
33 | signal rx_d2 :std_logic;
|
34 | signal rx_busy :std_logic;
|
35 | signal rx_is_empty :std_logic;
|
36 | signal tx_is_empty :std_logic;
|
37 | begin
|
38 | -- UART RX Logic
|
39 | process (rxclk, reset) begin
|
40 | if (reset = '1') then
|
41 | rx_reg <= (others=>'0');
|
42 | rx_data <= (others=>'0');
|
43 | rx_sample_cnt <= (others=>'0');
|
44 | rx_cnt <= (others=>'0');
|
45 | rx_frame_err <= '0';
|
46 | rx_over_run <= '0';
|
47 | rx_is_empty <= '1';
|
48 | rx_d1 <= '1';
|
49 | rx_d2 <= '1';
|
50 | rx_busy <= '0';
|
51 | elsif (rising_edge(rxclk)) then
|
52 | -- Synchronize the asynch signal
|
53 | rx_d1 <= rx_in;
|
54 | rx_d2 <= rx_d1;
|
55 | -- Uload the rx data
|
56 | if (uld_rx_data = '1') then
|
57 | rx_data <= rx_reg;
|
58 | rx_is_empty <= '1';
|
59 | end if;
|
60 | -- Receive data only when rx is enabled
|
61 | if (rx_enable = '1') then
|
62 | -- Check if just received start of frame
|
63 | if (rx_busy = '0' and rx_d2 = '0') then
|
64 | rx_busy <= '1';
|
65 | rx_sample_cnt <= X"1";
|
66 | rx_cnt <= X"0";
|
67 | end if;
|
68 | -- Start of frame detected, Proceed with rest of data
|
69 | if (rx_busy = '1') then
|
70 | rx_sample_cnt <= rx_sample_cnt + 1;
|
71 | -- Logic to sample at middle of data
|
72 | if (rx_sample_cnt = 7) then
|
73 | if ((rx_d2 = '1') and (rx_cnt = 0)) then
|
74 | rx_busy <= '0';
|
75 | else
|
76 | rx_cnt <= rx_cnt + 1;
|
77 | -- Start storing the rx data
|
78 | if (rx_cnt > 0 and rx_cnt < 9) then
|
79 | rx_reg(conv_integer(rx_cnt) - 1) <= rx_d2;
|
80 | end if;
|
81 | if (rx_cnt = 9) then
|
82 | rx_busy <= '0';
|
83 | -- Check if End of frame received correctly
|
84 | if (rx_d2 = '0') then
|
85 | rx_frame_err <= '1';
|
86 | else
|
87 | rx_is_empty <= '0';
|
88 | rx_frame_err <= '0';
|
89 | -- Check if last rx data was not unloaded,
|
90 | if (rx_is_empty = '1') then
|
91 | rx_over_run <= '0';
|
92 | else
|
93 | rx_over_run <= '1';
|
94 | end if;
|
95 | end if;
|
96 | end if;
|
97 | end if;
|
98 | end if;
|
99 | end if;
|
100 | end if;
|
101 | if (rx_enable = '0') then
|
102 | rx_busy <= '0';
|
103 | end if;
|
104 | end if;
|
105 | end process;
|
106 | rx_empty <= rx_is_empty;
|
107 |
|
108 | -- UART TX Logic
|
109 | process (txclk, reset) begin
|
110 | if (reset = '1') then
|
111 | tx_reg <= (others=>'0');
|
112 | tx_is_empty <= '1';
|
113 | tx_over_run <= '0';
|
114 | tx_out <= '1';
|
115 | tx_cnt <= (others=>'0');
|
116 | elsif (rising_edge(txclk)) then
|
117 |
|
118 | if (ld_tx_data = '1') then
|
119 | if (tx_is_empty = '0') then
|
120 | tx_over_run <= '0';
|
121 | else
|
122 | tx_reg <= tx_data;
|
123 | tx_is_empty <= '0';
|
124 | end if;
|
125 | end if;
|
126 | if (tx_enable = '1' and tx_is_empty = '0') then
|
127 | tx_cnt <= tx_cnt + 1;
|
128 | if (tx_cnt = 0) then
|
129 | tx_out <= '0';
|
130 | end if;
|
131 | if (tx_cnt > 0 and tx_cnt < 9) then
|
132 | tx_out <= tx_reg(conv_integer(tx_cnt) -1);
|
133 | end if;
|
134 | if (tx_cnt = 9) then
|
135 | tx_out <= '1';
|
136 | tx_cnt <= X"0";
|
137 | tx_is_empty <= '1';
|
138 | end if;
|
139 | end if;
|
140 | if (tx_enable = '0') then
|
141 | tx_cnt <= X"0";
|
142 | end if;
|
143 | end if;
|
144 | end process;
|
145 | tx_empty <= tx_is_empty;
|
146 |
|
147 | end architecture;
|