Search code examples
vhdl

Mealy machine 1011 detector in VHDL


I write a VHDL program for Mealy machine that can detect the pattern 1011 as the following:

LIBRARY ieee;
USE ieee.std_logic_1164.all;

ENTITY mealy_detector_1011 IS
    PORT(
        rst_n   : IN STD_LOGIC;
        clk     : IN STD_LOGIC;
        data    : IN STD_LOGIC;
        result  : OUT STD_LOGIC);
END ENTITY;

ARCHITECTURE beh OF mealy_detector_1011 IS
    TYPE state IS (IDLE, GOT1, GOT10, GOT101);
    SIGNAL current_state : state;
    SIGNAL next_state   : state;
BEGIN
    REG: PROCESS(clk, rst_n)
    BEGIN
        IF rst_n = '0' THEN
            current_state <= IDLE;
        ELSIF rising_edge(clk) THEN
            current_state <= next_state;
        END IF;
    END PROCESS REG;

    NEXTSTATE: PROCESS(data, current_state)
    BEGIN
        CASE current_state IS
            WHEN IDLE =>
                IF data = '1' THEN
                    next_state <= GOT1;
                ELSE next_state <= IDLE;
                END IF;
            WHEN GOT1 =>
                IF data = '0' THEN
                    next_state <= GOT10;
                ELSE next_state <= GOT1;
                END IF;
            WHEN GOT10 =>
                IF data = '1' THEN
                    next_state <= GOT101;
                ELSE next_state <= IDLE;
                END IF;
            WHEN GOT101 =>
                IF data = '1' THEN
                    next_state <= GOT1;
                ELSE 
                    next_state <= GOT10;
                END IF;
            WHEN OTHERS => NULL;
        END CASE;
    END PROCESS NEXTSTATE;
    result <= '1' WHEN (current_state = GOT101 and data = '1') ELSE '0';
END beh;

and file .do to simulating as the following

vcom mealy_detector_1011.vhd
vsim mealy_detector_1011
add wave -r /*
force -freeze /clk 1 0, 0 50 -r 100
force -freeze /rst_n 0 0, 1 10
force -freeze /data 0 0, 1 80, 0 180, 1 230, 0 330, 1 470, 0 530, 1 570, 0 620
run 800 ns

However, my simulation result isn't correct. Can you help me solve this problem? Thank you! enter image description here


Solution

  • You keep getting answers from people who seem to perceive a problem with result.

    The issue is that data is not synchronous to clk. You have transitions all over the place, the mealy output is doing exactly what's it's supposed to do.

    It's a combinatorial output and shouldn't be used as a clock. It can be used as an enable or an input to a register operating on clk.

    Here's a test bench for those of us without Modelsim:

    library ieee;
    use ieee.std_logic_1164.all;
    
    entity mealy_1011_tb is
    end entity;
    
    architecture foo of mealy_1011_tb is
        signal rst_n:     std_logic := '0';
        signal  clk:      std_logic := '1';
        signal  data:     std_logic := '0';
        signal  result:   std_logic;
    begin
    DUT:
        entity work.mealy_detector_1011
        port map (
            rst_n => rst_n,
            clk => clk,
            data => data,
            result => result
        );
    CLOCK:
        process
        begin
            wait for 50 ns;
            clk <= not clk;
            if Now > 799 ns then
                wait;
            end if;
        end process;
    STIMULUS:
        process
        begin
            wait for 10 ns;
            rst_n <= '1';
            wait for 70 ns;   
            data <= '1';     --  80 ns
            wait for 100 ns;
            data <= '0';     -- 180 ns
            wait for 50 ns;
            data <= '1';     -- 230 ns
            wait for 100 ns;
            data <= '0';     -- 330 ns
            wait for 140 ns;
            data <= '1';     -- 470 ns
            wait for 60 ns;
            data <= '0';     -- 530 ns
            wait for 40 ns;   
            data <= '1';     -- 570 ns
            wait for 50 ns;
            data <= '0';     -- 620 ns
            wait;
        end process;
    end architecture;
    

    And it gives the same answer as your simulation:

    mealy_1011_tb.png (clickable)

    You don't want to see the extra dip on result, make data clock synchronous. Your statemachine is doing exactly what's it's supposed to.

    And if data were clock synchronous you could gate result with clk using not clk nand result and produce a result event clock.