Skip to content

Commit a0473ef

Browse files
committed
UART: Added parity support
1 parent ccfc06f commit a0473ef

File tree

6 files changed

+223
-34
lines changed

6 files changed

+223
-34
lines changed

README.md

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,17 @@ Simple UART (Universal Asynchronous Receiver & Transmitter) module for serial co
44

55
**The default settings are 115200 baud rate, 8 data bits, 1 stop bit, no parity, disable input data FIFO, 50 MHz system clock.**
66

7-
The UART module was tested in hardware. In the near future it will be implemented generic support for parity bit and set the number of stop bits. Stay tuned!
7+
The UART module was tested in hardware. In the near future it will be implemented generic support settings of stop bits. Stay tuned!
88

99
**Synthesis resource usage summary:**
1010

11-
Input FIFO | LE (LUT) | FF | BRAM
12-
--- | --- | --- | ---
13-
disable | 72 | 46 | 0
14-
enable | 110 | 63 | 1
11+
Parity | Input FIFO | LE (LUT) | FF | BRAM
12+
--- | --- | --- | --- | ---
13+
none | disable | 72 | 46 | 0
14+
none | enable | 110 | 63 | 1
15+
even/odd | disable | 82 | 49 | 0
16+
even/odd | enable | 121 | 66 | 1
17+
mark/space | disable | 77 | 49 | 0
18+
mark/space | enable | 115 | 66 | 1
1519

1620
*Synthesis was performed using Quartus II 64-Bit Version 13.0.1 with default settings for FPGA Altera Cyclone II.*

example/uart_loopback.vhd

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,12 @@ use IEEE.NUMERIC_STD.ALL;
2929

