Receiving data from RS232, vhdl

1.7k Views Asked by At

I am using RS232 interface reference component from https://reference.digilentinc.com/reference/programmable-logic/nexys-2/start and an example code which is:

-------------------------------------------------------------------------
-- main.vhd
-------------------------------------------------------------------------
-- Author:  Dan Pederson
--          Copyright 2004 Digilent, Inc.
-------------------------------------------------------------------------
-- Description:     This file tests the included UART component by 
--                  sending data in serial form through the UART to
--                  change it to parallel form, and then sending the
--                  resultant data back through the UART to determine if
--                  the signal is corrupted or not.  When the serial 
--                  information is converted into parallel information, 
--                  the data byte is displayed on the 8 LEDs on the 
--                  system board.  
--
--                  NOTE:  Not all mapped signals are used in this test.
--                  The signals were mapped to ease the modification of
--                  test program.           
-------------------------------------------------------------------------
-- Revision History:
--      07/30/04 (DanP) Created
--      05/26/05 (DanP) Modified for Pegasus board/Updated commenting style
--      06/07/05    (DanP) LED scancode display added
-------------------------------------------------------------------------

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;

-------------------------------------------------------------------------
--
--Title:    Main entity
--
--Inputs:   3   :   RXD
--                  CLK
--                  RST
--
--Outputs:  1   :   TXD
--                  LEDS                    
--
--Description:  This describes the main entity that tests the included
--              UART component.   The LEDS signals are used to 
--              display the data byte on the LEDs, so it is set equal to 
--              the dbOutSig. Technically, the dbOutSig is the scan code 
--              backwards, which explains why the LEDs are mapped 
--              backwards to the dbOutSig.
--
-------------------------------------------------------------------------
entity DataCntrl is
    Port (  TXD     : out std_logic := '1';
            RXD     : in std_logic  := '1';
            CLK     : in std_logic;
            LEDS    : out std_logic_vector(7 downto 0) := "11111111";
            RST     : in std_logic  := '0');
end DataCntrl;

architecture Behavioral of DataCntrl is

-------------------------------------------------------------------------
-- Local Component, Type, and Signal declarations.                              
-------------------------------------------------------------------------

-------------------------------------------------------------------------
--
--Title:    Component Declarations
--
--Description:  This component is the UART that is to be tested.  
--              The UART code can be found in the included 
--              RS232RefComp.vhd file.
--
-------------------------------------------------------------------------
component RS232RefComp
   Port (   TXD     : out   std_logic   := '1';
            RXD     : in    std_logic;                  
            CLK     : in    std_logic;                          
            DBIN    : in    std_logic_vector (7 downto 0);
            DBOUT   : out   std_logic_vector (7 downto 0);
            RDA     : inout std_logic;                          
            TBE     : inout std_logic   := '1';             
            RD      : in    std_logic;                          
            WR      : in    std_logic;                          
            PE      : out   std_logic;                          
            FE      : out   std_logic;                          
            OE      : out   std_logic;                                          
            RST     : in    std_logic   := '0');                
end component;  
-------------------------------------------------------------------------
--
--Title:    Type Declarations
--
--Description:  There is one state machine used in this program, called 
--              the mainState state machine.  This state machine controls 
--              the flow of data around the UART; allowing for data to be
--              changed from serial to parallel, and then back to serial.
--
-------------------------------------------------------------------------
    type mainState is (
        stReceive,
        stSend);
-------------------------------------------------------------------------
--
--Title:  Local Signal Declarations
--
--Description:  The signals used by this entity are described below:
--
--              -dbInSig    :   This signal is the parallel data input  
--                              for the UART
--              -dbOutSig   :   This signal is the parallel data output 
--                              for the UART
--              -rdaSig     :   This signal will get the RDA signal from 
--                              the UART
--              -tbeSig     :   This signal will get the TBE signal from 
--                              the UART
--              -rdSig      :   This signal is the RD signal for the UART
--              -wrSig      :   This signal is the WR signal for the UART
--              -peSig      :   This signal will get the PE signal from 
--                              the UART
--              -feSig      :   This signal will get the FE signal from 
--                              the UART
--              -oeSig      :   This signal will get the OE signal from 
--                              the UART
--
--              The following signals are used by the main state machine
--              for state control:
--              
--              -stCur, stNext  
--  
-------------------------------------------------------------------------
    signal dbInSig  :   std_logic_vector(7 downto 0);
    signal dbOutSig :   std_logic_vector(7 downto 0);
    signal rdaSig   :   std_logic;
    signal tbeSig   :   std_logic;
    signal rdSig    :   std_logic;
    signal wrSig    :   std_logic;
    signal peSig    :   std_logic;
    signal feSig    :   std_logic;
    signal oeSig    :   std_logic;

    signal stCur    :   mainState := stReceive;
    signal stNext   :   mainState;

