6

只是想知道我是否在 VHDL 中实现了一个有限状态机,是否需要说明所有输出在每种可能状态下的状态?即使我知道某些输出不会从一种状态变为另一种状态,并且我知道状态的顺序也将是相同的顺序?

例如,在这个(强制)示例中:

entity test is
    port (
        clk : in std_logic;
        a : in std_logic;
        b: out std_logic;
        c: out std_logic;
    );
end test;

architecture Behavioral of test is

type executionStage is (s1,s2,s3);
signal currentstate, nextstate: executionStage;

begin
    process (clk)
    begin
          if(rising_edge(clk)) then
                 currentstate <= nextstate;
          else 
                 currentstate <= currentstate;
          end if;
    end process;

    process(currentstate)
    begin
        case currentstate is
            when s1 =>
                if (a = '1') then
                    b <= '1';
                    c <= '0';
                else
                    b <= '1';
                    c <= '1';
                end if;

                nextstate <= s2;

            when s2 =>
                -- b doesnt change state from s1 to here, do I need to define what it is here?
                if (a = '1') then
                    b <= '1';
                    c <= '1';
                else
                    b <= '1';
                    c <= '0';
                end if;

                nextstate <= s3;

            when s3 =>
                if (a = '1') then
                    b <= '0';
                    c <= '0';
                else
                    b <= '1';
                    c <= '1';
                end if;

                nextstate <= s1;
        end case;
    end process;
end Behavioral;

根据我的理解,如果我不这样做,那么会创建闩锁吗?

在那个例子中这没什么大不了的,但是如果我的机器有超过 10 个输出和超过 10 个状态,那么我的 VHDL 文件开始看起来非常混乱,我确信复制和粘贴一定是不好的做法同样的事情一遍又一遍。有没有更好的方法来做到这一点?

编辑:我可以为输出定义“默认”状态吗?IE 在所有进程之外将 b 设置为 1,然后仅在它为 0 的 case 语句中定义它是什么?那行得通吗?

4

6 回答 6

7

是的,如果您仅在过程的某些分支中驱动旨在组合的信号,您将推断出锁存器。

但是,您可以简单地通过在语句之前为信号分配一个值来为信号定义一个“默认”状态case(但在同一进程中)。例如:

process(currentstate, a)
begin
    b <= '1';
    c <= '1';
    case currentstate is
        when s1 =>
            if (a = '1') then
                c <= '0';
            end if;

            nextstate <= s2;

        when s2 =>
            -- b doesnt change state from s1 to here, do I need to define what it is here?
            if (a /= '1') then
                c <= '0';
            end if;

            nextstate <= s3;

        when s3 =>
            if (a = '1') then
                b <= '0';
                c <= '0';
            end if;

            nextstate <= s1;
    end case;
end process;
于 2011-05-14T14:53:41.420 回答
7

您的示例代码存在三个问题:

端口列表中的最后一个端口不应有分号:

port (
    clk : in std_logic;
    a : in std_logic;
    b: out std_logic;
    c: out std_logic -- no semicolon here!!!
    );

在您的注册过程中,您不应该有“else”语句。虽然这可能会被工具接受,但它会让您的 VHDL 设计人员感到困惑。

process (clk)
begin
    if(rising_edge(clk)) then
        currentstate <= nextstate;
    end if;
end process;

在您的组合逻辑中,敏感度列表应包含您读取的所有信号:process(a, currentstate). 在这种特殊情况下(再次),事情可能会很好,但如果您的敏感度列表不正确,您必然会推断出闩锁或导致其他问题。

至于你的问题:

  1. 是的,您需要为组合过程中的每个信号分配一个值(针对每个状态)。
  2. 正如 Tomi 所提到的,您可以通过在流程开始时分配默认值来轻松完成此操作。
  3. 但是您也可以在一个同步进程中编写整个状态机。这样,您不必为每个状态的每个信号分配一个值。
于 2011-05-15T12:58:47.243 回答
3

只是对菲利普回应的说明(不能直接评论吗?)..

