FPGARelated.com
Forums

UART Receiver Parity Check

Started by Unknown May 21, 2007
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).