+ Post New Thread
Results 1 to 6 of 6
  1. #1
    Newbie level 4
    Points: 243, Level: 2

    Join Date
    Jun 2018
    Posts
    6
    Helped
    0 / 0
    Points
    243
    Level
    2

    UART Transmitter by FPGA

    I want to send 8 bit data from FPGA to PC, 9600 baudrate, 8 bit data, 1 start&stop bit, no parity. I did coded my Basys3 Fpga and connected to PC. By using Tera Term, wanted to see how it works out. But probably something big I'm missing out. I just wrote a transmitter code and somewhere I saw that some button&top modules. Do I need them to see a 8-bit data's ASCII equivalent on my PC?

    My code is below,
    Code:
    library ieee;
    use ieee.std_logic_1164.all;
    
    
    entity rs232_omo is
    generic(clk_max:integer:=10400); --for baudrate
                                          
    
    port(
    
    clk : in std_logic;
    rst : in std_logic;
    start : in std_logic;
    input : in std_logic_vector(7 downto 0);
    done : out std_logic;
    output : out std_logic;
    showstates: out std_logic_vector(3 downto 0)
    
    );
    end entity;
    
    architecture dataflow of rs232_omo is
    
    type states is (idle_state,start_state,send_state,stop_state);
    signal present_state,next_state : states;
    signal data,data_next : std_logic;
    
    
    begin
    
    
    process(clk,rst)
    variable count : integer range 0 to clk_max;
    variable index : integer range 0 to 10;
    begin
            
        if rst='1' then
            present_state<=idle_state;
            count:=0;
            data<='1';
            
            
        elsif rising_edge(clk) then
            
            present_state<=next_state;
            count:=count+1;
            index:=index+1;
            data<=data_next;
    
        end if;
    
    end process;
    
    process(present_state,data,clk,rst,start)
    variable count : integer range 0 to clk_max;
    variable index : integer range 0 to 10;
    begin
    
    done<='0';
    data_next<='1';
    
        case present_state is
        
            when idle_state =>
                showstates<="1000";
                data_next<='1';
                
                if start='1' and rst='0' then
                    count:=count+1;
                    if count=clk_max then
                        next_state<=start_state;
                        count:=0;
                    end if;    
                end if;
                
            when start_state =>
                showstates<="0100";
                data_next<='0';
               
                count:=count+1;
                if count=clk_max then
                    next_state<=send_state;
                    count:=0;
                end if;
            
            when send_state =>
                showstates<="0010";
                count:=count+1;
                data_next<=input(index);
                
                if count=clk_max then
                    if index=7 then
                        index:=0;
                        next_state<=stop_state;
                    else
                        index:=index+1;
                    end if;
                count:=0;
                end if;
    
            when stop_state =>
                showstates<="0001";
                count:=count+1;
                if count=clk_max then
                next_state<=idle_state;
                done<='1';
                count:=0;
                end if;
                
    end case;
    
    end process;
    output<=data;
    
    end architecture;
    Testbench simulation(input is "00001111")

    Click image for larger version. 

