找回密码
 注册
关于网站域名变更的通知
查看: 207|回复: 5
打印 上一主题 下一主题

一个关于状态机的状态跳变问题,请大家看看是哪里逻辑不够严密?

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2020-5-13 18:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
  • module         dithering(
  •     input         clk,
  •     input         key_in,
  •     output reg  key
  •     );
  •     wire key_rising;
  •     wire key_falling;
  •     reg  key_mid = 0;                                           //按键输出的中间信号
  •     reg  counter_20ms_flag = 0;                   //计数标志,如果到达20ms则变为1
  •     reg  counter_20ms_en = 0;                   //计数器使能,检测到边沿开始计数
  •     reg  counter_20ms_falling_flag = 0;//下降标志信号
  •     reg  key_in_state0 ,key_in_state1;                   //寄存按键状态
  •     reg  [20:0]counter_20ms = 0;          //上升沿计数器
  •     assign key_rising  = ((~key_in_state1)&&key_in_state0); //上升
  •     assign key_falling = (key_in_state1&&(~key_in_state0));//下降
  •     parameter Idle                     = 4'b0001;
  •     parameter First_Filter  = 4'b0010;
  •         parameter Done              = 4'b0100;
  •         parameter Second_Filter = 4'b1000;
  •         reg [3:0]current_state = Idle;
  •         reg [3:0]next_state;
  •         always@(posedge clk)begin
  •                 key_in_state0 <= key_in;
  •                 key_in_state1 <= key_in_state0;
  •         end
  •         always@(posedge clk)
  •                 key <= key_mid;
  •     always@(posedge clk)
  •             current_state <= next_state;
  •     always@(posedge clk)begin
  •             case (current_state)
  •                     Idle                 :
  •                                                     IF(key_rising == 1)  begin
  •                                                             next_state <= First_Filter;
  •                                                             key_mid <= 0; end
  •                                                     else begin
  •                                                             next_state <= Idle;
  •                                                             key_mid <= 0; end
  •                     First_Filter:         if(key_falling == 1)begin
  •                                                             next_state <= Idle;
  •                                                             key_mid <= 0; end
  •                                                     else if(counter_20ms_flag) begin
  •                                                             next_state <= Done;
  •                                                             key_mid <= 0; end
  •                                                     else begin
  •                                                             next_state <= First_Filter;
  •                                                             key_mid <= 0; end
  •                     Done                :
  •                                                     if(key_falling) begin
  •                                                             next_state <= Second_Filter;
  •                                                             key_mid <= 1; end
  •                                                     else begin
  •                                                             next_state <= Done;
  •                                                             key_mid <= 1; end
  •               Second_Filter:
  •                                                       if(counter_20ms_flag) begin
  •                                                               next_state <= Idle;
  •                                                               key_mid <= 1; end
  •                                                       else if(key_rising) begin
  •                                                               next_state <= Done;
  •                                                               key_mid <= 1; end
  •                                                       else begin
  •                                                               next_state <= Second_Filter;
  •                                                               key_mid <= 1; end
  •                     default                :  next_state <= next_state;
  •             endcase
  •     end
  •     always@(posedge clk)begin
  •             if(counter_20ms_en == 1)
  •                     if(counter_20ms < 999999)
  •                             counter_20ms <= counter_20ms + 1'b1;
  •                     if(counter_20ms == 999999 && counter_20ms_en == 1) begin
  •                             counter_20ms_flag <= 1;        //满20ms输出一个时钟的标志信号
  •                             counter_20ms <= 0;end
  •             else begin
  •                             counter_20ms_flag <= 0;
  •                             counter_20ms <= 0; end
  •             end
  •     always@(posedge clk)begin
  •             case (current_state)
  •                     Idle                 :  counter_20ms_en <= 0;
  •                     First_Filter : counter_20ms_en <= 1;
  •                     Done                 : counter_20ms_en <= 0;
  •                     Second_Filter: counter_20ms_en <= 1;
  •                     default :           counter_20ms_en <= counter_20ms_en;
  •             endcase
  •     end
  • endmodule
  • 想用状态机写一个按键消抖模块,但是在仿真的时候出现了问题,:# ^  ?4 h3 a6 c$ z5 ~
    问题描述:当key_in为1时状态机的状态在第一个和第二个状态间来回跳变。2 ?0 e" W3 ]) i" \1 u
$ p- w# S' |: m; u( |3 w

该用户从未签到

2#
 楼主| 发表于 2020-5-13 18:19 | 只看该作者
01.三段式状态机写的有问题,导致状态机跳变,里面的key_mid赋值存在互斥情况。# _0 S* A" w* ?- l8 Z* B' s

, [/ h' ^6 ?3 w6 X: J1 t' m; }02.一般第二段只有状态机跳变,赋值操作放在第三段。% \' i8 ~, e/ X* p
03.我把999999改成"patameter  NUM=99",这样仿真运行4us即可。
7 o7 y% h7 j* \+ v8 d' N" G  Q1 l, d04.sys_rst_n相关的逻辑可以忽略掉,不影响系统功能。

该用户从未签到

3#
 楼主| 发表于 2020-5-13 18:19 | 只看该作者
没有使用你的仿真代码验证,自己试一下(注意sys_rst的处理)。

点评

第一次写三段式状态机所以有很多问题,我昨天将状态转换那里的敏感信号改成组合逻辑就成功了。然后昨晚上我上网搜了一些资料,发现三段式状态机的状态转换那个模块都是组合逻辑。这点我就不是很明白为什么不能用时序  详情 回复 发表于 2020-5-13 18:20

该用户从未签到

4#
发表于 2020-5-13 18:20 | 只看该作者
bookbook 发表于 2020-5-13 18:19
9 G7 H4 G& X* A6 Q8 `4 Q没有使用你的仿真代码验证,自己试一下(注意sys_rst的处理)。
1 h" N+ ~1 @& Z3 v# `3 k" z$ v
第一次写三段式状态机所以有很多问题,我昨天将状态转换那里的敏感信号改成组合逻辑就成功了。然后昨晚上我上网搜了一些资料,发现三段式状态机的状态转换那个模块都是组合逻辑。这点我就不是很明白为什么不能用时序逻辑。还有就是谢谢你的解答。8 q- b8 h8 i% q: a' T: I7 H& f* O

该用户从未签到

5#
 楼主| 发表于 2020-5-13 18:20 | 只看该作者
简单来讲,状态机的跃迁/跳变尽量不影响逻辑状态的运行,所以第二段推荐组合逻辑。
5 g* Q* c8 e7 u0 Q' L8 o如果想用时序逻辑,也可以实现,只不过正常的逻辑运行可能会滞后1~N个时钟周期。

点评

好的,谢谢![/backcolor]  详情 回复 发表于 2020-5-13 18:22

该用户从未签到

6#
发表于 2020-5-13 18:22 | 只看该作者
bookbook 发表于 2020-5-13 18:20. G, n4 d. J. O, [4 x* F7 J
简单来讲,状态机的跃迁/跳变尽量不影响逻辑状态的运行,所以第二段推荐组合逻辑。
2 r: m7 E* l* V如果想用时序逻辑,也 ...
! O8 K/ p1 q; R
好的,谢谢!; n* M) f& f! X: Q9 F1 n
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-21 13:26 , Processed in 0.109375 second(s), 24 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表