我确实更喜欢以两种进程样式编写状态机。它非常清楚您期望推断的触发器和不期望的触发器。它也更多地描述了硬件 - 例如,想象一下构建一个具有板级逻辑的状态机。注册的设备匹配 state <= next_state 进程,case 语句映射到状态寄存器前面的 and/or 数组。

话虽如此,我通常将一个进程状态机用于小型简单任务,而转移到两个进程状态机用于更大的任务。我有时甚至会使用第三个过程将状态输出组织到不同的“任务”组中......但不经常。一个非常大的状态机往往会告诉我架构需要工作。

于 2012-10-18T20:56:34.723 回答
0
process (clk)
begin
  if(rising_edge(clk)) then
    currentstate <= nextstate;
  end if;
end process;

你好

上述过程是有问题的,但不是由于敏感列表。只为顺序进程声明 clk 是可以的。仿真和综合工具都不会出现问题。毕竟,在您的代码中,clk 是最快的变化/转换信号。

但是,您应该使用(最好)异步复位。当然,现在的厂商都说,对于 FPGA 设计,甚至不需要复位。它们发生在启动时。或者他们建议同步重置。

尽管如此,异步复位对于基于板的环境还是很有价值的。

简而言之:为您的设计添加重置并正确修复其行为。

亲切的问候尼古拉斯·卡夫瓦迪亚斯

于 2011-06-23T10:45:31.033 回答
0

以下 VHDL 代码是电平敏感状态机。本例中的电平敏感过程将使“out1”与“clk”异相,“out2”与“clk”同相。

entity main_code is
    Port ( clk : in  STD_LOGIC;
           in1 : in  STD_LOGIC;
           in2 : in  STD_LOGIC;
           out1 : out  STD_LOGIC;
           out2 : out  STD_LOGIC);
end main_code;

architecture Behavioral of main_code is

-- here are temp signals to associate or assign output (out1 and out2) values indirectly
signal out1_temp : std_logic := '0';  
signal out2_temp : std_logic := '0';

-- counter registers 
signal counter : integer range 0 to 255 := 0;
signal counter_8th_clk : integer range 0 to 255 := 0;
-- state machines definition
type state_machine_type is (s0,s1);
signal state : state_machine_type := s0;
begin
-- concurrent assignments
out1 <= out1_temp;
out2 <= out2_temp;

--half clock generator process
half_clock : process (clk) is
begin
if rising_edge(clk) then
--out1_temp <= not out1_temp;
end if;
end process half_clock;

