安德鲁

[原创].怎样在有限状态机中延时.[FSM][Verilog]

0
阅读(3237)

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

案例

(1)fsm_with_delay_demo.v

001 modulefsm_with_delay_demo(
002 inputCLOCK_50,
003 inputRST_N,
004
005 outputregLED
006 );
007
008 //++++++++++++++++++++++++++++++++++++++
009 // 定时器1 开始
010 // 时长:1秒
011 //++++++++++++++++++++++++++++++++++++++
012 parameterTIMER1_VAL = 50_000_000;// 50M/50M = 1s
013
014 regtimer1_enable;
015 reg[25:0] timer1_cnt;
016 wiretimer1_done;
017
018 always@(posedgeCLOCK_50)
019 if(~timer1_enable)
020 timer1_cnt <= 0;
021 elseif(~timer1_done)
022 timer1_cnt <= timer1_cnt +1'b1;
023
024 assigntimer1_done = (timer1_cnt == TIMER1_VAL - 1);
025 //--------------------------------------
026 // 定时器1 结束
027 //--------------------------------------
028
029
030 //++++++++++++++++++++++++++++++++++++++
031 // 定时器2 开始
032 // 时长:4秒
033 //++++++++++++++++++++++++++++++++++++++
034 parameterTIMER2_VAL = 200_000_000;// 200M/50M = 4s
035
036 regtimer2_enable;
037 reg[27:0] timer2_cnt;
038 wiretimer2_done;
039
040 always@(posedgeCLOCK_50)
041 if(~timer2_enable)
042 timer2_cnt <= 0;
043 elseif(~timer2_done)
044 timer2_cnt <= timer2_cnt +1'b1;
045
046 assigntimer2_done = (timer2_cnt == TIMER2_VAL - 1);
047 //--------------------------------------
048 // 定时器2 结束
049 //--------------------------------------
050
051
052 //++++++++++++++++++++++++++++++++++++++
053 // 状态机部分 开始
054 //++++++++++++++++++++++++++++++++++++++
055 parameterS0 = 0;
056 parameterS1 = 1;
057
058
059 reg[5:0] current_state, next_state;// 现态、次态
060
061 always@ (posedgeCLOCK_50,negedgeRST_N)
062 begin:fsm_always_block1
063 if(!RST_N)
064 current_state <= S1;
065 else
066 current_state <= next_state;
067 end
068
069 // 根据条件转移状态,并给出相应逻辑
070 always@ *
071 begin:fsm_always_block2
072 /* 用户变量初始化 开始*/
073 LED <=1'b0;
074 /* 用户变量初始化 结束*/
075
076 /* 清定时器使能 开始 */
077 timer1_enable <=1'b0;
078 timer2_enable <=1'b0;
079 /* 清定时器使能 结束 */
080 case(current_state)
081 S0 :
082 begin
083 timer1_enable <= 1;// 使能定时器1
084
085 /* 用户代码 开始*/
086 LED <=1'b0;
087 /* 用户代码 结束*/
088
089 if(timer1_done/* && 用户条件 */)
090 next_state <= S1;
091 else
092 next_state <= S0;
093 end
094 S1 :
095 begin
096 timer2_enable <= 1;// 使能定时器1
097
098 /* 用户代码 开始*/
099 LED <=1'b1;
100 /* 用户代码 结束*/
101
102 if(timer2_done/* && 用户条件 */)
103 next_state <= S0;
104 else
105 next_state <= S1;
106 end
107 endcase
108 end
109 //--------------------------------------
110 // 状态机部分 结束
111 //--------------------------------------
112
113 endmodule

(2)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

Baidu
map