FPGA Notes

有限状态机编写

0
阅读(3550)

网上看到一篇关于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;
 

Baidu
map