There are several issues with your code. My rewritten version is below.
The main problem is that your code was that the assignment of Z was incorrect. The next problem was that the state machine itself was incorrect. As it was written, Z should have gone high after a pattern of "11", and not "110". It also would have gotten stuck in state S2 and not recovered.
I should also mention that there were several "stylistic" issues with your code too. Having two processes instead of one was a major one. I cleaned up that as well. This allowed for having only a single state signal, which makes the whole thing more readable as well.
library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
entity checker is
Port ( clk : in STD_LOGIC;
x : in STD_LOGIC;
z : out STD_LOGIC);
end checker;
architecture Behavioral of checker is
type state_type is (S0, S1, S2);
signal state: state_type := S0;
begin
process(clk)
begin
if rising_edge(clk) then
case state is
when S0 =>
z <= '0';
if x='1' then
state <= S1;
else
state <= S0;
end if;
when S1 =>
z <= '0';
if x = '1' then
state <= S2;
else
state <= S1; -- S1, not S0 because we also want to detect a "111...1110"
end if;
when S2 =>
if x = '0' then
state <= S0;
z <= '1'; -- Z='1' only when a match is made
else
state <= S0; -- Goes back to S0 to detect the next pattern
z <= '0';
end if;
when others =>
z <= '0';
state <= S0; -- In case the state machine is in an invalid state
end case;
end if;
end process;
end Behavioral;
Update: Here's a rewritten testbench:
library ieee;
use ieee.std_logic_1164.all;
entity testbench is
end testbench;
architecture arch_testbench of testbench is
component checker
port (clk :in std_logic;
x :in std_logic;
z :out std_logic);
end component;
signal clk :std_logic := '1';
signal x :std_logic := '0';
signal z :std_logic := '0';
signal sr :std_logic_vector (15 downto 0) := "0001100011111110";
begin
process (clk)
begin
if clk='1' then
clk <= '0' after 5.0 ns, '1' after 10 ns;
end if;
end process;
process (clk)
begin
if rising_edge(clk) then
sr <= sr(sr'high-1 downto 0) & "0";
end if;
end process;
x <= sr(sr'high);
UUT: checker
port map (clk, x, z);
end arch_testbench;
A FSM is a sequential piece of circuitry, and functions are combinational only, so a function cannot represent by itself a FSM. However, the combinational paths of the FSM can be represented with functions. Typical examples are coding the next state or the outputs based on the current state and inputs. It is a very clean way of coding a FSM.
A procedure, on the other hand, can contain sequential statements, but when they do they are mostly used for testbenches using wait
statements, which are not synthesizable.
Best Answer
Unclear what you are trying to achieve.
First, it seems like an odd restriction for Quartus to restrict state types to enumerations instead of other discrete types like integer or unsigned. But...
Do you really have 231 discrete states?
Or is range 34 to 50 a single state?
If you need to remain in that state for 17 separate events, consider a state and a separate counter. You could implement that as a pattern similar to a state machine with multiple delays.
If you need to translate a numeric input to a state, write a
to_state(int)
function returning your enumeration type.If there is similarity between groups of states, you might look at a hierarchical state machine or even decompose the state machine into one central SM controlling several others via handshaking.
EDIT from the relevant manual section aaah...
So you can use another discrete type like a ranged Natural, and it'll synthesise, probably to the same logic, you just don't get the nice report. I'd be tempted do that (write it in the most natural style) just to use the (speed/size) results as a benchmark to compare with the "Altera approved" style.
Project or company coding style rules may prohibit that, or require the pretty report artefact for verification, so I'm not pushing this as a solution, just as a way to calibrate the "official" solution ... possibly as a golden model for simulation (verify both SMs remain in step).