有限状态机 VHDL 重置

Finite state machine VHDL reset

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

A​​HDL实现波形图:

VHDL实现波形图:

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;

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

1) 去掉PS->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 就应该显示“00”。然后,一旦它被置低,y 应该在下一个时钟边沿改变。这才是正确的设计。第一张 (AHDL) 图片显示的内容不好:重置期间 y 的 activity。

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

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,如 "synchronous process"。但这不是真的,因为代码中的重置是异步的...

p.s.2:给你的信号一些合适的名字,而不是例如x...