FSM Using Excitation Equations and VHDL

I have been trying to create a FSM using the excitation equations I developed. I have not had much luck. The circuit has no output.

I DO NOT WANT TO USE 'TYPE' and custom state types. That is the easy way out. Please don't tell me that's what you would do! Its probably what I would do too. I am trying to force myself to learn new methods.

Below you will find my process for the sequence "2314". I set up my DE2 so the push buttons were each assigned a number, ie X(0) is push-button 0 or number "1".

I found out the program would need 5 states (3 FF) using a Moore machine. If there is no input on the state ("0000") then the input should hold. I decided to use D flip flops for this experiment for ease of transitions. Turns out its not so straight forward! Thanks for your help.

My equations for the D flip flops are as follows (derived from state diagram/ transition table) They may not be simplified completely, sorry!

d0 = Q2'.Q0'.(X1.Q1'+ X2.Q1)

d1 = Q2'.(X2'Q1.Q0' + X3.Q1'.Q0)

d2 = x0.Q2'.Q1.Q0

z = Q2.Q1'.Q0'

You will find the VHDL code below. The component is also shown below. The current VHDL file is just one of my many failed attempts. The simulation does not have an output, therefor z is a constant '0'.

library ieee;
use ieee.std_logic_1164.all;

entity sequencedetecttwo is

port (
x : in std_logic_vector (3 downto 0);
clk : in std_logic;
z : out std_logic
);

end entity sequencedetecttwo;

architecture arch of sequencedetecttwo is

signal q : std_logic_vector (2 downto 0);
signal d : std_logic_vector (2 downto 0);

component dflipflop is

port (
clk, d : in std_logic;
q : out std_logic
);

end component;

BEGIN

dff0 : dflipflop port map (clk => clk, d => d(0));
dff1 : dflipflop port map (clk => clk, d => d(1));
dff2 : dflipflop port map (clk => clk, d => d(2));

p0 : PROCESS(clk, q)

BEGIN

d(0) <= q(0);
d(1) <= q(1);
d(2) <= q(2);

IF (clk'EVENT AND clk = '1') THEN

q(0) <= not q(2) and not q(0) and ((x(1) and not q(1)) or (x(2) and q(1)));
q(1) <= not q(2) and ((not x(2) and q(1) and not q(0)) or (x(3) and not q(1) and q(0)));
q(2) <= x(0) and not q(2) and q(1) and q(0);

END IF;

END PROCESS p0;

z <= q(2) and not q(1) and not q(0);

END ARCHITECTURE arch;


And the flip flop component:

library ieee;
use ieee.std_logic_1164.all;

entity dflipflop is

port (
clk, d : in std_logic;
q : out std_logic
);
end entity dflipflop;

architecture arch of dflipflop is

begin

p0 : process (clk)

begin

if (clk'event and clk = '1') then

q <= d;

end if;
end process;
end architecture arch;

-

I'd use TYPE and ENUM! Ok, mostly I said that to make a point. And that point is that there are things in VHDL that make the code easier to read and figure out what is going on. The way your code is, it's almost unreadable. I certainly can't tell you exactly what's wrong, although I can find lots of things wrong. Before you start trying to do things the hard way, you should perfect doing things the easy way.

That being said, here are some things I found wrong. These are almost certainly not your main problem, but we might as well start somewhere...

1. Your instantiation of the D-Flip-Flops is wrong. You didn't specify where the outputs of the FF's goes. I'm actually surprised that the VHDL compiler let you get away with that.

2. You did not assign an initial value to signals d or q. This could be putting your state machine into an invalid state at startup. Even if it isn't, this is bad practice.

3. The lines "d(x) <= q(x);" in the first part of your process isn't great practice either. While technically OK, it will slow down simulations and on some older compilers will generate bad logic or just not compile at all. In the context of your code, these lines could just be deleted since you don't use d() anywhere. While you're at it, remove "q" from the sensitivity list.

4. Instead of saying "IF (clk'EVENT AND clk = '1') THEN", use "if rising_edge(clk) then". This is clearer, and works better for simulations in some cases.

Once you remove all of the useless code, your entire code can be reduced to something quite small. Here it is in its entirity:

library ieee;
use ieee.std_logic_1164.all;

entity sequencedetecttwo is
port (
x   :in  std_logic_vector (3 downto 0);
clk :in  std_logic;
z   :out std_logic
);
end entity sequencedetecttwo;

architecture arch of sequencedetecttwo is
signal q : std_logic_vector (2 downto 0) := (others=>'0');
signal d : std_logic_vector (2 downto 0) := (others=>'0');
begin

p0 : process(clk)
begin
if rising_edge(clk) then
q(0) <= not q(2) and not q(0) and ((x(1) and not q(1)) or (x(2) and q(1)));
q(1) <= not q(2) and ((not x(2) and q(1) and not q(0)) or (x(3) and not q(1) and q(0)));
q(2) <= x(0) and not q(2) and q(1) and q(0);
end if;
end process p0;

z <= q(2) and not q(1) and not q(0);
end architecture arch;


That being said, I still don't know why it doesn't work properly. And honestly, I'm not super excited to figure it out (just because you want to do it the hard way doesn't mean that I do too). But hopefully by clearing up the code a little you can better see what it's doing and why it might not be what you intended.

-
Thanks @David Kessner I will go through your corrections now and give it another go. You are definitely right about the perfection thing. The main problem I face is the fact that VHDL has a million different ways to do one task. The language doesn't seem to be as organized as say Java. Every VHDL text I pick up shows the same problem a different way! It can be a bit discouraging. Can you recommend a solid book? I will be sure to keep you posted on any improvements that I make. I will not code another VHDL file until I get this one to work!! –  atomSmasher Dec 25 '11 at 3:20
Ohhhhh boy. I think you will be excited to hear this.... When I simplified my expressions I accidentally added a NOT onto my X2 term. That mistake was crucial! Dropping the d signal also helped! I checked those equations three times, I can't believe I missed it. Oh well. Thanks for your help. –  atomSmasher Dec 25 '11 at 5:31