1
\$\begingroup\$

I have been trying to design an RS-232 receiver taking an FSM approach. I will admit that I do not have a very well-rounded understanding of VHDL, so I have been working on the code on the fly and learning as I go. However, I believe I've hit a brick wall at this point.

My issue is that I have two processes in my code, one to trigger the next state and the other to perform the combinational logic. My code is as follows:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;

entity ASyncReceiverV4 is
Port ( DataIn : in  STD_LOGIC;
              Enable : in STD_LOGIC;
           CLK : in  STD_LOGIC;
              BadData : out STD_LOGIC;
           DataOut : out  STD_LOGIC_VECTOR (7 downto 0));
end ASyncReceiverV4;

architecture Behavioral of ASyncReceiverV4 is

type states is (StartBitCheck, ReadData, StopBitCheck);
signal currentState, nextState : states;

begin

    process(CLK)
    begin
        if rising_edge(CLK) then
            currentState <= nextState;
        end if;
    end process;

    process(CLK)
    variable counter : integer := 0;
    variable dataIndex : integer := 0;
    begin
            case currentState is

                when StartBitCheck =>
                    if Enable = '1' then
                        if (DataIn = '0' and counter < 8)  then
                            counter := counter + 1;
                        elsif (DataIn = '0' and counter = 8) then
                            BadData <= '0';
                            nextState <= ReadData;
                            counter := 0;
                        else 
                            nextState <= StartBitCheck;
                        end if;
                    end if;

                when ReadData =>
                    if Enable = '1' then
                        if counter < 16 then
                            counter := counter + 1;
                        elsif (counter = 16 and dataIndex < 8) then
                            DataOut(dataIndex) <= DataIn;
                            counter := 0;
                            dataIndex := dataIndex + 1;
                        elsif dataIndex = 8 then
                            dataIndex := 0;
                            nextState <= StopBitCheck;
                        else
                            nextState <= ReadData;
                        end if;
                    end if;

                when StopBitCheck =>
                    if Enable = '1' then
                        if DataIn = '1' then
                            if counter < 16  then
                                counter := counter + 1;
                                nextState <= StopBitCheck;                          
                            elsif counter = 16 then
                                counter := 0;
                                nextState <= StartBitCheck;                         
                            end if;
                        else
                            DataOut <= "11111111";
                            BadData <= '1';
                            nextState <= StartBitCheck;
                        end if;
                    end if;

            end case;

    end process;


end Behavioral;

For whatever reason, based on my simulations, it seems that my processes are out of sync. Although things are only supposed to occur at the rising edge of the clock, I have transitions occurring at the falling edge. Furthermore, it seems like things are not changing according to the value of counter.

The Enable input is high in all of my simulations. However, this is just to keep it simple for now, it will eventually be fed the output of a 153,600 Baud generator (the Baud generator will be connected to the Enable input). Hence, I only want things to change when my Baud generator is high. Otherwise, do nothing. Am I taking the right approach for that with my code?

I can supply a screenshot of my simulation if that would be helpful. I am also not sure if I am including the correct variables in my process sensitivity list. Also, am I taking the right approach with my counter and dataIndex variables? What if I made them signals as part of my architecture before any of my processes?

Any help on this would be very much so appreciated!

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

First, use the correct terminology: RS-232 refers to an electrical specification (voltage and current levels) and has nothing to do with whatever communications protocol you might be using. What you're implementing is an "asynchronous serial receiver".

In your code, the second process lists only CLK in its sensitivity list, but it is not in fact a clocked process. The simulator is taking you at your word, however, and evaluating that process on every clock edge. Instead, this process should list all of the input signals, such as currentState, Enable and DataIn, that affect the next state.

Furthermore, you have variables in that second process (counter, dataIndex) that appear to be state variables that should only be updated on clock edges. These variables should be moved to the first process.

\$\endgroup\$
3
  • \$\begingroup\$ Thank you for the input! How would I go about moving my variables into the first process though? If I were to simply move the declaration of the variables to the first process, then they won't be recognized properly in the second. . . Are you recommending to rewrite the first proc to involve counter and dataIndex? \$\endgroup\$
    – coolDude
    Nov 24, 2014 at 2:57
  • \$\begingroup\$ Or should I have counter and dataIndex as signals underneath the Architecture statement? \$\endgroup\$
    – coolDude
    Nov 24, 2014 at 3:57
  • \$\begingroup\$ Yes, you need to move both the declarations and any of the code that affects them to the other process. \$\endgroup\$
    – Dave Tweed
    Nov 24, 2014 at 12:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.