EmbDev.net

Forum: FPGA, VHDL & Verilog UART RECEIVER


Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

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.

please find the attached code
Library ieee;
use ieee.std_logic_1164.all;
use ieee.numeric_std.all;
use ieee.std_logic_arith.all;

entity uart_rx is
  generic (
         baudrate_clk_count : integer:=5029
        );
  
  port ( 
       i_inclk        : in std_logic;
       i_serial_bit    : in std_logic;
       i_rx_data_bits  : out std_logic_vector(0 to 7):=(others=>'0');
       i_rx_done      : out std_logic;
       test_bench_test  : out std_logic;
       test_led      : out std_logic:='0';
       test_gpio      : out std_logic;
       o_rx_line_busy  : out std_logic
       
      ); 
       
end uart_rx;     

architecture behav of uart_rx is

  type rx_main_states is(rx_idle,rx_start,rx_data,rx_stop);
  signal rx_state: rx_main_states:= rx_idle;
  
  signal baud_rate_tic     : std_logic:='0';
  
  signal i_rx_data_byte    : std_logic_vector(0 to 7):=(others=>'0');

  signal baud_rate_counter : integer range 0 to baudrate_clk_count-1:=0;
  signal rx_data_r        : std_logic:='0'; 
  signal r_RX_Data_R     : std_logic:='0';
  signal index_reg       : integer range 0 to 7:=0;
  
  
  
  signal baud_rate_clock   : std_logic:='0';
  
  signal delay_counter     : integer:=0;

  
begin
  
--Baud rate clock process  
  process(i_inclk)
  begin
    if(rising_edge(i_inclk))then
      if(baud_rate_counter<baudrate_clk_count)then
        baud_rate_counter <= baud_rate_counter+1;
        baud_rate_tic <= '0';
      else
        baud_rate_counter <= 0;
        baud_rate_clock <= not(baud_rate_clock);
        baud_rate_tic <= '1';
      end if;
    end if;
  end process;
  
  test_bench_test <= baud_rate_clock;
  
  
--Recieving the UART data frame
  process(i_inclk)
  begin
    if(rising_edge(i_inclk))then
      if(baud_rate_tic='1')then
        r_RX_Data_R <= i_serial_bit;
        rx_data_r   <= r_RX_Data_R;
      end if;
    end if;
  end process;

--UART receiption process  
  process(i_inclk)
  begin
    if(rising_edge(i_inclk))then
      if(baud_rate_tic='1')then
        
        case rx_state is
          
          when rx_idle =>
          
            index_reg <= 0;
            o_rx_line_busy <= '0';
            i_rx_done <= '0';
            rx_state <= rx_start;
                
          when rx_start =>  
          
            if(rx_data_r = '0')then
              o_rx_line_busy <= '1';
              rx_state <= rx_data;
            else
              rx_state <= rx_start;
            end if;
          
          when rx_data =>
            i_rx_data_byte(index_reg) <= rx_data_r;  
            
            
            if(index_reg<7)then
              index_reg <= index_reg+1;
              rx_state <= rx_data;
            else
              index_reg<= 0;
              rx_state <= rx_stop;
            end if;
              
          when rx_stop =>  
          
            if(rx_data_r = '1')then
              o_rx_line_busy <= '0';
              i_rx_done <= '1';
              test_led  <= '1';
              rx_state <= rx_idle;
            else
              rx_state <= rx_stop;
            end if;
            
          when others =>
            rx_state <= rx_idle;

        end case;
      end if;
    end if;
  end process;
  
  i_rx_data_bits <= i_rx_data_byte;
  test_gpio <= i_serial_bit;
  
end behav;


Author: Lothar M. (lkmiller) (Moderator)
Posted on:

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.
  process(i_inclk)
  begin
    if(rising_edge(i_inclk))then
      if(baud_rate_tic='1')then
        r_RX_Data_R <= i_serial_bit;
        rx_data_r   <= r_RX_Data_R;
      end if;
    end if;
  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
Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:
Attached files:

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?

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

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:
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?

Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

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:
> 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.

Author: Lothar M. (lkmiller) (Moderator)
Posted on:

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:
      if(baud_rate_counter<baudrate_clk_count)then
        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!

Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

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:
>
>       if(baud_rate_counter<baudrate_clk_count)then
>         baud_rate_counter <= baud_rate_counter+1;
> 

yes i am getting this error.

Author: Hareesh M. (Company: Mindteck) (hareeshp)
Posted on:

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:
>>
>>       if(baud_rate_counter<baudrate_clk_count)then
>>         baud_rate_counter <= baud_rate_counter+1;
>> 
>
> yes i am getting this error.

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

Reply

Entering an e-mail address is optional. If you want to receive reply notifications by e-mail, please log in.

Rules — please read before posting

  • Post long source code as attachment, not in the text
  • Posting advertisements is forbidden.

Formatting options

  • [c]C code[/c]
  • [avrasm]AVR assembler code[/avrasm]
  • [vhdl]VHDL code[/vhdl]
  • [code]code in other languages, ASCII drawings[/code]
  • [math]formula (LaTeX syntax)[/math]




Bild automatisch verkleinern, falls nötig