[verilog] 倒计时系统设计(上)之计时模块

[复制链接]
 楼主| zhangyuhua 发表于 2017-3-18 20:29 | 显示全部楼层 |阅读模式
本帖最后由 zhangyuhua 于 2017-3-18 20:29 编辑

      一周才完成了一个倒计时系统的设计。效率太低了,即使有点低,但也总结下。     此系统实现的功能介绍。
        a.  两个按键key1/key2。key1是复位按键,此按键被按下,系统复位;key2按键是停止/开始按键,即当首次按下,系统开始计时,再次被按下,系统停止计时;再次按下,系统再次计时。
        b.  选用6个数码管的板子,来实现此功能系统。

     整个系统可分三个子系统,分别是计时模块、BCD转码模块和数码管显示模块这三个模块。下图是整个系统架构:

       下面分别详细介绍下,三个子系统是如何实现的。
(1)计时模块

(其中:cnt_ms代表毫秒信号
              cnt_s秒信号代表
              dout_vld代表此模块输出一个信号,可供下一个模块使用)
源代码:
  1. //`define         SIM
  2. module        cnt(
  3.                         //System Signals
  4.                         input                                sclk                ,
  5.                         input                                rst_n                ,
  6.                         //Others
  7.                         input                [1:0]        key                        ,        //key[1]---Start/Stop
  8.                                                                                                 //key=1----The key is not pressed;
  9.                                                                                                 //key=0----The key is pressed
  10.                                                                                                 //key[0]---Rst
  11.                         output        reg                        dout_vld        ,        //to tell next module start work
  12.                         output        reg        [7:0]        cnt_s                ,
  13.                         output        reg        [7:0]        cnt_ms               
  14.                 );
  15. //========================================================================\
  16. // **********Define Parameter and Internal Signals*******************
  17. //========================================================================/
  18. //`ifndef SIM
  19. parameter        DELAY_10ms        =        50_0000                ;
  20. //`else
  21. //parameter        DELAY_10ms        =        100                        ;
  22. //`endif

  23. //relation cnt_10ms
  24. reg        [18:0]        cnt_10ms                ;        //0.01s
  25. wire                add_cnt_10ms        ;
  26. wire                end_cnt_10ms        ;
  27. reg                        flag                        ;
  28. //relation cnt_ms
  29. wire                add_cnt_ms                ;
  30. wire                end_cnt_ms                ;

  31. //relation cnt_s
  32. wire                add_cnt_s                ;
  33. wire                end_cnt_s                ;

  34. //========================================================================\
  35. // **********Main Code*******************
  36. //========================================================================/
  37. //cnt_10ms
  38. always @(posedge sclk or negedge rst_n)
  39.         begin
  40.                 if(!rst_n)
  41.                         cnt_10ms<='d0;
  42.                 else        if(add_cnt_10ms)
  43.                                         if(end_cnt_10ms)
  44.                                                 cnt_10ms<='d0;
  45.                                         else        cnt_10ms<=cnt_10ms+1'b1;        
  46.         end
  47. assign        add_cnt_10ms=flag;
  48. assign        end_cnt_10ms=add_cnt_10ms && (cnt_10ms==DELAY_10ms-1);
  49. always        @(posedge sclk or negedge rst_n)
  50.         begin
  51.                 if(!rst_n)
  52.                         flag<=1'b0;
  53.                 else        if(key[0]==1'b0 || (end_cnt_s==1'b1))
  54.                                         flag<=1'b0;
  55.                                 else        if(key[1]==1'b0)
  56.                                                         flag<=~flag;
  57.         end
  58. //[7:0]cnt_ms
  59. always @(posedge sclk or negedge rst_n)
  60.         begin
  61.                 if(!rst_n)
  62.                         cnt_ms<=8'd99;
  63.                 else        begin
  64.                                         if(key[0]==1'b0)
  65.                                                 cnt_ms<=8'd99;
  66.                                         else        if(add_cnt_ms)
  67.                                                                 if(end_cnt_ms)
  68.                                                                         cnt_ms<='d99;
  69.                                                                 else        cnt_ms<=cnt_ms-1'b1;
  70.                                 end
  71.         end
  72. assign        add_cnt_ms=end_cnt_10ms;
  73. assign        end_cnt_ms=add_cnt_ms && cnt_ms==8'd0 ;        

  74. //cnt_s[7:0]
  75. always        @(posedge sclk or negedge rst_n)
  76.         begin
  77.                 if(!rst_n)
  78.                         cnt_s<='d23;
  79.                 else        begin
  80.                                         if(key[0]==1'b0)
  81.                                                 cnt_s<='d23;
  82.                                         else        if(add_cnt_s)
  83.                                                                 if(end_cnt_s)
  84.                                                                         cnt_s<='d23;
  85.                                                                 else        cnt_s<=cnt_s-1'b1;
  86.                                 end
  87.         end
  88. assign        add_cnt_s=end_cnt_ms;
  89. assign        end_cnt_s=add_cnt_s && cnt_s=='d0 ;

  90. //dout_vld
  91. always @(posedge sclk or negedge rst_n)
  92.         begin
  93.                 if(!rst_n)
  94.                         dout_vld<=1'b0;
  95.                 else        if(end_cnt_10ms)
  96.                                         dout_vld<=1'b1;
  97.                                 else        dout_vld<=1'b0;
  98.         end

  99. endmodule
      为了节省仿真时间,在这里使用了一个宏定义如下:
                            `ifndef   语句1
                             `else     语句2
                             `endif
   在这里不具体介绍这个语法是怎么使用的。可查看一些语法书籍。

(2)总结:      这个计时模块比较简单,内部就使用了3个计数器。
      设计整个倒计时系统,我花费的时间比较长,大概用了一周的时间。过了两天再重新看自己写的代码时,里面一些信号名就不知道它代表的意思了。还得重新看代码。这样会浪费大量的时间。所以,我自己总结了下自己的代码风格。以后都遵循这些规则,可以减少代码的修改时间。
     在模块中要使用三个信号。一是,模块触发信号(eg.此模块中的key_vld);二是,模块输出使能信号(eg.此模块中的dout_vld);三是,模块正在工作状态的信号(eg.此模块中的flag信号)。

本帖子中包含更多资源

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

×
fonst 发表于 2017-3-21 21:26 | 显示全部楼层
命名规范了,信号名就容易记住了
您需要登录后才可以回帖 登录 | 注册

本版积分规则

14

主题

26

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部