FPGA|CPLD|ASIC论坛
直播中

梅雪松

12年用户 1236经验值
擅长:可编程逻辑 嵌入式技术 EDA/IC设计 控制/MCU
私信 关注
[经验]

【连载视频教程(八)】小梅哥FPGA设计思想与验证方法视频教程之基于状态机的独立按键消抖

本帖最后由 小梅哥 于 2016-1-18 12:55 编辑

        大家好,今天,小梅哥继续连载本人精心录制和编辑的FPGA学习系列教程——《小梅哥FPGA设计思想与验证方法视频教程》。教程充分考虑0基础朋友的实际情况,手把手带领学习者分析思路、编写代码、仿真验证、板级调试。教语法,学仿真,一步一步,直到最后设计若干较为综合的逻辑系统。

                教程以我们自主开发的芯航线FPGA学习板为实验平台,通过若干基础和综合的系统设计讲解,一步一步掌握FPGA设计与验证的思想和方法,希望了解芯航线FPGA学习板的,请点击这里:

                今天是视频第八讲,主要通过独立按键消抖这样一个实验,来进一步举例讲解状态机的设计思想,独立按键消抖有多种方式可以实现,这里采用状态机的方式,既能方便大家理解按键消抖的整个过程,又能进一步领会状态机的设计思想。

                接下来,大家请看视频教程,由于视频中有部分网络的链接,因此上传优酷会被屏蔽,这里就直接分享在百度云盘中了。欢迎大家转载观看。(1280*720分辨率,MP4格式,用手机观看效果非常爽哦,建议大家下载了再观看)
好消息:
从此再也不需要一个一个回复才能看下载地址了

全部开源视频下载地址:
http://pan.baidu.com/s/1kUs0vkF

视频教程中配套源码下载地址:
http://pan.baidu.com/s/1qX5hz9y


觉得好的,记得回来帮忙顶个帖哦




​欢迎加入芯航线FPGA技术支持群:472607506
小梅哥
2015928日星期一
芯航线电子工作室
  • img.png

回帖(195)

besideyou

2015-9-30 16:16:49
举报

y990441

2015-9-30 16:17:40
用这个练习状态机不错,尤其是testbench写得佷威武
举报

y990441

2015-9-30 21:53:34
我按照视频的思想,写了个三段式的状态机,请梅总指点:
Step1. 接口设计
  1. //按键消抖实验
  2. //每次按下按键led翻转
  3. module key_filter(
  4.     clk_50M,
  5.     rst_n,
  6.     key_in,     //按键输入
  7.     key_out,    //滤波后的按键信号
  8.     led         //led灯,0亮,1灭
  9. );
  10.     input clk_50M;
  11.     input rst_n;
  12.     input key_in;
  13.     output key_out;
  14.     output led;
  15. endmodule

编译,只有警告
举报

y990441

