[原创].怎样在有限状态机中延时
本文借一小例,来示范在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
(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