为什么我用 VHDL 编写的 Mealy FSM 最后会卡在错误的状态?

问题描述 投票:0回答:1

我正在制作一台饮料自动售货机,其输入为:clk、reset、leu1(1 种货币)、lei5(5 种货币)、10lei(10 种货币)、3 个产品输入:product_3lei(花费 3 种货币)、 Product_5lei(花费 5 货币)、product_7lei(花费 7 货币)和一个要求找零的输入:cerere_rest。它有 3 种状态:累积,它接受最多 10 个最大余额的现金输入;分配,在一个周期内它只发出分配的信号;以及最终确定,在有人要求找零后它会去哪里。首先以尽可能多的 5 列伊钞票形式给出,然后尽可能多地以 1 列伊钞票形式给出,然后当余额为 0 时,它会返回到累积阶段。至少应该是这样。它陷入了最后阶段,看起来 1leu_rest 不断自行触发。我必须将这两个进程分开。这是VHDL代码和仿真图片:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity AutomatBauturi is
    Port (
        clk          : in  std_logic;
        reset        : in  std_logic;
        leu1         : in  std_logic;
        lei5         : in  std_logic;
        lei10        : in  std_logic;
        product_3lei : in  std_logic;
        product_5lei : in  std_logic;
        product_7lei : in  std_logic;
        cerere_rest  : in  std_logic;
        produs       : out std_logic;
        leu1_rest    : out std_logic;
        lei5_rest    : out std_logic;
        respingere   : out std_logic
    );
end AutomatBauturi;

architecture Behavioral of AutomatBauturi is

    -- States
    type state_type is (Accumulating, Dispensing, Finalizing);
    signal current_state, next_state : state_type;

    -- Internal signals
    signal product_price   : integer := 0; -- Stores the product price
    signal balance : integer := 0;
begin

    -- State Transition and Register Update Process
    process(clk, reset)
    begin
        if reset = '1' then
            current_state <= Accumulating;
        elsif rising_edge(clk) then
            current_state <= next_state;
        end if;
    end process;

    -- Combinational Process for FSM Logic
    process(current_state, leu1, lei5, lei10, product_3lei, product_5lei, product_7lei, cerere_rest)
    begin
        -- Default output values
        produs <= '0';
        leu1_rest <= '0';
        lei5_rest <= '0';
        respingere <= '0';
        next_state <= current_state;

        case current_state is
            -- State: Accumulating
            when Accumulating =>
                -- Handle money inputs
                if leu1 = '1' then
                    if balance + 1 > 10 then
                        respingere <= '1';
                    else
                        balance <= balance + 1;
                    end if;
                elsif lei5 = '1' then
                    if balance + 5 > 10 then
                        respingere <= '1';
                    else
                        balance <= balance + 5;
                    end if;
                elsif lei10 = '1' then
                    if balance + 10 > 10 then
                        respingere <= '1';
                    else
                        balance <= balance + 10;
                    end if;
                -- Handle product requests
                elsif product_3lei = '1' then
                    if balance >= 3 then
                        balance <= balance - 3;
                        next_state <= Dispensing;
                    end if;
                elsif product_5lei = '1' then
                    if balance >= 5 then
                        balance <= balance - 5;
                        next_state <= Dispensing;
                    end if;
                elsif product_7lei = '1' then
                    if balance >= 7 then
                        balance <= balance - 7;
                        next_state <= Dispensing;
                    end if;
                elsif cerere_rest = '1' then
                    next_state <= Finalizing;
                end if;

            -- State: Dispensing
            when Dispensing =>
                produs <= '1'; -- Activate product output
                next_state <= Accumulating; -- Return to Accumulating after one cycle

            -- State: Finalizing
            when Finalizing =>
                -- Dispense rest in 5 lei and 1 leu notes
                if balance >= 5 then
                    lei5_rest <= '1';
                    balance <= balance - 5;
                elsif balance >= 1 then
                    leu1_rest  <= '1';
                    balance <= balance - 1;
                else
                    next_state <= Accumulating;
                end if;
        end case;
    end process;

end Behavioral;

这是我正在使用的测试平台:

library IEEE;
use IEEE.STD_LOGIC_1164.ALL;
use IEEE.NUMERIC_STD.ALL;

entity AutomatBauturi_tb is
end AutomatBauturi_tb;

