[FPGA] 这是一个简单的按键控制数码管,我却找了三天的问题

[复制链接]
162|4
 楼主 | 2018-2-4 12:49 | 显示全部楼层 |阅读模式

  1. `timescale 1ns / 1ps
  2. //按键调试数码管显示,key1 归零,key2 +1。数值为0~9
  3. module a(
  4.         input clk,
  5.         input [1:0] key,
  6.         output [7:0] dig,
  7.         output [0:5] sel
  8. );

  9. //寄存器定义
  10. reg [19:0] delay; //延时20ms,判断按键
  11. reg [1:0] key_scan;//扫描20mS后按键
  12. reg [1:0] key_scan_r;//扫描按键
  13. reg [7:0] numb;//需要显示的初始值
  14. reg [3:0] ha;  //选择数字
  15. initial begin ha = 4'd5;end
  16. initial begin
  17.         numb <= 8'b0;
  18.         key_scan <= 2'b11;
  19.         key_scan_r <= 2'b11;        //初值都为1,计算后结果与key_true初值相同,在开始时不会触发numb变化,才会显示初值5
  20.         delay <= 20'd0;
  21.         end

  22. //*************扫描按键**************
  23. //说明:分两个寄存器采样,一个使用时钟频率,一个使用时钟频率分频后的频率,既可看成一个为检测初始信号,另一个延时20mS做确认
  24. always @(posedge clk) //扫描20mS后的按键
  25.         begin
  26.                 if (delay == 20'd999_999)//999_999
  27.                         begin
  28.                                 delay <= 20'b0;
  29.                                 key_scan <= key;  //若计满20ms采样按键输入
  30.                         end
  31.                 else delay <= delay + 20'b1; //计数加一
  32.         end

  33. always @(posedge clk) //扫描按键
  34.         key_scan_r <= key;

  35. wire [1:0] key_true = (~key_scan[1:0]) & (key_scan_r[1:0]);//确认按键

  36. //*****被选择数字存入寄存器*******
  37. always @(ha)
  38.         case (ha)
  39.                 4'd0: numb <= 8'hc0;
  40.                 4'd1: numb <= 8'hf9;
  41.                 4'd2: numb <= 8'ha4;
  42.                 4'd3: numb <= 8'hb0;
  43.                 4'd4: numb <= 8'h99;
  44.                 4'd5: numb <= 8'h92;
  45.                 4'd6: numb <= 8'h82;
  46.                 4'd7: numb <= 8'hf8;
  47.                 4'd8: numb <= 8'h80;
  48.                 4'd9: numb <= 8'h90;
  49.                 default: numb <= 8'hc0;
  50.         endcase
  51.        
  52. //***********按键选择数字*****************
  53. always @(posedge clk)
  54.         begin
  55.                 if(key_true[0]) ha <= 4'b0000;
  56.                 if(key_true[1])
  57.                 begin
  58.                         if(ha < 4'd9)
  59.                                 ha <= ha + 4'd1;
  60.                         else ha <= 4'd9;
  61.                 end
  62.         end

  63. //*****取出当前显示数值(BCD译码)*********


  64. assign dig = numb;
  65. assign sel = 6'b1101_11;
  66. endmodule
复制代码

这是我的程序,下边的“BCD译码”还未写可以忽略,这个程序出现的问题是,逻辑看起来并没有任何问题,但烧进去后,按键并未使它正确+1。程序中设定是按到9就不再加了,但我按一次就会直接跳到9。我在二楼贴出别人的程序别人可以正常使用的程序并提出我的一些其他疑问。

 楼主 | 2018-2-4 12:53 | 显示全部楼层
  1. `timescale 1ns / 1ps
  2. //////////////////////////////////////////////////////////////////////////////////
  3. //按键控制数码管加减一
  4. //功能:通过两个按键key1和key2分别控制共阳带小数点的数码管加减一
  5. //调试环境:ISE 10.1;火龙刀实验板
  6. //本程序参考了 EDN助学—CPLD学习小组 ilove314 的练习例程
  7. //////////////////////////////////////////////////////////////////////////////////
  8. module a(clk,key1,key2,led_cs,led_db);
  9. input clk,key1,key2;
  10. output led_cs;   //数码管的选择,本实例只用其中一个数码管,所以直接连续赋值assign led_cs=1'b1;
  11. output [7:0] led_db;  //七段数码管,带小数点,共阳
  12. reg [7:0] led_dbr;        //7段数码管寄存器
  13. reg [19:0] cnt;
  14. reg[3:0] num;   //显示数值
  15. /*初始化,因为实验板上的复位键失灵,没有多余的按键了,所以取消复位初始化reset,改用initial*/
  16. initial begin num=4'd0;end
  17. initial begin cnt=20'h00000;end
  18. always [url=home.php?mod=space&uid=72445]@[/url] (posedge clk)
  19. cnt <= cnt+1'b1;   //循环计数
  20. parameter   seg0    = 8'hc0,  //共阳七段数码管的值
  21.             seg1    = 8'hf9,
  22.             seg2    = 8'ha4,
  23.             seg3    = 8'hb0,
  24.             seg4    = 8'h99,
  25.             seg5    = 8'h92,
  26.             seg6    = 8'h82,
  27.             seg7    = 8'hf8,
  28.             seg8    = 8'h80,
  29.             seg9    = 8'h90;
  30. always @ (num)
  31.         case (num)
  32.             4'd0: led_dbr<= seg0;
  33.             4'd1: led_dbr<= seg1;
  34.             4'd2: led_dbr<= seg2;
  35.             4'd3: led_dbr<= seg3;
  36.             4'd4: led_dbr<= seg4;
  37.             4'd5: led_dbr<= seg5;
  38.             4'd6: led_dbr<= seg6;
  39.             4'd7: led_dbr<= seg7;
  40.             4'd8: led_dbr<= seg8;
  41.             4'd9: led_dbr<= seg9;
  42.             default: ;
  43.             endcase
  44.       
  45.    
  46. reg key1_flag,key2_flag,key1_flag_r,key2_flag_r;
  47. initial begin key1_flag=1'b0;key2_flag=1'b0;key1_flag_r=1'b0;key2_flag_r=1'b0;end  //定义存储键值的寄存器,并初始化
  48. always @ (posedge clk)  //如有按键按下,延时8'hfffff后,把键值赋予寄存器key1_flag和key2_flag
  49. if(cnt==20'hfffff)
  50. begin  
  51. key1_flag<=key1;
  52. key2_flag<=key2;
  53. end
  54. always @ (posedge clk)
  55. begin  
  56. key1_flag_r<=key1_flag;
  57. key2_flag_r<=key2_flag;
  58. end
  59. wire key1_f=(~key1_flag)&&key1_flag_r;  //相当于wire key1_f; assign key1_f=(~key1_flag)&&key1_flag_r;
  60. wire key2_f=(~key2_flag)&&key2_flag_r;
  61. always @(posedge clk)
  62. begin
  63. if(key1_f)
  64. begin
  65.   if(num<9) num<=num+4'd1;    //按键key1一次,数码管加一
  66.   else num<=9;
  67. end

  68. if(key2_f)
  69. begin
  70.   if(num>0)
  71.   num<=num-4'd1;//按键key2一次,数码管减一
  72.   else num<=0;
  73. end
  74. end
  75. assign led_db=led_dbr;  //数码管输出
  76. assign led_cs=1'b0;//数码管常亮
  77. endmodule
复制代码


这是别人的程序我原封未动。在这个程序中可以看见,他的default后面是没有写东西的,若我的程序这么写,会出现“Latch xx has unsafe behavior”的警告。

PS:我的FPGA的数码管是共阳的,位选低电平有效,按键低电平有效。
 楼主 | 2018-2-4 12:58 | 显示全部楼层
我的程序还出现了这么一个奇怪的问题,寄存器"key_scan"与"key_scan_r"可以在程序中看见,我是直接将按键"key"传递给它的。然而在signaltap中,我却看见这两个信号于按键未按下时是低电平,而按键按下后是高电平
| 2018-2-5 16:02 | 显示全部楼层
signaltap有这个毛病,不过只记得以前碰到过一次,也没有关心。
直接加到9的问题应该是按键没有去抖所致

评论

emmmm 2018-2-5 16:18 回复TA
不好意思哈,这个问题我已经解决了但不知道怎么删帖。这个问题确实出在消抖处,我抄程序抄错了,还是因为我对这个消抖没有理解。 
扫描二维码,随时随地手机跟帖
*滑动验证:
您需要登录后才可以回帖 登录 | 注册 手机登录

本版积分规则

快速回复

您需要登录后才可以回帖
登录 | 注册 手机登录
高级模式
我要创建版块

论坛热帖

关闭

热门推荐上一条 /4 下一条

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