-- max counter = ndiv -1; here ndiv=4; counter starts from zero;
one_fourth_clock : process (clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
    if (counter >= 3) then 
        counter <= 0;
--      out2_temp <= not out2_temp;
    end if;
end if;
end process one_fourth_clock;


one_eighth_clock : process (clk)
begin
if rising_edge(clk) then
counter_8th_clk <= counter_8th_clk + 1;
    if (counter_8th_clk>=7) then
        counter_8th_clk <= 0;
--      out2_temp <= not out2_temp;
    end if;
end if;
end process one_eighth_clock;

-- state_process creates two half clock (speed) with out1 out of phase with clk
-- and out2 in-phase with clk
-- following process is sensitive to clk level not edge
state_process_level_sensitive : process (clk)
begin
case state  is

    when s0 =>
        out1_temp <= not out1_temp;
        state <= s1;
    when s1 =>
        out2_temp <= not out2_temp;
        state <= s0;
end case;
end process state_process_level_sensitive;



end Behavioral;

这是测试台

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;

ENTITY my_test_bench IS
END my_test_bench;

ARCHITECTURE behavior OF my_test_bench IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT main_code
    PORT(
         clk : IN  std_logic;
         in1 : IN  std_logic;
         in2 : IN  std_logic;
         out1 : OUT  std_logic;
         out2 : OUT  std_logic
        );
    END COMPONENT;


   --Inputs
   signal clk : std_logic := '0';
   signal in1 : std_logic := '0';
   signal in2 : std_logic := '0';

    --Outputs
   signal out1 : std_logic;
   signal out2 : std_logic;

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: main_code PORT MAP (
          clk => clk,
          in1 => in1,
          in2 => in2,
          out1 => out1,
          out2 => out2
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
--      wait for 100 ns;    
--
--      wait for clk_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;
于 2019-12-14T05:20:43.180 回答
0

以下 VHDL 代码是边沿敏感状态机。本例中的边缘敏感过程将使“out1”和“out2”都与“clk”同相。

entity main_code is
    Port ( clk : in  STD_LOGIC;
           in1 : in  STD_LOGIC;
           in2 : in  STD_LOGIC;
           out1 : out  STD_LOGIC;
           out2 : out  STD_LOGIC);
end main_code;

architecture Behavioral of main_code is

-- here are temp signals to associate or assign output (out1 and out2) values indirectly
signal out1_temp : std_logic := '0';  
signal out2_temp : std_logic := '0';

-- counter registers 
signal counter : integer range 0 to 255 := 0;
signal counter_8th_clk : integer range 0 to 255 := 0;
-- state machines definition
type state_machine_type is (s0,s1);
signal state : state_machine_type := s0;
begin
-- concurrent assignments
out1 <= out1_temp;
out2 <= out2_temp;

--half clock generator process
half_clock : process (clk) is
begin
if rising_edge(clk) then
--out1_temp <= not out1_temp;
end if;
end process half_clock;

-- max counter = ndiv -1; here ndiv=4; counter starts from zero;
one_fourth_clock : process (clk)
begin
if rising_edge(clk) then
counter <= counter + 1;
    if (counter >= 3) then 
        counter <= 0;
--      out2_temp <= not out2_temp;
    end if;
end if;
end process one_fourth_clock;


one_eighth_clock : process (clk)
begin
if rising_edge(clk) then
counter_8th_clk <= counter_8th_clk + 1;
    if (counter_8th_clk>=7) then
        counter_8th_clk <= 0;
--      out2_temp <= not out2_temp;
    end if;
end if;
end process one_eighth_clock;

-- state_process creates two half clock (speed) with out1 out of phase with clk
-- and out2 in-phase with clk
-- following process is sensitive to clk level not edge
state_process_edge_sensitive : process (clk)
begin
if rising_edge (clk) then
case state  is

    when s0 =>
        out1_temp <= not out1_temp;
        state <= s1;
    when s1 =>
        out2_temp <= not out2_temp;
        state <= s0;
end case;
end if;

end process state_process_edge_sensitive;



end Behavioral;

这是测试台

LIBRARY ieee;
USE ieee.std_logic_1164.ALL;

-- Uncomment the following library declaration if using
-- arithmetic functions with Signed or Unsigned values
--USE ieee.numeric_std.ALL;

ENTITY my_test_bench IS
END my_test_bench;

ARCHITECTURE behavior OF my_test_bench IS 

    -- Component Declaration for the Unit Under Test (UUT)

    COMPONENT main_code
    PORT(
         clk : IN  std_logic;
         in1 : IN  std_logic;
         in2 : IN  std_logic;
         out1 : OUT  std_logic;
         out2 : OUT  std_logic
        );
    END COMPONENT;


   --Inputs
   signal clk : std_logic := '0';
   signal in1 : std_logic := '0';
   signal in2 : std_logic := '0';

    --Outputs
   signal out1 : std_logic;
   signal out2 : std_logic;

   -- Clock period definitions
   constant clk_period : time := 10 ns;

BEGIN

    -- Instantiate the Unit Under Test (UUT)
   uut: main_code PORT MAP (
          clk => clk,
          in1 => in1,
          in2 => in2,
          out1 => out1,
          out2 => out2
        );

   -- Clock process definitions
   clk_process :process
   begin
        clk <= '0';
        wait for clk_period/2;
        clk <= '1';
        wait for clk_period/2;
   end process;


   -- Stimulus process
   stim_proc: process
   begin        
      -- hold reset state for 100 ns.
--      wait for 100 ns;    
--
--      wait for clk_period*10;

      -- insert stimulus here 

      wait;
   end process;

END;
于 2019-12-14T05:41:49.863 回答