2015-9-30 21:54:22
Step2. 三段式状态机的前两段
  1. parameter
  2.         IDLE    = 4'b0001,
  3.         FILTER0 = 4'b0010,
  4.         DOWN    = 4'b0100,
  5.         FILTER1 = 4'b1000;
  6.     reg[3:0] cur_state;
  7.     reg[3:0] next_state;

  8.     always  @(posedge clk_50M or negedge rst_n)begin
  9.         if(rst_n==1'b0)begin
  10.             cur_state <= IDLE;
  11.         end
  12.         else begin
  13.             cur_state <= next_state;
  14.         end
  15.     end

  16.     always  @(*)begin
  17.         case( cur_state )
  18.             IDLE:
  19.                 if( nedge ) next_state = FILTER0;
  20.                 else next_state = IDLE;
  21.             FILTER0:
  22.                 if( down_20ms ) next_state = DOWN;
  23.                 else if( pedge || nedge ) next_state = IDLE;
  24.                 else next_state = FILTER0;
  25.             DOWN:
  26.                 if( pedge ) next_state = FILTER1;
  27.                 else next_state = DOWN;
  28.             FILTER1:
  29.                  if( down_20ms ) next_state = IDLE;
  30.                  else if( pedge || nedge ) next_state = DOWN;
  31.                  else next_state = FILTER1;
  32.             default: next_state = IDLE;
  33.         endcase
  34. end

编译,nedge,pedge,down_20ms没有定义,下面逐个定义它们。
举报

y990441

2015-9-30 21:55:13
Step3. pedge和nedge
  1.    reg key_in0;//key_in打两拍
  2.     reg key_in1;
  3.     wire pedge; //key_in上升沿检测
  4.     wire nedge; //key_in下降沿检测

  5.     //边沿检测得到pedge和nedge
  6.     always  @(posedge clk_50M or negedge rst_n)begin
  7.         if(rst_n==1'b0)begin
  8.             key_in0 <= 1'd1;
  9.             key_in1 <= 1'd1;
  10.         end
  11.         else begin
  12.             key_in0 <= key_in;
  13.             key_in1 <= key_in0;
  14.         end
  15.     end
  16.     assign pedge = key_in0 & ~key_in1;
  17.     assign nedge = ~key_in0 & key_in1;
举报

y990441

2015-9-30 21:55:42
Step4. down_20ms
  1. parameter
  2.         TOP_20MS = 20'd1_000_000;

  3.     reg[19:0] cnt;//20ms计数器
  4.     wire down_20ms;

  5.     //计数器计数得到down_20ms信号
  6.     always  @(posedge clk_50M or negedge rst_n)begin
  7.         if(rst_n==1'b0)begin
  8.             cnt <= 20'd0;
  9.         end
  10.         else begin
  11.             if( cur_state == FILTER0 || cur_state == FILTER1 ) begin
  12.                 if( pedge || nedge ) cnt <= 20'd0;
  13.                 else if( cnt < TOP_20MS-1 ) cnt <= cnt + 1'd1;
  14.                 else;
  15.             end
  16.             else cnt <= 20'd0;
  17.         end
  18.     end
  19.     assign down_20ms = ( cnt == TOP_20MS-1 );
举报

y990441

2015-9-30 21:56:04
Step5. 第三段状态机,处理输出信号
  1.    reg key_out_r;
  2.     reg led;
  3.     //输出信号处理
  4.     always  @(posedge clk_50M or negedge rst_n)begin
  5.         if(rst_n==1'b0)begin
  6.             key_out_r <= 1'd1;
  7.         end
  8.         else begin
  9.             key_out_r <= ~( cur_state == DOWN );
  10.         end
  11.     end
  12.     assign key_out = key_out_r;

  13.     always  @(posedge clk_50M or negedge rst_n)begin
  14.         if(rst_n==1'b0)begin
  15.             led <= 1'd0;
  16.         end
  17.         else begin
  18.             if( cur_state == FILTER0 && next_state == DOWN )
  19.                 led <= ~led;
  20.         end
  21.     end
举报

y990441

2015-9-30 21:56:29
整个文件
  1. //按键消抖实验
  2. //每次按下按键led翻转
  3. module key_filter(
  4.     clk_50M,
  5.     rst_n,
  6.     key_in,     //按键输入
  7.     key_out,    //滤波后的按键信号
  8.     led         //led灯,0亮,1灭
  9. );
  10.     input clk_50M;
  11.     input rst_n;
  12.     input key_in;
  13.     output key_out;
  14.     output led;

  15.     parameter
  16.         IDLE    = 4'b0001,
  17.         FILTER0 = 4'b0010,
  18.         DOWN    = 4'b0100,
  19.         FILTER1 = 4'b1000;

  20.     parameter
  21.         TOP_20MS = 20'd1_000_000;

  22.     reg[3:0] cur_state;
  23.     reg[3:0] next_state;

  24.     reg key_in0;//key_in打两拍
  25.     reg key_in1;
  26.     wire pedge; //key_in上升沿检测
  27.     wire nedge; //key_in下降沿检测

  28.     reg[19:0] cnt;//20ms计数器
  29.     wire down_20ms;

  30.     reg key_out_r;
  31.     reg led;

  32.     always  @(posedge clk_50M or negedge rst_n)begin
  33.         if(rst_n==1'b0)begin
  34.             cur_state <= IDLE;
  35.         end
  36.         else begin
  37.             cur_state <= next_state;
  38.         end
  39.     end

  40.     always  @(*)begin
  41.         case( cur_state )
  42.             IDLE:
  43.                 if( nedge ) next_state = FILTER0;
  44.                 else next_state = IDLE;
  45.             FILTER0:
  46.                 if( down_20ms ) next_state = DOWN;
  47.                 else if( pedge || nedge ) next_state = IDLE;
  48.                 else next_state = FILTER0;
  49.             DOWN:
  50.                 if( pedge ) next_state = FILTER1;
  51.                 else next_state = DOWN;
  52.             FILTER1:
  53.                  if( down_20ms ) next_state = IDLE;
  54.                  else next_state = FILTER1;
  55.             default: next_state = IDLE;
  56.         endcase
  57.     end

  58.     //边沿检测得到pedge和nedge
  59.     always  @(posedge clk_50M or negedge rst_n)begin
  60.         if(rst_n==1'b0)begin
  61.             key_in0 <= 1'd1;
  62.             key_in1 <= 1'd1;
  63.         end
  64.         else begin
  65.             key_in0 <= key_in;
  66.             key_in1 <= key_in0;
  67.         end
  68.     end
  69.     assign pedge = key_in0 & ~key_in1;
  70.     assign nedge = ~key_in0 & key_in1;


  71.     //计数器计数得到down_20ms信号
  72.     always  @(posedge clk_50M or negedge rst_n)begin
  73.         if(rst_n==1'b0)begin
  74.             cnt <= 20'd0;
  75.         end
  76.         else begin
  77.             if( cur_state == FILTER0 || cur_state == FILTER1 ) begin
  78.                 if( pedge || nedge ) cnt <= 20'd0;
  79.                 else if( cnt < TOP_20MS-1 ) cnt <= cnt + 1'd1;
  80.                 else;
  81.             end
  82.             else cnt <= 20'd0;
  83.         end
  84.     end
  85.     assign down_20ms = ( cnt == TOP_20MS-1 );

  86.     //输出信号处理
  87.     always  @(posedge clk_50M or negedge rst_n)begin
  88.         if(rst_n==1'b0)begin
  89.             key_out_r <= 1'd1;
  90.         end
  91.         else begin
  92.             key_out_r <= ~( cur_state == DOWN );
  93.         end
  94.     end
  95.     assign key_out = key_out_r;

  96.     always  @(posedge clk_50M or negedge rst_n)begin
  97.         if(rst_n==1'b0)begin
  98.             led <= 1'd0;
  99.         end
  100.         else begin
  101.             if( cur_state == FILTER0 && next_state == DOWN )
  102.                 led <= ~led;
  103.         end
  104.     end
  105. endmodule
举报

y990441

2015-9-30 22:10:28
感觉输出led和key_out没对齐,led似乎还应该再打一拍才对齐。
举报

y990441

2015-9-30 22:30:43
贴上仿真结果。。。远看看不见key_in的抖动。。。但近看。。。确实是有抖那么两三下的。。。
举报

梅雪松

2015-10-21 17:40:26
引用: y990441 发表于 2015-9-30 22:30
贴上仿真结果。。。远看看不见key_in的抖动。。。但近看。。。确实是有抖那么两三下的。。。

尝试将抖动次数加多,就能看到了吧
举报

756589738

2015-10-24 21:14:26
支持!感觉小梅哥讲的视频把老师一学期讲的课给概括了!点赞!
举报

sunhaopo

2015-10-25 20:36:02
小梅哥FPGA设计思想与验证方法视频教程
举报

柔情侠骨

2015-10-25 21:29:41
支持梅哥,好好学习,谢谢
举报

kingcard528

2015-10-26 19:38:08
好好好好好好好好好好好好好好好好好好好好
举报

王磊

2015-10-26 21:54:26
bucuo 支持                                 
举报

王磊

2015-10-26 21:55:01

好好好好好好好好好好好好好好好好好好好好
举报

easy5211

2015-10-26 23:07:13
顶 ,用这个练习状态机不错,学习中
举报

jiangzyw

2015-10-27 10:39:39
希望观看视频学习
举报

更多回帖

发帖
×
20
完善资料,
赚取积分