UART Receiver Parity Check

Guest
Hello,

I'm trying to learn VHDL and here I'm adding a parity bit to Ben
Cohen's UART Receiver. RxReg(9) is incoming parity bit from
transmitter side. A 0 output at Parity_err means no parity error
detected and otherwise. The receiver has to match the incoming parity
bit with its own parity bit which is calculated using XOR of its data
byte, RxReg(8 downto 0). My statement below is giving me a full byte
delay because my control statements for the parity check. I think it's
because of the process statement, but that's all I can think of now.

can someone let me know how to fix this?

Thanks,
AS
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-------------------------------------------------------------------------------
--
-- Project : ATEP
-- File name : uartrx.vhd
-- Title : UART Receiver
-- Description : UART receiver selection
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Author Revision
Comments
-- Sat Oct 30 10:05:49 1994 cohen Rev A Creation
-------------------------------------------------------------------------------
entity UartRx_Nty is
port (Clk16xT : in std_logic; -- 16 of these clocks per
bit
ResetF : in std_logic;
Serial_InT : in std_logic;
DataRdyT : out boolean;
DataOuT : out std_logic_Vector(7 downto 0);
Parity_err : out std_logic; -- Parity Error Output
BitClkT : out std_logic); -- same speed clock as Tx
end UartRx_Nty;


architecture UartRx_Beh of UartRx_Nty is
subtype Int0to15_Typ is integer range 0 to 15;
constant RxInit_c : std_logic_Vector(10 downto 0) := "11111111111";
signal RxReg_s : std_logic_Vector(10 downto 0); -- the receive
register
signal Count16_s : Int0to15_Typ; -- for divide by 16
signal RxMT_s : boolean; -- Receive register empty
signal RxIn_s : std_logic; -- registered
serial input
signal Parity_Reg : std_logic;

begin -- UartRx_Beh

-----------------------------------------------------------------------------
-- Process: Xmit_Lbl
-- Purpose: Models the receive portion of a UART.
-- Operation is as follows:
-- . All operations occur on rising edge of Clk16xT.
-- . Clk16xT runs 16x the bit clock rate
-- . If ResetF = '0' then
-- RxReg_s is reset to "11111111111".
-- Count_s is reset to 0.
-- . If (RxMT_s and RxIn_s = '0') then
-- Start of new byte
-- . If Count16_s = 7 and not RxMT_s then -- mid
clock
-- Sample here where bit most stable
-- RxReg_s <= RxIn_s & RxReg_s(9 downto 1);
-- . Entire byte received when
-- not RxMT_s and RxReg_s(9) = '1' and RxReg_s(0) =
'0'
--

-----------------------------------------------------------------------------
Rx_Lbl : process

begin -- process Rx_Lbl
wait until Clk16xT'event and Clk16xT = '1';
-- Clock serial input into RxIn_s
RxIn_s <= Serial_InT;

-- reset
if (ResetF = '0') then
Count16_s <= 0; -- reset divide by 16
counter
RxMT_s <= true; -- no message starting;
idle
RxReg_s <= RxInit_c;

-- new bit start
elsif (RxMT_s and RxIn_s = '0') then
Count16_s <= 0; -- reset divide by 16
counter
RxMT_s <= false; -- new message starting
RxReg_s <= RxInit_c;

-- If in a receive transaction mode
-- if @ mid bit clock then clock data into register
elsif Count16_s = 7 and not RxMT_s then -- mid clock
RxReg_s <= RxIn_s & RxReg_s(10 downto 1);
Count16_s <= Count16_s + 1;

-- if @ 16X clock rollover
elsif Count16_s = 15 then
Count16_s <= 0;

-- Normal count16 counter increment
else
Count16_s <= Count16_s + 1;
end if;

-------------------------------------------------------------Parity
Check Control
Statement---------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Check if a data word is received
if not RxMT_s and RxReg_s(10) = '1' and RxReg_s(0) = '0' then
Parity_reg = ((RxReg_s(1) xor RxReg_s(2)) xor (RxReg_s(3) xor
RxReg_s(4))) xor ((RxReg_s(5) xor RxReg_s(6)) xor (RxReg_s(7) xor
RxReg_s(8)))

if Parity_reg /= RxReg_s(9) then
Parity_err <= '1';
else
Parity_err <= '0';
end if;
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
DataRdyT <= true;
RxMT_s <= true;
else
DataRdyT <= false;
end if;
end process Rx_Lbl;

-------------------------------------------------------------------------------
-- Concurrent signal assignment for BitClkT and DataOut
-------------------------------------------------------------------------------

BitClkT <= '1' when Count16_s = 10
else '0';

DataOuT <= RxReg_s(8 downto 1);

end UartRx_Beh;
 
On May 21, 4:19 am, Anson.Stugg...@gmail.com wrote:
Hello,

I'm trying to learn VHDL and here I'm adding a parity bit to Ben
Cohen's UART Receiver. RxReg(9) is incoming parity bit from
transmitter side. A 0 output at Parity_err means no parity error
detected and otherwise. The receiver has to match the incoming parity
bit with its own parity bit which is calculated using XOR of its data
byte, RxReg(8 downto 0). My statement below is giving me a full byte
delay because my control statements for the parity check. I think it's
because of the process statement, but that's all I can think of now.

can someone let me know how to fix this?

