EmbDev.net

Forum: FPGA, VHDL & Verilog UART RECEIVER


von Hareesh M. (Company: Mindteck) (hareeshp)


Rate this post
useful
not useful
Hi i have written code for uart reception. I am using docklight for 
transmitting data. When i transmit data at very first time, i am able to 
receive correct data, but if i transmit the same data again the data is 
not correct.

please find the attached code
1
Library ieee;
2
use ieee.std_logic_1164.all;
3
use ieee.numeric_std.all;
4
use ieee.std_logic_arith.all;
5
6
entity uart_rx is
7
  generic (
8
         baudrate_clk_count : integer:=5029
9
        );
10
  
11
  port ( 
12
       i_inclk        : in std_logic;
13
       i_serial_bit    : in std_logic;
14
       i_rx_data_bits  : out std_logic_vector(0 to 7):=(others=>'0');
15
       i_rx_done      : out std_logic;
16
       test_bench_test  : out std_logic;
17
       test_led      : out std_logic:='0';
18
       test_gpio      : out std_logic;
19
       o_rx_line_busy  : out std_logic
20
       
21
      ); 
22
       
23
end uart_rx;     
24
25
architecture behav of uart_rx is
26
27
  type rx_main_states is(rx_idle,rx_start,rx_data,rx_stop);
28
  signal rx_state: rx_main_states:= rx_idle;
29
  
30
  signal baud_rate_tic     : std_logic:='0';
31
  
32
  signal i_rx_data_byte    : std_logic_vector(0 to 7):=(others=>'0');
33
34
  signal baud_rate_counter : integer range 0 to baudrate_clk_count-1:=0;
35
  signal rx_data_r        : std_logic:='0'; 
36
  signal r_RX_Data_R     : std_logic:='0';
37
  signal index_reg       : integer range 0 to 7:=0;
38
  
39
  
40
  
41
  signal baud_rate_clock   : std_logic:='0';
42
  
43
  signal delay_counter     : integer:=0;
44
45
  
46
begin
47
  
48
--Baud rate clock process  
49
  process(i_inclk)
50
  begin
51
    if(rising_edge(i_inclk))then
52
      if(baud_rate_counter<baudrate_clk_count)then
53
        baud_rate_counter <= baud_rate_counter+1;
54
        baud_rate_tic <= '0';
55
      else
56
        baud_rate_counter <= 0;
57
        baud_rate_clock <= not(baud_rate_clock);
58
        baud_rate_tic <= '1';
59
      end if;
60
    end if;
61
  end process;
62
  
63
  test_bench_test <= baud_rate_clock;
64
  
65
  
66
--Recieving the UART data frame
67
  process(i_inclk)
68
  begin
69
    if(rising_edge(i_inclk))then
70
      if(baud_rate_tic='1')then
71
        r_RX_Data_R <= i_serial_bit;
72
        rx_data_r   <= r_RX_Data_R;
73
      end if;
74
    end if;
75
  end process;
76
77
--UART receiption process  
78
  process(i_inclk)
79
  begin
80
    if(rising_edge(i_inclk))then
81
      if(baud_rate_tic='1')then
82
        
83
        case rx_state is
84
          
85
          when rx_idle =>
86
          
87
            index_reg <= 0;
88
            o_rx_line_busy <= '0';
89
            i_rx_done <= '0';
90
            rx_state <= rx_start;
91
                
92
          when rx_start =>  
93
          
94
            if(rx_data_r = '0')then
95
              o_rx_line_busy <= '1';
96
              rx_state <= rx_data;
97
            else
98
              rx_state <= rx_start;
99
            end if;
100
          
101
          when rx_data =>
102
            i_rx_data_byte(index_reg) <= rx_data_r;  
103
            
104
            
105
            if(index_reg<7)then
106
              index_reg <= index_reg+1;
107
              rx_state <= rx_data;
108
            else
109
              index_reg<= 0;
110
              rx_state <= rx_stop;
111
            end if;
112
              
113
          when rx_stop =>  
114
          
115
            if(rx_data_r = '1')then
116
              o_rx_line_busy <= '0';
117
              i_rx_done <= '1';
118
              test_led  <= '1';
119
              rx_state <= rx_idle;
120
            else
121
              rx_state <= rx_stop;
122
            end if;
123
            
124
          when others =>
125
            rx_state <= rx_idle;
126
127
        end case;
128
      end if;
129
    end if;
130
  end process;
131
  
132
  i_rx_data_bits <= i_rx_data_byte;
133
  test_gpio <= i_serial_bit;
134
  
135
end behav;

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Hareesh M. wrote:
> but if i transmit the same data again the data is not correct.
Thats a very detailed description of your problem. Therefore its kind of 
easy to find out whats going wrong...

> but if i transmit the same data again the data is not correct.
Do you have a screenshot of your simulation? What does the testbench 
look like?

> but if i transmit the same data again the data is not correct.
What data do you send? And what do you receive?

Hareesh M. wrote:
> use ieee.numeric_std.all;
> use ieee.std_logic_arith.all;
Never ever use both of those math packages together. You will get 
strange error messages and strange behaviour now and then due to 
multiple type definitions. The numeric_std has all you will ever need.
1
  process(i_inclk)
2
  begin
3
    if(rising_edge(i_inclk))then
4
      if(baud_rate_tic='1')then
5
        r_RX_Data_R <= i_serial_bit;
6
        rx_data_r   <= r_RX_Data_R;
7
      end if;
8
    end if;
9
  end process;
