

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;
USE ieee.std_logic_unsigned.ALL;

ENTITY rxcver IS
--Number of bits for the count in the clock divider (default = 3 for mclkx16/16)
generic (rxclkcount : positive := 3);
PORT (mclkx16   : IN std_logic;  -- input clock, 16x baudrate clock used for synchronization 
     read      : IN std_logic;  -- Read Strobe
      rx        : IN std_logic;  -- Receive Input Line
      reset     : IN std_logic;  -- Global Reset
      rxrdy     : OUT  std_logic;  -- Receiver data ready to read
      parityerr : OUT  std_logic;  -- Receiver parity error flag
      framingerr: OUT  std_logic;  -- Receiver framing error flag
      overrun   : OUT  std_logic;  -- Receiver overrun error flag
      data      : OUT  std_logic_vector(7 downto 0));  -- 8 bit output data bus
END rxcver;


ARCHITECTURE behave OF rxcver IS
   CONSTANT paritymode : std_logic := '0';  -- initializing to 1 = odd parity, 0 = even parity
   SIGNAL rxcnt : std_logic_vector(rxclkcount downto 0);  -- clock cycle count
   SIGNAL rx1, read1, read2, idle1 : std_logic;  -- delayed versions of rx, read, idle
   SIGNAL hunt  : std_logic;  -- hunting for start bit flag
   SIGNAL rhr : std_logic_vector(7 downto 0);  -- Receiver hold register
   SIGNAL rsr : std_logic_vector(7 downto 0);  -- Receiver serial -&gt; parallel shift register
   SIGNAL rxparity  :  std_logic;  -- parity bit of received data
   SIGNAL paritygen :  std_logic;  -- generated parity of received data
   SIGNAL rxstop : std_logic;  -- stop bit of received data
   SIGNAL rxclk  : std_logic;  -- Receive data shift clock
   SIGNAL idle  :  std_logic;  -- ='1' when receiver is idling
   SIGNAL rxdatardy : std_logic;  -- = '1' when data is ready to be read
BEGIN


        idle_preset : PROCESS (rxclk, reset)
        BEGIN
       IF reset = '1' THEN
          idle &lt;= '1';
       ELSIF rxclk'EVENT AND rxclk = '1' THEN
          idle &lt;= (NOT idle) AND (NOT rsr(0));
       END IF;
    END PROCESS;


--      // A start bit is eight clock times with rx=0 after a falling edge of rx. 
        rxclk_sync : PROCESS (mclkx16, reset)
        BEGIN
                IF reset = '1' THEN
                        hunt &lt;= '0';
--          set rxcnt to 1
            rxcnt(rxclkcount downto 1) &lt;= &quot;0&quot;;
            rxcnt(0) &lt;= '1';
                        rx1 &lt;= '1';
                        rxclk &lt;= '0';
                ELSIF (mclkx16 = '1') AND mclkx16'EVENT THEN
                        IF (idle = '1' AND rx = '0' AND rx1 = '1') THEN
               hunt &lt;= '1';
                        ELSE
                           IF (idle = '0' OR rx = '1') THEN
                              hunt &lt;= '0';
               END IF;
               IF (idle = '0' OR hunt = '1') THEN
                  rxcnt &lt;= rxcnt + 1;
               ELSE
--                set rxcnt to 1
                  rxcnt(rxclkcount downto 1) &lt;= &quot;0&quot;;
                  rxcnt(0) &lt;= '1';
               END IF;
            END IF;
            rx1 &lt;= rx;
            rxclk &lt;= rxcnt(rxclkcount);
            END IF;
        END PROCESS;

-- When not idling, sample data at the rx input, and generate parity.
   sample_data : PROCESS (rxclk, reset)
   BEGIN
      IF (reset = '1') THEN
      -- idle_reset   
         rsr &lt;= &quot;11111111&quot;;  -- All 1's ensure that idle stays low during data shifting.
         rxparity &lt;= '1';  -- Preset to high to ensure idle = 0 during data shifting.
             paritygen &lt;= paritymode;  --Preset paritygen to parity mode.
             rxstop &lt;= '0';
      ELSIF (rxclk = '1') AND (rxclk'EVENT) THEN
         IF (idle = '1') THEN
            -- idle_reset
            rsr &lt;= &quot;11111111&quot;;  -- All 1's ensure that idle stays low during data shifting.
                rxparity &lt;= '1';  -- Preset to high to ensure idle = 0 during data shifting.          
            paritygen &lt;= paritymode;  -- Preset paritygen to parity mode.
                rxstop &lt;= '0';
         ELSE
                -- shift_data
                rsr &lt;= '0'&amp;rsr(7 downto 1);  -- Right shift receive shift register.     
            rsr(7) &lt;= rxparity;  -- Load rsr[7] with rxparity.
            rxparity &lt;= rxstop;  -- Load rxparity with rxstop.
            rxstop &lt;= rx;  -- Load rxstop with rx. At 1'st shift rxstop gets low &quot;start bit&quot;. 
            paritygen &lt;= paritygen XOR rxstop;  -- Generate parity as data are shifted.
         END IF;
      END IF;
   END PROCESS;

-- Generate status &amp; error flags.
   generate_flag : PROCESS (mclkx16, reset)
   BEGIN
      IF (reset = '1') THEN
          rhr &lt;= &quot;00000000&quot;;
          rxdatardy &lt;= '0';
          overrun &lt;= '0';
          parityerr &lt;= '0';
          framingerr &lt;= '0';
          idle1 &lt;= '1';
          read2 &lt;= '1';
          read1 &lt;= '1';
      ELSIF (mclkx16 = '1') AND (mclkx16'EVENT) THEN
         IF (idle = '1' AND idle1 = '0') THEN
            IF (rxdatardy = '1') THEN
               overrun &lt;= '1';
            ELSE
               overrun &lt;= '0';  -- No overrun error, since holding register is empty.
               rhr &lt;= rsr;  -- Update holding register with contents of shift register.
               parityerr &lt;= paritygen;  -- paritygen = 1, if parity error.
               framingerr &lt;= NOT rxstop;  -- Framingerror, if stop bit is not 1.
               rxdatardy &lt;= '1';  -- Data is ready for reading flag.
            END IF;
ú
--         END IF;  --Modification (2) Changed to elsif to get receiver to receive properly^M
                 elsIF (read2 = '0' AND read1 = '1') THEN
--         IF (read2 = '0' AND read1 = '1') THEN

            rxdatardy  &lt;= '0';
            parityerr  &lt;= '0';
            framingerr &lt;= '0';
            overrun    &lt;= '0';
         END IF;

         idle1 &lt;= idle;  -- idle delayed 1 cycle for edge detect.
         read2 &lt;= read1;  -- 2 cycle delayed version of read, used for edge detection.
         read1 &lt;= read;  -- 1 cycle delayed version of read, used for edge detection.
      END IF;
   END PROCESS;

   rxrdy &lt;= rxdatardy;

   latch_data : PROCESS (read, rhr)
   BEGIN
      IF (read = '1') THEN
         data &lt;= rhr;
      END IF;
   END PROCESS;
END behave;