Name:	rs232.jpg 
Views:	10 
Size:	72.8 KB 
ID:	154741


    For any help, I appreciate in advance
    Last edited by huytergan; 2nd August 2019 at 20:10.

    •   AltAdvertisement

        
       

  2. #2
    Super Moderator
    Points: 77,678, Level: 67
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    15,745
    Helped
    3587 / 3587
    Points
    77,678
    Level
    67

    Re: UART Transmitter by FPGA

    Hi,

    Honestly, I don't understand your code....maybe because I'm not that experienced. But usually when I see cide, then I understand at least a little.

    But here I don't recognize
    * what's your system clock frequency
    * where the baud rate generator is, that generates an ENABLE every 1/9600 s
    * and where the state machine is: idle, start, 8 bits data, stop...then return to start or idle

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



    •   AltAdvertisement

        
       

  3. #3
    Newbie level 4
    Points: 243, Level: 2

    Join Date
    Jun 2018
    Posts
    6
    Helped
    0 / 0
    Points
    243
    Level
    2

    Re: UART Transmitter by FPGA

    Quote Originally Posted by KlausST View Post
    Hi,

    Honestly, I don't understand your code....maybe because I'm not that experienced. But usually when I see cide, then I understand at least a little.

    But here I don't recognize
    * what's your system clock frequency
    * where the baud rate generator is, that generates an ENABLE every 1/9600 s
    * and where the state machine is: idle, start, 8 bits data, stop...then return to start or idle

    Klaus
    Hi,
    System clock frequency is 100 MHz(10 ns)
    For baud rate generator, 1/9600 = clk_max x 10 ns equation tells me the clk_max will be 10400 which’s defined in entity’s generic. For each state/bit, ‘count’ is counting up to ‘clk_max’, then change state/bit.

    States are defined in declaration part of Architecture. And their operation is shown inside of second process.(idle_state, start_state, send_state, stop_state)



    •   AltAdvertisement

        
       

  4. #4
    Super Moderator
    Points: 77,678, Level: 67
    Achievements:
    7 years registered
    Awards:
    Most Frequent Poster 3rd Helpful Member

    Join Date
    Apr 2014
    Posts
    15,745
    Helped
    3587 / 3587
    Points
    77,678
    Level
    67

    Re: UART Transmitter by FPGA

    Hi,

    It will not cause your UART communication to fail, but it won't hurt to do the math more precisely:
    100,000,000 / 9,600 = 10,416.6666. Thus 10,417 is the rounded integer value. The counter should run 0.... 10,416.

    I understand a bit more now of your code. It's hard to read. I really recommend to do the baudrate generation in an extra process.

    In your first process you handle the reset state, I assume correctly.
    But then there is an "else if" where COUNT is incremented unconditionally and INDEX is incremented unconditionally.
    But the same is handled in your second process, too. This may cause problems.

    ****
    Some other issues.
    I recommend to buffer your INPUT. It sould be latched when you start transmission, to prevent transmitting a corrupted byte when INPUT is modified externally.

    When RESET is asserted you stop transmission immediately. I may want this or not ... but when you do this, it will cause problems at the receiver, because the byte is not transmitted completely .... and - when you start to transmit a new byte too soon it will be corrupted at the receiver, too.
    If you really want to stop immediately: you should at least wait for 10 bit times outputting "1" before you start to transmit a new byte.

    Klaus
    Please don´t contact me via PM, because there is no time to respond to them. No friend requests. Thank you.



  5. #5
    Advanced Member level 4
    Points: 6,208, Level: 18

    Join Date
    Feb 2015
    Posts
    1,020
    Helped
    287 / 287
    Points
    6,208
    Level
    18

    Re: UART Transmitter by FPGA

    index/count are variables local to each process. index/count in the first process are never used but are assigned. The are different from index/count declared in the second process.

    The need to hold start for 10k cycles is odd. It basically forces two stop bits. But that only affects bandwidth and not functionality.

    You would need to get inputs to this module, define the clock constraint, and define the IO placement for all of the external IO. If this module is intended to be the top level module you would also need to define where the inputs come from and where the output goes. It makes more sense to have a top level module that has your rs232 as a module. In that case you wouldn't need to connect done/showstates to external IO.

    If you have specific problems you should post them.

    --edit: also, for the two-process style of code you should place next_state <= present_state (and next_data <= data) before the case statement. this is a simple trick to avoid latches.

    More important, the count/index inside the second process only work in simulation. The expression x = x + 1 inside a combinatorial process doesn't make sense. in works in simulation because the sensitivity list prevents x from incrementing multiple times, but the synthesis tool ignores this.
    Last edited by vGoodtimes; 3rd August 2019 at 10:11.



    •   AltAdvertisement

        
       

  6. #6
    Super Moderator
    Points: 260,190, Level: 100
    Awards:
    1st Helpful Member

    Join Date
    Jan 2008
    Location
    Bochum, Germany
    Posts
    45,437
    Helped
    13824 / 13824
    Points
    260,190
    Level
    100

    Re: UART Transmitter by FPGA

    index/count are variables local to each process. index/count in the first process are never used but are assigned. The are different from index/count declared in the second process.
    Unfortunately index/count are incremented in a combination process without clock edge sensitivity condition. This "works" in a simulation as a side effect of the sensitivity list but not in real hardware because a counter without clock isn't synthesizable. You need to restructure your two process FSM.

    As for the original question "do I need a top module". The present code (if made synthesizable) can send a constant single character endlessly, but not output meaningful UART data. Your PC won't be able to receive the endlessly repeated character correctly without a preceeding pause.



--[[ ]]--