------------------------------------------------------------------------
-- Module Implementation
------------------------------------------------------------------------

begin

------------------------------------------------------------------------
--
--Title:    LED definitions
--
--Description:  This series of definitions allows the scan code to be
--              displayed on the LEDs on the FPGA system board.  Because the
--              dbOutSig is the scan code backwards, the LEDs must be
--              defined backwards from the dbOutSig.
--
------------------------------------------------------------------------
    LEDS(7) <= dbOutSig(0);
    LEDS(6) <= dbOutSig(1);
    LEDS(5) <= dbOutSig(2);
    LEDS(4) <= dbOutSig(3);
    LEDS(3) <= dbOutSig(4);
    LEDS(2) <= dbOutSig(5);
    LEDS(1) <= dbOutSig(6);
    LEDS(0) <= dbOutSig(7);
-------------------------------------------------------------------------
--
--Title:        RS232RefComp map
--
--Description:  This maps the signals and ports in main to the 
--              RS232RefComp.  The TXD, RXD, CLK, and RST of main are
--              directly tied to the TXD, RXD, CLK, and RST of the 
--              RS232RefComp.  The remaining RS232RefComp ports are 
--              mapped to internal signals in main.
--
-------------------------------------------------------------------------
    UART: RS232RefComp port map (   TXD     => TXD,
                                    RXD     => RXD,
                                    CLK     => CLK,
                                    DBIN    => dbInSig,
                                    DBOUT   => dbOutSig,
                                    RDA     => rdaSig,
                                    TBE     => tbeSig,  
                                    RD      => rdSig,
                                    WR      => wrSig,
                                    PE      => peSig,
                                    FE      => feSig,
                                    OE      => oeSig,
                                    RST     => RST);
