zoukankan      html  css  js  c++  java
  • [原创].怎样在有限状态机中延时

     

    本文借一小例,来示范在FSM中如何延时。

    案例

    (1)fsm_with_delay_demo.v

    module fsm_with_delay_demo(
      input      CLOCK_50,
      input      RST_N,
      
      output reg LED
    );
    
    //++++++++++++++++++++++++++++++++++++++
    // 定时器1 开始
    // 时长:1秒
    //++++++++++++++++++++++++++++++++++++++
    parameter TIMER1_VAL = 50_000_000;      // 50M/50M = 1s
    
    reg        timer1_enable;
    reg [25:0] timer1_cnt;
    wire       timer1_done;
    
    always @(posedge CLOCK_50)
      if (~timer1_enable) 
        timer1_cnt <= 0;
      else if (~timer1_done) 
        timer1_cnt <= timer1_cnt + 1'b1;
        
    assign timer1_done = (timer1_cnt == TIMER1_VAL - 1);
    //--------------------------------------
    // 定时器1 结束
    //--------------------------------------
    
    
    //++++++++++++++++++++++++++++++++++++++
    // 定时器2 开始
    // 时长:4秒
    //++++++++++++++++++++++++++++++++++++++
    parameter TIMER2_VAL = 200_000_000;     // 200M/50M = 4s
    
    reg        timer2_enable;
    reg [27:0] timer2_cnt;
    wire       timer2_done;
    
    always @(posedge CLOCK_50)
      if (~timer2_enable) 
        timer2_cnt <= 0;
      else if (~timer2_done) 
        timer2_cnt <= timer2_cnt + 1'b1;
        
    assign timer2_done = (timer2_cnt == TIMER2_VAL - 1);
    //--------------------------------------
    // 定时器2 结束
    //--------------------------------------
    
    
    //++++++++++++++++++++++++++++++++++++++
    // 状态机部分 开始
    //++++++++++++++++++++++++++++++++++++++
    parameter S0 = 0;
    parameter S1 = 1;
    
    
    reg [5:0] current_state, next_state;    // 现态、次态
    
    always @ (posedge CLOCK_50, negedge RST_N)
    begin:fsm_always_block1
      if (!RST_N)
        current_state <= S1;
      else
        current_state <= next_state;
    end
    
    // 根据条件转移状态,并给出相应逻辑
    always @ *
    begin:fsm_always_block2
      /* 用户变量初始化  开始*/
      LED           = 1'b0;
      /* 用户变量初始化  结束*/
      
      /* 清定时器使能 开始 */
      timer1_enable = 1'b0;
      timer2_enable = 1'b0;
      /* 清定时器使能 结束 */
      case (current_state)
        S0 :
          begin
            timer1_enable = 1;              // 使能定时器1
            
            /* 用户代码  开始*/
            LED = 1'b0;
            /* 用户代码  结束*/
            
            if (timer1_done /* && 用户条件 */)
              next_state = S1;
            else
              next_state = S0;
          end
        S1 :
          begin
            timer2_enable = 1;              // 使能定时器1
            
            /* 用户代码  开始*/
            LED = 1'b1;
            /* 用户代码  结束*/
            
            if (timer2_done /* && 用户条件 */)
              next_state = S0;
            else
              next_state = S1;
          end  
      endcase
    end
    //--------------------------------------
    // 状态机部分 结束
    //--------------------------------------
    
    endmodule

    (2)QII综合的FSM

    图1 QII综合的FSM

    图1 QII综合的FSM

    (3)实验现象

    该例中,FSM有两个状态,S0持续1s,S1持续4s,然后循环交替。

    假设案例中的LED是送1亮,送0灭,那么LED灭1秒亮4秒,如此循环交替。

    分析

    众所周知,FSM有三种写法:1个always块;两个always块;三个always块。其中1个always块的fsm,由于各种弊端,为大家所不齿。然而加入定时器这一动作在3个always块又不能很好地实现,于是退而求其次,使用2个always块的fsm。

    这样一来,我们只需在第一个always块内实现现次态交替转变即可。在第二个always块内,根据状态迁移,来写各状态的逻辑。由于定时器的加入,而其使能又是reg变量,所以在初始化时,必须将使能清零,以免无法实现定时效果。在各状态中,如果只需持续一个clock,则无需使能定时器。倘若需要持续一段时间,使能定时器即可,然后等定时完毕,再转移状态;未定时完毕,则保持当前状态。至于其他的用户条件,可与定时完毕标志逻辑与在一起,以实现所需功能。

     

    参考

    1. Terasic.DE1_CD_v0.8\DE1_demonstrations\DE1_USB_API\HW\ps2_keyboard.v

    http://www.terasic.com/downloads/cd-rom/de1/DE1_CD_v08.zip

  • 相关阅读:
    Linux 学习笔记1
    Openstack中的LoadBalancer(负载均衡)功能使用实例
    分析事务与锁3
    MemoryStream
    JBPM4学习之路2:流程部署
    在MongoDB中一起使用$or和sort()
    使用avalon msui绑定实现基于组件的开发
    深度剖析Byteart Retail案例:应用程序的配置
    最年轻的系统分析员的考试心得
    linux学习体会,献给初学者
  • 原文地址:https://www.cnblogs.com/yuphone/p/1733867.html
Copyright © 2011-2022 走看看