如何从另一个状态机调用状态机并以VHDL形式获取响应

时间:2015-04-06 05:07:06

标签: vhdl verilog hdl

我想对状态机进行VHDL编程。在这种状态机中,一个状态本身就是另一个状态机。我怎么能从主状态机调用这个状态机? 我实际想做的事情的例子如下:

主状态机(sm_main.vhd): -

clk_process : process (clk, reset)   
begin  
if(reset = '1') then   
state_reg <= start;   
elsif (clk'event and clk =' 1'  ) then  
state_reg <= state_next;  
end if;  
end process;

state_process : process (state_reg,input,enable)  
begin  
case state_reg is   
 when start =>  
     if (input =1) then  
      state_next <= wait;     
      else
      state_next <= start;  
  end if;

 when wait =>
     if  (enable =1)  then
     output <= '1';
     state_next <= execute;
         else
 output <='0';
  state_next <= wait; 
  end  if ;


 when execute =>
    if (enable =1) then 
     state_next <= done;
     else

     state_next <= start;

 end if;

 when done =>
if(result = 1) then
state_next <= execute;
else
state_next <= start;
     end if;

end case;
end process;   

子状态机(sm_execute.vhd): -

上述状态机的执行状态本身就是另一个状态机程序。

 state_process : process (state_reg,a,b)    
 begin    
 case state_reg is    
 when start =>    
     if (a=1) then    
      state_next <= s1;          
      else    
      state_next <= s2;     
  end if;     

 when s1 =>     
     if  (b =1)  then
     state_next <= s3;
         else
     state_next <= s3; 
  end  if ;


 when s3=>
if(c=1) then
 result <= '1';
state_next <= s3
else
 result <='0';
state_next <= start
 end case;
end process;

我想要的是在sm_main.vhd的执行状态下调用此sm_execute.vhd。作为结果的sm_execute的输出将用作输入,以确定在sm_main.vhd中执行后的下一个状态。这意味着我想调用子状态机程序,并在子状态机程序完成执行后将值返回到主状态机程序。

提前谢谢 Sruthi Rajan

1 个答案:

答案 0 :(得分:1)

握手。第一台机器发出第二台机器的信号,等待它确认。然后它缩回启动信号并等待第二个完成。

这不是唯一的方法,但是你可以将第二个状态机分成它自己的进程,它可能是最简单的。

首先是SM(主人):

SM_1 : process(clock,reset)
begin
   if reset = '1' then 
      State_1 <= Idle;
   elsif rising_edge(clock) then
      -- default actions
      Start <= '0';
      -- state machine proper
      case State_1 is
      ...
      when Need_Result => 
         Start <= '1'; 
         -- wait here until slave SM starts processing
         if Done = '0' then
            State_1 <= Wait_Result;
         end if;
      when Wait_Result =>
         if Done = '1' then
            State_1 <= Have_Result;
         end if;
      ...
      when others => State_1 <= Idle;
      end case;
   end if;
end process;

第二个SM(奴隶):

SM_2 : process(clock,reset)
begin
   if reset = '1' then 
      State_2 <= Idle;
   elsif rising_edge(clock) then
      case State_2 is
      when Idle => 
         Done <= '1';  
         if Start = '1' then
            Done <= '0';
            State_2 <= Start_Process;
         end if;
      when Start_Process =>
         State_2 <= Process_Done;
      when Process_Done =>
         Done <= '1';
         if Start = '0' then
            State_2 <= Idle;
         end if;
      when others => State_2 <= Idle;
      end case;
   end if;
end process;

请注意,在此实现中,主服务器等待从服务器开始处理(done = '0';)。这包括奴隶可能无法立即响应的情况。它不包括已经Done='0'的情况,因为从服务器正在为另一个主服务器处理数据。

奴隶还等待主人撤回开始,然后返回空闲状态。通常Start已经是'0'但如果不是,你可能不希望奴隶立即重新触发。

如果你能保证这些情况都不会发生,你可以稍微简化一下握手,但设计对信号时序的变化会更敏感。

另请注意,由于默认分配,Start默认为'0',但Done没有默认分配,因此在处理期间保留其状态。除非您在Done设置为指示处理已停止时返回空闲状态(可能通过错误路径)。

如果对处理是否完成存在不确定性,您可能希望主机超时,而不是死锁等待不会发生的事情。我这样做是通过添加一个延迟计时器,可以由不同的状态用于不同的目的:在这里它检测一个冻结的从属,让我们处理错误。

首先是SM(主人):

SM_1 : process(clock,reset)
   variable Delay : natural range 0 to 100;
   constant Timeout : natural := 50;
begin
   if reset = '1' then 
      State_1 <= Idle;
      Delay := 0;
   elsif rising_edge(clock) then
      -- default actions
      Start <= '0';
      if Delay > 0 then
         Delay := Delay - 1;
      end if;
      -- state machine proper
      case State_1 is
      ...
      when Need_Result => 
         Start <= '1'; 
         -- wait here until slave SM starts processing
         if Done = '0' then
            Delay := Timeout;
            State_1 <= Wait_Result;
         end if;
      when Wait_Result =>
         if Done = '1' then
            State_1 <= Have_Result;
         elsif Delay = 0 then
            State_1 <= Timed_Out;  -- do error processing
         end if;
      ...
      when others => State_1 <= Idle;
      end case;
   end if;
end process;