-------------------------------------------------------------------------
--
--Title: Main State Machine controller 
--
--Description:  This process takes care of the Main state machine 
--              movement.  It causes the next state to be evaluated on 
--              each rising edge of CLK.  If the RST signal is strobed, 
--              the state is changed to the default starting state, which 
--              is stReceive.
--
-------------------------------------------------------------------------
    process (CLK, RST)
        begin
            if (CLK = '1' and CLK'Event) then
                if RST = '1' then
                    stCur <= stReceive;
                else
                    stCur <= stNext;
                end if;
            end if;
        end process;
-------------------------------------------------------------------------
--
--Title: Main State Machine 
--
--Description:  This process defines the next state logic for the Main
--              state machine.  The main state machine controls the data
--              flow for this testing program in order to send and 
--              receive data.
--
-------------------------------------------------------------------------
    process (stCur, rdaSig, dboutsig)
        begin
            case stCur is
-------------------------------------------------------------------------
--
--Title: stReceive state 
--
--Description:  This state waits for the UART to receive data.  While in
--              this state, the rdSig and wrSig are held low to keep the
--              UART from transmitting any data.  Once the rdaSig is set
--              high, data has been received, and is safe to transmit. At
--              this time, the stSend state is loaded, and the dbOutSig 
--              is copied to the dbInSig in order to transmit the newly
--              acquired parallel information.
--
-------------------------------------------------------------------------   
                when stReceive =>
                    rdSig <= '0';
                    wrSig <= '0';

                    if rdaSig = '1' then
                        dbInSig <= dbOutSig;
                        stNext <= stSend;
                    else
                        stNext <= stReceive;
                    end if;         
-------------------------------------------------------------------------
--
--Title: stSend state 
--
--Description:  This state tells the UART to send the parallel 
--              information found in dbInSig.  It does this by strobing 
--              both the rdSig and wrSig signals high.  Once these 
--              signals have been strobed high, the stReceive state is 
--              loaded.
--
-------------------------------------------------------------------------
                when stSend =>
                    rdSig <= '1'; 
                    wrSig <= '1';

                    stNext <= stReceive;
            end case;
        end process;
end Behavioral;

On the basis of above code,I am trying to make my own state machine that allows me to receive few bytes from a terminal in a row to a buffer, change the state and send this bytes from a buffer to a terminal on my PC. I've started from making counter that counts the amounts of the received bytes. I ended up not knowing what is going on, because the counter changes its value not by one but randomly. I am new to VHDL and any suggestions will be appreciated.

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.STD_LOGIC_ARITH.ALL;
use IEEE.STD_LOGIC_UNSIGNED.ALL;
use IEEE.NUMERIC_STD.ALL;

entity DataCntrl is
    Port (  TXD     : out std_logic := '1';
            RXD     : in std_logic  := '1';
            CLK     : in std_logic;
            LED : out std_logic_vector(7 downto 0) := "00000000";
            RST     : in std_logic  := '0');
end DataCntrl;

architecture Behavioral of DataCntrl is


component RS232RefComp
   Port (   TXD     : out   std_logic   := '1';
            RXD     : in    std_logic;                  
            CLK     : in    std_logic;                          
            DBIN    : in    std_logic_vector (7 downto 0);
            DBOUT   : out   std_logic_vector (7 downto 0);
            RDA     : inout std_logic;                          
            TBE     : inout std_logic   := '1';             
            RD      : in    std_logic;                          
            WR      : in    std_logic;                          
            PE      : out   std_logic;                          
            FE      : out   std_logic;                          
            OE      : out   std_logic;                                          
            RST     : in    std_logic   := '0');                
end component;  

    type mainState is (
        stReceive, stA, 
        stRereceive);

    signal dbInSig  :   std_logic_vector(7 downto 0);
    signal dbOutSig :   std_logic_vector(7 downto 0);
    signal rdaSig   :   std_logic;
    signal tbeSig   :   std_logic;
    signal rdSig    :   std_logic;
    signal wrSig    :   std_logic;
    signal peSig    :   std_logic;
    signal feSig    :   std_logic;
    signal oeSig    :   std_logic;

    signal stCur    :   mainState := stReceive;
    signal stNext   :   mainState;


begin


    UART: RS232RefComp port map (   TXD     => TXD,
                                    RXD     => RXD,
                                    CLK     => CLK,
                                    DBIN    => dbInSig,
                                    DBOUT   => dbOutSig,
                                    RDA     => rdaSig,
                                    TBE     => tbeSig,  
                                    RD      => rdSig,
                                    WR      => wrSig,
                                    PE      => peSig,
                                    FE      => feSig,
                                    OE      => oeSig,
                                    RST     => RST);

    process (CLK, RST)
        begin
            if (CLK = '1' and CLK'Event) then
                if RST = '1' then
                    stCur <= stReceive;
                else
                    stCur <= stNext;
                end if;
            end if;
        end process;

    process (stCur, rdaSig, dboutsig)
    variable Send: std_logic :='0';
    variable Count: integer  :=0;
        variable Jol: integer  :=0;
        begin
        Jol:=Count;
        Led<=std_logic_vector(to_unsigned(Jol,8));
            case stCur is

                when stReceive =>
                    rdSig <= '0';
                    wrSig <= '0';

                    if rdaSig = '1' then
                    Send:='0';
                        dbInSig <= dbOutSig;
                    if(Count=4) then
                        dbInSig <= "11101111";
                    stNext <= stA;

                        else
                        stNext <= stRereceive;
                        end if;
                    else
                        stNext <= stReceive;
                    end if;         

                when stRereceive =>
                    rdSig <= '1'; 
                    if(Send='0') then
                    Count:=Count+1;
                    Send:='1';
                    end if;
                    stNext <= stReceive;

                when stA=>
                    wrSig <= '1';
                    rdSig <= '1'; 


            end case;
        end process;
end Behavioral;
1

There are 1 best solutions below

0
On

So, take a look at your counter increment code:

process (stCur, rdaSig, dboutsig)
    [...]
    variable Count: integer := 0;
begin
    [...]
    case stCur is
        [...]
        when stRereceive =>
            [...]
            if(Send='0') then
                Count:=Count+1;

Let's analyse what we see here.

  1. count is a variable.
  2. count is increased in a combinatorial process.

[let's leave out that your sensitivity list is incomplete]

When you say "the counter changes its value not by one", I assume you want it to increase by one every clock cycle (or comparable). But to be able to increase over a previous value, the counter must hold that previous value. That means registers are required. However, registers required a clock input. So in a clock-less combinatorial process no registers are inferred.

Then: don't use variables for registered values. There are only very little situations in which you should use variables, and this is not one of them.

Here's an example of a clocked counter process

architecture rtl of ent is
    signal count : unsigned(3 downto 0) := (others => '0');
begin
    clk_proc : process (clk)
    begin
        if rising_edge(clk) then
            if [condition] then
                count <= count + 1;
            end if;
            if reset = '1' then
                count <= (others => '0');
            end if;
        end if;
    end process;