Email: Password: Remember Me | Create Account (Free)

Back to Subject List

Old thread has been locked -- no new posts accepted in this thread
Jez Smith
04/05/06 05:02
Read: 471 times
Birmingham
England


 
#113647 - serial reciever
Since weve had lots of posts about slightly unusual requirements ofr rs232 recievers recently here is some VHDL which will implement a reciever which samples the input at 16 times the baud rate and generates the data clock once it has found a valid start bit.Its a bit basic and its part of a larger project but it does what it says on the tin and can be the basis of a more complex design.
Enjoy :-)
By the way I don't know why its lost the indentations.
pre>

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 -> 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 <= '1';
ELSIF rxclk'EVENT AND rxclk = '1' THEN
idle <= (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 <= '0';
-- set rxcnt to 1
rxcnt(rxclkcount downto 1) <= "0";
rxcnt(0) <= '1';
rx1 <= '1';
rxclk <= '0';
ELSIF (mclkx16 = '1') AND mclkx16'EVENT THEN
IF (idle = '1' AND rx = '0' AND rx1 = '1') THEN
hunt <= '1';
ELSE
IF (idle = '0' OR rx = '1') THEN
hunt <= '0';
END IF;
IF (idle = '0' OR hunt = '1') THEN
rxcnt <= rxcnt + 1;
ELSE
-- set rxcnt to 1
rxcnt(rxclkcount downto 1) <= "0";
rxcnt(0) <= '1';
END IF;
END IF;
rx1 <= rx;
rxclk <= 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 <= "11111111"; -- All 1's ensure that idle stays low during data shifting.
rxparity <= '1'; -- Preset to high to ensure idle = 0 during data shifting.
paritygen <= paritymode; --Preset paritygen to parity mode.
rxstop <= '0';
ELSIF (rxclk = '1') AND (rxclk'EVENT) THEN
IF (idle = '1') THEN
-- idle_reset
rsr <= "11111111"; -- All 1's ensure that idle stays low during data shifting.
rxparity <= '1'; -- Preset to high to ensure idle = 0 during data shifting.
paritygen <= paritymode; -- Preset paritygen to parity mode.
rxstop <= '0';
ELSE
-- shift_data
rsr <= '0'&rsr(7 downto 1); -- Right shift receive shift register.
rsr(7) <= rxparity; -- Load rsr[7] with rxparity.
rxparity <= rxstop; -- Load rxparity with rxstop.
rxstop <= rx; -- Load rxstop with rx. At 1'st shift rxstop gets low "start bit".
paritygen <= paritygen XOR rxstop; -- Generate parity as data are shifted.
END IF;
END IF;
END PROCESS;

-- Generate status & error flags.
generate_flag : PROCESS (mclkx16, reset)
BEGIN
IF (reset = '1') THEN
rhr <= "00000000";
rxdatardy <= '0';
overrun <= '0';
parityerr <= '0';
framingerr <= '0';
idle1 <= '1';
read2 <= '1';
read1 <= '1';
ELSIF (mclkx16 = '1') AND (mclkx16'EVENT) THEN
IF (idle = '1' AND idle1 = '0') THEN
IF (rxdatardy = '1') THEN
overrun <= '1';
ELSE
overrun <= '0'; -- No overrun error, since holding register is empty.
rhr <= rsr; -- Update holding register with contents of shift register.
parityerr <= paritygen; -- paritygen = 1, if parity error.
framingerr <= NOT rxstop; -- Framingerror, if stop bit is not 1.
rxdatardy <= '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 <= '0';
parityerr <= '0';
framingerr <= '0';
overrun <= '0';
END IF;

idle1 <= idle; -- idle delayed 1 cycle for edge detect.
read2 <= read1; -- 2 cycle delayed version of read, used for edge detection.
read1 <= read; -- 1 cycle delayed version of read, used for edge detection.
END IF;
END PROCESS;

rxrdy <= rxdatardy;

latch_data : PROCESS (read, rhr)
BEGIN
IF (read = '1') THEN
data <= rhr;
END IF;
END PROCESS;
END behave;


List of 5 messages in thread
TopicAuthorDate
serial reciever      Jez Smith      04/05/06 05:02      
   Indented, but monochrome      Andy Neil      04/05/06 14:43      
   Indented, but monochrome      Andy Neil      04/05/06 14:43      
      Oops      Andy Neil      04/05/06 14:44      
         Thanks for sorting that out for me.      Jez Smith      04/05/06 15:04      

Back to Subject List