Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

RS232 Receiver in VHDL

Status
Not open for further replies.

omerysmi

Member level 5
Member level 5
Joined
Oct 10, 2014
Messages
91
Helped
0
Reputation
0
Reaction score
0
Trophy points
6
Activity points
1,128
I want to implement rs232 receiver in vhdl with FPGA Altera DE1.
I have try to write some code but I know that is not good, my main problem is that I dont know how to get an indictaion that new data(serial data) is coming..so actually what I did is to move each bit of the serial data to the out parallel data (8 bits) every rising edge of the main clock

This is the code I have wrriten (again, it's not good of course):

Code:
library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
entity receiver is
port(Clock, Reset : in std_logic;
	  Data_in : in std_logic;
	  Data_Out : out std_logic_vector(7 downto 0));
end entity;

architecture arc of receiver is
signal index : integer range 0 to 7:=0;
signal inbuffer : std_logic;
begin
	process(Clock, Reset)
		begin
			if Reset='0' then
				Data_Out<=(others=>'0');
				index<=0;
			elsif rising_edge(Clock) then
				if(index<8)
				inbuffer<=Data_in;
				Data_Out(index)<=inbuffer;
				index<=index+1;
				else
				index<=0;
				end if;
			end if;
end process;
end arc;
 

Hi,

I never used RS232, or better say UART, on FPGA, but there should be plenty code for it.

****
UART is idle high. Start bit is low, so a falling edge after idle starts the timing.
After 1.5 bit periods sample the first bit,
All other bits with a delay of 1 bit rate.
Resync after idle...

You should consider at least 4 times oversampling.

Klaus
 

Hi,

I never used RS232, or better say UART, on FPGA, but there should be plenty code for it.

****
UART is idle high. Start bit is low, so a falling edge after idle starts the timing.
After 1.5 bit periods sample the first bit,
All other bits with a delay of 1 bit rate.
Resync after idle...

You should consider at least 4 times oversampling.

Klaus

if for example i have 9600 Baud, how can i know how much bits move per second? Does it 9600?
 

if for example i have 9600 Baud, how can i know how much bits move per second? Does it 9600?
Yes,
As long as you know the length of start and stop bits...
 

Instead of unsigned, use numeric library. Asynchronous serial data is asynchronous to your FPGA baud clock, so YOU have to do the synchronization. That means, you have to use oversampling, like 8 times, 16 times baud rate (usually power of 2, makes live easier). Then you search for your start condition, and if you find it you reset your counter. From there on your counter is synchronous to the incoming data and overflows on every new bit. Now sampling (reading) your data at that moment is not wise, bc there, your serial data is toggling. To read the stabilized data, you should wait a little, aiming for the middle to create a "centered interface".



Code VHDL - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
 
entity receiver is
port(
    Reset : in std_logic;    -- assynchronous reset
    Enable : in std_logic;   -- add an enable?
    SYS_CLK : in std_logic;  -- system clock - you will probably not want to run your complete FPGA-Design on the same freq. like baud rate?
    UART_CLK : in std_logic; -- 16 x baud
    -- receiver
    SIN : in std_logic; -- serial in
    RX_Rd : in std_logic; -- read your received bytes at system clock
    RX_Empty : out std_logic; -- receiver empty - there are no received byte data for your FPGA design to process :(
    RX_Data_Out : out std_logic_vector(7 downto 0)
    );
end entity;
 
architecture arc of receiver is
 
signal iSIN_t1 : std_logic; -- serial data, delayed version
signal iSIN_t2 : std_logic; -- serial data, delayed version
 
begin
    process(UART_CLK, Reset)
    begin
        if Reset='0' then
            iSOF <= '0';  -- no start of frame
            iSIN_t1 <= '1'; -- uart is idle high!
            iSIN_t2 <= '1'; -- uart is idle high!
        elsif rising_edge(UART_CLK) then
            -- synchronize the assynchronous UART RX with your UART_CLK
            iSIN_t1 <= SIN;       -- shift in your serial data
            iSIN_t2 <= iSIN_t1;   -- shift again
            if enable = '1' then
                -- if no start of frame detected, find it!
                if iSIN_t2 = '0' and iSOF = '0' then
                    iSOF <= '1';      -- there, you found it!
                    iCLK_CNT <= 0; -- initialize your counter
                end if;   
 
                if iSOF = '1' then 
                    iCLK_CNT <= iCLK_CNT + 1; -- keep counting clock cycles
                    if iCLK_CNT = 7 then -- UART CLK is 16 x baud, remember?
                        -- sample SIN at the center of baud clock
                        -- so we initialized clk counter at start of frame,
                        -- and keep counting to find the middle between clock period
                    end if;
                    -- check for errors
                    -- save your byte
                end if;      
            end if ;
        end if;
    end process;
 
    -- save your byte
    -- to use it with your system clock of the FPGA design,
    -- you need to synchronize between the two clock domains
    -- us a small FIFO for this, 8 / 16 bytes depth is enough
    -- you can use a core generator to generate the fifo
    rx_fifo_buffer : fifo_dc
    port map (
        WrCLK => UART_CLK,
        RdCLK => SYS_CLK,
        Din   => iUART_BYTE_DATA,
        Dout  => RX_Data_Out,
        Empty => RX_Empty
    );
 
end arc;



That is enough to get you started. There are lots of information regarding this topic. Have a closer look on the timing diagrams to understand serial transmission. It is usually easier to start with the transmitter, if you need that as well. simulate it!


Just as a sidenote, uart communication can tolerate +- 6% baud rate in theory (almost). In practice it means that your communication still works if you are using a clock that is 3% off the actual baud rate.

This is helpful if you have difficulties to create the correct baud rate on your fpga, especially for support of various baudrates.
 
Last edited:

Hi,

independent of Start bit, Stop bit or data bit... all have the same length.

For 9600 baud: = 1s/9600 = 104us.

Klaus

- - - Updated - - -

Hi again,

Please google for "VHDL UART code" or "VHDL UART IP"
There are a lot of descriptions, online or as PDF, even video tutorials.....

Klaus
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top