怎样在有限状态机中延时

来源:互联网 发布:视频制作gif软件 编辑:程序博客网 时间:2024/06/10 08:59

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

 

案例

(1)fsm_with_delay_demo.v

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
modulefsm_with_delay_demo(
  input     CLOCK_50,
  input     RST_N,
   
  outputreg LED
);
 
//++++++++++++++++++++++++++++++++++++++
// 定时器1 开始
// 时长:1秒
//++++++++++++++++++++++++++++++++++++++
parameterTIMER1_VAL = 50_000_000;      // 50M/50M = 1s
 
reg       timer1_enable;
reg[25:0] timer1_cnt;
wire      timer1_done;
 
always@(posedgeCLOCK_50)
  if(~timer1_enable)
    timer1_cnt <= 0;
  elseif (~timer1_done)
    timer1_cnt <= timer1_cnt + 1'b1;
     
assigntimer1_done = (timer1_cnt == TIMER1_VAL - 1);
//--------------------------------------
// 定时器1 结束
//--------------------------------------
 
 
//++++++++++++++++++++++++++++++++++++++
// 定时器2 开始
// 时长:4秒
//++++++++++++++++++++++++++++++++++++++
parameterTIMER2_VAL = 200_000_000;     // 200M/50M = 4s
 
reg       timer2_enable;
reg[27:0] timer2_cnt;
wire      timer2_done;
 
always@(posedgeCLOCK_50)
  if(~timer2_enable)
    timer2_cnt <= 0;
  elseif (~timer2_done)
    timer2_cnt <= timer2_cnt + 1'b1;
     
assigntimer2_done = (timer2_cnt == TIMER2_VAL - 1);
//--------------------------------------
// 定时器2 结束
//--------------------------------------
 
 
//++++++++++++++++++++++++++++++++++++++
// 状态机部分 开始
//++++++++++++++++++++++++++++++++++++++
parameterS0 = 0;
parameterS1 = 1;
 
 
reg[5:0] current_state, next_state;    // 现态、次态
 
always@ (posedgeCLOCK_50, negedgeRST_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

原创粉丝点击