我见过很多像Altera这样的状态机:
ARCHITECTURE a OF state_machine IS
TYPE STATE_TYPE IS (s0, s1, s2);
SIGNAL state : STATE_TYPE;
BEGIN
PROCESS (clk, reset)
BEGIN
IF reset = '1' THEN
state <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
CASE state IS
WHEN ...
对此的改变是:
ARCHITECTURE a OF state_machine IS
TYPE STATE_TYPE IS (s0, s1, s2);
BEGIN
PROCESS (clk, reset)
VARIABLE state : STATE_TYPE := s0;
BEGIN
IF reset = '1' THEN
state <= s0;
ELSIF (clk'EVENT AND clk = '1') THEN
CASE state IS
WHEN ...
有什么优点(如果有的话)和另类方式的缺点?我只在一个地方看到了另一种选择,我猜测必须有一些很好的理由。
答案 0 :(得分:2)
我喜欢将本地事物保留在本地,因此如果只在流程中需要状态信息,我会使用变量。在这种情况下,我还想在进程中声明状态类型:
ARCHITECTURE a OF state_machine IS
BEGIN
PROCESS (clk, reset)
TYPE STATE_TYPE IS (s0, s1, s2);
VARIABLE state : STATE_TYPE := s0;
BEGIN
...
在极少数情况下,我需要从另一个进程(例如交互式状态机)访问FSM的状态,我将使用一个信号来存储状态。
信号与变量决策通常只是品味问题。一些开发人员认为变量是邪恶的,永远不会使用它们。其他人(像我一样)只要能够将当地的东西保存在当地就可以使用它们。作为奖励,由于变量是比信号更轻量级的对象,因此它们也可以更快地模拟。
答案 1 :(得分:1)
使用变量保持状态意味着您无法使用波形查看器查看状态。
用于分支的信号输入可能存在一些同步问题,零时间模型中的delta周期不匹配。
从状态派生的任何状态机输出在任何情况下都需要信号 - 每个并发语句都有一个等效的进程,VHDL模拟器执行进程,进程通过信号进行通信。
唯一可以想到的是,它将是一个更紧凑的模型(代码大小)并执行得更快。
答案 2 :(得分:1)
我经常使用名为variable
的{{1}}。它使定义隐藏,仅对正在使用它的进程保密。如果在一个进程中有2个通信状态机,则它们都可以拥有一个名为state
的变量。有时候效果很好。其他时候令人困惑!
与许多代码风格问题一样,您必须决定最易读的方法。没有功能的理由不使用变量(任何类型,而不仅仅是状态变量)。
您可以对变量执行的另一项操作是在过程结束时读取预期的下一个状态,这在您需要减少输出延迟时非常有用。同样,需要小心,因为你可以无意中创建长链逻辑,这可能会减慢设计速度。
答案 3 :(得分:-1)
如果要确定在同一时钟周期中在过程中进一步使用的部分和或中间产品,则变量非常好。但是,如果每个时钟周期都没有驱动变量,那么将推断出锁存器。因为你会希望记住这个州的状态。对于下一个时钟周期,如果使用没有辅助寄存器信号的变量,您将获得一个锁存器。澄清...
signal state_sig : state_type;
begin
process(clk, rst)
variable state : state_type := s0;
begin
if rst = '1' then
state_sig <= s0;
elsif rising_edge(clk) then
state := state_sig
case state is
when s0 =>
if blah = '0' then
state := s1;
end if;
....
....
end case;
if state = s1 then state := s2; end if;
state_sig <= state;
end if;
end process;
在上面的例子中,您可以通过在注册之前修改状态变量来避免进入状态s1。一种快速而又脏的方式来改变状态机的行为。但是,必须使用state_sig信号来记住&#39;国家避免闩锁推断。