Forum Discussion
State machine counter problems
I do not understand why my state machine does absolutely nothing. Can anyone identify why? It seems simple enough to me, 4 states that have three possibilities based on two inputs (2 state changes and 1 no state change), and upon changing states increment or decrement one of 8 counters (variables) then assign these variables to out ports. The simulation outputs nothing. This is the first state machine I have written.
Thanks so much!library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.numeric_std.ALL;
entity pmodcounter is
Port (Ain, Bin : in STD_LOGIC;
reset : in STD_LOGIC;
out12, out23, out34, out41, out43, out32, out21, out 14 : out unsigned(25 downto 0));
end pmodcounter;
architecture Behavioral of pmodcounter is
type states is (st1, st2, st3, st4);
signal present_state, next_state: states;
begin
process (reset,clk)
begin
if (reset='1') then
present_state <= st1;
elsif rising_edge(clk) then
present_state <= next_state;
end if;
end process;
process (Ain, Bin, present_state)
-- Counting variables
variable c12, c23, c34, c41, c43, c32, c21, c14: unsigned(25 downto 0):="01000000000000000000000000";
begin
case present_state is
when st1=>
if (Ain='0' and Bin='1') then
c12:=c12+1;
next_state <= st2;
elsif (Ain='1' and Bin='0') then
c14:=c14-1;
next_state <= st4;
else
end if;
when st2=>
if (Ain='1' and Bin='1') then
c23:=c23+1;
next_state <= st3;
elsif (Ain='0' and Bin='0') then
c21:=c21-1;
next_state <= st1;
else
end if;
when st3=>
if (Ain='1' and Bin='0') then
c34:=c34+1;
next_state <= st4;
elsif (Ain='0' and Bin='1') then
c32:=c32-1;
next_state <= st2;
else
end if;
when st4=>
if (Ain='0' and Bin='0') then
c41:=c41+1;
next_state <= st1;
elsif (Ain='1' and Bin='1') then
c43:=c43-1;
next_state <= st3;
else
end if;
end case;
out12<=c12;
out23<=c23;
out34<=c34;
out41<=c41;
out43<=c43;
out32<=c32;
out21<=c21;
out14<=c14;
end process;
end behavioral;
3 Replies
- Altera_Forum
Honored Contributor
There are several things wrong here:
1. Because of the way VHDL works, your outputs will only change when Ain, Bin or present_state actually change. Be warned - the way you have your circuit will mean that the code will behave differently to hardware. 2. How would you expect the counters to work. Your code implies that the counters should add one when conditions are met - but they will keep adding 1 in a feedback loop. You need to move the counters to a clocked process to actually work as expected. - Altera_Forum
Honored Contributor
Thank you, this gives me material to think about for sure. Given my signal I thought it would trigger counts and restrict any loop counts. I changed the code to change states on edges of my signal, but now my variables depend on multiple clock edges. My signal will always look like what is shown, two square waves with a 90 degree phase difference (50% duty cycle, varying period, and process can reverse in time). This is a piece of scientific instrumentation that is fundamentally asynchronous so it would be nice to avoid a master clock and only depend on these two inputs (blasphemous or not).
https://alteraforum.com/forum/attachment.php?attachmentid=14226&stc=1
--- Quote Start --- There are several things wrong here: 1. Because of the way VHDL works, your outputs will only change when Ain, Bin or present_state actually change. Be warned - the way you have your circuit will mean that the code will behave differently to hardware. 2. How would you expect the counters to work. Your code implies that the counters should add one when conditions are met - but they will keep adding 1 in a feedback loop. You need to move the counters to a clocked process to actually work as expected. --- Quote End ---process (Ain, Bin, present_state) -- Counting variables variable c12, c23, c34, c41, c43, c32, c21, c14: unsigned(25 downto 0):="01000000000000000000000000"; begin case present_state is when st1=> if (rising_edge(Bin)) then c12:=c12+1; next_state <= st2; elsif (rising_edge(Ain)) then c14:=c14-1; next_state <= st4; else next_state <= st1; end if; when st2=> if (rising_edge(Ain)) then c23:=c23+1; next_state <= st3; elsif (falling_edge(Bin)) then c21:=c21-1; next_state <= st1; else next_state <= st2; end if; when st3=> if (falling_edge(Ain)) then c34:=c34+1; next_state <= st4; elsif (falling_edge(Bin)) then c32:=c32-1; next_state <= st2; else next_state <= st3; end if; when st4=> if (falling_edge(Ain)) then c41:=c41+1; next_state <= st1; elsif (rising_edge(Bin)) then c43:=c43-1; next_state <= st3; else next_state <= st4; end if; end case; out12<=c12; out23<=c23; out34<=c34; out41<=c41; out43<=c43; out32<=c32; out21<=c21; out14<=c14; end process; - Altera_Forum
Honored Contributor
Your code will not compile. Apart from 2 clocks, they are not the outermost part of the process.
You really need to do 2 things. First of all, draw your circuit out on paper. Without knowing what your circuit should be, you shouldn't be writing HDL. Second, using that circuit, read up on how to code those components.