在VHDL中的Mealy机器1011检测器

时间:2014-12-18 05:14:29

标签: vhdl

我为Mealy机器编写了一个VHDL程序,可以检测模式1011,如下所示:

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;

并将.do模拟为以下

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

但是,我的模拟结果并不正确。你能帮我解决这个问题吗?谢谢! enter image description here

2 个答案:

答案 0 :(得分:3)

您不断从似乎认为result出现问题的人那里得到答案。

问题是dataclk不同步。你在整个地方都有过渡,粉状输出正在做它应该做的事情。

它是组合输出,不应用作时钟。它可以用作clk上运行的寄存器的使能或输入。

对于我们这些没有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;

它给出了与模拟相同的答案:

mealy_1011_tb.png (点击)

您不希望在result上看到额外的延迟,使data时钟同步。你的状态机正在做它应该做的事情。

如果data是时钟同步的,您可以使用result使用clknot clk nand result并生成结果事件时钟。

答案 1 :(得分:0)

您只需将Mealy输出写入流程的if-then-else转换分支。

NEXTSTATE: PROCESS(data, current_state)
BEGIN
    -- default assignments
    next_state <= state;       -- so your code won't create latches
    result     <= '0';         -- result is always 0, except of transition GOT101 to GOT1

    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
                result     <= '1';
                next_state <= GOT1;
            ELSE 
                next_state <= GOT10;
            END IF;
        WHEN OTHERS => NULL;
    END CASE;
END PROCESS NEXTSTATE;