architecture Behavioral of AutomatBauturi_tb is

    -- Component Declaration for the Unit Under Test (UUT)
    component AutomatBauturi
        Port (
            clk          : in  std_logic;
            reset        : in  std_logic;
            leu1         : in  std_logic;
            lei5         : in  std_logic;
            lei10        : in  std_logic;
            product_3lei : in  std_logic;
            product_5lei : in  std_logic;
            product_7lei : in  std_logic;
            cerere_rest  : in  std_logic;
            produs       : out std_logic;
            leu1_rest    : out std_logic;
            lei5_rest    : out std_logic;
            respingere   : out std_logic
        );
    end component;

    -- Testbench Signals
    signal clk          : std_logic := '0';
    signal reset        : std_logic := '0';
    signal leu1         : std_logic := '0';
    signal lei5         : std_logic := '0';
    signal lei10        : std_logic := '0';
    signal product_3lei : std_logic := '0';
    signal product_5lei : std_logic := '0';
    signal product_7lei : std_logic := '0';
    signal cerere_rest  : std_logic := '0';
    signal produs       : std_logic;
    signal leu1_rest    : std_logic;
    signal lei5_rest    : std_logic;
    signal respingere   : std_logic;

    constant clk_period : time := 10 ns;

begin

    -- Instantiate the Unit Under Test (UUT)
    uut: AutomatBauturi
        Port map (
            clk => clk,
            reset => reset,
            leu1 => leu1,
            lei5 => lei5,
            lei10 => lei10,
            product_3lei => product_3lei,
            product_5lei => product_5lei,
            product_7lei => product_7lei,
            cerere_rest => cerere_rest,
            produs => produs,
            leu1_rest => leu1_rest,
            lei5_rest => lei5_rest,
            respingere => respingere
        );

    -- Clock Generation
    clk_process : process
    begin
        while true loop
            clk <= '0';
            wait for clk_period / 2;
            clk <= '1';
            wait for clk_period / 2;
        end loop;
    end process;

    -- Stimulus Process
    stimulus_process : process
    begin
        -- Reset the system
        reset <= '1';
        wait for clk_period;
        reset <= '0';

        -- Insert 5 lei
        lei5 <= '1';
        wait for clk_period;
        lei5 <= '0';
        wait for clk_period;

        -- Insert another 5 lei
        lei5 <= '1';
        wait for clk_period;
        lei5 <= '0';
        wait for clk_period;

        -- Insert another 5 lei
        lei5 <= '1';
        wait for clk_period;
        lei5 <= '0';
        wait for clk_period;

        -- Get the 7 lei product
        product_7lei <= '1';
        wait for clk_period;
        product_7lei <= '0';
        wait for clk_period;

        -- Insert 1 leu
        leu1 <= '1';
        wait for clk_period;
        leu1 <= '0';
        wait for clk_period;

        -- Insert another 1 leu
        leu1 <= '1';
        wait for clk_period;
        leu1 <= '0';
        wait for clk_period;

        -- Get the 5 lei product
        product_5lei <= '1';
        wait for clk_period;
        product_5lei <= '0';
        wait for clk_period;

        -- Insert 5 lei
        lei5 <= '1';
        wait for clk_period;
        lei5 <= '0';
        wait for clk_period;

        -- Insert 1 leu
        leu1 <= '1';
        wait for clk_period;
        leu1 <= '0';
        wait for clk_period;

        -- Get rest
        cerere_rest <= '1';
        wait for clk_period;
        cerere_rest <= '0';
        wait for clk_period;

        -- End simulation
        wait;
    end process;

end Behavioral;

这是模拟

waves

最后应该返还6个货币。 5 个 1 脉冲,1 也是如此,然后就保持这样。

我尝试将天平的信号切换为变量并使用辅助信号来更新它,但没有成功。

vhdl xilinx vivado fsm
1个回答
0
投票

这里有几个问题。 它遇到的问题是

balance
不在敏感度列表中。如果您使用的是VHDL 2008,您只需将敏感度列表替换为
process(all)
,编译器将自动确定敏感度列表。

但是在敏感度列表中添加平衡也会导致一个问题 - 你将在硬件中创建一个逻辑循环,并且状态在模拟中会立即发生变化。

您需要确保

balance
仅在时钟进程中修改。您可以通过在异步进程中生成
balance_next
信号并在时钟进程中设置
balance
来实现此目的,与生成
next_state
current_state
信号的方式相同。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.