3030
entity UART_LOOPBACK is
3131
Generic (
32-
BAUD_RATE : integer := 115200;
33-
DATA_BITS : integer := 8;
34-
CLK_FREQ : integer := 50e6;
35-
INPUT_FIFO : boolean := True;
36-
FIFO_DEPTH : integer := 256
32+
BAUD_RATE : integer := 115200; -- baud rate value
33+
DATA_BITS : integer := 8; -- legal values: 5,6,7,8
34+
PARITY_BIT : string := "none"; -- legal values: "none", "even", "odd", "mark", "space"
35+
CLK_FREQ : integer := 50e6; -- set system clock frequency in Hz
36+
INPUT_FIFO : boolean := True; -- enable input data FIFO
37+
FIFO_DEPTH : integer := 256 -- set depth of input data FIFO
3738
);
3839
Port (
3940
CLK : in std_logic; -- system clock
@@ -65,6 +66,7 @@ begin
6566
generic map (
6667
BAUD_RATE => BAUD_RATE,
6768
DATA_BITS => DATA_BITS,
69+
PARITY_BIT => PARITY_BIT,
6870
CLK_FREQ => CLK_FREQ,
6971
INPUT_FIFO => INPUT_FIFO,
7072
FIFO_DEPTH => FIFO_DEPTH

example/uart_loopback_tb.vhd

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,12 @@ begin
4949

5050
utt: entity work.UART_LOOPBACK
5151
generic map (
52-
BAUD_RATE => 115200, -- baud rate value
53-
DATA_BITS => 8, -- legal values: 5,6,7,8
54-
CLK_FREQ => 50e6, -- set system clock frequency in Hz
55-
INPUT_FIFO => True, -- enable input data FIFO
56-
FIFO_DEPTH => 256 -- set depth of input data FIFO
52+
BAUD_RATE => 115200,
53+
DATA_BITS => 8,
54+
PARITY_BIT => "none",
55+
CLK_FREQ => 50e6,
56+
INPUT_FIFO => True,
57+
FIFO_DEPTH => 256
5758
)
5859
port map (
5960
CLK => CLK,

source/comp/uart_parity.vhd

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
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+
-- Website: https://github.com/jakubcabal/uart_for_fpga
24+
--------------------------------------------------------------------------------
25+
26+
library IEEE;
27+
use IEEE.STD_LOGIC_1164.ALL;
28+
use IEEE.NUMERIC_STD.ALL;
29+
30+
entity UART_PARITY is
31+
Generic (
32+
DATA_WIDTH : integer := 8;
33+
PARITY_TYPE : string := "none" -- legal values: "none", "even", "odd", "mark", "space"
34+
);
35+
Port (
36+
DATA_IN : in std_logic_vector(DATA_WIDTH-1 downto 0);
37+
PARITY_OUT : out std_logic
38+
);
39+
end UART_PARITY;
40+
41+
architecture FULL of UART_PARITY is
42+
43+
begin
44+
45+
-- -------------------------------------------------------------------------
46+
-- PARITY BIT GENERATOR
47+
-- -------------------------------------------------------------------------
48+
49+
even_parity_g : if (PARITY_TYPE = "even") generate
50+
51+
process (DATA_IN)
52+
variable parity_temp : std_logic;
53+
begin
54+
parity_temp := '0';
55+
for i in DATA_IN'range loop
56+
parity_temp := parity_temp XOR DATA_IN(i);
57+
end loop;
58+
PARITY_OUT <= parity_temp;
59+
end process;
60+
61+
end generate;
62+
63+
odd_parity_g : if (PARITY_TYPE = "odd") generate
64+
65+
process (DATA_IN)
66+
variable parity_temp : std_logic;
67+
begin
68+
parity_temp := '1';
69+
for i in DATA_IN'range loop
70+
parity_temp := parity_temp XOR DATA_IN(i);
71+
end loop;
72+
PARITY_OUT <= parity_temp;
73+
end process;
74+
75+
end generate;
76+
77+
mark_parity_g : if (PARITY_TYPE = "mark") generate
78+
79+
PARITY_OUT <= '1';
80+
81+
end generate;
82+
83+
space_parity_g : if (PARITY_TYPE = "space") generate
84+
85+
PARITY_OUT <= '0';
86+
87+
end generate;
88+
89+
end FULL;

source/uart.vhd

Lines changed: 100 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ entity UART is
3131
Generic (
3232
BAUD_RATE : integer := 115200; -- baud rate value
3333
DATA_BITS : integer := 8; -- legal values: 5,6,7,8
34-
--PARITY_BIT : string := "none"; -- TODO, now must be none parity bit, legal values: "none", "odd", "even", "mark", "space"
35-
--STOP_BITS : integer; -- TODO, now must be 1 stop bit
34+
PARITY_BIT : string := "none"; -- legal values: "none", "even", "odd", "mark", "space"
35+
--STOP_BITS : integer; -- TODO, now must be 1 stop bit
3636
CLK_FREQ : integer := 50e6; -- set system clock frequency in Hz
3737
INPUT_FIFO : boolean := False; -- enable input data FIFO
3838
FIFO_DEPTH : integer := 256 -- set depth of input data FIFO
@@ -67,6 +67,7 @@ architecture FULL of UART is
6767
signal tx_busy : std_logic;
6868
signal tx_data_in : std_logic_vector(DATA_BITS-1 downto 0);
6969
signal tx_data_send : std_logic;
70+
signal tx_parity_bit : std_logic;
7071

7172
signal uart_ticks : integer range 0 to divider_value-1;
7273
signal uart_clk_en : std_logic;
@@ -82,8 +83,11 @@ architecture FULL of UART is
8283
signal rx_bit_count_en : std_logic;
8384
signal rx_bit_count_rst : std_logic;
8485
signal rx_data_shreg_en : std_logic;
86+
signal rx_parity_bit : std_logic;
87+
signal rx_parity_error : std_logic := '0';
88+
signal rx_parity_check_en : std_logic;
8589

86-
type state is (idle, txsync, startbit, databits, stopbit);
90+
type state is (idle, txsync, startbit, databits, paritybit, stopbit);
8791
signal tx_pstate : state;
8892
signal tx_nstate : state;
8993
signal rx_pstate : state;
@@ -207,6 +211,24 @@ begin
207211
end if;
208212
end process;
209213

214+
-- -------------------------------------------------------------------------
215+
-- UART TRANSMITTER PARITY GENERATOR
216+
-- -------------------------------------------------------------------------
217+
218+
tx_parity_g : if (PARITY_BIT /= "none") generate
219+
220+
tx_parity_gen_i: entity work.UART_PARITY
221+
generic map (
222+
DATA_WIDTH => DATA_BITS,
223+
PARITY_TYPE => PARITY_BIT
224+
)
225+
port map (
226+
DATA_IN => tx_data,
227+
PARITY_OUT => tx_parity_bit
228+
);
229+
230+
end generate;
231+
210232
-- -------------------------------------------------------------------------
211233
-- UART TRANSMITTER FSM
212234
-- -------------------------------------------------------------------------
@@ -224,7 +246,7 @@ begin
224246
end process;
225247

226248
-- NEXT STATE AND OUTPUTS LOGIC
227-
process (tx_pstate, tx_data_send, tx_clk_en, tx_data, tx_bit_count)
249+
process (tx_pstate, tx_data_send, tx_clk_en, tx_data, tx_bit_count, tx_parity_bit)
228250
begin
229251

230252
case tx_pstate is
@@ -272,11 +294,27 @@ begin
272294
tx_bit_count_en <= '1';
273295

274296
if ((tx_clk_en = '1') AND (tx_bit_count = DATA_BITS-1)) then
275-
tx_nstate <= idle;
297+
if (PARITY_BIT = "none") then
298+
tx_nstate <= idle;
299+
else
300+
tx_nstate <= paritybit;
301+
end if ;
276302
else
277303
tx_nstate <= databits;
278304
end if;
279305

306+
when paritybit =>
307+
tx_busy <= '1';
308+
TX_UART <= tx_parity_bit;
309+
tx_bit_count_rst <= '1';
310+
tx_bit_count_en <= '0';
311+
312+
if (tx_clk_en = '1') then
313+
tx_nstate <= idle;
314+
else
315+
tx_nstate <= paritybit;
316+
end if;
317+
280318
when others =>
281319
tx_busy <= '1';
282320
TX_UART <= '1';
@@ -353,6 +391,35 @@ begin
353391

354392
DATA_OUT <= rx_data;
355393

394+
-- -------------------------------------------------------------------------
395+
-- UART RECEIVER PARITY GENERATOR AND CHECK
396+
-- -------------------------------------------------------------------------
397+
398+
rx_parity_g : if (PARITY_BIT /= "none") generate
399+
400+
rx_parity_gen_i: entity work.UART_PARITY
401+
generic map (
402+
DATA_WIDTH => DATA_BITS,
403+
PARITY_TYPE => PARITY_BIT
404+
)
405+
port map (
406+
DATA_IN => rx_data,
407+
PARITY_OUT => rx_parity_bit
408+
);
409+
410+
rx_parity_check_reg : process (CLK)
411+
begin
412+
if (rising_edge(CLK)) then
413+
if (RST = '1') then
414+
rx_parity_error <= '0';
415+
elsif (rx_parity_check_en = '1') then
416+
rx_parity_error <= rx_parity_bit XOR RX_UART;
417+
end if;
418+
end if;
419+
end process;
420+
421+
end generate;
422+
356423
-- -------------------------------------------------------------------------
357424
-- UART RECEIVER FSM
358425
-- -------------------------------------------------------------------------
@@ -370,7 +437,7 @@ begin
370437
end process;
371438

372439
-- NEXT STATE AND OUTPUTS LOGIC
373-
process (rx_pstate, RX_UART, rx_clk_en, rx_bit_count)
440+
process (rx_pstate, RX_UART, rx_clk_en, rx_bit_count, rx_parity_error)
374441
begin
375442
case rx_pstate is
376443

@@ -381,6 +448,7 @@ begin
381448
rx_bit_count_en <= '0';
382449
rx_data_shreg_en <= '0';
383450
rx_clk_divider_en <= '0';
451+
rx_parity_check_en <= '0';
384452

385453
if (RX_UART = '0') then
386454
rx_nstate <= startbit;
@@ -395,6 +463,7 @@ begin
395463
rx_bit_count_en <= '0';
396464
rx_data_shreg_en <= '0';
397465
rx_clk_divider_en <= '1';
466+
rx_parity_check_en <= '0';
398467

399468
if (rx_clk_en = '1') then
400469
rx_nstate <= databits;
@@ -409,22 +478,44 @@ begin
409478
rx_bit_count_en <= '1';
410479
rx_data_shreg_en <= '1';
411480
rx_clk_divider_en <= '1';
481+
rx_parity_check_en <= '0';
412482

413483
if ((rx_clk_en = '1') AND (rx_bit_count = DATA_BITS-1)) then
414-
rx_nstate <= stopbit;
484+
if (PARITY_BIT = "none") then
485+
rx_nstate <= stopbit;
486+
else
487+
rx_nstate <= paritybit;
488+
end if ;
415489
else
416490
rx_nstate <= databits;
417491
end if;
418492

493+
when paritybit =>
494+
DATA_VLD <= '0';
495+
FRAME_ERROR <= '0';
496+
rx_bit_count_rst <= '1';
497+
rx_bit_count_en <= '0';
498+
rx_data_shreg_en <= '0';
499+
rx_clk_divider_en <= '1';
500+
501+
if (rx_clk_en = '1') then
502+
rx_nstate <= stopbit;
503+
rx_parity_check_en <= '1';
504+
else
505+
rx_nstate <= paritybit;
506+
rx_parity_check_en <= '0';
507+
end if;
508+
419509
when stopbit =>
420510
rx_bit_count_rst <= '1';
421511
rx_bit_count_en <= '0';
422512
rx_data_shreg_en <= '0';
423513
rx_clk_divider_en <= '1';
514+
rx_parity_check_en <= '0';
424515

425516
if (rx_clk_en = '1') then
426517
rx_nstate <= idle;
427-
DATA_VLD <= '1';
518+
DATA_VLD <= NOT rx_parity_error;
428519
FRAME_ERROR <= NOT RX_UART;
429520
else
430521
rx_nstate <= stopbit;
@@ -439,6 +530,7 @@ begin
439530
rx_bit_count_en <= '0';
440531
rx_data_shreg_en <= '0';
441532
rx_clk_divider_en <= '0';
533+
rx_parity_check_en <= '0';
442534
rx_nstate <= idle;
443535

444536
end case;

0 commit comments

Comments
 (0)