Why do you invoke the baud_rate_tic here when synching in the rx line?
Thats one of the problems here: your detection of the start bit is wrong 
to to nearly "undersampling" the input signal.
The other is, that your whole receiver does not synchronize to the 
edges of the start bit. Instead you simply assume that the timing is 
somehow like you painted it on a sheet of paper...

In a working RS232 receiver you detect the falling edge of the startbit. 
Then you wait for 1.5 bit durations. Then you sample the data bits after 
each 1.0 bit durations in the mid of each bits.

In a very good RS232 receiver you detect the falling edge of the start 
bit, then you wait for 0.4 bit times, then you sample the start bit 
value 3 times with 0.1 bit times between the samples and check those 
three samples to be all '0'. If there is one or two '1' in it, the you 
set a error flag. Then you wait for 0.8 bit times and sample first data 
bit 3 times with a delay of 0.1 bit times in between. When one of those 
3 samples is different, then you set an error flag and take the major 
value out of those 3 samples as th data bit. The same happens in the mid 
time of the following data bits. And then you check the stop bit to be a 
'1' in the same manner by sampling it 3 times.

: Edited by Moderator
von Hareesh M. (Company: Mindteck) (hareeshp)


Attached files:

Rate this post
useful
not useful
Lothar M. wrote:
> Hareesh M. wrote:
>> but if i transmit the same data again the data is not correct.
> Thats a very detailed description of your problem. Therefore its kind of
> easy to find out whats going wrong...
>
>> but if i transmit the same data again the data is not correct.
> Do you have a screenshot of your simulation? What does the testbench
> look like?

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
You see, thats no testbench for a VHDL design...

I urge you to set up a real VHDL testbench. Its fairly easy to generate 
a simple RS232 signal and send different characters to the "unit under 
test". See this for a testbench sample:
http://www.lothar-miller.de/s9y/uploads/tb_RS232IO.vhd

Then you can dig in deep and look whats going on, where are the sampling 
points, hows the timing and so forth.

> baudrate_clk_count : integer:=5029
What FPGA clock do you have to need such an odd prescaling value?

von Hareesh M. (Company: Mindteck) (hareeshp)


Rate this post
useful
not useful
Lothar M. wrote:
> You see, thats no testbench for a VHDL design...
>
> I urge you to set up a real VHDL testbench. Its fairly easy to generate
> a simple RS232 signal and send different characters to the "unit under
> test". See this for a testbench sample:
> http://www.lothar-miller.de/s9y/uploads/tb_RS232IO.vhd
>
> Then you can dig in deep and look whats going on, where are the sampling
> points, hows the timing and so forth.

yes, i will write test bench. Thanks for your response
>> baudrate_clk_count : integer:=5029
> What FPGA clock do you have to need such an odd prescaling value?

i_inclk is 50mhz.

von Lothar M. (Company: Titel) (lkmiller) (Moderator)


Rate this post
useful
not useful
Hareesh M. wrote:
>> What FPGA clock do you have to need such an odd prescaling value?
> i_inclk is 50mhz.
Fifty millihertz? Really?

If its the usual 50MHz (fifty Megahertz) then your expected baudrate is 
somewhat like 50000000/5930 = 9940 bits per sec?
Looks weird to me....

Hareesh M. wrote:
> yes, i will write test bench.
Thats good.
You will get an out of range errror in this line:
1
      if(baud_rate_counter<baudrate_clk_count)then
2
        baud_rate_counter <= baud_rate_counter+1;
Because baudrate_clk_count is 5029 and the highest adissible value for 
baud_rate_counter is 5028. Therfore when baudrate_clk_count is 5028 it 
is less than 5029 and finally it will become incremented. This leads to 
a value higher than the allowed 5028 --> overflow error!

von Hareesh M. (Company: Mindteck) (hareeshp)


Rate this post
useful
not useful
Lothar M. wrote:
> Hareesh M. wrote:
>>> What FPGA clock do you have to need such an odd prescaling value?
>> i_inclk is 50mhz.
> Fifty millihertz? Really?

sorry!, actually the value is 5208 not 5029.
>
> If its the usual 50MHz (fifty Megahertz) then your expected baudrate is
> somewhat like 50000000/5930 = 9940 bits per sec?
> Looks weird to me....
>
> Hareesh M. wrote:
>> yes, i will write test bench.
> Thats good.
> You will get an out of range errror in this line:
>
1
>       if(baud_rate_counter<baudrate_clk_count)then
2
>         baud_rate_counter <= baud_rate_counter+1;
3
>

yes i am getting this error.

von Hareesh M. (Company: Mindteck) (hareeshp)


Rate this post
useful
not useful
Hareesh M. wrote:
> Lothar M. wrote:
>> Hareesh M. wrote:
>>>> What FPGA clock do you have to need such an odd prescaling value?
>>> i_inclk is 50mhz.
>> Fifty millihertz? Really?
>
> sorry!, actually the value is 5208 not 5029.
>>
>> If its the usual 50MHz (fifty Megahertz) then your expected baudrate is
>> somewhat like 50000000/5930 = 9940 bits per sec?
>> Looks weird to me....
>>
>> Hareesh M. wrote:
>>> yes, i will write test bench.
>> Thats good.
>> You will get an out of range errror in this line:
>>
1
>>       if(baud_rate_counter<baudrate_clk_count)then
2
>>         baud_rate_counter <= baud_rate_counter+1;
3
>>
>
> yes i am getting this error.

i have solved this issue by putting
1
signal baud_rate_counter: integer range 0 to 5028:=0;

Please log in before posting. Registration is free and takes only a minute.
Existing account
Do you have a Google/GoogleMail account? No registration required!
Log in with Google account
No account? Register here.