Jan 16

有限状态机编写

RickySu , 14:04 , 技术经验 , 评论(3) , 引用(0) , 阅读(1600) , Via 本站原创 | |
网上看到一篇关于Finite State Machine (FSM) - 有限状态机的文章《有限状态机的VHDL优化设计》,写得挺详细,有些感想和经验记录于此:

1. 关于使用的语言 - VHDL和Verilog大同小异,想法是一样的,万变不离其宗。

2. 模板 - 大家都会讨论是一段两端还是三段。争执在两端和三段的情况时有发生。其实只要综合器能综合出设计者期望的电路,怎么写都无所谓。代码是给人看的,如果能让别人更容易读懂,就是好代码。我偏好两段,因为这样在察看代码时能一眼看出某一个state的跳出条件和输出信号。如果状态机的状态数很多,需要上下翻阅才能分别得知跳出条件和输出信号,真是太麻烦了。

3. 结构 - 当前状态用时钟驱动,next_state由组合逻辑生成,这些都是固定的。唯一可能有争议的是输出信号需不需要加寄存器打一拍?
点击在新窗口中浏览此图片

不加寄存器的输出


点击在新窗口中浏览此图片

输出由寄存器驱动



一般来说,如果是模块的输出,我会用寄存器打一拍,保证模块所有输出都由寄存器驱动(因为无法预测负载要经过多少级LUT才能到达下一级寄存器)。这样一来有个坏处:某个状态的输出信号要到下一个时钟才有效,而不是和state一起变化。在某些设计中这个限制会导致一些问题。因此如果是本模块自己使用的信号,我就不用寄存器打一拍了,只要布局布线后能满足Period约束就可以。

4. 状态转换输出 - 对于输出信号的赋值,通常会有两种状况:某个state时需要保持的输出;状态跳转的时候需要一个脉冲的输出。对于第二种输出要求,可以把输出信号写在状态跳转条件的if语句中。

5. 我的模板

   <FSM_NAME>_SYNC_PROC: process (<clock>)
   begin
      if (<clock>'event and <clock> = '1') then
         if (<reset> = '1') then
            <fsm>_state <= st1_<name_state>;
            -- Output signals here will have one clock delay of the <state>
            <output1> <= '0';
            <output2> <= '0';

         else
            <fsm>_state <= <fsm>_next_state;
            <output1> <= <output1>_c;
            <output2> <= <output2>_c;

         -- assign other outputs to internal signals

         end if;        
      end if;
   end process;


   <FSM_NAME>_NEXT_STATE_DECODE: process (<fsm>_state, <input1>, <input2>, ...)
   begin
      --declare default state for next_state to avoid latches
      <fsm>_next_state <= <fsm>_state;  
      -- default is to stay in current state
      -- so there are no else branch in the if statement
      case (<fsm>_state) is
         when <fsm>_st1_<name> =>
            -- State Change Condition
            if <input_1> = '1' then
               <fsm>_next_state <= <fsm>_st2_<name>;
               -- Internal Output can put here
               -- Only occur on state transaction (next_state changed but state not changed)
               -- If output need to assert at first cycle of one state,
               -- we can delay this output one clock in <FSM_NAME>_SYNC_PROC process
            end if;
            -- Internal Output can put here
            -- This output will be asserted till state change

         when <fsm>_st2_<name> =>
            if <input_2> = '1' then
               <fsm>_next_state <= <fsm>_st3_<name>;
            end if;
         when <fsm>_st3_<name> =>
            <fsm>_next_state <= <fsm>_st1_<name>;
         when others =>
            <fsm>_next_state <= <fsm>_st1_<name>;
      end case;      
   end process;
Tags: , ,
tyj
2009/10/14 19:48
确实跟状态机的写法没关系,之所以才跑160是由于计数器的位数太长了 导致了很长的进位链,现在将计数器分割,速度上来不少 谢谢你的解答
tyj
2009/10/12 09:41
还是我,我在顶层中实例化了一个BUFGMUX来切换两个时钟,单独仿真时,都可以达到速度要求,当将两个系统在顶层模块中实现的时候,速率却下降的厉害,请问此时综合的那个Fmax是时钟切换的选择信号的Fmax吗?


我的第一个问题中设计的标准三段式状态机只能跑到160M,为什么?还需要做什么改进吗 系统要求跑至少200M

希望可以得到您的帮助
RickySu 回复于 2009/10/13 23:11
整个设计的瓶颈在哪里还是需要查看时序分析报告来确定,并不是说两段式或者三段式的状态机速度就快的。
tyj
2009/10/10 09:55
老师您好,我现在要做这样一个设计,某些状态的转移需要通过一个同步计数器的数值来控制,我在第二段中always敏感表里将该计数器的值插入(同步计数器在另一个always中依靠对状态的判断生成)。这样做有什么好处,对于组合和时序混合控制状态的庄毅还有更好的办法吗?
RickySu 回复于 2009/10/13 23:13
计数器单独一个always。计数器信号作为判断Next state的条件,所以要写到<FSM_NAME>_NEXT_STATE_DECODE这个Process的敏感信号列表中。
分页: 1/1 第一页 1 最后页
发表评论
表情
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
emotemotemotemotemot
打开HTML
打开UBB
打开表情
隐藏
记住我
昵称   密码   游客无需密码
网址   电邮   [注册]