# Forum: FPGA, VHDL & Verilog UART RECEIVER

Rate this post
 0 ▲ 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.


 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  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; 

Rate this post
 0 ▲ 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

Rate this post
 0 ▲ 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?

Rate this post
 0 ▲ 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:

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?

Rate this post
 0 ▲ 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:
>
> 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.

Rate this post
 0 ▲ 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
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!

Rate this post
 0 ▲ 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 baud_rate_counter <= baud_rate_counter+1;  3 > 

yes i am getting this error.

Rate this post
 0 ▲ 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> 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; `

• $formula (LaTeX syntax)$