Thanks,
AS
-------------------------------------------------------------------------------
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
-------------------------------------------------------------------------------
--
-- Project : ATEP
-- File name : uartrx.vhd
-- Title : UART Receiver
-- Description : UART receiver selection
--
-------------------------------------------------------------------------------
-- Revisions :
-- Date Author Revision
Comments
-- Sat Oct 30 10:05:49 1994 cohen Rev A Creation
-------------------------------------------------------------------------------
entity UartRx_Nty is
port (Clk16xT : in std_logic; -- 16 of these clocks per
bit
ResetF : in std_logic;
Serial_InT : in std_logic;
DataRdyT : out boolean;
DataOuT : out std_logic_Vector(7 downto 0);
Parity_err : out std_logic; -- Parity Error Output
BitClkT : out std_logic); -- same speed clock as Tx
end UartRx_Nty;

architecture UartRx_Beh of UartRx_Nty is
subtype Int0to15_Typ is integer range 0 to 15;
constant RxInit_c : std_logic_Vector(10 downto 0) := "11111111111";
signal RxReg_s : std_logic_Vector(10 downto 0); -- the receive
register
signal Count16_s : Int0to15_Typ; -- for divide by 16
signal RxMT_s : boolean; -- Receive register empty
signal RxIn_s : std_logic; -- registered
serial input
signal Parity_Reg : std_logic;

begin -- UartRx_Beh

-----------------------------------------------------------------------------
-- Process: Xmit_Lbl
-- Purpose: Models the receive portion of a UART.
-- Operation is as follows:
-- . All operations occur on rising edge of Clk16xT.
-- . Clk16xT runs 16x the bit clock rate
-- . If ResetF = '0' then
-- RxReg_s is reset to "11111111111".
-- Count_s is reset to 0.
-- . If (RxMT_s and RxIn_s = '0') then
-- Start of new byte
-- . If Count16_s = 7 and not RxMT_s then -- mid
clock
-- Sample here where bit most stable
-- RxReg_s <= RxIn_s & RxReg_s(9 downto 1);
-- . Entire byte received when
-- not RxMT_s and RxReg_s(9) = '1' and RxReg_s(0) =
'0'
--

-----------------------------------------------------------------------------
Rx_Lbl : process

begin -- process Rx_Lbl
wait until Clk16xT'event and Clk16xT = '1';
-- Clock serial input into RxIn_s
RxIn_s <= Serial_InT;

-- reset
if (ResetF = '0') then
Count16_s <= 0; -- reset divide by 16
counter
RxMT_s <= true; -- no message starting;
idle
RxReg_s <= RxInit_c;

-- new bit start
elsif (RxMT_s and RxIn_s = '0') then
Count16_s <= 0; -- reset divide by 16
counter
RxMT_s <= false; -- new message starting
RxReg_s <= RxInit_c;

-- If in a receive transaction mode
-- if @ mid bit clock then clock data into register
elsif Count16_s = 7 and not RxMT_s then -- mid clock
RxReg_s <= RxIn_s & RxReg_s(10 downto 1);
Count16_s <= Count16_s + 1;

-- if @ 16X clock rollover
elsif Count16_s = 15 then
Count16_s <= 0;

-- Normal count16 counter increment
else
Count16_s <= Count16_s + 1;
end if;

-------------------------------------------------------------Parity
Check Control
Statement---------------------------------------------------------
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
-- Check if a data word is received
if not RxMT_s and RxReg_s(10) = '1' and RxReg_s(0) = '0' then
Parity_reg = ((RxReg_s(1) xor RxReg_s(2)) xor (RxReg_s(3) xor
RxReg_s(4))) xor ((RxReg_s(5) xor RxReg_s(6)) xor (RxReg_s(7) xor
RxReg_s(8)))

if Parity_reg /= RxReg_s(9) then
Parity_err <= '1';
else
Parity_err <= '0';
end if;
--------------------------------------------------------------------------------------------------------------------------------------------------------------------
DataRdyT <= true;
RxMT_s <= true;
else
DataRdyT <= false;
end if;
end process Rx_Lbl;

-------------------------------------------------------------------------------
-- Concurrent signal assignment for BitClkT and DataOut
-------------------------------------------------------------------------------

BitClkT <= '1' when Count16_s = 10
else '0';

DataOuT <= RxReg_s(8 downto 1);

end UartRx_Beh;

The point of sending the parity bit at the end of a transmission
is that you can compute the parity as you transmit, one bit at a
time. Regardless of the parity bit location, you can do the same
for receiving because as far as parity checking is concerned, the
parity bit is just another input to your XOR function.

There is no need to calculate parity on the 8-bit parallel data.
You can receive "running" parity one bit at a time as you fill
the shift register, then your parity check will be complete at
the same time you transfer data to the parallel register.

Parity checking is effectively just a "T" flip-flop that gets
cleared between data words. The T input is attached to the
incoming data. Clock is enabled at the same time as your shift
register. When all bits including parity have been shifted in,
the Q of the flip-flop should have a constant value which only
depends on the type of parity (even or odd).

By the way, the reason you're getting a delay in your code
is that the check is inside the clocked process that loads
the parity register. So the data on the output of the
parity register at the time the process runs is from the
previous word. If you wanted to use a parallel method
of parity checking, you either need to calculate the
parity in a separate non-clocked process or use a
variable for Parity_Reg so the parity check is
executed in the same cycle.

HTH,
Gabor
 
Anson.Stuggart@gmail.com writes:
bit with its own parity bit which is calculated using XOR of its data
byte, RxReg(8 downto 0). My statement below is giving me a full byte
delay because my control statements for the parity check. I think it's
because of the process statement, but that's all I can think of now.

can someone let me know how to fix this?
The usual way to generate parity in a UART is to do it one bit at a
time, rather than all in parallel. Since a UART is already shifting
the bits serially, this reduces the parity computation to a single
XOR gate and a single D FF.

Once per character (e.g., during the start bit), init the FF state
(value depending on whether you want even or odd parity).
 

Welcome to EDABoard.com

Sponsor

Back
Top