有限状态机VHDL复位

时间:2017-05-20 15:34:58

标签: vhdl hdl state-machine quartus

我是VHDL的新手,我对FSM的实施有疑问。 我想要图片中显示的行为(我用AHDL实现了相同的FSM)。当我在VHDL中实现它时,我有一个不同的复位行为:如果它检测到reset = 1并且同时存在上升沿,则FSM不会继续,但它会继续将PS置于S0。 我知道问题是如果...... elsif(它检测到第一个条件是正确的,并且我没想进入第二个条件)。 我已经尝试了许多不同的方法,但仍然没有工作,输出在第一个上升沿之后也保持在00.

AHDL实施的波形: Waveforms of AHDL implementation

VHDL实施的波形: Waveforms of VHDL implementation

LIBRARY ieee; -- Bibliotheksvereinbarung
USE ieee.std_logic_1164.all;

ENTITY sumconvol IS -- Schaltungssymbol
PORT
(
    x : IN STD_LOGIC; --input of 1st FF
    clk : IN STD_LOGIC; --clock of all the 3 FFs
    clrn : IN STD_LOGIC;
    y : OUT STD_LOGIC_VECTOR (1 downto 0) --vector of output data
);
END sumconvol;

ARCHITECTURE a OF sumconvol IS -- Creation of architecture
    --SIGNAL output_tmp : STD_LOGIC_VECTOR (1 downto 0); -- temporary variables (e.g. input/output between FFs)7
    TYPE state_type IS (S0,S1,S2,S3);
    SIGNAL NS,PS : state_type;
    SIGNAL stato : STD_LOGIC;

BEGIN
    sync_proc: PROCESS (clk,clrn)
    BEGIN
        if ((clrn='1')) THEN 
            PS<=S0;
            y <= "00";
        elsif (rising_edge(clk)) then 
            PS <= NS;
            CASE PS IS
            when S0 => 
                if ((x='0'))then
                        NS <= S0;
                        y <= "00";
                    else 
                        NS <= S1;
                        y <= "11";
                end if;
            when S1 => 
                if (x='0') then
                    NS <= S2;
                    y<="10";
                else 
                    NS <= S3;
                    y <= "01";
                end if;
            when S2 => 
                if (x='0') then
                    NS <= S0;
                    y <="11";
                else 
                    NS <= S1;
                    y <= "00";
                end if;
            when S3 => 
                if (x='0') then
                    NS <= S2;
                    y <="01";
                else 
                    NS <= S3;
                    y <= "10";
                end if;
            end case;
        end if;
    end process sync_proc;
END a;

1 个答案:

答案 0 :(得分:2)

您可能没有注意到的一件事是,您将PS(之前的状态)和NS(下一个状态)放在一个时钟进程中。这意味着为两个信号推断寄存器。因此,NS将在一个时间之后设置为PS,这可能是您所期望的。这可以通过两种方式解决:

1)删除PS - &gt; NS部分,然后使用state

sync_proc: PROCESS (clk, clr)
BEGIN
    if clr = '1' THEN 
        state <= S0;
        y <= "00";
    elsif rising_edge(clk) then 
        CASE state IS
        when S0 => 
            if x = '0' then
                    state <= S0;
                    y <= "00";
                else 
                    state <= S1;
                    y <= "11";
            end if;
        when S1 => 
            if x = '0' then
                state <= S2;
                y<="10";
            else 
                state <= S3;
                y <= "01";
            end if;
        when S2 => 
            if x = '0' then
                state <= S0;
                y <="11";
            else 
                state <= S1;
                y <= "00";
            end if;
        when S3 => 
            if (x='0') then
                state <= S2;
                y <="01";
            else 
                state <= S3;
                y <= "10";
            end if;
        end case;
    end if;
end process sync_proc;

2)将过程分为计时和组合过程。

clk_proc: PROCESS (clk, clr)
BEGIN
    if clr = '1' THEN 
        PS <= S0;
        y <= "00";
    elsif rising_edge(clk) then 
        PS <= NS;
        y <= next_y;
    end if;
end process;

comb_proc : process(PS, x)
begin
    CASE PS IS
        when S0 => 
            if x = '0' then
                    NS <= S0;
                    next_y <= "00";
                else 
                    NS <= S1;
                    next_y <= "11";
            end if;
        when S1 => 
            if x = '0' then
                NS <= S2;
                next_y <= "10";
            else 
                NS <= S3;
                next_y <= "01";
            end if;
        when S2 => 
            if x = '0' then
                NS <= S0;
                next_y <="11";
            else 
                NS <= S1;
                next_y <= "00";
            end if;
        when S3 => 
            if x = '0' then
                NS <= S2;
                next_y <="01";
            else 
                NS <= S3;
                next_y <= "10";
            end if;
    end case;
end process;

接下来,我无法通过重置了解您的需求。 VHDL代码正在做它应该做的事情。这是使用复位的正确方法:只要复位被置位,y就会显示&#34; 00&#34;。然后,一旦它被置为无效,y应该在下一个时钟边沿发生变化。这是正确的设计。第一张(AHDL)图片显示的不好:重置期间y的活动。

但无论如何,如果你真的很顽固,你可以使用一些技巧来获得第一张图片中的行为。

sync_proc: PROCESS (clk)
BEGIN
    if (rising_edge(clk)) then 
        if clr = '1' THEN 
            state <= S0;
            y <= "11";
        else
            case state is
[...]

P.S。您正在调用流程sync_proc,如同#34;同步流程&#34;。但事实并非如此,因为代码中的重置是异步的......

p.s.2:给你的信号一些正确的名字,而不是x ...