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

  • 相关阅读:
    173. Binary Search Tree Iterator
    199. Binary Tree Right Side View
    230. Kth Smallest Element in a BST
    236. Lowest Common Ancestor of a Binary Tree
    337. House Robber III
    449. Serialize and Deserialize BST
    508. Most Frequent Subtree Sum
    513. Find Bottom Left Tree Value
    129. Sum Root to Leaf Numbers
    652. Find Duplicate Subtrees
  • 原文地址:https://www.cnblogs.com/yuphone/p/1733867.html
Copyright © 2011-2022 走看看