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