1 |
2 |
martin.xrm |
-------------------------------------------------------------------------------
|
2 |
|
|
-- Use of this source code through a simulator and/or a compiler tool
|
3 |
|
|
-- is illegal if not authorised through Author License agreement.
|
4 |
|
|
-------------------------------------------------------------------------------
|
5 |
|
|
-- top level : uart_serial.vhd
|
6 |
|
|
-- File : uart_serial.vhd
|
7 |
|
|
-- Author : Xavier Martin
|
8 |
|
|
-- Email :
|
9 |
|
|
-- Organization:
|
10 |
|
|
-- Created : 2008, june 30th
|
11 |
|
|
-- Last update :
|
12 |
|
|
-- Simulators : ModelSim Altera 6.0c
|
13 |
|
|
-- Synthesizers: Quartus II 5.0
|
14 |
|
|
-- Targets :
|
15 |
|
|
-- Dependency :
|
16 |
|
|
-------------------------------------------------------------------------------
|
17 |
|
|
-- Description : This entity is a generic UART block
|
18 |
|
|
-- UART allows to work with one or two bits stop
|
19 |
|
|
-- baud : 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200
|
20 |
|
|
-- 230400, 460800, 921600
|
21 |
|
|
-- Note:
|
22 |
|
|
-- Br*br_divisor=921.600
|
23 |
|
|
-- Fclk/921.600=clk_divisor
|
24 |
|
|
-- => Br=Fclk/(clk_divisor*br_divisor)=1/((clk_divisor*Tclk)*br_divisor)
|
25 |
|
|
-------------------------------------------------------------------------------
|
26 |
|
|
-- Version : 1.0
|
27 |
|
|
-- Date :
|
28 |
|
|
-- Modifier :
|
29 |
|
|
-- Modif. :
|
30 |
|
|
-------------------------------------------------------------------------------
|
31 |
|
|
|
32 |
|
|
library ieee;
|
33 |
|
|
use ieee.std_logic_1164.all;
|
34 |
|
|
use ieee.std_logic_unsigned.all;
|
35 |
|
|
use ieee.numeric_std.all;
|
36 |
|
|
|
37 |
|
|
entity uart_serial is
|
38 |
|
|
port(
|
39 |
|
|
-- Global signal
|
40 |
|
|
reset : in std_logic; -- reset control signal
|
41 |
|
|
clk : in std_logic; -- 14.7456 Mhz Clock frequency
|
42 |
|
|
-- Reception channel
|
43 |
|
|
rx_data_serial : in std_logic; -- Received Serial data from RS232
|
44 |
|
|
rx_data_out : out std_logic_vector(7 downto 0); -- Received Data
|
45 |
|
|
rx_data_en : out std_logic; -- Received data enable control signal
|
46 |
|
|
rx_ovf_err : out std_logic; -- Received data over frame error detected
|
47 |
|
|
rx_parity_err : out std_logic; -- Received data parity error
|
48 |
|
|
-- Transmition channel
|
49 |
|
|
tx_data_serial : out std_logic; -- Transmited Serial data to RS232
|
50 |
|
|
tx_data_in : in std_logic_vector(7 downto 0); -- Transmited data
|
51 |
|
|
tx_data_en : in std_logic; -- Transmited data latch enable
|
52 |
|
|
tx_ch_rdy : out std_logic; -- Transmition channel ready status signal
|
53 |
|
|
-- Control command
|
54 |
|
|
baud_sel : in std_logic_vector(3 downto 0); -- Baud value see Note
|
55 |
|
|
parity_en : in std_logic; -- Enable parity control signal active HIGH
|
56 |
|
|
parity_type : in std_logic); -- 1:ODD parity / 0:EVEN parity
|
57 |
|
|
end entity;
|
58 |
|
|
|
59 |
|
|
|
60 |
|
|
architecture rtl of uart_serial is
|
61 |
|
|
|
62 |
|
|
-------------------------------------------------------------------------------
|
63 |
|
|
-- CONSTANT DECLARATION
|
64 |
|
|
-------------------------------------------------------------------------------
|
65 |
|
|
constant ODD_PARITY : std_logic := '1';
|
66 |
|
|
constant EVEN_PARITY : std_logic := '0';
|
67 |
|
|
constant CLK_DIVISOR : integer := 16; -- clock divisor to obtain 921600 bauds - CLK_DIVISOR = Fclk/921600
|
68 |
|
|
constant BR_DIVISOR_300 : integer := 3072; -- 300 bauds bit rate divisor value
|
69 |
|
|
constant BR_DIVISOR_1200 : integer := 768; -- 1200 bauds bit rate divisor value
|
70 |
|
|
constant BR_DIVISOR_2400 : integer := 384; -- 2400 bauds bit rate divisor value
|
71 |
|
|
constant BR_DIVISOR_4800 : integer := 192; -- 4800 bauds bit rate divisor value
|
72 |
|
|
constant BR_DIVISOR_9600 : integer := 96; -- 9600 bauds bit rate divisor value
|
73 |
|
|
constant BR_DIVISOR_19200 : integer := 48; -- 19200 bauds bit rate divisor value
|
74 |
|
|
constant BR_DIVISOR_38400 : integer := 24; -- 38400 bauds bit rate divisor value
|
75 |
|
|
constant BR_DIVISOR_57600 : integer := 16; -- 57600 bauds bit rate divisor value
|
76 |
|
|
constant BR_DIVISOR_115200 : integer := 8; -- 115200 bauds bit rate divisor value
|
77 |
|
|
constant BR_DIVISOR_230400 : integer := 4; -- 230400 bauds bit rate divisor value
|
78 |
|
|
constant BR_DIVISOR_460800 : integer := 2; -- 460800 bauds bit rate divisor value
|
79 |
|
|
constant BR_DIVISOR_921600 : integer := 1; -- 921600 bauds bit rate divisor value
|
80 |
|
|
|
81 |
|
|
|
82 |
|
|
-------------------------------------------------------------------------------
|
83 |
|
|
-- SIGNAL DECLARATION
|
84 |
|
|
-------------------------------------------------------------------------------
|
85 |
|
|
type tx_state_m is (IDLE,LOAD_TX_DATA,TX_DATA,TX_STOP);
|
86 |
|
|
type rx_state_m is (IDLE,START_RX,EDGE_RX,SHIFT_RX,STOP_RX,RX_OVF);
|
87 |
|
|
signal tx_state : tx_state_m;
|
88 |
|
|
signal rx_state : rx_state_m;
|
89 |
|
|
signal br_divisor : std_logic_vector(9 downto 0); -- Bit rate divisor
|
90 |
|
|
signal top_ref_baud : std_logic; -- Top reference baud 921600
|
91 |
|
|
signal tx_top_baud : std_logic; -- Transmit Top selected baud
|
92 |
|
|
signal rx_top_baud : std_logic; -- Transmit Top selected baud
|
93 |
|
|
signal tx_data_s : std_logic_vector(7 downto 0); -- Sample Transmited data input
|
94 |
|
|
signal tx_data_reg : std_logic_vector(10 downto 0); -- Transmited data register
|
95 |
|
|
signal rx_data_i : std_logic_vector(7 downto 0); -- Intermediary Received data
|
96 |
|
|
signal rx_parity_err_i : std_logic; -- Intermediary parity error status signal
|
97 |
|
|
signal clr_rx_baud : std_logic; -- clear Receive baud counter divisor counter
|
98 |
|
|
|
99 |
|
|
-------------------------------------------------------------------------------
|
100 |
|
|
-- FUNCTION DECLARATION
|
101 |
|
|
------------------------------------------------------------------------------
|
102 |
|
|
function parity (data: std_logic_vector; parity_type : std_logic) return std_logic is
|
103 |
|
|
variable tmp : std_logic;
|
104 |
|
|
begin
|
105 |
|
|
if parity_type = EVEN_PARITY then -- making the number of data even
|
106 |
|
|
tmp := '0';
|
107 |
|
|
for i in data'range loop
|
108 |
|
|
tmp := tmp xor data(i);
|
109 |
|
|
end loop;
|
110 |
|
|
elsif parity_type = ODD_PARITY then -- making the number of data odd
|
111 |
|
|
tmp := '1';
|
112 |
|
|
for i in data'range loop
|
113 |
|
|
tmp := tmp xnor data(i);
|
114 |
|
|
end loop;
|
115 |
|
|
end if;
|
116 |
|
|
|
117 |
|
|
return tmp;
|
118 |
|
|
end function;
|
119 |
|
|
|
120 |
|
|
|
121 |
|
|
begin
|
122 |
|
|
|
123 |
|
|
|
124 |
|
|
-------------------------------------------------------------------------------
|
125 |
|
|
-- This process is used to select bit rate divisor associated to baud_sel
|
126 |
|
|
-- vector value. The bit rate divisor is necessary to obtain the correct baud
|
127 |
|
|
-- once the 921600 baud is obtain by clock division
|
128 |
|
|
-------------------------------------------------------------------------------
|
129 |
|
|
baud_sel_proc:
|
130 |
|
|
process(reset, clk)
|
131 |
|
|
begin
|
132 |
|
|
if reset = '1' then
|
133 |
|
|
br_divisor <= (others => '0');
|
134 |
|
|
elsif rising_edge(clk) then
|
135 |
|
|
case baud_sel is
|
136 |
|
|
when x"0" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_300,br_divisor'length)); -- 300 bauds
|
137 |
|
|
when x"1" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_1200,br_divisor'length)); -- 1200 bauds
|
138 |
|
|
when x"2" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_2400,br_divisor'length)); -- 2400 bauds
|
139 |
|
|
when x"3" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_4800,br_divisor'length)); -- 4800 bauds
|
140 |
|
|
when x"4" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_9600,br_divisor'length)); -- 9600 bauds
|
141 |
|
|
when x"5" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_19200,br_divisor'length)); -- 19200 bauds
|
142 |
|
|
when x"6" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_38400,br_divisor'length)); -- 38400 bauds
|
143 |
|
|
when x"7" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_57600,br_divisor'length)); -- 57600 bauds
|
144 |
|
|
when x"8" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_115200,br_divisor'length)); -- 115200 bauds
|
145 |
|
|
when x"9" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_230400,br_divisor'length)); -- 230400 bauds
|
146 |
|
|
when x"A" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_460800,br_divisor'length)); -- 460800 bauds
|
147 |
|
|
when x"B" => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_921600,br_divisor'length)); -- 921600 bauds
|
148 |
|
|
when others => br_divisor <= std_logic_vector(to_unsigned(BR_DIVISOR_115200,br_divisor'length));
|
149 |
|
|
end case;
|
150 |
|
|
end if;
|
151 |
|
|
end process;
|
152 |
|
|
|
153 |
|
|
|
154 |
|
|
-------------------------------------------------------------------------------
|
155 |
|
|
-- This process is neccessary to obtain the 921600 baud. This baud is obtained by
|
156 |
|
|
-- dividing clock frequency with the followed equation CLK_DIVISOR = Fclk/921600
|
157 |
|
|
-- This baud will be the reference one to obtain others ones.
|
158 |
|
|
-------------------------------------------------------------------------------
|
159 |
|
|
baud_ref_proc:
|
160 |
|
|
process(reset, clk)
|
161 |
|
|
variable clk_divisor_cnt : integer range 0 to CLK_DIVISOR; -- Clock divisier counter
|
162 |
|
|
begin
|
163 |
|
|
if reset = '1' then
|
164 |
|
|
top_ref_baud <= '0';
|
165 |
|
|
clk_divisor_cnt := 0;
|
166 |
|
|
elsif rising_edge(clk) then
|
167 |
|
|
top_ref_baud <= '0';
|
168 |
|
|
clk_divisor_cnt := clk_divisor_cnt + 1;
|
169 |
|
|
|
170 |
|
|
if clk_divisor_cnt = CLK_DIVISOR then
|
171 |
|
|
top_ref_baud <= '1';
|
172 |
|
|
clk_divisor_cnt := 0;
|
173 |
|
|
end if;
|
174 |
|
|
|
175 |
|
|
end if;
|
176 |
|
|
end process;
|
177 |
|
|
|
178 |
|
|
|
179 |
|
|
-------------------------------------------------------------------------------
|
180 |
|
|
-- This process is necessary to obtain the selected bit rate by divising the
|
181 |
|
|
-- 921600 reference baud with baud selected value.
|
182 |
|
|
-------------------------------------------------------------------------------
|
183 |
|
|
tx_baud_proc:
|
184 |
|
|
process(reset, clk)
|
185 |
|
|
variable tx_br_divisor_cnt : integer range 0 to BR_DIVISOR_300;
|
186 |
|
|
begin
|
187 |
|
|
if reset = '1' then
|
188 |
|
|
tx_top_baud <= '0';
|
189 |
|
|
tx_br_divisor_cnt := 0;
|
190 |
|
|
elsif rising_edge(clk) then
|
191 |
|
|
tx_top_baud <= '0';
|
192 |
|
|
if top_ref_baud = '1' then
|
193 |
|
|
tx_br_divisor_cnt := tx_br_divisor_cnt + 1;
|
194 |
|
|
|
195 |
|
|
if tx_br_divisor_cnt = br_divisor then
|
196 |
|
|
tx_top_baud <= '1';
|
197 |
|
|
tx_br_divisor_cnt := 0;
|
198 |
|
|
end if;
|
199 |
|
|
|
200 |
|
|
end if;
|
201 |
|
|
end if;
|
202 |
|
|
end process;
|
203 |
|
|
|
204 |
|
|
rx_baud_proc:
|
205 |
|
|
process(reset, clk)
|
206 |
|
|
variable rx_br_divisor_cnt : std_logic_vector(9 downto 0);
|
207 |
|
|
begin
|
208 |
|
|
if reset = '1' then
|
209 |
|
|
rx_top_baud <= '0';
|
210 |
|
|
rx_br_divisor_cnt := (others => '0');
|
211 |
|
|
elsif rising_edge(clk) then
|
212 |
|
|
rx_top_baud <= '0';
|
213 |
|
|
if clr_rx_baud = '1' then
|
214 |
|
|
rx_br_divisor_cnt := (others => '0');
|
215 |
|
|
elsif top_ref_baud = '1' and rx_state /= IDLE then
|
216 |
|
|
rx_br_divisor_cnt := rx_br_divisor_cnt + 1;
|
217 |
|
|
|
218 |
|
|
if rx_br_divisor_cnt(8 downto 0) = br_divisor(9 downto 1) then
|
219 |
|
|
rx_top_baud <= '1';
|
220 |
|
|
rx_br_divisor_cnt := (others => '0');
|
221 |
|
|
end if;
|
222 |
|
|
|
223 |
|
|
end if;
|
224 |
|
|
end if;
|
225 |
|
|
end process;
|
226 |
|
|
|
227 |
|
|
|
228 |
|
|
-------------------------------------------------------------------------------
|
229 |
|
|
-- Transmition process
|
230 |
|
|
-------------------------------------------------------------------------------
|
231 |
|
|
tx_proc:
|
232 |
|
|
process(reset, clk)
|
233 |
|
|
variable tx_bit_cnt : integer;
|
234 |
|
|
begin
|
235 |
|
|
if reset = '1' then
|
236 |
|
|
tx_data_s <= (others => '0');
|
237 |
|
|
tx_data_reg <= (others => '1');
|
238 |
|
|
tx_ch_rdy <= '0';
|
239 |
|
|
elsif rising_edge(clk) then
|
240 |
|
|
case tx_state is
|
241 |
|
|
when IDLE =>
|
242 |
|
|
if tx_data_en = '1' then
|
243 |
|
|
tx_data_s <= tx_data_in;
|
244 |
|
|
tx_ch_rdy <= '0';
|
245 |
|
|
tx_state <= LOAD_TX_DATA;
|
246 |
|
|
else
|
247 |
|
|
tx_ch_rdy <= '1';
|
248 |
|
|
end if;
|
249 |
|
|
|
250 |
|
|
when LOAD_TX_DATA =>
|
251 |
|
|
if tx_top_baud = '1' then
|
252 |
|
|
if parity_en = '1' then
|
253 |
|
|
-- start + data + parity + stop
|
254 |
|
|
tx_bit_cnt := 8 + 3;
|
255 |
|
|
tx_data_reg(10 downto 0) <= '1' & parity(tx_data_s,parity_type) & tx_data_s(7 downto 0) & '0';
|
256 |
|
|
else
|
257 |
|
|
-- start + data + stop
|
258 |
|
|
tx_bit_cnt := 8 + 2;
|
259 |
|
|
tx_data_reg(10 downto 0) <= "11" & tx_data_s(7 downto 0) & '0';
|
260 |
|
|
end if;
|
261 |
|
|
tx_state <= TX_DATA;
|
262 |
|
|
end if;
|
263 |
|
|
|
264 |
|
|
when TX_DATA =>
|
265 |
|
|
if tx_top_baud = '1' then
|
266 |
|
|
tx_data_reg(10 downto 0) <= '1' & tx_data_reg(10 downto 1);
|
267 |
|
|
tx_bit_cnt := tx_bit_cnt-1;
|
268 |
|
|
if tx_bit_cnt = 1 then
|
269 |
|
|
tx_state <= TX_STOP;
|
270 |
|
|
end if;
|
271 |
|
|
end if;
|
272 |
|
|
|
273 |
|
|
when TX_STOP => -- stop bit
|
274 |
|
|
if tx_top_baud = '1' then
|
275 |
|
|
tx_state <= IDLE;
|
276 |
|
|
end if;
|
277 |
|
|
|
278 |
|
|
when others =>
|
279 |
|
|
null;
|
280 |
|
|
end case;
|
281 |
|
|
end if;
|
282 |
|
|
end process;
|
283 |
|
|
|
284 |
|
|
tx_data_serial <= tx_data_reg(0);
|
285 |
|
|
|
286 |
|
|
|
287 |
|
|
-------------------------------------------------------------------------------
|
288 |
|
|
-- Reception process
|
289 |
|
|
-------------------------------------------------------------------------------
|
290 |
|
|
process(reset, clk)
|
291 |
|
|
variable rx_bit_cnt : integer;
|
292 |
|
|
begin
|
293 |
|
|
if reset = '1' then
|
294 |
|
|
rx_data_out <= (others => '0');
|
295 |
|
|
rx_data_en <= '0';
|
296 |
|
|
rx_ovf_err <= '0';
|
297 |
|
|
rx_data_i <= (others => '0');
|
298 |
|
|
rx_parity_err <= '0';
|
299 |
|
|
rx_parity_err_i<= '0';
|
300 |
|
|
|
301 |
|
|
elsif rising_edge(clk) then
|
302 |
|
|
|
303 |
|
|
clr_rx_baud <= '0';
|
304 |
|
|
rx_ovf_err <= '0';
|
305 |
|
|
rx_parity_err <= '0';
|
306 |
|
|
rx_parity_err_i<= '0';
|
307 |
|
|
rx_data_en <= '0';
|
308 |
|
|
|
309 |
|
|
case rx_state is
|
310 |
|
|
when IDLE => -- Wait start bit
|
311 |
|
|
if top_ref_baud = '1' then
|
312 |
|
|
if rx_data_serial = '0' then
|
313 |
|
|
clr_rx_baud <= '1';
|
314 |
|
|
rx_state <= START_RX;
|
315 |
|
|
rx_bit_cnt := 1;
|
316 |
|
|
end if;
|
317 |
|
|
end if;
|
318 |
|
|
|
319 |
|
|
|
320 |
|
|
when START_RX =>
|
321 |
|
|
if rx_top_baud = '1' then
|
322 |
|
|
if rx_data_serial = '1' then
|
323 |
|
|
rx_state <= RX_OVF;
|
324 |
|
|
else
|
325 |
|
|
rx_state <= EDGE_RX;
|
326 |
|
|
end if;
|
327 |
|
|
end if;
|
328 |
|
|
|
329 |
|
|
|
330 |
|
|
when EDGE_RX =>
|
331 |
|
|
if rx_top_baud = '1' then
|
332 |
|
|
if (parity_en = '1' and rx_bit_cnt = 10) or -- start + data + parity + stop
|
333 |
|
|
(parity_en = '0' and rx_bit_cnt = 9) then -- start + data + stop
|
334 |
|
|
rx_state <= STOP_RX;
|
335 |
|
|
else -- data
|
336 |
|
|
rx_state <= SHIFT_RX;
|
337 |
|
|
end if;
|
338 |
|
|
end if;
|
339 |
|
|
|
340 |
|
|
when SHIFT_RX =>
|
341 |
|
|
if rx_top_baud = '1' then
|
342 |
|
|
rx_bit_cnt := rx_bit_cnt + 1;
|
343 |
|
|
if not((parity_en = '1' and rx_bit_cnt = 10)) then -- start + data + parity + stop
|
344 |
|
|
rx_data_i(7 downto 0) <= rx_data_serial & rx_data_i(7 downto 1);
|
345 |
|
|
else
|
346 |
|
|
if parity(rx_data_i,parity_type) /= rx_data_serial then
|
347 |
|
|
rx_parity_err_i <= '1';
|
348 |
|
|
end if;
|
349 |
|
|
end if;
|
350 |
|
|
rx_state <= EDGE_RX;
|
351 |
|
|
end if;
|
352 |
|
|
|
353 |
|
|
|
354 |
|
|
when STOP_RX =>
|
355 |
|
|
-- if rx_top_baud = '1' then
|
356 |
|
|
rx_data_out <= rx_data_i;
|
357 |
|
|
rx_parity_err <= rx_parity_err_i;
|
358 |
|
|
rx_ovf_err <= '0';
|
359 |
|
|
rx_data_en <= '1';
|
360 |
|
|
rx_state <= IDLE;
|
361 |
|
|
-- end if;
|
362 |
|
|
|
363 |
|
|
when RX_OVF => -- Overframe error
|
364 |
|
|
rx_ovf_err <= '1';
|
365 |
|
|
if rx_data_serial = '1' then
|
366 |
|
|
rx_state <= IDLE;
|
367 |
|
|
end if;
|
368 |
|
|
|
369 |
|
|
when others => null;
|
370 |
|
|
end case;
|
371 |
|
|
end if;
|
372 |
|
|
end process;
|
373 |
|
|
|
374 |
|
|
end rtl;
|